fix(shader): use pixel format for texture component type classification

Use the resolved pixel format (IsPixelFormatInteger/SignedInteger)
instead of checking individual TIC component type fields to determine
SamplerComponentType. Inspecting r_type/g_type/b_type/a_type individually
can misclassify textures when unused channels have arbitrary type values
(e.g., BCn compressed or single-channel formats), causing a mismatch
between the SPIR-V image sampled type and the Vulkan image view format
that leads to transparency artifacts on rendered objects.

Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2026-02-14 11:10:35 +10:00
parent 19acc53fb6
commit 5ec6c493f2

View File

@@ -3,7 +3,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm> #include <algorithm>
#include <bitset>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <memory> #include <memory>
@@ -87,36 +86,16 @@ static Shader::SamplerComponentType ConvertSamplerComponentType(
: Shader::SamplerComponentType::Stencil; : Shader::SamplerComponentType::Stencil;
} }
// Use std::bitset for cleaner tracking of component types // Use the resolved pixel format to determine the component type, rather than
std::bitset<2> component_flags{}; // [0]=has_signed, [1]=has_unsigned // checking individual TIC component type fields. This ensures the SPIR-V image
const auto accumulate = [&component_flags](const Tegra::Texture::ComponentType component) { // sampled type matches the Vulkan image view format. Checking individual component
switch (component) { // types (r_type, g_type, b_type, a_type) can misclassify textures when unused
case Tegra::Texture::ComponentType::SINT: // channels have arbitrary type values (e.g., BCn compressed or single-channel
component_flags.set(0); // formats where unused component types may default to SINT/UINT).
break; if (VideoCore::Surface::IsPixelFormatSignedInteger(pixel_format)) {
case Tegra::Texture::ComponentType::UINT:
component_flags.set(1);
break;
default:
break;
}
};
accumulate(entry.r_type);
accumulate(entry.g_type);
accumulate(entry.b_type);
accumulate(entry.a_type);
if (component_flags[0] && !component_flags[1]) {
return Shader::SamplerComponentType::Sint; return Shader::SamplerComponentType::Sint;
} }
if (component_flags[1] && !component_flags[0]) { if (VideoCore::Surface::IsPixelFormatInteger(pixel_format)) {
return Shader::SamplerComponentType::Uint;
}
if (component_flags[0]) {
return Shader::SamplerComponentType::Sint;
}
if (component_flags[1]) {
return Shader::SamplerComponentType::Uint; return Shader::SamplerComponentType::Uint;
} }
return Shader::SamplerComponentType::Float; return Shader::SamplerComponentType::Float;