mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	Merge pull request #3991 from ReinUsesLisp/depth-sampling
texture_cache: Implement depth stencil texture swizzles
This commit is contained in:
		@@ -977,16 +977,12 @@ void RasterizerOpenGL::SetupTexture(u32 binding, const Tegra::Texture::FullTextu
 | 
			
		||||
        glBindTextureUnit(binding, 0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    glBindTextureUnit(binding, view->GetTexture());
 | 
			
		||||
 | 
			
		||||
    if (view->GetSurfaceParams().IsBuffer()) {
 | 
			
		||||
        return;
 | 
			
		||||
    const GLuint handle = view->GetTexture(texture.tic.x_source, texture.tic.y_source,
 | 
			
		||||
                                           texture.tic.z_source, texture.tic.w_source);
 | 
			
		||||
    glBindTextureUnit(binding, handle);
 | 
			
		||||
    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) {
 | 
			
		||||
@@ -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);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (!tic.IsBuffer()) {
 | 
			
		||||
        view->ApplySwizzle(tic.x_source, tic.y_source, tic.z_source, tic.w_source);
 | 
			
		||||
    }
 | 
			
		||||
    if (entry.is_written) {
 | 
			
		||||
        view->MarkAsModified(texture_cache.Tick());
 | 
			
		||||
    }
 | 
			
		||||
    glBindImageTexture(binding, view->GetTexture(), 0, GL_TRUE, 0, GL_READ_WRITE,
 | 
			
		||||
                       view->GetFormat());
 | 
			
		||||
    const GLuint handle = view->GetTexture(tic.x_source, tic.y_source, tic.z_source, tic.w_source);
 | 
			
		||||
    glBindImageTexture(binding, handle, 0, GL_TRUE, 0, GL_READ_WRITE, view->GetFormat());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RasterizerOpenGL::SyncViewport() {
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ MICROPROFILE_DEFINE(OpenGL_Texture_Buffer_Copy, "OpenGL", "Texture Buffer Copy",
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
struct FormatTuple {
 | 
			
		||||
    GLint internal_format;
 | 
			
		||||
    GLenum internal_format;
 | 
			
		||||
    GLenum format = GL_NONE;
 | 
			
		||||
    GLenum type = GL_NONE;
 | 
			
		||||
};
 | 
			
		||||
@@ -238,6 +238,12 @@ OGLTexture CreateTexture(const SurfaceParams& params, GLenum target, GLenum inte
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
CachedSurface::CachedSurface(const GPUVAddr gpu_addr, const SurfaceParams& params,
 | 
			
		||||
@@ -381,7 +387,7 @@ void CachedSurface::DecorateSurfaceName() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
@@ -397,14 +403,13 @@ View CachedSurface::CreateViewInner(const ViewParams& view_key, const bool is_pr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CachedSurfaceView::CachedSurfaceView(CachedSurface& surface, const ViewParams& params,
 | 
			
		||||
                                     const bool is_proxy)
 | 
			
		||||
    : VideoCommon::ViewBase(params), surface{surface}, is_proxy{is_proxy} {
 | 
			
		||||
    target = GetTextureTarget(params.target);
 | 
			
		||||
    format = GetFormatTuple(surface.GetSurfaceParams().pixel_format).internal_format;
 | 
			
		||||
                                     bool is_proxy)
 | 
			
		||||
    : VideoCommon::ViewBase(params), surface{surface},
 | 
			
		||||
      format{GetFormatTuple(surface.GetSurfaceParams().pixel_format).internal_format},
 | 
			
		||||
      target{GetTextureTarget(params.target)}, is_proxy{is_proxy} {
 | 
			
		||||
    if (!is_proxy) {
 | 
			
		||||
        texture_view = CreateTextureView();
 | 
			
		||||
        main_view = CreateTextureView();
 | 
			
		||||
    }
 | 
			
		||||
    swizzle = EncodeSwizzle(SwizzleSource::R, SwizzleSource::G, SwizzleSource::B, SwizzleSource::A);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CachedSurfaceView::~CachedSurfaceView() = default;
 | 
			
		||||
@@ -447,27 +452,49 @@ 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) {
 | 
			
		||||
    u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
 | 
			
		||||
    if (new_swizzle == swizzle)
 | 
			
		||||
        return;
 | 
			
		||||
    swizzle = new_swizzle;
 | 
			
		||||
    const std::array gl_swizzle = {GetSwizzleSource(x_source), GetSwizzleSource(y_source),
 | 
			
		||||
                                   GetSwizzleSource(z_source), GetSwizzleSource(w_source)};
 | 
			
		||||
    const GLuint handle = GetTexture();
 | 
			
		||||
    const PixelFormat format = surface.GetSurfaceParams().pixel_format;
 | 
			
		||||
    switch (format) {
 | 
			
		||||
    if (GetSurfaceParams().IsBuffer()) {
 | 
			
		||||
        return GetTexture();
 | 
			
		||||
    }
 | 
			
		||||
    const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
 | 
			
		||||
    if (current_swizzle == new_swizzle) {
 | 
			
		||||
        return current_view;
 | 
			
		||||
    }
 | 
			
		||||
    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};
 | 
			
		||||
 | 
			
		||||
    switch (const PixelFormat format = GetSurfaceParams().pixel_format) {
 | 
			
		||||
    case PixelFormat::Z24S8:
 | 
			
		||||
    case PixelFormat::Z32FS8:
 | 
			
		||||
    case PixelFormat::S8Z24:
 | 
			
		||||
        glTextureParameteri(handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
 | 
			
		||||
        UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G);
 | 
			
		||||
        glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
 | 
			
		||||
                            GetComponent(format, x_source == SwizzleSource::R));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        glTextureParameteriv(handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data());
 | 
			
		||||
 | 
			
		||||
        // 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(view.handle, GL_TEXTURE_SWIZZLE_RGBA, gl_swizzle.data());
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
    return view.handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
OGLTextureView CachedSurfaceView::CreateTextureView() const {
 | 
			
		||||
 
 | 
			
		||||
@@ -83,7 +83,7 @@ public:
 | 
			
		||||
    /// Attaches this texture view to the current bound GL_DRAW_FRAMEBUFFER
 | 
			
		||||
    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 z_source,
 | 
			
		||||
                      Tegra::Texture::SwizzleSource w_source);
 | 
			
		||||
@@ -98,7 +98,7 @@ public:
 | 
			
		||||
        if (is_proxy) {
 | 
			
		||||
            return surface.GetTexture();
 | 
			
		||||
        }
 | 
			
		||||
        return texture_view.handle;
 | 
			
		||||
        return main_view.handle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    GLenum GetFormat() const {
 | 
			
		||||
@@ -110,23 +110,19 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
    CachedSurface& surface;
 | 
			
		||||
    GLenum target{};
 | 
			
		||||
    GLenum format{};
 | 
			
		||||
    const GLenum format;
 | 
			
		||||
    const GLenum target;
 | 
			
		||||
    const bool is_proxy;
 | 
			
		||||
 | 
			
		||||
    OGLTextureView texture_view;
 | 
			
		||||
    u32 swizzle{};
 | 
			
		||||
    bool is_proxy{};
 | 
			
		||||
    std::unordered_map<u32, OGLTextureView> view_cache;
 | 
			
		||||
    OGLTextureView main_view;
 | 
			
		||||
 | 
			
		||||
    // Use an invalid default so it always fails the comparison test
 | 
			
		||||
    u32 current_swizzle = 0xffffffff;
 | 
			
		||||
    GLuint current_view = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class TextureCacheOpenGL final : public TextureCacheBase {
 | 
			
		||||
 
 | 
			
		||||
@@ -354,26 +354,23 @@ CachedSurfaceView::~CachedSurfaceView() = default;
 | 
			
		||||
 | 
			
		||||
VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y_source,
 | 
			
		||||
                                         SwizzleSource z_source, SwizzleSource w_source) {
 | 
			
		||||
    const u32 swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
 | 
			
		||||
    if (last_image_view && last_swizzle == swizzle) {
 | 
			
		||||
    const u32 new_swizzle = EncodeSwizzle(x_source, y_source, z_source, w_source);
 | 
			
		||||
    if (last_image_view && last_swizzle == new_swizzle) {
 | 
			
		||||
        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;
 | 
			
		||||
    if (!is_cache_miss) {
 | 
			
		||||
        return last_image_view = *image_view;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto swizzle_x = MaxwellToVK::SwizzleSource(x_source);
 | 
			
		||||
    auto swizzle_y = MaxwellToVK::SwizzleSource(y_source);
 | 
			
		||||
    auto swizzle_z = MaxwellToVK::SwizzleSource(z_source);
 | 
			
		||||
    auto swizzle_w = MaxwellToVK::SwizzleSource(w_source);
 | 
			
		||||
 | 
			
		||||
    std::array swizzle{MaxwellToVK::SwizzleSource(x_source), MaxwellToVK::SwizzleSource(y_source),
 | 
			
		||||
                       MaxwellToVK::SwizzleSource(z_source), MaxwellToVK::SwizzleSource(w_source)};
 | 
			
		||||
    if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) {
 | 
			
		||||
        // 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
 | 
			
		||||
@@ -395,11 +392,11 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y
 | 
			
		||||
            UNIMPLEMENTED();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Vulkan doesn't seem to understand swizzling of a depth stencil image, use identity
 | 
			
		||||
        swizzle_x = VK_COMPONENT_SWIZZLE_R;
 | 
			
		||||
        swizzle_y = VK_COMPONENT_SWIZZLE_G;
 | 
			
		||||
        swizzle_z = VK_COMPONENT_SWIZZLE_B;
 | 
			
		||||
        swizzle_w = VK_COMPONENT_SWIZZLE_A;
 | 
			
		||||
        // Make sure we sample the first component
 | 
			
		||||
        std::transform(
 | 
			
		||||
            swizzle.begin(), swizzle.end(), swizzle.begin(), [](VkComponentSwizzle component) {
 | 
			
		||||
                return component == VK_COMPONENT_SWIZZLE_G ? VK_COMPONENT_SWIZZLE_R : component;
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VkImageViewCreateInfo ci;
 | 
			
		||||
@@ -409,7 +406,7 @@ VkImageView CachedSurfaceView::GetHandle(SwizzleSource x_source, SwizzleSource y
 | 
			
		||||
    ci.image = surface.GetImageHandle();
 | 
			
		||||
    ci.viewType = image_view_type;
 | 
			
		||||
    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.baseMipLevel = base_level;
 | 
			
		||||
    ci.subresourceRange.levelCount = num_levels;
 | 
			
		||||
 
 | 
			
		||||
@@ -991,7 +991,9 @@ private:
 | 
			
		||||
        params.target = target;
 | 
			
		||||
        params.is_tiled = false;
 | 
			
		||||
        params.srgb_conversion = false;
 | 
			
		||||
        params.is_layered = false;
 | 
			
		||||
        params.is_layered =
 | 
			
		||||
            target == SurfaceTarget::Texture1DArray || target == SurfaceTarget::Texture2DArray ||
 | 
			
		||||
            target == SurfaceTarget::TextureCubemap || target == SurfaceTarget::TextureCubeArray;
 | 
			
		||||
        params.block_width = 0;
 | 
			
		||||
        params.block_height = 0;
 | 
			
		||||
        params.block_depth = 0;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user