#version 450 #ifndef OUTPUT_FORMAT #define OUTPUT_FORMAT rgba16f #endif layout(local_size_x=8, local_size_y=8) in; layout(OUTPUT_FORMAT, set=0, binding=0) uniform writeonly image2D destinationImage; layout(std430, set=0, binding=1) readonly buffer Pixels { uvec2 pixels[]; }; layout(push_constant) uniform Size { uint width; uint height; } size; // Bit decoding avoids a hardware half conversion that could flush subnormals. float halfValue(uint h) { uint sign = (h & 0x8000u) << 16; uint exponent = (h >> 10) & 31u; uint mantissa = h & 1023u; if (exponent == 0u) { if (mantissa == 0u) return uintBitsToFloat(sign); int leading = findMSB(mantissa); return uintBitsToFloat(sign | ((uint(leading) + 103u) << 23) | ((mantissa << uint(23-leading)) & 0x7fffffu)); } if (exponent == 31u) return uintBitsToFloat(sign | 0x7f800000u | (mantissa << 13)); return uintBitsToFloat(sign | ((exponent + 112u) << 23) | (mantissa << 13)); } void main() { uvec2 p = gl_GlobalInvocationID.xy; if (p.x >= size.width || p.y >= size.height || any(greaterThanEqual(ivec2(p), imageSize(destinationImage)))) return; uvec2 h = pixels[p.y * size.width + p.x]; imageStore(destinationImage, ivec2(p), vec4(halfValue(h.x & 65535u), halfValue(h.x >> 16), halfValue(h.y & 65535u), halfValue(h.y >> 16))); }