From 6a454520877624f35ac5e2c34b4e8317c34f1ab6 Mon Sep 17 00:00:00 2001 From: bomabomabomaboma <69987043+goldislead@users.noreply.github.com> Date: Wed, 5 Aug 2026 16:38:39 -0700 Subject: [PATCH] [GPU] Walk the guest swizzle for integer scales; update comments Fixed integer fetches are updated to look widths up through the guest swizzle, so every output channel is scaled by the width it came from. Previously, host swizzle was being walked, and it was causing some 6 bit channels to be scaled as 5 bits and vice versa. Co-authored-by: philtimmes <5494151+philtimmes@users.noreply.github.com> --- src/xenia/gpu/dxbc_shader_translator.h | 1 + src/xenia/gpu/spirv_shader_translator.h | 3 ++- src/xenia/gpu/texture_cache.cc | 11 +++++------ src/xenia/gpu/texture_cache.h | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/xenia/gpu/dxbc_shader_translator.h b/src/xenia/gpu/dxbc_shader_translator.h index fbaaae8a8..4e8786789 100644 --- a/src/xenia/gpu/dxbc_shader_translator.h +++ b/src/xenia/gpu/dxbc_shader_translator.h @@ -417,6 +417,7 @@ class DxbcShaderTranslator : public ShaderTranslator { // to turn normalized host samples back into guest integer values. // bits 0:3 = component_bits - 1 // bit 4 = signed + // bit 5 = unsigned-biased // Zero means no scale. uint32_t texture_integer_scale_bits[32]; diff --git a/src/xenia/gpu/spirv_shader_translator.h b/src/xenia/gpu/spirv_shader_translator.h index 92546ce9a..f1bd00060 100644 --- a/src/xenia/gpu/spirv_shader_translator.h +++ b/src/xenia/gpu/spirv_shader_translator.h @@ -305,7 +305,8 @@ class SpirvShaderTranslator : public ShaderTranslator { // Integer num_format on fixed textures. Each dword packs the scale needed // to turn normalized host samples back into guest integer values. // bits 0:3 = component_bits - 1 - // bit 4 = signed. + // bit 4 = signed + // bit 5 = unsigned-biased // Zero means no scale. uint32_t texture_integer_scale_bits[32]; }; diff --git a/src/xenia/gpu/texture_cache.cc b/src/xenia/gpu/texture_cache.cc index 782e34f49..c017ffdf8 100644 --- a/src/xenia/gpu/texture_cache.cc +++ b/src/xenia/gpu/texture_cache.cc @@ -364,9 +364,8 @@ void TextureCache::RequestTextures(uint32_t used_texture_mask) { uint32_t old_host_swizzle = binding.host_swizzle; binding.host_swizzle = GuestToHostSwizzle(fetch.swizzle, GetHostFormatSwizzle(binding.key)); - binding.integer_scale_bits = - GetIntegerScaleBits(fetch.format, fetch.num_format, - binding.host_swizzle, binding.swizzled_signs); + binding.integer_scale_bits = GetIntegerScaleBits( + fetch.format, fetch.num_format, fetch.swizzle, binding.swizzled_signs); // Check if need to load the unsigned and the signed versions of the texture // (if the format is emulated with different host bit representations for @@ -690,11 +689,11 @@ TextureCache::Texture* TextureCache::FindOrCreateTexture(TextureKey key) { // undo the host sampler's normalization - the guest wants e.g. [0, 255], not // [0, 1]. 6 bits per output component: bits 0:3 = width - 1, bit 4 = signed, // bit 5 = unsigned-biased. The scale lands after swizzling, so each output lane -// walks the host swizzle back to its source component's width; constant (0/1) +// walks the guest swizzle back to its source component's width; constant (0/1) // lanes, gamma, and non-fixed formats have nothing to rescale and stay 0. uint32_t TextureCache::GetIntegerScaleBits(xenos::TextureFormat guest_format, uint32_t num_format, - uint32_t host_swizzle, + uint32_t guest_swizzle, uint8_t swizzled_signs) { // num_format 0 is the normalized/fractional fetch - nothing to rescale. const FormatInfo& format_info = *FormatInfo::Get(guest_format); @@ -705,7 +704,7 @@ uint32_t TextureCache::GetIntegerScaleBits(xenos::TextureFormat guest_format, } for (uint32_t i = 0; i < 4; ++i) { - uint32_t source_component = (host_swizzle >> (i * 3)) & 0b111; + uint32_t source_component = (guest_swizzle >> (i * 3)) & 0b111; if (source_component >= xenos::XE_GPU_TEXTURE_SWIZZLE_0) { continue; } diff --git a/src/xenia/gpu/texture_cache.h b/src/xenia/gpu/texture_cache.h index 61412c72f..029aaf213 100644 --- a/src/xenia/gpu/texture_cache.h +++ b/src/xenia/gpu/texture_cache.h @@ -522,7 +522,7 @@ class TextureCache { struct TextureBinding { TextureKey key; - // Packed integer scale, 5 bits per component. + // Packed integer scale, 6 bits per component. uint32_t integer_scale_bits; // Destination swizzle merged with guest to host format swizzle. uint32_t host_swizzle; @@ -605,7 +605,7 @@ class TextureCache { // shader to restore guest integer units from normalized host samples. static uint32_t GetIntegerScaleBits(xenos::TextureFormat guest_format, uint32_t num_format, - uint32_t host_swizzle, + uint32_t guest_swizzle, uint8_t swizzled_signs); bool LoadTextureData(Texture& texture); void LoadTexturesData(Texture** textures, uint32_t n_textures);