mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	texture_cache: Implement depth stencil texture swizzles
Stop ignoring image swizzles on depth and stencil images. This doesn't fix a known issue on Xenoblade Chronicles 2 where an OpenGL texture changes swizzles twice before being used. A proper fix would be having a small texture view cache for this like we do on Vulkan.
This commit is contained in:
		
							parent
							
								
									86345c126a
								
							
						
					
					
						commit
						8bba84a401
					
				@ -238,6 +238,12 @@ OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum inte
 | 
				
			|||||||
    return texture;
 | 
					    return texture;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr u32 EncodeSwizzle(SwizzleSource x_source, SwizzleSource y_source, SwizzleSource z_source,
 | 
				
			||||||
 | 
					                            SwizzleSource w_source) {
 | 
				
			||||||
 | 
					    return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) |
 | 
				
			||||||
 | 
					           (static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // Anonymous namespace
 | 
					} // Anonymous namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& params,
 | 
					CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& params,
 | 
				
			||||||
@ -404,7 +410,8 @@ CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& p
 | 
				
			|||||||
    if (!is_proxy) {
 | 
					    if (!is_proxy) {
 | 
				
			||||||
        texture_view = CreateTextureView();
 | 
					        texture_view = CreateTextureView();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    swizzle = EncodeSwizzle(SwizzleSource::R, SwizzleSource::G, SwizzleSource::B, SwizzleSource::A);
 | 
					    current_swizzle =
 | 
				
			||||||
 | 
					        EncodeSwizzle(SwizzleSource::R, SwizzleSource::G, SwizzleSource::B, SwizzleSource::A);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CachedSurfaceView::~CachedSurfaceView() = default;
 | 
					CachedSurfaceView::~CachedSurfaceView() = default;
 | 
				
			||||||
@ -449,26 +456,36 @@ void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_source,
 | 
					void CachedSurfaceView::ApplySwizzle(SwizzleSource x_source, SwizzleSource y_source,
 | 
				
			||||||
                                     SwizzleSource z_source, SwizzleSource w_source) {
 | 
					                                     SwizzleSource z_source, SwizzleSource w_source) {
 | 
				
			||||||
    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 (new_swizzle == swizzle)
 | 
					    if (current_swizzle == new_swizzle) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    swizzle = new_swizzle;
 | 
					    }
 | 
				
			||||||
    const std::array gl_swizzle = {GetSwizzleSource(x_source), GetSwizzleSource(y_source),
 | 
					    current_swizzle = new_swizzle;
 | 
				
			||||||
                                   GetSwizzleSource(z_source), GetSwizzleSource(w_source)};
 | 
					
 | 
				
			||||||
 | 
					    std::array swizzle{x_source, y_source, z_source, w_source};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const GLuint handle = GetTexture();
 | 
					    const GLuint handle = GetTexture();
 | 
				
			||||||
    const PixelFormat format = surface.GetSurfaceParams().pixel_format;
 | 
					    switch (const PixelFormat format = surface.GetSurfaceParams().pixel_format) {
 | 
				
			||||||
    switch (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);
 | 
				
			||||||
        glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
 | 
					        glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
 | 
				
			||||||
                            GetComponent(format, x_source == SwizzleSource::R));
 | 
					                            GetComponent(format, x_source == SwizzleSource::R));
 | 
				
			||||||
        break;
 | 
					
 | 
				
			||||||
    default:
 | 
					        // Make sure we sample the first component
 | 
				
			||||||
 | 
					        std::transform(swizzle.begin(), swizzle.end(), swizzle.begin(), [](SwizzleSource value) {
 | 
				
			||||||
 | 
					            return value == SwizzleSource::G ? SwizzleSource::R : value;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        [[fallthrough]];
 | 
				
			||||||
 | 
					    default: {
 | 
				
			||||||
 | 
					        const std::array gl_swizzle = {GetSwizzleSource(swizzle[0]), GetSwizzleSource(swizzle[1]),
 | 
				
			||||||
 | 
					                                       GetSwizzleSource(swizzle[2]), GetSwizzleSource(swizzle[3])};
 | 
				
			||||||
        glTextureParameteriv(handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data());
 | 
					        glTextureParameteriv(handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data());
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OGLTextureView CachedSurfaceView::CreateTextureView() const {
 | 
					OGLTextureView CachedSurfaceView::CreateTextureView() const {
 | 
				
			||||||
    OGLTextureView texture_view;
 | 
					    OGLTextureView texture_view;
 | 
				
			||||||
 | 
				
			|||||||
@ -110,14 +110,6 @@ public:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    u32 EncodeSwizzle(Tegra::Texture::SwizzleSource x_source,
 | 
					 | 
				
			||||||
                      Tegra::Texture::SwizzleSource y_source,
 | 
					 | 
				
			||||||
                      Tegra::Texture::SwizzleSource z_source,
 | 
					 | 
				
			||||||
                      Tegra::Texture::SwizzleSource w_source) const {
 | 
					 | 
				
			||||||
        return (static_cast<u32>(x_source) << 24) | (static_cast<u32>(y_source) << 16) |
 | 
					 | 
				
			||||||
               (static_cast<u32>(z_source) << 8) | static_cast<u32>(w_source);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    OGLTextureView CreateTextureView() const;
 | 
					    OGLTextureView CreateTextureView() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CachedSurface& surface;
 | 
					    CachedSurface& surface;
 | 
				
			||||||
@ -125,7 +117,7 @@ private:
 | 
				
			|||||||
    GLenum format{};
 | 
					    GLenum format{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    OGLTextureView texture_view;
 | 
					    OGLTextureView texture_view;
 | 
				
			||||||
    u32 swizzle{};
 | 
					    u32 current_swizzle{};
 | 
				
			||||||
    bool is_proxy{};
 | 
					    bool is_proxy{};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -354,26 +354,23 @@ CachedSurfaceView::~CachedSurfaceView() = default;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y_source,
 | 
					VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y_source,
 | 
				
			||||||
                                         SwizzleSource z_source, SwizzleSource w_source) {
 | 
					                                         SwizzleSource z_source, SwizzleSource w_source) {
 | 
				
			||||||
    const u32 swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
 | 
					    const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
 | 
				
			||||||
    if (last_image_view && last_swizzle == swizzle) {
 | 
					    if (last_image_view && last_swizzle == new_swizzle) {
 | 
				
			||||||
        return last_image_view;
 | 
					        return last_image_view;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    last_swizzle = swizzle;
 | 
					    last_swizzle = new_swizzle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto [entry, is_cache_miss] = view_cache.try_emplace(swizzle);
 | 
					    const auto [entry, is_cache_miss] = view_cache.try_emplace(new_swizzle);
 | 
				
			||||||
    auto& image_view = entry->second;
 | 
					    auto& image_view = entry->second;
 | 
				
			||||||
    if (!is_cache_miss) {
 | 
					    if (!is_cache_miss) {
 | 
				
			||||||
        return last_image_view = *image_view;
 | 
					        return last_image_view = *image_view;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto swizzle_x = MaxwellToVK::SwizzleSource(x_source);
 | 
					    std::array swizzle{MaxwellToVK::SwizzleSource(x_source), MaxwellToVK::SwizzleSource(y_source),
 | 
				
			||||||
    auto swizzle_y = MaxwellToVK::SwizzleSource(y_source);
 | 
					                       MaxwellToVK::SwizzleSource(z_source), MaxwellToVK::SwizzleSource(w_source)};
 | 
				
			||||||
    auto swizzle_z = MaxwellToVK::SwizzleSource(z_source);
 | 
					 | 
				
			||||||
    auto swizzle_w = MaxwellToVK::SwizzleSource(w_source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) {
 | 
					    if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) {
 | 
				
			||||||
        // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here.
 | 
					        // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here.
 | 
				
			||||||
        std::swap(swizzle_x, swizzle_z);
 | 
					        std::swap(swizzle[0], swizzle[2]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Games can sample depth or stencil values on textures. This is decided by the swizzle value on
 | 
					    // Games can sample depth or stencil values on textures. This is decided by the swizzle value on
 | 
				
			||||||
@ -395,11 +392,11 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y
 | 
				
			|||||||
            UNIMPLEMENTED();
 | 
					            UNIMPLEMENTED();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Vulkan doesn't seem to understand swizzling of a depth stencil image, use identity
 | 
					        // Make sure we sample the first component
 | 
				
			||||||
        swizzle_x = VK_COMPONENT_SWIZZLE_R;
 | 
					        std::transform(
 | 
				
			||||||
        swizzle_y = VK_COMPONENT_SWIZZLE_G;
 | 
					            swizzle.begin(), swizzle.end(), swizzle.begin(), [](VkComponentSwizzle component) {
 | 
				
			||||||
        swizzle_z = VK_COMPONENT_SWIZZLE_B;
 | 
					                return component == VK_COMPONENT_SWIZZLE_G ? VK_COMPONENT_SWIZZLE_R : component;
 | 
				
			||||||
        swizzle_w = VK_COMPONENT_SWIZZLE_A;
 | 
					            });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    VkImageViewCreateInfo ci;
 | 
					    VkImageViewCreateInfo ci;
 | 
				
			||||||
@ -409,7 +406,7 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y
 | 
				
			|||||||
    ci.image = surface.GetImageHandle();
 | 
					    ci.image = surface.GetImageHandle();
 | 
				
			||||||
    ci.viewType = image_view_type;
 | 
					    ci.viewType = image_view_type;
 | 
				
			||||||
    ci.format = surface.GetImage().GetFormat();
 | 
					    ci.format = surface.GetImage().GetFormat();
 | 
				
			||||||
    ci.components = {swizzle_x, swizzle_y, swizzle_z, swizzle_w};
 | 
					    ci.components = {swizzle[0], swizzle[1], swizzle[2], swizzle[3]};
 | 
				
			||||||
    ci.subresourceRange.aspectMask = aspect;
 | 
					    ci.subresourceRange.aspectMask = aspect;
 | 
				
			||||||
    ci.subresourceRange.baseMipLevel = base_level;
 | 
					    ci.subresourceRange.baseMipLevel = base_level;
 | 
				
			||||||
    ci.subresourceRange.levelCount = num_levels;
 | 
					    ci.subresourceRange.levelCount = num_levels;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user