mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	
						commit
						c5a849212f
					
				@ -731,11 +731,15 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (mag_filter != config.mag_filter) {
 | 
					    if (mag_filter != config.mag_filter) {
 | 
				
			||||||
        mag_filter = config.mag_filter;
 | 
					        mag_filter = config.mag_filter;
 | 
				
			||||||
        glSamplerParameteri(s, GL_TEXTURE_MAG_FILTER, MaxwellToGL::TextureFilterMode(mag_filter));
 | 
					        glSamplerParameteri(
 | 
				
			||||||
 | 
					            s, GL_TEXTURE_MAG_FILTER,
 | 
				
			||||||
 | 
					            MaxwellToGL::TextureFilterMode(mag_filter, Tegra::Texture::TextureMipmapFilter::None));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (min_filter != config.min_filter) {
 | 
					    if (min_filter != config.min_filter || mip_filter != config.mip_filter) {
 | 
				
			||||||
        min_filter = config.min_filter;
 | 
					        min_filter = config.min_filter;
 | 
				
			||||||
        glSamplerParameteri(s, GL_TEXTURE_MIN_FILTER, MaxwellToGL::TextureFilterMode(min_filter));
 | 
					        mip_filter = config.mip_filter;
 | 
				
			||||||
 | 
					        glSamplerParameteri(s, GL_TEXTURE_MIN_FILTER,
 | 
				
			||||||
 | 
					                            MaxwellToGL::TextureFilterMode(min_filter, mip_filter));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (wrap_u != config.wrap_u) {
 | 
					    if (wrap_u != config.wrap_u) {
 | 
				
			||||||
 | 
				
			|||||||
@ -93,6 +93,7 @@ private:
 | 
				
			|||||||
    private:
 | 
					    private:
 | 
				
			||||||
        Tegra::Texture::TextureFilter mag_filter;
 | 
					        Tegra::Texture::TextureFilter mag_filter;
 | 
				
			||||||
        Tegra::Texture::TextureFilter min_filter;
 | 
					        Tegra::Texture::TextureFilter min_filter;
 | 
				
			||||||
 | 
					        Tegra::Texture::TextureMipmapFilter mip_filter;
 | 
				
			||||||
        Tegra::Texture::WrapMode wrap_u;
 | 
					        Tegra::Texture::WrapMode wrap_u;
 | 
				
			||||||
        Tegra::Texture::WrapMode wrap_v;
 | 
					        Tegra::Texture::WrapMode wrap_v;
 | 
				
			||||||
        Tegra::Texture::WrapMode wrap_p;
 | 
					        Tegra::Texture::WrapMode wrap_p;
 | 
				
			||||||
 | 
				
			|||||||
@ -91,27 +91,36 @@ void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {
 | 
					std::size_t SurfaceParams::InnerMipmapMemorySize(u32 mip_level, bool force_gl, bool layer_only,
 | 
				
			||||||
 | 
					                                                 bool uncompressed) const {
 | 
				
			||||||
    const u32 compression_factor{GetCompressionFactor(pixel_format)};
 | 
					    const u32 compression_factor{GetCompressionFactor(pixel_format)};
 | 
				
			||||||
    const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)};
 | 
					    const u32 bytes_per_pixel{GetBytesPerPixel(pixel_format)};
 | 
				
			||||||
    u32 m_depth = (layer_only ? 1U : depth);
 | 
					    u32 m_depth = (layer_only ? 1U : depth);
 | 
				
			||||||
    u32 m_width = std::max(1U, width / compression_factor);
 | 
					    u32 m_width = MipWidth(mip_level);
 | 
				
			||||||
    u32 m_height = std::max(1U, height / compression_factor);
 | 
					    u32 m_height = MipHeight(mip_level);
 | 
				
			||||||
    std::size_t size = Tegra::Texture::CalculateSize(is_tiled, bytes_per_pixel, m_width, m_height,
 | 
					    m_width = uncompressed ? m_width
 | 
				
			||||||
                                                     m_depth, block_height, block_depth);
 | 
					                           : std::max(1U, (m_width + compression_factor - 1) / compression_factor);
 | 
				
			||||||
    u32 m_block_height = block_height;
 | 
					    m_height = uncompressed
 | 
				
			||||||
    u32 m_block_depth = block_depth;
 | 
					                   ? m_height
 | 
				
			||||||
    std::size_t block_size_bytes = 512 * block_height * block_depth; // 512 is GOB size
 | 
					                   : std::max(1U, (m_height + compression_factor - 1) / compression_factor);
 | 
				
			||||||
    for (u32 i = 1; i < max_mip_level; i++) {
 | 
					    m_depth = std::max(1U, m_depth >> mip_level);
 | 
				
			||||||
        m_width = std::max(1U, m_width / 2);
 | 
					    u32 m_block_height = MipBlockHeight(mip_level);
 | 
				
			||||||
        m_height = std::max(1U, m_height / 2);
 | 
					    u32 m_block_depth = MipBlockDepth(mip_level);
 | 
				
			||||||
        m_depth = std::max(1U, m_depth / 2);
 | 
					    return Tegra::Texture::CalculateSize(force_gl ? false : is_tiled, bytes_per_pixel, m_width,
 | 
				
			||||||
        m_block_height = std::max(1U, m_block_height / 2);
 | 
					                                         m_height, m_depth, m_block_height, m_block_depth);
 | 
				
			||||||
        m_block_depth = std::max(1U, m_block_depth / 2);
 | 
					}
 | 
				
			||||||
        size += Tegra::Texture::CalculateSize(is_tiled, bytes_per_pixel, m_width, m_height, m_depth,
 | 
					
 | 
				
			||||||
                                              m_block_height, m_block_depth);
 | 
					std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only,
 | 
				
			||||||
 | 
					                                           bool uncompressed) const {
 | 
				
			||||||
 | 
					    std::size_t block_size_bytes = Tegra::Texture::GetGOBSize() * block_height * block_depth;
 | 
				
			||||||
 | 
					    std::size_t size = 0;
 | 
				
			||||||
 | 
					    for (u32 i = 0; i < max_mip_level; i++) {
 | 
				
			||||||
 | 
					        size += InnerMipmapMemorySize(i, force_gl, layer_only, uncompressed);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return is_tiled ? Common::AlignUp(size, block_size_bytes) : size;
 | 
					    if (!force_gl && is_tiled) {
 | 
				
			||||||
 | 
					        size = Common::AlignUp(size, block_size_bytes);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return size;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*static*/ SurfaceParams SurfaceParams::CreateForTexture(
 | 
					/*static*/ SurfaceParams SurfaceParams::CreateForTexture(
 | 
				
			||||||
@ -189,7 +198,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {
 | 
				
			|||||||
    params.unaligned_height = config.height;
 | 
					    params.unaligned_height = config.height;
 | 
				
			||||||
    params.target = SurfaceTarget::Texture2D;
 | 
					    params.target = SurfaceTarget::Texture2D;
 | 
				
			||||||
    params.depth = 1;
 | 
					    params.depth = 1;
 | 
				
			||||||
    params.max_mip_level = 0;
 | 
					    params.max_mip_level = 1;
 | 
				
			||||||
    params.is_layered = false;
 | 
					    params.is_layered = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Render target specific parameters, not used for caching
 | 
					    // Render target specific parameters, not used for caching
 | 
				
			||||||
@ -223,7 +232,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {
 | 
				
			|||||||
    params.unaligned_height = zeta_height;
 | 
					    params.unaligned_height = zeta_height;
 | 
				
			||||||
    params.target = SurfaceTarget::Texture2D;
 | 
					    params.target = SurfaceTarget::Texture2D;
 | 
				
			||||||
    params.depth = 1;
 | 
					    params.depth = 1;
 | 
				
			||||||
    params.max_mip_level = 0;
 | 
					    params.max_mip_level = 1;
 | 
				
			||||||
    params.is_layered = false;
 | 
					    params.is_layered = false;
 | 
				
			||||||
    params.rt = {};
 | 
					    params.rt = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -250,7 +259,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool layer_only) const {
 | 
				
			|||||||
    params.unaligned_height = config.height;
 | 
					    params.unaligned_height = config.height;
 | 
				
			||||||
    params.target = SurfaceTarget::Texture2D;
 | 
					    params.target = SurfaceTarget::Texture2D;
 | 
				
			||||||
    params.depth = 1;
 | 
					    params.depth = 1;
 | 
				
			||||||
    params.max_mip_level = 0;
 | 
					    params.max_mip_level = 1;
 | 
				
			||||||
    params.rt = {};
 | 
					    params.rt = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    params.InitCacheParameters(config.Address());
 | 
					    params.InitCacheParameters(config.Address());
 | 
				
			||||||
@ -374,13 +383,13 @@ static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType
 | 
				
			|||||||
    return format;
 | 
					    return format;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MathUtil::Rectangle<u32> SurfaceParams::GetRect() const {
 | 
					MathUtil::Rectangle<u32> SurfaceParams::GetRect(u32 mip_level) const {
 | 
				
			||||||
    u32 actual_height{unaligned_height};
 | 
					    u32 actual_height{std::max(1U, unaligned_height >> mip_level)};
 | 
				
			||||||
    if (IsPixelFormatASTC(pixel_format)) {
 | 
					    if (IsPixelFormatASTC(pixel_format)) {
 | 
				
			||||||
        // ASTC formats must stop at the ATSC block size boundary
 | 
					        // ASTC formats must stop at the ATSC block size boundary
 | 
				
			||||||
        actual_height = Common::AlignDown(actual_height, GetASTCBlockSize(pixel_format).second);
 | 
					        actual_height = Common::AlignDown(actual_height, GetASTCBlockSize(pixel_format).second);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return {0, actual_height, width, 0};
 | 
					    return {0, actual_height, MipWidth(mip_level), 0};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN
 | 
					/// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN
 | 
				
			||||||
@ -564,28 +573,31 @@ static constexpr GLConversionArray gl_to_morton_fns = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void SwizzleFunc(const GLConversionArray& functions, const SurfaceParams& params,
 | 
					void SwizzleFunc(const GLConversionArray& functions, const SurfaceParams& params,
 | 
				
			||||||
                 std::vector<u8>& gl_buffer) {
 | 
					                 std::vector<u8>& gl_buffer, u32 mip_level) {
 | 
				
			||||||
    u32 depth = params.depth;
 | 
					    u32 depth = params.MipDepth(mip_level);
 | 
				
			||||||
    if (params.target == SurfaceParams::SurfaceTarget::Texture2D) {
 | 
					    if (params.target == SurfaceParams::SurfaceTarget::Texture2D) {
 | 
				
			||||||
        // TODO(Blinkhawk): Eliminate this condition once all texture types are implemented.
 | 
					        // TODO(Blinkhawk): Eliminate this condition once all texture types are implemented.
 | 
				
			||||||
        depth = 1U;
 | 
					        depth = 1U;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (params.is_layered) {
 | 
					    if (params.is_layered) {
 | 
				
			||||||
        u64 offset = 0;
 | 
					        u64 offset = params.GetMipmapLevelOffset(mip_level);
 | 
				
			||||||
        u64 offset_gl = 0;
 | 
					        u64 offset_gl = 0;
 | 
				
			||||||
        u64 layer_size = params.LayerMemorySize();
 | 
					        u64 layer_size = params.LayerMemorySize();
 | 
				
			||||||
        u64 gl_size = params.LayerSizeGL();
 | 
					        u64 gl_size = params.LayerSizeGL(mip_level);
 | 
				
			||||||
        for (u32 i = 0; i < depth; i++) {
 | 
					        for (u32 i = 0; i < params.depth; i++) {
 | 
				
			||||||
            functions[static_cast<std::size_t>(params.pixel_format)](
 | 
					            functions[static_cast<std::size_t>(params.pixel_format)](
 | 
				
			||||||
                params.width, params.block_height, params.height, params.block_depth, 1,
 | 
					                params.MipWidth(mip_level), params.MipBlockHeight(mip_level),
 | 
				
			||||||
 | 
					                params.MipHeight(mip_level), params.MipBlockDepth(mip_level), 1,
 | 
				
			||||||
                gl_buffer.data() + offset_gl, gl_size, params.addr + offset);
 | 
					                gl_buffer.data() + offset_gl, gl_size, params.addr + offset);
 | 
				
			||||||
            offset += layer_size;
 | 
					            offset += layer_size;
 | 
				
			||||||
            offset_gl += gl_size;
 | 
					            offset_gl += gl_size;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 | 
					        u64 offset = params.GetMipmapLevelOffset(mip_level);
 | 
				
			||||||
        functions[static_cast<std::size_t>(params.pixel_format)](
 | 
					        functions[static_cast<std::size_t>(params.pixel_format)](
 | 
				
			||||||
            params.width, params.block_height, params.height, params.block_depth, depth,
 | 
					            params.MipWidth(mip_level), params.MipBlockHeight(mip_level),
 | 
				
			||||||
            gl_buffer.data(), gl_buffer.size(), params.addr);
 | 
					            params.MipHeight(mip_level), params.MipBlockDepth(mip_level), depth, gl_buffer.data(),
 | 
				
			||||||
 | 
					            gl_buffer.size(), params.addr + offset);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -840,31 +852,38 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
 | 
				
			|||||||
        // Only pre-create the texture for non-compressed textures.
 | 
					        // Only pre-create the texture for non-compressed textures.
 | 
				
			||||||
        switch (params.target) {
 | 
					        switch (params.target) {
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture1D:
 | 
					        case SurfaceParams::SurfaceTarget::Texture1D:
 | 
				
			||||||
            glTexStorage1D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format,
 | 
					            glTexStorage1D(SurfaceTargetToGL(params.target), params.max_mip_level,
 | 
				
			||||||
                           rect.GetWidth());
 | 
					                           format_tuple.internal_format, rect.GetWidth());
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture2D:
 | 
					        case SurfaceParams::SurfaceTarget::Texture2D:
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::TextureCubemap:
 | 
					        case SurfaceParams::SurfaceTarget::TextureCubemap:
 | 
				
			||||||
            glTexStorage2D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format,
 | 
					            glTexStorage2D(SurfaceTargetToGL(params.target), params.max_mip_level,
 | 
				
			||||||
                           rect.GetWidth(), rect.GetHeight());
 | 
					                           format_tuple.internal_format, rect.GetWidth(), rect.GetHeight());
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture3D:
 | 
					        case SurfaceParams::SurfaceTarget::Texture3D:
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture2DArray:
 | 
					        case SurfaceParams::SurfaceTarget::Texture2DArray:
 | 
				
			||||||
            glTexStorage3D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format,
 | 
					            glTexStorage3D(SurfaceTargetToGL(params.target), params.max_mip_level,
 | 
				
			||||||
                           rect.GetWidth(), rect.GetHeight(), params.depth);
 | 
					                           format_tuple.internal_format, rect.GetWidth(), rect.GetHeight(),
 | 
				
			||||||
 | 
					                           params.depth);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
 | 
					            LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
 | 
				
			||||||
                         static_cast<u32>(params.target));
 | 
					                         static_cast<u32>(params.target));
 | 
				
			||||||
            UNREACHABLE();
 | 
					            UNREACHABLE();
 | 
				
			||||||
            glTexStorage2D(GL_TEXTURE_2D, 1, format_tuple.internal_format, rect.GetWidth(),
 | 
					            glTexStorage2D(GL_TEXTURE_2D, params.max_mip_level, format_tuple.internal_format,
 | 
				
			||||||
                           rect.GetHeight());
 | 
					                           rect.GetWidth(), rect.GetHeight());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
					    glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
				
			||||||
 | 
					    glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
				
			||||||
    glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 | 
					    glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 | 
				
			||||||
    glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 | 
					    glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 | 
				
			||||||
 | 
					    glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL,
 | 
				
			||||||
 | 
					                    params.max_mip_level - 1);
 | 
				
			||||||
 | 
					    if (params.max_mip_level == 1) {
 | 
				
			||||||
 | 
					        glTexParameterf(SurfaceTargetToGL(params.target), GL_TEXTURE_LOD_BIAS, 1000.0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LabelGLObject(GL_TEXTURE, texture.handle, params.addr,
 | 
					    LabelGLObject(GL_TEXTURE, texture.handle, params.addr,
 | 
				
			||||||
                  SurfaceParams::SurfaceTargetName(params.target));
 | 
					                  SurfaceParams::SurfaceTargetName(params.target));
 | 
				
			||||||
@ -993,20 +1012,22 @@ static void ConvertFormatAsNeeded_FlushGLBuffer(std::vector<u8>& data, PixelForm
 | 
				
			|||||||
MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192));
 | 
					MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 64, 192));
 | 
				
			||||||
void CachedSurface::LoadGLBuffer() {
 | 
					void CachedSurface::LoadGLBuffer() {
 | 
				
			||||||
    MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
 | 
					    MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
 | 
				
			||||||
 | 
					    gl_buffer.resize(params.max_mip_level);
 | 
				
			||||||
    gl_buffer.resize(params.size_in_bytes_gl);
 | 
					    for (u32 i = 0; i < params.max_mip_level; i++)
 | 
				
			||||||
 | 
					        gl_buffer[i].resize(params.GetMipmapSizeGL(i));
 | 
				
			||||||
    if (params.is_tiled) {
 | 
					    if (params.is_tiled) {
 | 
				
			||||||
        ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}",
 | 
					        ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}",
 | 
				
			||||||
                   params.block_width, static_cast<u32>(params.target));
 | 
					                   params.block_width, static_cast<u32>(params.target));
 | 
				
			||||||
 | 
					        for (u32 i = 0; i < params.max_mip_level; i++)
 | 
				
			||||||
        SwizzleFunc(morton_to_gl_fns, params, gl_buffer);
 | 
					            SwizzleFunc(morton_to_gl_fns, params, gl_buffer[i], i);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        const auto texture_src_data{Memory::GetPointer(params.addr)};
 | 
					        const auto texture_src_data{Memory::GetPointer(params.addr)};
 | 
				
			||||||
        const auto texture_src_data_end{texture_src_data + params.size_in_bytes_gl};
 | 
					        const auto texture_src_data_end{texture_src_data + params.size_in_bytes_gl};
 | 
				
			||||||
        gl_buffer.assign(texture_src_data, texture_src_data_end);
 | 
					        gl_buffer[0].assign(texture_src_data, texture_src_data_end);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    for (u32 i = 0; i < params.max_mip_level; i++)
 | 
				
			||||||
    ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer, params.pixel_format, params.width, params.height);
 | 
					        ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i),
 | 
				
			||||||
 | 
					                                           params.MipHeight(i));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64));
 | 
					MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64));
 | 
				
			||||||
@ -1016,7 +1037,8 @@ void CachedSurface::FlushGLBuffer() {
 | 
				
			|||||||
    ASSERT_MSG(!IsPixelFormatASTC(params.pixel_format), "Unimplemented");
 | 
					    ASSERT_MSG(!IsPixelFormatASTC(params.pixel_format), "Unimplemented");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // OpenGL temporary buffer needs to be big enough to store raw texture size
 | 
					    // OpenGL temporary buffer needs to be big enough to store raw texture size
 | 
				
			||||||
    gl_buffer.resize(GetSizeInBytes());
 | 
					    gl_buffer.resize(1);
 | 
				
			||||||
 | 
					    gl_buffer[0].resize(GetSizeInBytes());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type);
 | 
					    const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type);
 | 
				
			||||||
    // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
 | 
					    // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
 | 
				
			||||||
@ -1025,9 +1047,9 @@ void CachedSurface::FlushGLBuffer() {
 | 
				
			|||||||
    ASSERT(!tuple.compressed);
 | 
					    ASSERT(!tuple.compressed);
 | 
				
			||||||
    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
 | 
					    glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
 | 
				
			||||||
    glGetTextureImage(texture.handle, 0, tuple.format, tuple.type,
 | 
					    glGetTextureImage(texture.handle, 0, tuple.format, tuple.type,
 | 
				
			||||||
                      static_cast<GLsizei>(gl_buffer.size()), gl_buffer.data());
 | 
					                      static_cast<GLsizei>(gl_buffer[0].size()), gl_buffer[0].data());
 | 
				
			||||||
    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
 | 
					    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
 | 
				
			||||||
    ConvertFormatAsNeeded_FlushGLBuffer(gl_buffer, params.pixel_format, params.width,
 | 
					    ConvertFormatAsNeeded_FlushGLBuffer(gl_buffer[0], params.pixel_format, params.width,
 | 
				
			||||||
                                        params.height);
 | 
					                                        params.height);
 | 
				
			||||||
    ASSERT(params.type != SurfaceType::Fill);
 | 
					    ASSERT(params.type != SurfaceType::Fill);
 | 
				
			||||||
    const u8* const texture_src_data = Memory::GetPointer(params.addr);
 | 
					    const u8* const texture_src_data = Memory::GetPointer(params.addr);
 | 
				
			||||||
@ -1036,26 +1058,21 @@ void CachedSurface::FlushGLBuffer() {
 | 
				
			|||||||
        ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}",
 | 
					        ASSERT_MSG(params.block_width == 1, "Block width is defined as {} on texture type {}",
 | 
				
			||||||
                   params.block_width, static_cast<u32>(params.target));
 | 
					                   params.block_width, static_cast<u32>(params.target));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SwizzleFunc(gl_to_morton_fns, params, gl_buffer);
 | 
					        SwizzleFunc(gl_to_morton_fns, params, gl_buffer[0], 0);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        std::memcpy(Memory::GetPointer(GetAddr()), gl_buffer.data(), GetSizeInBytes());
 | 
					        std::memcpy(Memory::GetPointer(GetAddr()), gl_buffer[0].data(), GetSizeInBytes());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192));
 | 
					void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
 | 
				
			||||||
void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) {
 | 
					                                          GLuint draw_fb_handle) {
 | 
				
			||||||
    if (params.type == SurfaceType::Fill)
 | 
					    const auto& rect{params.GetRect(mip_map)};
 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    MICROPROFILE_SCOPE(OpenGL_TextureUL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto& rect{params.GetRect()};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Load data from memory to the surface
 | 
					    // Load data from memory to the surface
 | 
				
			||||||
    const GLint x0 = static_cast<GLint>(rect.left);
 | 
					    const GLint x0 = static_cast<GLint>(rect.left);
 | 
				
			||||||
    const GLint y0 = static_cast<GLint>(rect.bottom);
 | 
					    const GLint y0 = static_cast<GLint>(rect.bottom);
 | 
				
			||||||
    std::size_t buffer_offset =
 | 
					    std::size_t buffer_offset =
 | 
				
			||||||
        static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.width +
 | 
					        static_cast<std::size_t>(static_cast<std::size_t>(y0) * params.MipWidth(mip_map) +
 | 
				
			||||||
                                 static_cast<std::size_t>(x0)) *
 | 
					                                 static_cast<std::size_t>(x0)) *
 | 
				
			||||||
        SurfaceParams::GetBytesPerPixel(params.pixel_format);
 | 
					        SurfaceParams::GetBytesPerPixel(params.pixel_format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1073,88 +1090,117 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle
 | 
				
			|||||||
    cur_state.Apply();
 | 
					    cur_state.Apply();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
 | 
					    // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
 | 
				
			||||||
    ASSERT(params.width * SurfaceParams::GetBytesPerPixel(params.pixel_format) % 4 == 0);
 | 
					    ASSERT(params.MipWidth(mip_map) * SurfaceParams::GetBytesPerPixel(params.pixel_format) % 4 ==
 | 
				
			||||||
    glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.width));
 | 
					           0);
 | 
				
			||||||
 | 
					    glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(params.MipWidth(mip_map)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    GLsizei image_size = static_cast<GLsizei>(params.GetMipmapSizeGL(mip_map, false));
 | 
				
			||||||
    glActiveTexture(GL_TEXTURE0);
 | 
					    glActiveTexture(GL_TEXTURE0);
 | 
				
			||||||
    if (tuple.compressed) {
 | 
					    if (tuple.compressed) {
 | 
				
			||||||
        switch (params.target) {
 | 
					        switch (params.target) {
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture2D:
 | 
					        case SurfaceParams::SurfaceTarget::Texture2D:
 | 
				
			||||||
            glCompressedTexImage2D(
 | 
					            glCompressedTexImage2D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format,
 | 
				
			||||||
                SurfaceTargetToGL(params.target), 0, tuple.internal_format,
 | 
					                                   static_cast<GLsizei>(params.MipWidth(mip_map)),
 | 
				
			||||||
                static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height), 0,
 | 
					                                   static_cast<GLsizei>(params.MipHeight(mip_map)), 0, image_size,
 | 
				
			||||||
                static_cast<GLsizei>(params.size_in_bytes_gl), &gl_buffer[buffer_offset]);
 | 
					                                   &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture3D:
 | 
					        case SurfaceParams::SurfaceTarget::Texture3D:
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture2DArray:
 | 
					            glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format,
 | 
				
			||||||
            glCompressedTexImage3D(
 | 
					                                   static_cast<GLsizei>(params.MipWidth(mip_map)),
 | 
				
			||||||
                SurfaceTargetToGL(params.target), 0, tuple.internal_format,
 | 
					                                   static_cast<GLsizei>(params.MipHeight(mip_map)),
 | 
				
			||||||
                static_cast<GLsizei>(params.width), static_cast<GLsizei>(params.height),
 | 
					                                   static_cast<GLsizei>(params.MipDepth(mip_map)), 0, image_size,
 | 
				
			||||||
                static_cast<GLsizei>(params.depth), 0,
 | 
					                                   &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
                static_cast<GLsizei>(params.size_in_bytes_gl), &gl_buffer[buffer_offset]);
 | 
					 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::TextureCubemap:
 | 
					        case SurfaceParams::SurfaceTarget::Texture2DArray:
 | 
				
			||||||
 | 
					            glCompressedTexImage3D(SurfaceTargetToGL(params.target), mip_map, tuple.internal_format,
 | 
				
			||||||
 | 
					                                   static_cast<GLsizei>(params.MipWidth(mip_map)),
 | 
				
			||||||
 | 
					                                   static_cast<GLsizei>(params.MipHeight(mip_map)),
 | 
				
			||||||
 | 
					                                   static_cast<GLsizei>(params.depth), 0, image_size,
 | 
				
			||||||
 | 
					                                   &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case SurfaceParams::SurfaceTarget::TextureCubemap: {
 | 
				
			||||||
 | 
					            GLsizei layer_size = static_cast<GLsizei>(params.LayerSizeGL(mip_map));
 | 
				
			||||||
            for (std::size_t face = 0; face < params.depth; ++face) {
 | 
					            for (std::size_t face = 0; face < params.depth; ++face) {
 | 
				
			||||||
                glCompressedTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face),
 | 
					                glCompressedTexImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face),
 | 
				
			||||||
                                       0, tuple.internal_format, static_cast<GLsizei>(params.width),
 | 
					                                       mip_map, tuple.internal_format,
 | 
				
			||||||
                                       static_cast<GLsizei>(params.height), 0,
 | 
					                                       static_cast<GLsizei>(params.MipWidth(mip_map)),
 | 
				
			||||||
                                       static_cast<GLsizei>(params.SizeInBytesCubeFaceGL()),
 | 
					                                       static_cast<GLsizei>(params.MipHeight(mip_map)), 0,
 | 
				
			||||||
                                       &gl_buffer[buffer_offset]);
 | 
					                                       layer_size, &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
                buffer_offset += params.SizeInBytesCubeFace();
 | 
					                buffer_offset += layer_size;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
 | 
					            LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
 | 
				
			||||||
                         static_cast<u32>(params.target));
 | 
					                         static_cast<u32>(params.target));
 | 
				
			||||||
            UNREACHABLE();
 | 
					            UNREACHABLE();
 | 
				
			||||||
            glCompressedTexImage2D(
 | 
					            glCompressedTexImage2D(GL_TEXTURE_2D, mip_map, tuple.internal_format,
 | 
				
			||||||
                GL_TEXTURE_2D, 0, tuple.internal_format, static_cast<GLsizei>(params.width),
 | 
					                                   static_cast<GLsizei>(params.MipWidth(mip_map)),
 | 
				
			||||||
                static_cast<GLsizei>(params.height), 0,
 | 
					                                   static_cast<GLsizei>(params.MipHeight(mip_map)), 0,
 | 
				
			||||||
                static_cast<GLsizei>(params.size_in_bytes_gl), &gl_buffer[buffer_offset]);
 | 
					                                   static_cast<GLsizei>(params.size_in_bytes_gl),
 | 
				
			||||||
 | 
					                                   &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        switch (params.target) {
 | 
					        switch (params.target) {
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture1D:
 | 
					        case SurfaceParams::SurfaceTarget::Texture1D:
 | 
				
			||||||
            glTexSubImage1D(SurfaceTargetToGL(params.target), 0, x0,
 | 
					            glTexSubImage1D(SurfaceTargetToGL(params.target), mip_map, x0,
 | 
				
			||||||
                            static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type,
 | 
					                            static_cast<GLsizei>(rect.GetWidth()), tuple.format, tuple.type,
 | 
				
			||||||
                            &gl_buffer[buffer_offset]);
 | 
					                            &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture2D:
 | 
					        case SurfaceParams::SurfaceTarget::Texture2D:
 | 
				
			||||||
            glTexSubImage2D(SurfaceTargetToGL(params.target), 0, x0, y0,
 | 
					            glTexSubImage2D(SurfaceTargetToGL(params.target), mip_map, x0, y0,
 | 
				
			||||||
                            static_cast<GLsizei>(rect.GetWidth()),
 | 
					                            static_cast<GLsizei>(rect.GetWidth()),
 | 
				
			||||||
                            static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
 | 
					                            static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
 | 
				
			||||||
                            &gl_buffer[buffer_offset]);
 | 
					                            &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture3D:
 | 
					        case SurfaceParams::SurfaceTarget::Texture3D:
 | 
				
			||||||
 | 
					            glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0,
 | 
				
			||||||
 | 
					                            static_cast<GLsizei>(rect.GetWidth()),
 | 
				
			||||||
 | 
					                            static_cast<GLsizei>(rect.GetHeight()), params.MipDepth(mip_map),
 | 
				
			||||||
 | 
					                            tuple.format, tuple.type, &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::Texture2DArray:
 | 
					        case SurfaceParams::SurfaceTarget::Texture2DArray:
 | 
				
			||||||
            glTexSubImage3D(SurfaceTargetToGL(params.target), 0, x0, y0, 0,
 | 
					            glTexSubImage3D(SurfaceTargetToGL(params.target), mip_map, x0, y0, 0,
 | 
				
			||||||
                            static_cast<GLsizei>(rect.GetWidth()),
 | 
					                            static_cast<GLsizei>(rect.GetWidth()),
 | 
				
			||||||
                            static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format,
 | 
					                            static_cast<GLsizei>(rect.GetHeight()), params.depth, tuple.format,
 | 
				
			||||||
                            tuple.type, &gl_buffer[buffer_offset]);
 | 
					                            tuple.type, &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case SurfaceParams::SurfaceTarget::TextureCubemap:
 | 
					        case SurfaceParams::SurfaceTarget::TextureCubemap: {
 | 
				
			||||||
 | 
					            std::size_t start = buffer_offset;
 | 
				
			||||||
            for (std::size_t face = 0; face < params.depth; ++face) {
 | 
					            for (std::size_t face = 0; face < params.depth; ++face) {
 | 
				
			||||||
                glTexSubImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), 0, x0,
 | 
					                glTexSubImage2D(static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face), mip_map,
 | 
				
			||||||
                                y0, static_cast<GLsizei>(rect.GetWidth()),
 | 
					                                x0, y0, static_cast<GLsizei>(rect.GetWidth()),
 | 
				
			||||||
                                static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
 | 
					                                static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
 | 
				
			||||||
                                &gl_buffer[buffer_offset]);
 | 
					                                &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
                buffer_offset += params.SizeInBytesCubeFace();
 | 
					                buffer_offset += params.LayerSizeGL(mip_map);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
            LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
 | 
					            LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
 | 
				
			||||||
                         static_cast<u32>(params.target));
 | 
					                         static_cast<u32>(params.target));
 | 
				
			||||||
            UNREACHABLE();
 | 
					            UNREACHABLE();
 | 
				
			||||||
            glTexSubImage2D(GL_TEXTURE_2D, 0, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
 | 
					            glTexSubImage2D(GL_TEXTURE_2D, mip_map, x0, y0, static_cast<GLsizei>(rect.GetWidth()),
 | 
				
			||||||
                            static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
 | 
					                            static_cast<GLsizei>(rect.GetHeight()), tuple.format, tuple.type,
 | 
				
			||||||
                            &gl_buffer[buffer_offset]);
 | 
					                            &gl_buffer[mip_map][buffer_offset]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
 | 
					    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 64, 192));
 | 
				
			||||||
 | 
					void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) {
 | 
				
			||||||
 | 
					    if (params.type == SurfaceType::Fill)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    MICROPROFILE_SCOPE(OpenGL_TextureUL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (u32 i = 0; i < params.max_mip_level; i++)
 | 
				
			||||||
 | 
					        UploadGLMipmapTexture(i, read_fb_handle, draw_fb_handle);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RasterizerCacheOpenGL::RasterizerCacheOpenGL() {
 | 
					RasterizerCacheOpenGL::RasterizerCacheOpenGL() {
 | 
				
			||||||
    read_framebuffer.Create();
 | 
					    read_framebuffer.Create();
 | 
				
			||||||
    draw_framebuffer.Create();
 | 
					    draw_framebuffer.Create();
 | 
				
			||||||
 | 
				
			|||||||
@ -834,7 +834,7 @@ struct SurfaceParams {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Returns the rectangle corresponding to this surface
 | 
					    /// Returns the rectangle corresponding to this surface
 | 
				
			||||||
    MathUtil::Rectangle<u32> GetRect() const;
 | 
					    MathUtil::Rectangle<u32> GetRect(u32 mip_level = 0) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Returns the total size of this surface in bytes, adjusted for compression
 | 
					    /// Returns the total size of this surface in bytes, adjusted for compression
 | 
				
			||||||
    std::size_t SizeInBytesRaw(bool ignore_tiled = false) const {
 | 
					    std::size_t SizeInBytesRaw(bool ignore_tiled = false) const {
 | 
				
			||||||
@ -865,7 +865,7 @@ struct SurfaceParams {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /// Returns the exact size of memory occupied by the texture in VRAM, including mipmaps.
 | 
					    /// Returns the exact size of memory occupied by the texture in VRAM, including mipmaps.
 | 
				
			||||||
    std::size_t MemorySize() const {
 | 
					    std::size_t MemorySize() const {
 | 
				
			||||||
        std::size_t size = InnerMemorySize(is_layered);
 | 
					        std::size_t size = InnerMemorySize(false, is_layered);
 | 
				
			||||||
        if (is_layered)
 | 
					        if (is_layered)
 | 
				
			||||||
            return size * depth;
 | 
					            return size * depth;
 | 
				
			||||||
        return size;
 | 
					        return size;
 | 
				
			||||||
@ -874,12 +874,78 @@ struct SurfaceParams {
 | 
				
			|||||||
    /// Returns the exact size of the memory occupied by a layer in a texture in VRAM, including
 | 
					    /// Returns the exact size of the memory occupied by a layer in a texture in VRAM, including
 | 
				
			||||||
    /// mipmaps.
 | 
					    /// mipmaps.
 | 
				
			||||||
    std::size_t LayerMemorySize() const {
 | 
					    std::size_t LayerMemorySize() const {
 | 
				
			||||||
        return InnerMemorySize(true);
 | 
					        return InnerMemorySize(false, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Returns the size of a layer of this surface in OpenGL.
 | 
					    /// Returns the size of a layer of this surface in OpenGL.
 | 
				
			||||||
    std::size_t LayerSizeGL() const {
 | 
					    std::size_t LayerSizeGL(u32 mip_level) const {
 | 
				
			||||||
        return SizeInBytesRaw(true) / depth;
 | 
					        return InnerMipmapMemorySize(mip_level, true, is_layered, false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::size_t GetMipmapSizeGL(u32 mip_level, bool ignore_compressed = true) const {
 | 
				
			||||||
 | 
					        std::size_t size = InnerMipmapMemorySize(mip_level, true, is_layered, ignore_compressed);
 | 
				
			||||||
 | 
					        if (is_layered)
 | 
				
			||||||
 | 
					            return size * depth;
 | 
				
			||||||
 | 
					        return size;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::size_t GetMipmapLevelOffset(u32 mip_level) const {
 | 
				
			||||||
 | 
					        std::size_t offset = 0;
 | 
				
			||||||
 | 
					        for (u32 i = 0; i < mip_level; i++)
 | 
				
			||||||
 | 
					            offset += InnerMipmapMemorySize(i, false, is_layered);
 | 
				
			||||||
 | 
					        return offset;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::size_t GetMipmapLevelOffsetGL(u32 mip_level) const {
 | 
				
			||||||
 | 
					        std::size_t offset = 0;
 | 
				
			||||||
 | 
					        for (u32 i = 0; i < mip_level; i++)
 | 
				
			||||||
 | 
					            offset += InnerMipmapMemorySize(i, true, is_layered);
 | 
				
			||||||
 | 
					        return offset;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u32 MipWidth(u32 mip_level) const {
 | 
				
			||||||
 | 
					        return std::max(1U, width >> mip_level);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u32 MipHeight(u32 mip_level) const {
 | 
				
			||||||
 | 
					        return std::max(1U, height >> mip_level);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u32 MipDepth(u32 mip_level) const {
 | 
				
			||||||
 | 
					        return std::max(1U, depth >> mip_level);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Auto block resizing algorithm from:
 | 
				
			||||||
 | 
					    // https://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
 | 
				
			||||||
 | 
					    u32 MipBlockHeight(u32 mip_level) const {
 | 
				
			||||||
 | 
					        if (mip_level == 0)
 | 
				
			||||||
 | 
					            return block_height;
 | 
				
			||||||
 | 
					        u32 alt_height = MipHeight(mip_level);
 | 
				
			||||||
 | 
					        u32 h = GetDefaultBlockHeight(pixel_format);
 | 
				
			||||||
 | 
					        u32 blocks_in_y = (alt_height + h - 1) / h;
 | 
				
			||||||
 | 
					        u32 bh = 16;
 | 
				
			||||||
 | 
					        while (bh > 1 && blocks_in_y <= bh * 4) {
 | 
				
			||||||
 | 
					            bh >>= 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return bh;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u32 MipBlockDepth(u32 mip_level) const {
 | 
				
			||||||
 | 
					        if (mip_level == 0)
 | 
				
			||||||
 | 
					            return block_depth;
 | 
				
			||||||
 | 
					        if (is_layered)
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        u32 depth = MipDepth(mip_level);
 | 
				
			||||||
 | 
					        u32 bd = 32;
 | 
				
			||||||
 | 
					        while (bd > 1 && depth * 2 <= bd) {
 | 
				
			||||||
 | 
					            bd >>= 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (bd == 32) {
 | 
				
			||||||
 | 
					            u32 bh = MipBlockHeight(mip_level);
 | 
				
			||||||
 | 
					            if (bh >= 4)
 | 
				
			||||||
 | 
					                return 16;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return bd;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Creates SurfaceParams from a texture configuration
 | 
					    /// Creates SurfaceParams from a texture configuration
 | 
				
			||||||
@ -940,7 +1006,10 @@ struct SurfaceParams {
 | 
				
			|||||||
    } rt;
 | 
					    } rt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    std::size_t InnerMemorySize(bool layer_only = false) const;
 | 
					    std::size_t InnerMipmapMemorySize(u32 mip_level, bool force_gl = false, bool layer_only = false,
 | 
				
			||||||
 | 
					                                      bool uncompressed = false) const;
 | 
				
			||||||
 | 
					    std::size_t InnerMemorySize(bool force_gl = false, bool layer_only = false,
 | 
				
			||||||
 | 
					                                bool uncompressed = false) const;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}; // namespace OpenGL
 | 
					}; // namespace OpenGL
 | 
				
			||||||
@ -1002,8 +1071,10 @@ public:
 | 
				
			|||||||
    void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle);
 | 
					    void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
					    void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    OGLTexture texture;
 | 
					    OGLTexture texture;
 | 
				
			||||||
    std::vector<u8> gl_buffer;
 | 
					    std::vector<std::vector<u8>> gl_buffer;
 | 
				
			||||||
    SurfaceParams params;
 | 
					    SurfaceParams params;
 | 
				
			||||||
    GLenum gl_target;
 | 
					    GLenum gl_target;
 | 
				
			||||||
    std::size_t cached_size_in_bytes;
 | 
					    std::size_t cached_size_in_bytes;
 | 
				
			||||||
 | 
				
			|||||||
@ -135,12 +135,29 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
 | 
				
			|||||||
    return {};
 | 
					    return {};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode) {
 | 
					inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode,
 | 
				
			||||||
 | 
					                                Tegra::Texture::TextureMipmapFilter mip_filter_mode) {
 | 
				
			||||||
    switch (filter_mode) {
 | 
					    switch (filter_mode) {
 | 
				
			||||||
    case Tegra::Texture::TextureFilter::Linear:
 | 
					    case Tegra::Texture::TextureFilter::Linear: {
 | 
				
			||||||
        return GL_LINEAR;
 | 
					        switch (mip_filter_mode) {
 | 
				
			||||||
    case Tegra::Texture::TextureFilter::Nearest:
 | 
					        case Tegra::Texture::TextureMipmapFilter::None:
 | 
				
			||||||
        return GL_NEAREST;
 | 
					            return GL_LINEAR;
 | 
				
			||||||
 | 
					        case Tegra::Texture::TextureMipmapFilter::Nearest:
 | 
				
			||||||
 | 
					            return GL_NEAREST_MIPMAP_LINEAR;
 | 
				
			||||||
 | 
					        case Tegra::Texture::TextureMipmapFilter::Linear:
 | 
				
			||||||
 | 
					            return GL_LINEAR_MIPMAP_LINEAR;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case Tegra::Texture::TextureFilter::Nearest: {
 | 
				
			||||||
 | 
					        switch (mip_filter_mode) {
 | 
				
			||||||
 | 
					        case Tegra::Texture::TextureMipmapFilter::None:
 | 
				
			||||||
 | 
					            return GL_NEAREST;
 | 
				
			||||||
 | 
					        case Tegra::Texture::TextureMipmapFilter::Nearest:
 | 
				
			||||||
 | 
					            return GL_NEAREST_MIPMAP_NEAREST;
 | 
				
			||||||
 | 
					        case Tegra::Texture::TextureMipmapFilter::Linear:
 | 
				
			||||||
 | 
					            return GL_LINEAR_MIPMAP_NEAREST;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode={}",
 | 
					    LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode={}",
 | 
				
			||||||
                 static_cast<u32>(filter_mode));
 | 
					                 static_cast<u32>(filter_mode));
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Tegra::Texture {
 | 
					namespace Tegra::Texture {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GOBSize constant. Calculated by 64 bytes in x multiplied by 8 y coords, represents
 | 
				
			||||||
 | 
					// an small rect of (64/bytes_per_pixel)X8.
 | 
				
			||||||
 | 
					inline std::size_t GetGOBSize() {
 | 
				
			||||||
 | 
					    return 512;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Unswizzles a swizzled texture without changing its format.
 | 
					 * Unswizzles a swizzled texture without changing its format.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user