renderer: optimize tiling and reuse centralized image layouts

This commit is contained in:
nmzik
2026-10-09 22:23:02 +02:00
parent 1c301c9aab
commit 5559cfcbb2
18 changed files with 1373 additions and 1533 deletions
@@ -6,20 +6,13 @@ layout(local_size_x = 64) in;
layout(set = 0, binding = 0, std430) readonly buffer Input { uint data[]; } input_buffer;
layout(set = 0, binding = 1, std430) buffer Output { uint data[]; } output_buffer;
layout(push_constant, std430) uniform Push {
layout(push_constant, std430) uniform Conversion {
uint src_base;
uint dst_base;
uint width;
uint height;
uint depth;
uint surface_z;
uint pitch_bytes;
uint slice_bytes;
uint blocks_per_row;
uint blocks_per_slice;
uint tail_x;
uint tail_y;
uint tail;
uint source_pitch;
uint target_pitch;
uint color_transform;
uint to_host;
} params;
@@ -1,66 +1,84 @@
layout(local_size_x = 8, local_size_y = 8) in;
#extension GL_EXT_shader_8bit_storage : require
#extension GL_EXT_shader_16bit_storage : require
layout(local_size_x = 64) in;
layout(set = 0, binding = 0, std430) readonly buffer Input { uint data[]; } input_buffer;
layout(set = 0, binding = 1, std430) buffer Output { uint data[]; } output_buffer;
layout(set = 0, binding = 0, std430) readonly buffer Input8 { uint8_t data[]; } input_buffer8;
layout(set = 0, binding = 1, std430) buffer Output8 { uint8_t data[]; } output_buffer8;
layout(set = 0, binding = 0, std430) readonly buffer Input16 { uint16_t data[]; } input_buffer16;
layout(set = 0, binding = 1, std430) buffer Output16 { uint16_t data[]; } output_buffer16;
layout(set = 0, binding = 2, std140) uniform Push {
struct Mip {
uint src_base;
uint dst_base;
uint width;
uint height;
uint depth;
uint surface_z;
uint pitch_bytes;
uint slice_bytes;
uint tiled_slice_bytes;
uint blocks_per_row;
uint blocks_per_slice;
uint surface_z;
uint tail_x;
uint tail_y;
uint tail;
uint num_texels;
};
layout(set = 0, binding = 2, std140) uniform TilingInfo {
uint num_texels;
uint color_transform;
} params;
Mip mips[16];
} info;
#include "gpu_tiler_color.inc"
void copy_element(uint src, uint dst) {
if ((ELEMENT_BYTES == 4u || ELEMENT_BYTES == 8u) && params.color_transform != 0u) {
if ((ELEMENT_BYTES == 4u || ELEMENT_BYTES == 8u) && info.color_transform != 0u) {
uvec2 value = uvec2(input_buffer.data[src >> 2], 0u);
if (ELEMENT_BYTES == 8u) value.y = input_buffer.data[(src >> 2) + 1u];
value = transform_color(value, params.color_transform, TILE == 0u);
value = transform_color(value, info.color_transform, TILE == 0u);
output_buffer.data[dst >> 2] = value.x;
if (ELEMENT_BYTES == 8u) output_buffer.data[(dst >> 2) + 1u] = value.y;
} else if (ELEMENT_BYTES >= 4) {
for (uint i = 0; i < ELEMENT_BYTES; i += 4) {
output_buffer.data[(dst + i) >> 2] = input_buffer.data[(src + i) >> 2];
}
} else if (ELEMENT_BYTES == 2) {
output_buffer16.data[dst >> 1] = input_buffer16.data[src >> 1];
} else {
uint mask = ELEMENT_BYTES == 1 ? 0xffu : 0xffffu;
uint value = (input_buffer.data[src >> 2] >> ((src & 3u) * 8u)) & mask;
uint shift = (dst & 3u) * 8u;
atomicAnd(output_buffer.data[dst >> 2], ~(mask << shift));
atomicOr(output_buffer.data[dst >> 2], value << shift);
output_buffer8.data[dst] = input_buffer8.data[src];
}
}
void main() {
uvec3 p = gl_GlobalInvocationID;
if (p.x >= params.width || p.y >= params.height || p.z >= params.depth) {
uint group = gl_WorkGroupID.y * gl_NumWorkGroups.x + gl_WorkGroupID.x;
// Reject padding groups before multiplying: the active range may approach 4 GiB.
if (group > (info.num_texels - 1u) / 64u) {
return;
}
uint texel = group * 64u + gl_LocalInvocationID.x;
if (texel >= info.num_texels) {
return;
}
uint mip = 0u;
uint mip_texels = info.mips[mip].num_texels;
while (texel >= mip_texels) {
texel -= mip_texels;
mip_texels = info.mips[++mip].num_texels;
}
Mip params = info.mips[mip];
uint row = texel / params.width;
uint z = row / params.height;
uvec3 p = uvec3(texel - row * params.width, row - z * params.height, z);
uvec3 extent = block_extent();
uvec3 swizzle = p;
uvec3 block = uvec3(0);
if (params.tail != 0) {
swizzle.xy += uvec2(params.tail_x, params.tail_y);
} else {
block = p / extent;
}
uvec3 block = p / extent;
uvec3 swizzle = p + uvec3(params.tail_x, params.tail_y, params.surface_z);
uint block_index = block.z * params.blocks_per_slice +
block.y * params.blocks_per_row + block.x;
uint tiled = block_index * BLOCK_BYTES +
block_offset(uvec3(swizzle.xy, swizzle.z + params.surface_z));
uint block_index = block.y * params.blocks_per_row + block.x;
uint tiled = block.z * params.tiled_slice_bytes + block_index * BLOCK_BYTES +
block_offset(swizzle);
uint linear = p.z * params.slice_bytes + p.y * params.pitch_bytes +
p.x * ELEMENT_BYTES;
if (TILE == 0) {
@@ -6,20 +6,15 @@ layout(local_size_x = 64) in;
layout(set = 0, binding = 0, std430) readonly buffer Input { uint data[]; } input_buffer;
layout(set = 0, binding = 1, std430) buffer Output { uint data[]; } output_buffer;
layout(push_constant, std430) uniform Push {
layout(push_constant, std430) uniform Conversion {
uint src_base;
uint dst_base;
uint width;
uint height;
uint depth;
uint surface_z;
uint pitch_bytes;
uint slice_bytes;
uint blocks_per_row;
uint blocks_per_slice;
uint tail_x;
uint tail_y;
uint tail;
uint source_pitch;
uint target_pitch;
uint color_transform;
uint to_host;
} params;
uint decode(uint value) {
@@ -35,8 +30,8 @@ void main() {
if (x >= params.width || y >= params.height) {
return;
}
uint src = params.src_base + y * params.pitch_bytes + x * 4u;
uint dst = params.dst_base + y * params.slice_bytes + x * 2u;
uint src = params.src_base + y * params.source_pitch + x * 4u;
uint dst = params.dst_base + y * params.target_pitch + x * 2u;
uint shift = (dst & 2u) * 8u;
uint mask = 0xffffu << shift;
uint word = dst >> 2u;
@@ -6,20 +6,15 @@ layout(local_size_x = 64) in;
layout(set = 0, binding = 0, std430) readonly buffer Input { uint data[]; } input_buffer;
layout(set = 0, binding = 1, std430) buffer Output { uint data[]; } output_buffer;
layout(push_constant, std430) uniform Push {
layout(push_constant, std430) uniform Conversion {
uint src_base;
uint dst_base;
uint width;
uint height;
uint depth;
uint surface_z;
uint pitch_bytes;
uint slice_bytes;
uint blocks_per_row;
uint blocks_per_slice;
uint tail_x;
uint tail_y;
uint tail;
uint source_pitch;
uint target_pitch;
uint color_transform;
uint to_host;
} params;
void main() {
@@ -28,12 +23,12 @@ void main() {
if (x >= params.width || y >= params.height) {
return;
}
uint src = params.src_base + y * params.pitch_bytes + x * 2u;
uint src = params.src_base + y * params.source_pitch + x * 2u;
uint packed = input_buffer.data[src >> 2u];
uint value = (packed >> ((src & 2u) * 8u)) & 0xffffu;
uint encoded = D32 != 0u
? floatBitsToUint(float(value) / 65535.0)
: value * 256u + (value + 128u) / 257u;
uint dst = params.dst_base + y * params.slice_bytes + x * 4u;
uint dst = params.dst_base + y * params.target_pitch + x * 4u;
output_buffer.data[dst >> 2u] = encoded;
}