From 972c8b05c2814633aaa055f952bdafe58d7714f4 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sat, 16 May 2026 09:32:06 +0300 Subject: [PATCH 1/2] fixed single channel formats --- src/video_core/texture_cache/image_view.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index 4dd9ddf60..d2e507847 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -67,6 +67,23 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageReso if (!is_storage) { mapping = Vulkan::LiverpoolToVK::ComponentMapping(image.DstSelect()); + // PS4 single-channel formats use the texel as either R or A depending on dst_sel. + // Vulkan single-channel formats expose the texel only via R + const bool is_single_channel = + (dfmt == AmdGpu::DataFormat::Format8 || dfmt == AmdGpu::DataFormat::Format16 || + dfmt == AmdGpu::DataFormat::Format32); + if (is_single_channel) { + auto fixup = [](vk::ComponentSwizzle& c) { + if (c == vk::ComponentSwizzle::eG || c == vk::ComponentSwizzle::eB || + c == vk::ComponentSwizzle::eA) { + c = vk::ComponentSwizzle::eR; + } + }; + fixup(mapping.r); + fixup(mapping.g); + fixup(mapping.b); + fixup(mapping.a); + } } } From 05bc8d08bc7dec298ce66ba9ebfd1633b607c0df Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 21 May 2026 16:17:12 +0300 Subject: [PATCH 2/2] fix based on @squidbus suggestion --- src/video_core/amdgpu/pixel_format.h | 18 ++++++++++++++++++ src/video_core/texture_cache/image_view.cpp | 17 ----------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/video_core/amdgpu/pixel_format.h b/src/video_core/amdgpu/pixel_format.h index 69e082edb..72b2482c3 100644 --- a/src/video_core/amdgpu/pixel_format.h +++ b/src/video_core/amdgpu/pixel_format.h @@ -279,6 +279,24 @@ constexpr CompMapping RemapSwizzle(const DataFormat format, const CompMapping sw result.a = swizzle.a; return result; } + case DataFormat::Format8: + case DataFormat::Format16: + case DataFormat::Format32: { + // PS4 single-channel formats expose the texel as either R or A depending on dst_sel, + // but Vulkan single-channel formats expose it only via R. Redirect any selector + // that points at Alpha to Red so the texel is read correctly. + CompMapping result = swizzle; + const auto remap_alpha_to_red = [](CompSwizzle& c) { + if (c == CompSwizzle::Alpha) { + c = CompSwizzle::Red; + } + }; + remap_alpha_to_red(result.r); + remap_alpha_to_red(result.g); + remap_alpha_to_red(result.b); + remap_alpha_to_red(result.a); + return result; + } default: return swizzle; } diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index d2e507847..4dd9ddf60 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -67,23 +67,6 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageReso if (!is_storage) { mapping = Vulkan::LiverpoolToVK::ComponentMapping(image.DstSelect()); - // PS4 single-channel formats use the texel as either R or A depending on dst_sel. - // Vulkan single-channel formats expose the texel only via R - const bool is_single_channel = - (dfmt == AmdGpu::DataFormat::Format8 || dfmt == AmdGpu::DataFormat::Format16 || - dfmt == AmdGpu::DataFormat::Format32); - if (is_single_channel) { - auto fixup = [](vk::ComponentSwizzle& c) { - if (c == vk::ComponentSwizzle::eG || c == vk::ComponentSwizzle::eB || - c == vk::ComponentSwizzle::eA) { - c = vk::ComponentSwizzle::eR; - } - }; - fixup(mapping.r); - fixup(mapping.g); - fixup(mapping.b); - fixup(mapping.a); - } } }