Files
Xenia-Canary/src/xenia/gpu/d3d12/shaders/pixel_formats.hlsli
2018-08-23 13:25:36 +03:00

75 lines
3.4 KiB
HLSL

#ifndef XENIA_GPU_D3D12_SHADERS_PIXEL_FORMATS_HLSLI_
#define XENIA_GPU_D3D12_SHADERS_PIXEL_FORMATS_HLSLI_
// https://github.com/Microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexConvert.cpp
uint XeFloat16To7e3(uint4 rgba_f16u32) {
float4 rgba_f32 = f16tof32(rgba_f16u32);
uint3 rgb_f32u32 = asuint(rgba_f32.xyz);
// Keep only positive (high bit set means negative for both float and int) and
// saturate to 31.875 (also dropping NaNs).
rgb_f32u32 = uint3(clamp(int3(rgb_f32u32), 0, 0x41FF0000));
uint3 normalized = rgb_f32u32 + 0xC2000000u;
uint3 denormalized = ((rgb_f32u32 & 0x7FFFFFu) | 0x800000u) >>
((125u).xxx - (rgb_f32u32 >> 23u));
uint3 rgb_f10u32 = normalized + (denormalized - normalized) *
uint3(rgb_f32u32 < 0x3E800000u);
rgb_f10u32 =
((rgb_f10u32 + 0x7FFFu + ((rgb_f10u32 >> 16u) & 1u)) >> 16u) & 0x3FFu;
return rgb_f10u32.r | (rgb_f10u32.g << 10u) | (rgb_f10u32.b << 20u) |
(uint(saturate(rgba_f32.a) * 3.0) << 30u);
}
uint4 XeFloat7e3To16(uint rgba_packed) {
uint3 rgb_f10u32 = (rgba_packed.xxx >> uint3(0u, 10u, 20u)) & 0x3FFu;
uint3 mantissa = rgb_f10u32 & 0x7Fu;
uint3 exponent = rgb_f10u32 >> 7u;
// Normalize the values for the denormalized components.
// Exponent = 1;
// do { Exponent--; Mantissa <<= 1; } while ((Mantissa & 0x80) == 0);
uint3 is_denormalized = uint3(exponent == 0u);
uint3 mantissa_lzcnt = (7u).xxx - firstbithigh(mantissa);
exponent += ((1u).xxx - mantissa_lzcnt - exponent) * is_denormalized;
mantissa +=
(((mantissa << mantissa_lzcnt) & 0x7Fu) - mantissa) * is_denormalized;
// Combine into 32-bit float bits and clear zeros.
uint3 rgb_f32u32 = (((exponent + 124u) << 23u) | (mantissa << 16u)) *
uint3(rgb_f10u32 != 0u);
return f32tof16(float4(asfloat(rgb_f32u32),
float(rgba_packed >> 30u) * (1.0 / 3.0)));
}
// Based on CFloat24 from d3dref9.dll and the 6e4 code from:
// https://github.com/Microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexConvert.cpp
// 6e4 has a different exponent bias allowing [0,512) values, 20e4 allows [0,2).
// We also can't clamp the stored value to 1 as load->store->load must be exact.
uint4 XeFloat32To20e4(uint4 f32u32) {
// Keep only positive (high bit set means negative for both float and int) and
// saturate to the maximum representable value near 2 (also dropping NaNs).
f32u32 = uint4(clamp(int4(f32u32), 0, 0x3FFFFFF8));
uint4 normalized = f32u32 + 0xC8000000u;
uint4 denormalized =
((f32u32 & 0x7FFFFFu) | 0x800000u) >> ((113u).xxxx - (f32u32 >> 23u));
uint4 f24u32 =
normalized + (denormalized - normalized) * uint4(f32u32 < 0x38800000u);
return ((f24u32 + 3u + ((f24u32 >> 3u) & 1u)) >> 3u) & 0xFFFFFFu;
}
uint4 XeFloat20e4To32(uint4 f24u32) {
uint4 mantissa = f24u32 & 0xFFFFFu;
uint4 exponent = f24u32 >> 20u;
// Normalize the values for the denormalized components.
// Exponent = 1;
// do { Exponent--; Mantissa <<= 1; } while ((Mantissa & 0x100000) == 0);
uint4 is_denormalized = uint4(exponent == 0u);
uint4 mantissa_lzcnt = (20u).xxxx - firstbithigh(mantissa);
exponent += ((1u).xxxx - mantissa_lzcnt - exponent) * is_denormalized;
mantissa +=
(((mantissa << mantissa_lzcnt) & 0xFFFFFu) - mantissa) * is_denormalized;
// Combine into 32-bit float bits and clear zeros.
return (((exponent + 112u) << 23u) | (mantissa << 3u)) * uint4(f24u32 != 0u);
}
#endif // XENIA_GPU_D3D12_SHADERS_PIXEL_FORMATS_HLSLI_