#version 450 layout( local_size_x = 8, local_size_y = 8, local_size_z = 1) in; layout(binding = 0) writeonly uniform image2D dst; layout(binding = 1) uniform usamplerBuffer src; layout(push_constant) uniform u_info_t { uvec2 extent; } u_info; float unormalize(uint value, int bits) { const int range = (1 << bits) - 1; return float(value) / float(range); } float snormalize(int value, int bits) { const int range = (1 << (bits - 1)) - 1; // Min because, -32 and -31 map to -1.0f, and we // divide by 31. return max(float(value) / float(range), -1.0f); } void main() { ivec3 thread_id = ivec3(gl_GlobalInvocationID); if (all(lessThan(thread_id.xy, u_info.extent))) { uint offset = thread_id.x + thread_id.y * u_info.extent.x; uint value = texelFetch(src, int(offset)).r; // Sign-extend magic! int u5 = bitfieldExtract(int (value), 0, 5); int v5 = bitfieldExtract(int (value), 5, 5); uint l6 = bitfieldExtract(uint(value), 10, 6); vec4 color = vec4( snormalize(u5, 5), snormalize(v5, 5), unormalize(l6, 6), 1.0f); imageStore(dst, thread_id.xy, color); } }