mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	gl_texture_cache: Implement small texture view cache for swizzles
This fixes cases where the texture swizzle was applied twice on the same draw to a texture bound to two different slots.
This commit is contained in:
		
							parent
							
								
									8bba84a401
								
							
						
					
					
						commit
						b17fe82973
					
				@ -977,16 +977,12 @@ void RasterizerOpenGL::SetupTexture(u32 binding, const Tegra::Texture::FullTextu
 | 
				
			|||||||
        glBindTextureUnit(binding, 0);
 | 
					        glBindTextureUnit(binding, 0);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    glBindTextureUnit(binding, view->GetTexture());
 | 
					    const GLuint handle = view->GetTexture(texture.tic.x_source, texture.tic.y_source,
 | 
				
			||||||
 | 
					                                           texture.tic.z_source, texture.tic.w_source);
 | 
				
			||||||
    if (view->GetSurfaceParams().IsBuffer()) {
 | 
					    glBindTextureUnit(binding, handle);
 | 
				
			||||||
        return;
 | 
					    if (!view->GetSurfaceParams().IsBuffer()) {
 | 
				
			||||||
 | 
					        glBindSampler(binding, sampler_cache.GetSampler(texture.tsc));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Apply swizzle to textures that are not buffers.
 | 
					 | 
				
			||||||
    view->ApplySwizzle(texture.tic.x_source, texture.tic.y_source, texture.tic.z_source,
 | 
					 | 
				
			||||||
                       texture.tic.w_source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    glBindSampler(binding, sampler_cache.GetSampler(texture.tsc));
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RasterizerOpenGL::SetupDrawImages(std::size_t stage_index, const Shader& shader) {
 | 
					void RasterizerOpenGL::SetupDrawImages(std::size_t stage_index, const Shader& shader) {
 | 
				
			||||||
@ -1015,14 +1011,11 @@ void RasterizerOpenGL::SetupImage(u32 binding, const Tegra::Texture::TICEntry& t
 | 
				
			|||||||
        glBindImageTexture(binding, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
 | 
					        glBindImageTexture(binding, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!tic.IsBuffer()) {
 | 
					 | 
				
			||||||
        view->ApplySwizzle(tic.x_source, tic.y_source, tic.z_source, tic.w_source);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (entry.is_written) {
 | 
					    if (entry.is_written) {
 | 
				
			||||||
        view->MarkAsModified(texture_cache.Tick());
 | 
					        view->MarkAsModified(texture_cache.Tick());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    glBindImageTexture(binding, view->GetTexture(), 0, GL_TRUE, 0, GL_READ_WRITE,
 | 
					    const GLuint handle = view->GetTexture(tic.x_source, tic.y_source, tic.z_source, tic.w_source);
 | 
				
			||||||
                       view->GetFormat());
 | 
					    glBindImageTexture(binding, handle, 0, GL_TRUE, 0, GL_READ_WRITE, view->GetFormat());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void RasterizerOpenGL::SyncViewport() {
 | 
					void RasterizerOpenGL::SyncViewport() {
 | 
				
			||||||
 | 
				
			|||||||
@ -35,7 +35,7 @@ MICROPROFILE_DEFINE(OpenGL_Texture_Buffer_Copy, "OpenGL", "Texture Buffer Copy",
 | 
				
			|||||||
namespace {
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct FormatTuple {
 | 
					struct FormatTuple {
 | 
				
			||||||
    GLint internal_format;
 | 
					    GLenum internal_format;
 | 
				
			||||||
    GLenum format = GL_NONE;
 | 
					    GLenum format = GL_NONE;
 | 
				
			||||||
    GLenum type = GL_NONE;
 | 
					    GLenum type = GL_NONE;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -387,7 +387,7 @@ void CachedSurface::DecorateSurfaceName() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) {
 | 
					void CachedSurfaceView::DecorateViewName(GPUVAddr gpu_addr, std::string prefix) {
 | 
				
			||||||
    LabelGLObject(GL_TEXTURE, texture_view.handle, gpu_addr, prefix);
 | 
					    LabelGLObject(GL_TEXTURE, main_view.handle, gpu_addr, prefix);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
View CachedSurface::CreateView(const ViewParams& view_key) {
 | 
					View CachedSurface::CreateView(const ViewParams& view_key) {
 | 
				
			||||||
@ -403,15 +403,13 @@ View CachedSurface::CreateViewInner(const ViewParams& view_key, const bool is_pr
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& params,
 | 
					CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& params,
 | 
				
			||||||
                                     const bool is_proxy)
 | 
					                                     bool is_proxy)
 | 
				
			||||||
    : VideoCommon::ViewBase(params), surface{surface}, is_proxy{is_proxy} {
 | 
					    : VideoCommon::ViewBase(params), surface{surface},
 | 
				
			||||||
    target = GetTextureTarget(params.target);
 | 
					      format{GetFormatTuple(surface.GetSurfaceParams().pixel_format).internal_format},
 | 
				
			||||||
    format = GetFormatTuple(surface.GetSurfaceParams().pixel_format).internal_format;
 | 
					      target{GetTextureTarget(params.target)}, is_proxy{is_proxy} {
 | 
				
			||||||
    if (!is_proxy) {
 | 
					    if (!is_proxy) {
 | 
				
			||||||
        texture_view = CreateTextureView();
 | 
					        main_view = CreateTextureView();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    current_swizzle =
 | 
					 | 
				
			||||||
        EncodeSwizzle(SwizzleSource::R, SwizzleSource::G, SwizzleSource::B, SwizzleSource::A);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CachedSurfaceView::~CachedSurfaceView() = default;
 | 
					CachedSurfaceView::~CachedSurfaceView() = default;
 | 
				
			||||||
@ -454,23 +452,34 @@ void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_source,
 | 
					GLuint CachedSurfaceView::GetTexture(SwizzleSource x_source, SwizzleSource y_source,
 | 
				
			||||||
                                     SwizzleSource z_source, SwizzleSource w_source) {
 | 
					                                     SwizzleSource z_source, SwizzleSource w_source) {
 | 
				
			||||||
 | 
					    if (GetSurfaceParams().IsBuffer()) {
 | 
				
			||||||
 | 
					        return GetTexture();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
 | 
					    const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
 | 
				
			||||||
    if (current_swizzle == new_swizzle) {
 | 
					    if (current_swizzle == new_swizzle) {
 | 
				
			||||||
        return;
 | 
					        return current_view;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    current_swizzle = new_swizzle;
 | 
					    current_swizzle = new_swizzle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto [entry, is_cache_miss] = view_cache.try_emplace(new_swizzle);
 | 
				
			||||||
 | 
					    OGLTextureView& view = entry->second;
 | 
				
			||||||
 | 
					    if (!is_cache_miss) {
 | 
				
			||||||
 | 
					        current_view = view.handle;
 | 
				
			||||||
 | 
					        return view.handle;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    view = CreateTextureView();
 | 
				
			||||||
 | 
					    current_view = view.handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::array swizzle{x_source, y_source, z_source, w_source};
 | 
					    std::array swizzle{x_source, y_source, z_source, w_source};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const GLuint handle = GetTexture();
 | 
					    switch (const PixelFormat format = GetSurfaceParams().pixel_format) {
 | 
				
			||||||
    switch (const PixelFormat format = surface.GetSurfaceParams().pixel_format) {
 | 
					 | 
				
			||||||
    case PixelFormat::S8Z24:
 | 
					 | 
				
			||||||
    case PixelFormat::Z24S8:
 | 
					    case PixelFormat::Z24S8:
 | 
				
			||||||
    case PixelFormat::Z32FS8:
 | 
					    case PixelFormat::Z32FS8:
 | 
				
			||||||
 | 
					    case PixelFormat::S8Z24:
 | 
				
			||||||
        UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G);
 | 
					        UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G);
 | 
				
			||||||
        glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
 | 
					        glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
 | 
				
			||||||
                            GetComponent(format, x_source == SwizzleSource::R));
 | 
					                            GetComponent(format, x_source == SwizzleSource::R));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Make sure we sample the first component
 | 
					        // Make sure we sample the first component
 | 
				
			||||||
@ -481,10 +490,11 @@ void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_sou
 | 
				
			|||||||
    default: {
 | 
					    default: {
 | 
				
			||||||
        const std::array gl_swizzle = {GetSwizzleSource(swizzle[0]), GetSwizzleSource(swizzle[1]),
 | 
					        const std::array gl_swizzle = {GetSwizzleSource(swizzle[0]), GetSwizzleSource(swizzle[1]),
 | 
				
			||||||
                                       GetSwizzleSource(swizzle[2]), GetSwizzleSource(swizzle[3])};
 | 
					                                       GetSwizzleSource(swizzle[2]), GetSwizzleSource(swizzle[3])};
 | 
				
			||||||
        glTextureParameteriv(handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data());
 | 
					        glTextureParameteriv(view.handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data());
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    return view.handle;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OGLTextureView CachedSurfaceView::CreateTextureView() const {
 | 
					OGLTextureView CachedSurfaceView::CreateTextureView() const {
 | 
				
			||||||
 | 
				
			|||||||
@ -83,7 +83,7 @@ public:
 | 
				
			|||||||
    /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER
 | 
					    /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER
 | 
				
			||||||
    void Attach(GLenum attachment, GLenum target) const;
 | 
					    void Attach(GLenum attachment, GLenum target) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void ApplySwizzle(Tegra::Texture::SwizzleSource x_source,
 | 
					    GLuint GetTexture(Tegra::Texture::SwizzleSource x_source,
 | 
				
			||||||
                      Tegra::Texture::SwizzleSource y_source,
 | 
					                      Tegra::Texture::SwizzleSource y_source,
 | 
				
			||||||
                      Tegra::Texture::SwizzleSource z_source,
 | 
					                      Tegra::Texture::SwizzleSource z_source,
 | 
				
			||||||
                      Tegra::Texture::SwizzleSource w_source);
 | 
					                      Tegra::Texture::SwizzleSource w_source);
 | 
				
			||||||
@ -98,7 +98,7 @@ public:
 | 
				
			|||||||
        if (is_proxy) {
 | 
					        if (is_proxy) {
 | 
				
			||||||
            return surface.GetTexture();
 | 
					            return surface.GetTexture();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return texture_view.handle;
 | 
					        return main_view.handle;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GLenum GetFormat() const {
 | 
					    GLenum GetFormat() const {
 | 
				
			||||||
@ -113,12 +113,16 @@ private:
 | 
				
			|||||||
    OGLTextureView CreateTextureView() const;
 | 
					    OGLTextureView CreateTextureView() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CachedSurface& surface;
 | 
					    CachedSurface& surface;
 | 
				
			||||||
    GLenum target{};
 | 
					    const GLenum format;
 | 
				
			||||||
    GLenum format{};
 | 
					    const GLenum target;
 | 
				
			||||||
 | 
					    const bool is_proxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    OGLTextureView texture_view;
 | 
					    std::unordered_map<u32, OGLTextureView> view_cache;
 | 
				
			||||||
    u32 current_swizzle{};
 | 
					    OGLTextureView main_view;
 | 
				
			||||||
    bool is_proxy{};
 | 
					
 | 
				
			||||||
 | 
					    // Use an invalid default so it always fails the comparison test
 | 
				
			||||||
 | 
					    u32 current_swizzle = 0xffffffff;
 | 
				
			||||||
 | 
					    GLuint current_view = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TextureCacheOpenGL final : public TextureCacheBase {
 | 
					class TextureCacheOpenGL final : public TextureCacheBase {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user