[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>
This commit is contained in:
bomabomabomaboma
2026-08-05 16:38:39 -07:00
committed by Radosław Gliński
parent 25597a5465
commit 6a45452087
4 changed files with 10 additions and 9 deletions

View File

@@ -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];

View File

@@ -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];
};

View File

@@ -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;
}

View File

@@ -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);