7 changed files with 748 additions and 0 deletions
-
2src/video_core/host_shaders/CMakeLists.txt
-
104src/video_core/host_shaders/block_linear_unswizzle_2d_buffer.comp
-
105src/video_core/host_shaders/block_linear_unswizzle_3d_buffer.comp
-
477src/video_core/renderer_vulkan/vk_compute_pass.cpp
-
38src/video_core/renderer_vulkan/vk_compute_pass.h
-
20src/video_core/renderer_vulkan/vk_texture_cache.cpp
-
2src/video_core/renderer_vulkan/vk_texture_cache.h
@ -0,0 +1,104 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-3.0-or-later |
||||
|
|
||||
|
#version 430 |
||||
|
|
||||
|
#extension GL_EXT_shader_16bit_storage : require |
||||
|
#extension GL_EXT_shader_8bit_storage : require |
||||
|
|
||||
|
#define BINDING_INPUT_BUFFER 0 |
||||
|
#define BINDING_OUTPUT_BUFFER 1 |
||||
|
|
||||
|
layout(push_constant) uniform PushConstants { |
||||
|
uvec3 dim; |
||||
|
uint bytes_per_block_log2; |
||||
|
|
||||
|
uvec3 origin; |
||||
|
uint layer_stride; |
||||
|
|
||||
|
uint block_size; |
||||
|
uint x_shift; |
||||
|
uint block_height; |
||||
|
uint block_height_mask; |
||||
|
} pc; |
||||
|
|
||||
|
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU32 { uint u32data[]; }; |
||||
|
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU64 { uvec2 u64data[]; }; |
||||
|
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU128 { uvec4 u128data[]; }; |
||||
|
|
||||
|
layout(binding = BINDING_OUTPUT_BUFFER, std430) writeonly buffer OutputBuffer { |
||||
|
uint out_u32[]; |
||||
|
}; |
||||
|
|
||||
|
layout(local_size_x = 16, local_size_y = 8, local_size_z = 1) in; |
||||
|
|
||||
|
const uint GOB_SIZE_X = 64; |
||||
|
const uint GOB_SIZE_Y = 8; |
||||
|
|
||||
|
const uint GOB_SIZE_X_SHIFT = 6; |
||||
|
const uint GOB_SIZE_Y_SHIFT = 3; |
||||
|
const uint GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT; |
||||
|
|
||||
|
const uvec2 SWIZZLE_MASK = uvec2(GOB_SIZE_X - 1u, GOB_SIZE_Y - 1u); |
||||
|
|
||||
|
uint SwizzleTable(uint pos) { |
||||
|
const uint t[8] = uint[]( |
||||
|
0x12100200, 0x13110301, 0x16140604, 0x17150705, |
||||
|
0x1a180a08, 0x1b190b09, 0x1e1c0e0c, 0x1f1d0f0d |
||||
|
); |
||||
|
const uint i = pos >> 4; |
||||
|
const uint h = (t[i / 4] >> ((i % 4) * 8)) & 0xff; |
||||
|
return (h << 4) | (pos & 0xf); |
||||
|
} |
||||
|
|
||||
|
uint SwizzleOffset(uvec2 pos) { |
||||
|
pos = pos & SWIZZLE_MASK; |
||||
|
return SwizzleTable(pos.y * 64u + pos.x); |
||||
|
} |
||||
|
|
||||
|
uvec4 ReadTexel(uint offset) { |
||||
|
switch (pc.bytes_per_block_log2) { |
||||
|
case 2u: |
||||
|
return uvec4(u32data[offset / 4u], 0u, 0u, 0u); |
||||
|
case 3u: |
||||
|
return uvec4(u64data[offset / 8u], 0u, 0u); |
||||
|
case 4u: |
||||
|
return u128data[offset / 16u]; |
||||
|
} |
||||
|
return uvec4(0u); |
||||
|
} |
||||
|
|
||||
|
void main() { |
||||
|
uvec3 coord = gl_GlobalInvocationID; |
||||
|
if (coord.x >= pc.dim.x || coord.y >= pc.dim.y || coord.z >= pc.dim.z) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
uvec3 pos = coord + pc.origin; |
||||
|
pos.x <<= pc.bytes_per_block_log2; |
||||
|
|
||||
|
uint swizzle = SwizzleOffset(pos.xy); |
||||
|
uint block_y = pos.y >> GOB_SIZE_Y_SHIFT; |
||||
|
|
||||
|
uint offset = 0u; |
||||
|
offset += pos.z * pc.layer_stride; |
||||
|
offset += (block_y >> pc.block_height) * pc.block_size; |
||||
|
offset += (block_y & pc.block_height_mask) << GOB_SIZE_SHIFT; |
||||
|
offset += (pos.x >> GOB_SIZE_X_SHIFT) << pc.x_shift; |
||||
|
offset += swizzle; |
||||
|
|
||||
|
uvec4 texel = ReadTexel(offset); |
||||
|
|
||||
|
uint words = 1u << (pc.bytes_per_block_log2 - 2u); |
||||
|
uint linear_index = coord.x + coord.y * pc.dim.x + coord.z * pc.dim.x * pc.dim.y; |
||||
|
uint out_idx = linear_index * words; |
||||
|
|
||||
|
out_u32[out_idx] = texel.x; |
||||
|
if (words > 1u) { |
||||
|
out_u32[out_idx + 1u] = texel.y; |
||||
|
} |
||||
|
if (words > 2u) { |
||||
|
out_u32[out_idx + 2u] = texel.z; |
||||
|
out_u32[out_idx + 3u] = texel.w; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,105 @@ |
|||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project |
||||
|
// SPDX-License-Identifier: GPL-3.0-or-later |
||||
|
|
||||
|
#version 430 |
||||
|
|
||||
|
#define BINDING_INPUT_BUFFER 0 |
||||
|
#define BINDING_OUTPUT_BUFFER 1 |
||||
|
|
||||
|
layout(push_constant) uniform PushConstants { |
||||
|
uvec3 dim; |
||||
|
uint bytes_per_block_log2; |
||||
|
|
||||
|
uvec3 origin; |
||||
|
uint slice_size; |
||||
|
|
||||
|
uint block_size; |
||||
|
uint x_shift; |
||||
|
uint block_height; |
||||
|
uint block_height_mask; |
||||
|
|
||||
|
uint block_depth; |
||||
|
uint block_depth_mask; |
||||
|
} pc; |
||||
|
|
||||
|
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU32 { uint u32data[]; }; |
||||
|
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU64 { uvec2 u64data[]; }; |
||||
|
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU128 { uvec4 u128data[]; }; |
||||
|
|
||||
|
layout(binding = BINDING_OUTPUT_BUFFER, std430) writeonly buffer OutputBuffer { |
||||
|
uint out_u32[]; |
||||
|
}; |
||||
|
|
||||
|
layout(local_size_x = 8, local_size_y = 8, local_size_z = 4) in; |
||||
|
|
||||
|
const uint GOB_SIZE_X = 64; |
||||
|
const uint GOB_SIZE_Y = 8; |
||||
|
|
||||
|
const uint GOB_SIZE_X_SHIFT = 6; |
||||
|
const uint GOB_SIZE_Y_SHIFT = 3; |
||||
|
const uint GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT; |
||||
|
|
||||
|
const uvec2 SWIZZLE_MASK = uvec2(GOB_SIZE_X - 1u, GOB_SIZE_Y - 1u); |
||||
|
|
||||
|
uint SwizzleTable(uint pos) { |
||||
|
const uint t[8] = uint[]( |
||||
|
0x12100200, 0x13110301, 0x16140604, 0x17150705, |
||||
|
0x1a180a08, 0x1b190b09, 0x1e1c0e0c, 0x1f1d0f0d |
||||
|
); |
||||
|
const uint i = pos >> 4; |
||||
|
const uint h = (t[i / 4] >> ((i % 4) * 8)) & 0xff; |
||||
|
return (h << 4) | (pos & 0xf); |
||||
|
} |
||||
|
|
||||
|
uint SwizzleOffset(uvec2 pos) { |
||||
|
pos = pos & SWIZZLE_MASK; |
||||
|
return SwizzleTable(pos.y * 64u + pos.x); |
||||
|
} |
||||
|
|
||||
|
uvec4 ReadTexel(uint offset) { |
||||
|
switch (pc.bytes_per_block_log2) { |
||||
|
case 2u: |
||||
|
return uvec4(u32data[offset / 4u], 0u, 0u, 0u); |
||||
|
case 3u: |
||||
|
return uvec4(u64data[offset / 8u], 0u, 0u); |
||||
|
case 4u: |
||||
|
return u128data[offset / 16u]; |
||||
|
} |
||||
|
return uvec4(0u); |
||||
|
} |
||||
|
|
||||
|
void main() { |
||||
|
uvec3 coord = gl_GlobalInvocationID; |
||||
|
if (coord.x >= pc.dim.x || coord.y >= pc.dim.y || coord.z >= pc.dim.z) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
uvec3 pos = coord + pc.origin; |
||||
|
pos.x <<= pc.bytes_per_block_log2; |
||||
|
|
||||
|
uint swizzle = SwizzleOffset(pos.xy); |
||||
|
uint block_y = pos.y >> GOB_SIZE_Y_SHIFT; |
||||
|
|
||||
|
uint offset = 0u; |
||||
|
offset += (pos.z >> pc.block_depth) * pc.slice_size; |
||||
|
offset += (pos.z & pc.block_depth_mask) << (GOB_SIZE_SHIFT + pc.block_height); |
||||
|
offset += (block_y >> pc.block_height) * pc.block_size; |
||||
|
offset += (block_y & pc.block_height_mask) << GOB_SIZE_SHIFT; |
||||
|
offset += (pos.x >> GOB_SIZE_X_SHIFT) << pc.x_shift; |
||||
|
offset += swizzle; |
||||
|
|
||||
|
uvec4 texel = ReadTexel(offset); |
||||
|
|
||||
|
uint words = 1u << (pc.bytes_per_block_log2 - 2u); |
||||
|
uint linear_index = coord.x + coord.y * pc.dim.x + coord.z * pc.dim.x * pc.dim.y; |
||||
|
uint out_idx = linear_index * words; |
||||
|
|
||||
|
out_u32[out_idx] = texel.x; |
||||
|
if (words > 1u) { |
||||
|
out_u32[out_idx + 1u] = texel.y; |
||||
|
} |
||||
|
if (words > 2u) { |
||||
|
out_u32[out_idx + 2u] = texel.z; |
||||
|
out_u32[out_idx + 3u] = texel.w; |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue