rpcs3/rpcs3/Emu/RSX/Program/GLSLSnippets/GPUDeswizzle.glsl

129 lines
No EOL
3.1 KiB
GLSL

R"(
#version 450
#define SSBO_LOCATION(x) (x + %loc)
layout(local_size_x = %ws, local_size_y = 1, local_size_z = 1) in;
layout(%set, binding=SSBO_LOCATION(0), std430) buffer ssbo0{ uint data_in[]; };
layout(%set, binding=SSBO_LOCATION(1), std430) buffer ssbo1{ uint data_out[]; };
layout(%push_block) uniform parameters
{
uint image_width;
uint image_height;
uint image_depth;
uint image_logw;
uint image_logh;
uint image_logd;
uint lod_count;
};
struct invocation_properties
{
uint data_offset;
uvec3 size;
uvec3 size_log2;
};
#define bswap_u16(bits) (bits & 0xFF) << 8 | (bits & 0xFF00) >> 8 | (bits & 0xFF0000) << 8 | (bits & 0xFF000000) >> 8
#define bswap_u32(bits) (bits & 0xFF) << 24 | (bits & 0xFF00) << 8 | (bits & 0xFF0000) >> 8 | (bits & 0xFF000000) >> 24
invocation_properties invocation;
bool init_invocation_properties(const in uint offset)
{
invocation.data_offset = 0;
invocation.size.x = image_width;
invocation.size.y = image_height;
invocation.size.z = image_depth;
invocation.size_log2.x = image_logw;
invocation.size_log2.y = image_logh;
invocation.size_log2.z = image_logd;
uint level_end = image_width * image_height * image_depth;
uint level = 1;
while (offset >= level_end && level < lod_count)
{
invocation.data_offset = level_end;
invocation.size.xy /= 2;
invocation.size.xy = max(invocation.size.xy, uvec2(1));
invocation.size_log2.xy = max(invocation.size_log2.xy, uvec2(1));
invocation.size_log2.xy --;
level_end += (invocation.size.x * invocation.size.y * image_depth);
level++;
}
return (offset < level_end);
}
uint get_z_index(const in uint x_, const in uint y_, const in uint z_)
{
uint offset = 0;
uint shift = 0;
uint x = x_;
uint y = y_;
uint z = z_;
uint log2w = invocation.size_log2.x;
uint log2h = invocation.size_log2.y;
uint log2d = invocation.size_log2.z;
do
{
if (log2w > 0)
{
offset |= (x & 1) << shift;
shift++;
x >>= 1;
log2w--;
}
if (log2h > 0)
{
offset |= (y & 1) << shift;
shift++;
y >>= 1;
log2h--;
}
if (log2d > 0)
{
offset |= (z & 1) << shift;
shift++;
z >>= 1;
log2d--;
}
}
while(x > 0 || y > 0 || z > 0);
return offset;
}
void main()
{
uint invocations_x = (gl_NumWorkGroups.x * gl_WorkGroupSize.x);
uint texel_id = (gl_GlobalInvocationID.y * invocations_x) + gl_GlobalInvocationID.x;
uint word_count = %_wordcount;
if (!init_invocation_properties(texel_id))
return;
// Calculations done in texels, not bytes
uint row_length = invocation.size.x;
uint slice_length = (invocation.size.y * row_length);
uint level_offset = (texel_id - invocation.data_offset);
uint slice_offset = (level_offset % slice_length);
uint z = (level_offset / slice_length);
uint y = (slice_offset / row_length);
uint x = (slice_offset % row_length);
uint src_texel_id = get_z_index(x, y, z);
uint dst_id = (texel_id * word_count);
uint src_id = (src_texel_id + invocation.data_offset) * word_count;
for (uint i = 0; i < word_count; ++i)
{
uint value = data_in[src_id++];
data_out[dst_id++] = %f(value);
}
}
)"