diff --git a/reference/opt/shaders-hlsl/frag/unorm-snorm-packing.frag b/reference/opt/shaders-hlsl/frag/unorm-snorm-packing.frag index 241cb80..57b5950 100644 --- a/reference/opt/shaders-hlsl/frag/unorm-snorm-packing.frag +++ b/reference/opt/shaders-hlsl/frag/unorm-snorm-packing.frag @@ -1,15 +1,21 @@ static float4 FP32Out; static uint UNORM8; static uint SNORM8; +static uint UNORM16; +static uint SNORM16; static uint UNORM8Out; static float4 FP32; static uint SNORM8Out; +static uint UNORM16Out; +static uint SNORM16Out; struct SPIRV_Cross_Input { nointerpolation uint SNORM8 : TEXCOORD0; nointerpolation uint UNORM8 : TEXCOORD1; - nointerpolation float4 FP32 : TEXCOORD2; + nointerpolation uint SNORM16 : TEXCOORD2; + nointerpolation uint UNORM16 : TEXCOORD3; + nointerpolation float4 FP32 : TEXCOORD4; }; struct SPIRV_Cross_Output @@ -17,6 +23,8 @@ struct SPIRV_Cross_Output float4 FP32Out : SV_Target0; uint UNORM8Out : SV_Target1; uint SNORM8Out : SV_Target2; + uint UNORM16Out : SV_Target3; + uint SNORM16Out : SV_Target4; }; uint SPIRV_Cross_packUnorm4x8(float4 value) @@ -44,23 +52,58 @@ float4 SPIRV_Cross_unpackSnorm4x8(uint value) return clamp(float4(Packed) / 127.0, -1.0, 1.0); } +uint SPIRV_Cross_packUnorm2x16(float2 value) +{ + uint2 Packed = uint2(round(saturate(value) * 65535.0)); + return Packed.x | (Packed.y << 16); +} + +float2 SPIRV_Cross_unpackUnorm2x16(uint value) +{ + uint2 Packed = uint2(value & 0xffff, value >> 16); + return float2(Packed) / 65535.0; +} + +uint SPIRV_Cross_packSnorm2x16(float2 value) +{ + int2 Packed = int2(round(clamp(value, -1.0, 1.0) * 32767.0)) & 0xffff; + return uint(Packed.x | (Packed.y << 16)); +} + +float2 SPIRV_Cross_unpackSnorm2x16(uint value) +{ + int SignedValue = int(value); + int2 Packed = int2(SignedValue << 16, SignedValue) >> 16; + return clamp(float2(Packed) / 32767.0, -1.0, 1.0); +} + void frag_main() { FP32Out = SPIRV_Cross_unpackUnorm4x8(UNORM8); FP32Out = SPIRV_Cross_unpackSnorm4x8(SNORM8); + float2 _21 = SPIRV_Cross_unpackUnorm2x16(UNORM16); + FP32Out = float4(_21.x, _21.y, FP32Out.z, FP32Out.w); + float2 _26 = SPIRV_Cross_unpackSnorm2x16(SNORM16); + FP32Out = float4(_26.x, _26.y, FP32Out.z, FP32Out.w); UNORM8Out = SPIRV_Cross_packUnorm4x8(FP32); SNORM8Out = SPIRV_Cross_packSnorm4x8(FP32); + UNORM16Out = SPIRV_Cross_packUnorm2x16(FP32.xy); + SNORM16Out = SPIRV_Cross_packSnorm2x16(FP32.zw); } SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) { UNORM8 = stage_input.UNORM8; SNORM8 = stage_input.SNORM8; + UNORM16 = stage_input.UNORM16; + SNORM16 = stage_input.SNORM16; FP32 = stage_input.FP32; frag_main(); SPIRV_Cross_Output stage_output; stage_output.FP32Out = FP32Out; stage_output.UNORM8Out = UNORM8Out; stage_output.SNORM8Out = SNORM8Out; + stage_output.UNORM16Out = UNORM16Out; + stage_output.SNORM16Out = SNORM16Out; return stage_output; } diff --git a/reference/shaders-hlsl/frag/unorm-snorm-packing.frag b/reference/shaders-hlsl/frag/unorm-snorm-packing.frag index 241cb80..57b5950 100644 --- a/reference/shaders-hlsl/frag/unorm-snorm-packing.frag +++ b/reference/shaders-hlsl/frag/unorm-snorm-packing.frag @@ -1,15 +1,21 @@ static float4 FP32Out; static uint UNORM8; static uint SNORM8; +static uint UNORM16; +static uint SNORM16; static uint UNORM8Out; static float4 FP32; static uint SNORM8Out; +static uint UNORM16Out; +static uint SNORM16Out; struct SPIRV_Cross_Input { nointerpolation uint SNORM8 : TEXCOORD0; nointerpolation uint UNORM8 : TEXCOORD1; - nointerpolation float4 FP32 : TEXCOORD2; + nointerpolation uint SNORM16 : TEXCOORD2; + nointerpolation uint UNORM16 : TEXCOORD3; + nointerpolation float4 FP32 : TEXCOORD4; }; struct SPIRV_Cross_Output @@ -17,6 +23,8 @@ struct SPIRV_Cross_Output float4 FP32Out : SV_Target0; uint UNORM8Out : SV_Target1; uint SNORM8Out : SV_Target2; + uint UNORM16Out : SV_Target3; + uint SNORM16Out : SV_Target4; }; uint SPIRV_Cross_packUnorm4x8(float4 value) @@ -44,23 +52,58 @@ float4 SPIRV_Cross_unpackSnorm4x8(uint value) return clamp(float4(Packed) / 127.0, -1.0, 1.0); } +uint SPIRV_Cross_packUnorm2x16(float2 value) +{ + uint2 Packed = uint2(round(saturate(value) * 65535.0)); + return Packed.x | (Packed.y << 16); +} + +float2 SPIRV_Cross_unpackUnorm2x16(uint value) +{ + uint2 Packed = uint2(value & 0xffff, value >> 16); + return float2(Packed) / 65535.0; +} + +uint SPIRV_Cross_packSnorm2x16(float2 value) +{ + int2 Packed = int2(round(clamp(value, -1.0, 1.0) * 32767.0)) & 0xffff; + return uint(Packed.x | (Packed.y << 16)); +} + +float2 SPIRV_Cross_unpackSnorm2x16(uint value) +{ + int SignedValue = int(value); + int2 Packed = int2(SignedValue << 16, SignedValue) >> 16; + return clamp(float2(Packed) / 32767.0, -1.0, 1.0); +} + void frag_main() { FP32Out = SPIRV_Cross_unpackUnorm4x8(UNORM8); FP32Out = SPIRV_Cross_unpackSnorm4x8(SNORM8); + float2 _21 = SPIRV_Cross_unpackUnorm2x16(UNORM16); + FP32Out = float4(_21.x, _21.y, FP32Out.z, FP32Out.w); + float2 _26 = SPIRV_Cross_unpackSnorm2x16(SNORM16); + FP32Out = float4(_26.x, _26.y, FP32Out.z, FP32Out.w); UNORM8Out = SPIRV_Cross_packUnorm4x8(FP32); SNORM8Out = SPIRV_Cross_packSnorm4x8(FP32); + UNORM16Out = SPIRV_Cross_packUnorm2x16(FP32.xy); + SNORM16Out = SPIRV_Cross_packSnorm2x16(FP32.zw); } SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) { UNORM8 = stage_input.UNORM8; SNORM8 = stage_input.SNORM8; + UNORM16 = stage_input.UNORM16; + SNORM16 = stage_input.SNORM16; FP32 = stage_input.FP32; frag_main(); SPIRV_Cross_Output stage_output; stage_output.FP32Out = FP32Out; stage_output.UNORM8Out = UNORM8Out; stage_output.SNORM8Out = SNORM8Out; + stage_output.UNORM16Out = UNORM16Out; + stage_output.SNORM16Out = SNORM16Out; return stage_output; } diff --git a/shaders-hlsl/frag/unorm-snorm-packing.frag b/shaders-hlsl/frag/unorm-snorm-packing.frag index efd4cd2..c0a01aa 100644 --- a/shaders-hlsl/frag/unorm-snorm-packing.frag +++ b/shaders-hlsl/frag/unorm-snorm-packing.frag @@ -2,15 +2,23 @@ layout(location = 0) flat in uint SNORM8; layout(location = 1) flat in uint UNORM8; -layout(location = 2) flat in vec4 FP32; +layout(location = 2) flat in uint SNORM16; +layout(location = 3) flat in uint UNORM16; +layout(location = 4) flat in vec4 FP32; layout(location = 0) out vec4 FP32Out; layout(location = 1) out uint UNORM8Out; layout(location = 2) out uint SNORM8Out; +layout(location = 3) out uint UNORM16Out; +layout(location = 4) out uint SNORM16Out; void main() { FP32Out = unpackUnorm4x8(UNORM8); FP32Out = unpackSnorm4x8(SNORM8); + FP32Out.xy = unpackUnorm2x16(UNORM16); + FP32Out.xy = unpackSnorm2x16(SNORM16); UNORM8Out = packUnorm4x8(FP32); SNORM8Out = packSnorm4x8(FP32); + UNORM16Out = packUnorm2x16(FP32.xy); + SNORM16Out = packSnorm2x16(FP32.zw); } diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index bc6e7b4..ff9e998 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -1201,6 +1201,7 @@ void CompilerHLSL::emit_resources() statement(""); } + // HLSL does not seem to have builtins for these operation, so roll them by hand ... if (requires_unorm8_packing) { statement("uint SPIRV_Cross_packUnorm4x8(float4 value)"); @@ -1235,6 +1236,41 @@ void CompilerHLSL::emit_resources() end_scope(); statement(""); } + + if (requires_unorm16_packing) + { + statement("uint SPIRV_Cross_packUnorm2x16(float2 value)"); + begin_scope(); + statement("uint2 Packed = uint2(round(saturate(value) * 65535.0));"); + statement("return Packed.x | (Packed.y << 16);"); + end_scope(); + statement(""); + + statement("float2 SPIRV_Cross_unpackUnorm2x16(uint value)"); + begin_scope(); + statement("uint2 Packed = uint2(value & 0xffff, value >> 16);"); + statement("return float2(Packed) / 65535.0;"); + end_scope(); + statement(""); + } + + if (requires_snorm16_packing) + { + statement("uint SPIRV_Cross_packSnorm2x16(float2 value)"); + begin_scope(); + statement("int2 Packed = int2(round(clamp(value, -1.0, 1.0) * 32767.0)) & 0xffff;"); + statement("return uint(Packed.x | (Packed.y << 16));"); + end_scope(); + statement(""); + + statement("float2 SPIRV_Cross_unpackSnorm2x16(uint value)"); + begin_scope(); + statement("int SignedValue = int(value);"); + statement("int2 Packed = int2(SignedValue << 16, SignedValue) >> 16;"); + statement("return clamp(float2(Packed) / 32767.0, -1.0, 1.0);"); + end_scope(); + statement(""); + } } string CompilerHLSL::layout_for_member(const SPIRType &type, uint32_t index) @@ -2315,6 +2351,42 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop, emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackUnorm4x8"); break; + case GLSLstd450PackSnorm2x16: + if (!requires_snorm16_packing) + { + requires_snorm16_packing = true; + force_recompile = true; + } + emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_packSnorm2x16"); + break; + + case GLSLstd450UnpackSnorm2x16: + if (!requires_snorm16_packing) + { + requires_snorm16_packing = true; + force_recompile = true; + } + emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackSnorm2x16"); + break; + + case GLSLstd450PackUnorm2x16: + if (!requires_unorm16_packing) + { + requires_unorm16_packing = true; + force_recompile = true; + } + emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_packUnorm2x16"); + break; + + case GLSLstd450UnpackUnorm2x16: + if (!requires_unorm16_packing) + { + requires_unorm16_packing = true; + force_recompile = true; + } + emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackUnorm2x16"); + break; + default: CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count); break; diff --git a/spirv_hlsl.hpp b/spirv_hlsl.hpp index d402cbf..90df68c 100644 --- a/spirv_hlsl.hpp +++ b/spirv_hlsl.hpp @@ -119,6 +119,8 @@ private: bool requires_fp16_packing = false; bool requires_unorm8_packing = false; bool requires_snorm8_packing = false; + bool requires_unorm16_packing = false; + bool requires_snorm16_packing = false; uint64_t required_textureSizeVariants = 0; void require_texture_query_variant(const SPIRType &type);