nx2: decode ASTC textures with the Switch 2 GOB layout

The GPU ASTC decoder unswizzles block-linear data itself and never applied
the native (Switch 2) GOB swizzle that the other unswizzle paths use, so
ASTC textures came out with 16-byte blocks swapped wherever the image
varies. Title 4's UI is ASTC (10x5, 4x4, 8x8): portraits, buttons and the
squid cursor had hatched edges and clean interiors. Pass the native tiling
flag to the decoder and swap offset bits 5 and 6 as
block_linear_unswizzle_2d.comp does.
This commit is contained in:
Takoroka 2026-10-28 05:14:02 -04:00
commit 034b9cab96
3 changed files with 10 additions and 1 deletions

View file

@ -33,6 +33,7 @@ UNIFORM(3) uint block_size;
UNIFORM(4) uint x_shift;
UNIFORM(5) uint block_height;
UNIFORM(6) uint block_height_mask;
UNIFORM(7) uint native_tiling;
END_PUSH_CONSTANTS
struct EncodingData {
@ -1404,7 +1405,12 @@ uint SwizzleOffset(uvec2 pos) {
void main() {
uvec3 pos = gl_GlobalInvocationID;
pos.x <<= BYTES_PER_BLOCK_LOG2;
const uint swizzle = SwizzleOffset(pos.xy);
uint swizzle = SwizzleOffset(pos.xy);
if (native_tiling != 0u) {
// Switch 2 GOBs swap offset bits 5 and 6 (see block_linear_unswizzle_2d.comp).
const uint difference = ((swizzle >> 5u) ^ (swizzle >> 6u)) & 1u;
swizzle ^= (difference << 5u) | (difference << 6u);
}
const uint block_y = pos.y >> GOB_SIZE_Y_SHIFT;
uint offset = 0;

View file

@ -96,6 +96,7 @@ void UtilShaders::ASTCDecode(Image& image, const StagingBufferMap& map,
glUniform1ui(4, params.x_shift);
glUniform1ui(5, params.block_height);
glUniform1ui(6, params.block_height_mask);
glUniform1ui(7, params.native_tiling);
// ASTC texture data
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset,

View file

@ -183,6 +183,7 @@ struct AstcPushConstants {
u32 x_shift;
u32 block_height;
u32 block_height_mask;
u32 native_tiling;
};
struct QueriesPrefixScanPushConstants {
@ -583,6 +584,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
.x_shift = params.x_shift,
.block_height = params.block_height,
.block_height_mask = params.block_height_mask,
.native_tiling = params.native_tiling,
};
const VkDescriptorSet set = descriptor_allocator.Commit();
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);