From b22c069f7af3dc4ebf33632adc30bfa22296e5f1 Mon Sep 17 00:00:00 2001 From: LoopDawg Date: Wed, 6 Dec 2017 16:52:03 -0700 Subject: [PATCH] HLSL: add optional position.Y inversion Adds command line options: --invert-y --iy (synonyms) which invert position.Y on vertex shader output. Handles these cases: * Direct single variable return * Member of direct returned struct * Single variable output parameter * Member of struct output parameter API: // Enables position.Y output negation in vertex shader void TShader::setInvertY(bool invert); Fixes #1173 --- StandAlone/StandAlone.cpp | 8 + Test/baseResults/hlsl.y-negate-1.vert.out | 113 +++++++++++ Test/baseResults/hlsl.y-negate-2.vert.out | 121 ++++++++++++ Test/baseResults/hlsl.y-negate-3.vert.out | 177 ++++++++++++++++++ Test/hlsl.y-negate-1.vert | 9 + Test/hlsl.y-negate-2.vert | 8 + Test/hlsl.y-negate-3.vert | 18 ++ Test/runtests | 11 ++ glslang/MachineIndependent/ShaderLang.cpp | 2 + .../MachineIndependent/localintermediate.h | 10 + glslang/Public/ShaderLang.h | 1 + hlsl/hlslParseHelper.cpp | 71 ++++++- hlsl/hlslParseHelper.h | 1 + 13 files changed, 549 insertions(+), 1 deletion(-) create mode 100644 Test/baseResults/hlsl.y-negate-1.vert.out create mode 100644 Test/baseResults/hlsl.y-negate-2.vert.out create mode 100644 Test/baseResults/hlsl.y-negate-3.vert.out create mode 100644 Test/hlsl.y-negate-1.vert create mode 100644 Test/hlsl.y-negate-2.vert create mode 100644 Test/hlsl.y-negate-3.vert diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index e7844eb21..6b09c8bda 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -98,6 +98,7 @@ enum TOptions { EOptionStdin = (1 << 27), EOptionOptimizeDisable = (1 << 28), EOptionOptimizeSize = (1 << 29), + EOptionInvertY = (1 << 30), }; // @@ -519,6 +520,9 @@ void ProcessArguments(std::vector>& workItem variableName = argv[1]; bumpArg(); break; + } else if (lowerword == "invert-y" || // synonyms + lowerword == "iy") { + Options |= EOptionInvertY; } else { usage(); } @@ -840,6 +844,9 @@ void CompileAndLinkShaderUnits(std::vector compUnits) if (Options & EOptionAutoMapLocations) shader->setAutoMapLocations(true); + if (Options & EOptionInvertY) + shader->setInvertY(true); + // Set up the environment, some subsettings take precedence over earlier // ways of setting things. if (Options & EOptionSpv) { @@ -1359,6 +1366,7 @@ void usage() " uint32_t array named \n" " initialized with the shader binary code.\n" " --vn synonym for --variable-name \n" + " --invert-y | --iy invert position.Y output in vertex shader\n" ); exit(EFailUsage); diff --git a/Test/baseResults/hlsl.y-negate-1.vert.out b/Test/baseResults/hlsl.y-negate-1.vert.out new file mode 100644 index 000000000..332339eb1 --- /dev/null +++ b/Test/baseResults/hlsl.y-negate-1.vert.out @@ -0,0 +1,113 @@ +hlsl.y-negate-1.vert +Shader version: 500 +0:? Sequence +0:7 Function Definition: @main( ( temp 4-component vector of float) +0:7 Function Parameters: +0:? Sequence +0:8 Branch: Return with expression +0:8 pos: direct index for structure ( uniform 4-component vector of float) +0:8 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float pos}) +0:8 Constant: +0:8 0 (const uint) +0:7 Function Definition: main( ( temp void) +0:7 Function Parameters: +0:? Sequence +0:7 Sequence +0:7 move second child to first child ( temp 4-component vector of float) +0:7 '@position' ( temp 4-component vector of float) +0:7 Function Call: @main( ( temp 4-component vector of float) +0:7 move second child to first child ( temp float) +0:7 direct index ( temp float) +0:7 '@position' ( temp 4-component vector of float) +0:7 Constant: +0:7 1 (const int) +0:7 Negate value ( temp float) +0:7 direct index ( temp float) +0:7 '@position' ( temp 4-component vector of float) +0:7 Constant: +0:7 1 (const int) +0:7 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' ( out 4-component vector of float Position) +0:7 '@position' ( temp 4-component vector of float) +0:? Linker Objects +0:? 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float pos}) +0:? '@entryPointOutput' ( out 4-component vector of float Position) + + +Linked vertex stage: + + +Shader version: 500 +0:? Sequence +0:7 Function Definition: @main( ( temp 4-component vector of float) +0:7 Function Parameters: +0:? Sequence +0:8 Branch: Return with expression +0:8 pos: direct index for structure ( uniform 4-component vector of float) +0:8 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float pos}) +0:8 Constant: +0:8 0 (const uint) +0:7 Function Definition: main( ( temp void) +0:7 Function Parameters: +0:? Sequence +0:7 Sequence +0:7 move second child to first child ( temp 4-component vector of float) +0:7 '@position' ( temp 4-component vector of float) +0:7 Function Call: @main( ( temp 4-component vector of float) +0:7 move second child to first child ( temp float) +0:7 direct index ( temp float) +0:7 '@position' ( temp 4-component vector of float) +0:7 Constant: +0:7 1 (const int) +0:7 Negate value ( temp float) +0:7 direct index ( temp float) +0:7 '@position' ( temp 4-component vector of float) +0:7 Constant: +0:7 1 (const int) +0:7 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput' ( out 4-component vector of float Position) +0:7 '@position' ( temp 4-component vector of float) +0:? Linker Objects +0:? 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float pos}) +0:? '@entryPointOutput' ( out 4-component vector of float Position) + +// Module Version 10000 +// Generated by (magic number): 80002 +// Id's are bound by 41 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 32 + Source HLSL 500 + Name 4 "main" + Name 11 "$Global" + MemberName 11($Global) 0 "pos" + Name 13 "" + Name 32 "@entryPointOutput" + MemberDecorate 11($Global) 0 Offset 0 + Decorate 11($Global) Block + Decorate 13 DescriptorSet 0 + Decorate 32(@entryPointOutput) BuiltIn Position + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 11($Global): TypeStruct 7(fvec4) + 12: TypePointer Uniform 11($Global) + 13: 12(ptr) Variable Uniform + 14: TypeInt 32 1 + 15: 14(int) Constant 0 + 16: TypePointer Uniform 7(fvec4) + 31: TypePointer Output 7(fvec4) +32(@entryPointOutput): 31(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 35: 16(ptr) AccessChain 13 15 + 36: 7(fvec4) Load 35 + 38: 6(float) CompositeExtract 36 1 + 29: 6(float) FNegate 38 + 40: 7(fvec4) CompositeInsert 29 36 1 + Store 32(@entryPointOutput) 40 + Return + FunctionEnd diff --git a/Test/baseResults/hlsl.y-negate-2.vert.out b/Test/baseResults/hlsl.y-negate-2.vert.out new file mode 100644 index 000000000..57f8e01a4 --- /dev/null +++ b/Test/baseResults/hlsl.y-negate-2.vert.out @@ -0,0 +1,121 @@ +hlsl.y-negate-2.vert +Shader version: 500 +0:? Sequence +0:6 Function Definition: @main(vf4; ( temp void) +0:6 Function Parameters: +0:6 'position' ( out 4-component vector of float) +0:? Sequence +0:7 move second child to first child ( temp 4-component vector of float) +0:7 'position' ( out 4-component vector of float) +0:7 pos: direct index for structure ( uniform 4-component vector of float) +0:7 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float pos}) +0:7 Constant: +0:7 0 (const uint) +0:6 Function Definition: main( ( temp void) +0:6 Function Parameters: +0:? Sequence +0:6 Function Call: @main(vf4; ( temp void) +0:? 'position' ( temp 4-component vector of float) +0:6 Sequence +0:6 move second child to first child ( temp 4-component vector of float) +0:6 '@position' ( temp 4-component vector of float) +0:? 'position' ( temp 4-component vector of float) +0:6 move second child to first child ( temp float) +0:6 direct index ( temp float) +0:6 '@position' ( temp 4-component vector of float) +0:6 Constant: +0:6 1 (const int) +0:6 Negate value ( temp float) +0:6 direct index ( temp float) +0:6 '@position' ( temp 4-component vector of float) +0:6 Constant: +0:6 1 (const int) +0:6 move second child to first child ( temp 4-component vector of float) +0:? 'position' ( out 4-component vector of float Position) +0:6 '@position' ( temp 4-component vector of float) +0:? Linker Objects +0:? 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float pos}) +0:? 'position' ( out 4-component vector of float Position) + + +Linked vertex stage: + + +Shader version: 500 +0:? Sequence +0:6 Function Definition: @main(vf4; ( temp void) +0:6 Function Parameters: +0:6 'position' ( out 4-component vector of float) +0:? Sequence +0:7 move second child to first child ( temp 4-component vector of float) +0:7 'position' ( out 4-component vector of float) +0:7 pos: direct index for structure ( uniform 4-component vector of float) +0:7 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float pos}) +0:7 Constant: +0:7 0 (const uint) +0:6 Function Definition: main( ( temp void) +0:6 Function Parameters: +0:? Sequence +0:6 Function Call: @main(vf4; ( temp void) +0:? 'position' ( temp 4-component vector of float) +0:6 Sequence +0:6 move second child to first child ( temp 4-component vector of float) +0:6 '@position' ( temp 4-component vector of float) +0:? 'position' ( temp 4-component vector of float) +0:6 move second child to first child ( temp float) +0:6 direct index ( temp float) +0:6 '@position' ( temp 4-component vector of float) +0:6 Constant: +0:6 1 (const int) +0:6 Negate value ( temp float) +0:6 direct index ( temp float) +0:6 '@position' ( temp 4-component vector of float) +0:6 Constant: +0:6 1 (const int) +0:6 move second child to first child ( temp 4-component vector of float) +0:? 'position' ( out 4-component vector of float Position) +0:6 '@position' ( temp 4-component vector of float) +0:? Linker Objects +0:? 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float pos}) +0:? 'position' ( out 4-component vector of float Position) + +// Module Version 10000 +// Generated by (magic number): 80002 +// Id's are bound by 43 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 35 + Source HLSL 500 + Name 4 "main" + Name 13 "$Global" + MemberName 13($Global) 0 "pos" + Name 15 "" + Name 35 "position" + MemberDecorate 13($Global) 0 Offset 0 + Decorate 13($Global) Block + Decorate 15 DescriptorSet 0 + Decorate 35(position) BuiltIn Position + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 13($Global): TypeStruct 7(fvec4) + 14: TypePointer Uniform 13($Global) + 15: 14(ptr) Variable Uniform + 16: TypeInt 32 1 + 17: 16(int) Constant 0 + 18: TypePointer Uniform 7(fvec4) + 34: TypePointer Output 7(fvec4) + 35(position): 34(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 37: 18(ptr) AccessChain 15 17 + 38: 7(fvec4) Load 37 + 40: 6(float) CompositeExtract 38 1 + 32: 6(float) FNegate 40 + 42: 7(fvec4) CompositeInsert 32 38 1 + Store 35(position) 42 + Return + FunctionEnd diff --git a/Test/baseResults/hlsl.y-negate-3.vert.out b/Test/baseResults/hlsl.y-negate-3.vert.out new file mode 100644 index 000000000..5983c2b79 --- /dev/null +++ b/Test/baseResults/hlsl.y-negate-3.vert.out @@ -0,0 +1,177 @@ +hlsl.y-negate-3.vert +Shader version: 500 +0:? Sequence +0:11 Function Definition: @main( ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Function Parameters: +0:? Sequence +0:14 move second child to first child ( temp 4-component vector of float) +0:14 pos: direct index for structure ( temp 4-component vector of float) +0:14 'vsout' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:14 Constant: +0:14 0 (const int) +0:14 position: direct index for structure ( uniform 4-component vector of float) +0:14 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float position}) +0:14 Constant: +0:14 0 (const uint) +0:15 move second child to first child ( temp int) +0:15 somethingelse: direct index for structure ( temp int) +0:15 'vsout' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:15 Constant: +0:15 1 (const int) +0:15 Constant: +0:15 42 (const int) +0:17 Branch: Return with expression +0:17 'vsout' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Function Definition: main( ( temp void) +0:11 Function Parameters: +0:? Sequence +0:11 Sequence +0:11 move second child to first child ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 'flattenTemp' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Function Call: @main( ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Sequence +0:11 move second child to first child ( temp 4-component vector of float) +0:11 '@position' ( temp 4-component vector of float) +0:11 pos: direct index for structure ( temp 4-component vector of float) +0:11 'flattenTemp' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Constant: +0:11 0 (const int) +0:11 move second child to first child ( temp float) +0:11 direct index ( temp float) +0:11 '@position' ( temp 4-component vector of float) +0:11 Constant: +0:11 1 (const int) +0:11 Negate value ( temp float) +0:11 direct index ( temp float) +0:11 '@position' ( temp 4-component vector of float) +0:11 Constant: +0:11 1 (const int) +0:11 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput.pos' ( out 4-component vector of float Position) +0:11 '@position' ( temp 4-component vector of float) +0:11 move second child to first child ( temp int) +0:? '@entryPointOutput.somethingelse' (layout( location=0) out int) +0:11 somethingelse: direct index for structure ( temp int) +0:11 'flattenTemp' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Constant: +0:11 1 (const int) +0:? Linker Objects +0:? 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float position}) +0:? '@entryPointOutput.pos' ( out 4-component vector of float Position) +0:? '@entryPointOutput.somethingelse' (layout( location=0) out int) + + +Linked vertex stage: + + +Shader version: 500 +0:? Sequence +0:11 Function Definition: @main( ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Function Parameters: +0:? Sequence +0:14 move second child to first child ( temp 4-component vector of float) +0:14 pos: direct index for structure ( temp 4-component vector of float) +0:14 'vsout' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:14 Constant: +0:14 0 (const int) +0:14 position: direct index for structure ( uniform 4-component vector of float) +0:14 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float position}) +0:14 Constant: +0:14 0 (const uint) +0:15 move second child to first child ( temp int) +0:15 somethingelse: direct index for structure ( temp int) +0:15 'vsout' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:15 Constant: +0:15 1 (const int) +0:15 Constant: +0:15 42 (const int) +0:17 Branch: Return with expression +0:17 'vsout' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Function Definition: main( ( temp void) +0:11 Function Parameters: +0:? Sequence +0:11 Sequence +0:11 move second child to first child ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 'flattenTemp' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Function Call: @main( ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Sequence +0:11 move second child to first child ( temp 4-component vector of float) +0:11 '@position' ( temp 4-component vector of float) +0:11 pos: direct index for structure ( temp 4-component vector of float) +0:11 'flattenTemp' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Constant: +0:11 0 (const int) +0:11 move second child to first child ( temp float) +0:11 direct index ( temp float) +0:11 '@position' ( temp 4-component vector of float) +0:11 Constant: +0:11 1 (const int) +0:11 Negate value ( temp float) +0:11 direct index ( temp float) +0:11 '@position' ( temp 4-component vector of float) +0:11 Constant: +0:11 1 (const int) +0:11 move second child to first child ( temp 4-component vector of float) +0:? '@entryPointOutput.pos' ( out 4-component vector of float Position) +0:11 '@position' ( temp 4-component vector of float) +0:11 move second child to first child ( temp int) +0:? '@entryPointOutput.somethingelse' (layout( location=0) out int) +0:11 somethingelse: direct index for structure ( temp int) +0:11 'flattenTemp' ( temp structure{ temp 4-component vector of float pos, temp int somethingelse}) +0:11 Constant: +0:11 1 (const int) +0:? Linker Objects +0:? 'anon@0' (layout( row_major std140) uniform block{ uniform 4-component vector of float position}) +0:? '@entryPointOutput.pos' ( out 4-component vector of float Position) +0:? '@entryPointOutput.somethingelse' (layout( location=0) out int) + +// Module Version 10000 +// Generated by (magic number): 80002 +// Id's are bound by 67 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 44 47 + Source HLSL 500 + Name 4 "main" + Name 9 "VS_OUT" + MemberName 9(VS_OUT) 0 "pos" + MemberName 9(VS_OUT) 1 "somethingelse" + Name 16 "$Global" + MemberName 16($Global) 0 "position" + Name 18 "" + Name 44 "@entryPointOutput.pos" + Name 47 "@entryPointOutput.somethingelse" + MemberDecorate 16($Global) 0 Offset 0 + Decorate 16($Global) Block + Decorate 18 DescriptorSet 0 + Decorate 44(@entryPointOutput.pos) BuiltIn Position + Decorate 47(@entryPointOutput.somethingelse) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypeInt 32 1 + 9(VS_OUT): TypeStruct 7(fvec4) 8(int) + 15: 8(int) Constant 0 + 16($Global): TypeStruct 7(fvec4) + 17: TypePointer Uniform 16($Global) + 18: 17(ptr) Variable Uniform + 19: TypePointer Uniform 7(fvec4) + 25: 8(int) Constant 42 + 43: TypePointer Output 7(fvec4) +44(@entryPointOutput.pos): 43(ptr) Variable Output + 46: TypePointer Output 8(int) +47(@entryPointOutput.somethingelse): 46(ptr) Variable Output + 4(main): 2 Function None 3 + 5: Label + 52: 19(ptr) AccessChain 18 15 + 53: 7(fvec4) Load 52 + 64: 6(float) CompositeExtract 53 1 + 41: 6(float) FNegate 64 + 66: 7(fvec4) CompositeInsert 41 53 1 + Store 44(@entryPointOutput.pos) 66 + Store 47(@entryPointOutput.somethingelse) 25 + Return + FunctionEnd diff --git a/Test/hlsl.y-negate-1.vert b/Test/hlsl.y-negate-1.vert new file mode 100644 index 000000000..ee62ec24b --- /dev/null +++ b/Test/hlsl.y-negate-1.vert @@ -0,0 +1,9 @@ + +// Test Y negation from entry point return + +float4 pos; + +float4 main() : SV_Position +{ + return pos; +} diff --git a/Test/hlsl.y-negate-2.vert b/Test/hlsl.y-negate-2.vert new file mode 100644 index 000000000..01fa6ce71 --- /dev/null +++ b/Test/hlsl.y-negate-2.vert @@ -0,0 +1,8 @@ +// Test Y negation from entry point out parameter + +float4 pos; + +void main(out float4 position : SV_Position) +{ + position = pos; +} diff --git a/Test/hlsl.y-negate-3.vert b/Test/hlsl.y-negate-3.vert new file mode 100644 index 000000000..a0c4a8d63 --- /dev/null +++ b/Test/hlsl.y-negate-3.vert @@ -0,0 +1,18 @@ +// Test Y negation from entry point out parameter + +float4 position; + +struct VS_OUT { + float4 pos : SV_Position; + int somethingelse; +}; + +VS_OUT main() +{ + VS_OUT vsout; + + vsout.pos = position; + vsout.somethingelse = 42; + + return vsout; +} diff --git a/Test/runtests b/Test/runtests index 814210ba4..3a5b17534 100755 --- a/Test/runtests +++ b/Test/runtests @@ -186,6 +186,17 @@ diff -b $BASEDIR/remap.invalid-spirv-1.out $TARGETDIR/remap.invalid-spirv-1.out $REMAPEXE --do-everything -i remap.invalid-spirv-2.spv -o $TARGETDIR > $TARGETDIR/remap.invalid-spirv-2.out && HASERROR=1 diff -b $BASEDIR/remap.invalid-spirv-2.out $TARGETDIR/remap.invalid-spirv-2.out || HASERROR=1 +# +# Testing position Y inversion +# +echo "Testing position Y inversion" +$EXE -H -e main -V -D -H -i --iy hlsl.y-negate-1.vert > $TARGETDIR/hlsl.y-negate-1.vert.out +diff -b $BASEDIR/hlsl.y-negate-1.vert.out $TARGETDIR/hlsl.y-negate-1.vert.out || HASERROR=1 +$EXE -H -e main -V -D -H -i --invert-y hlsl.y-negate-2.vert > $TARGETDIR/hlsl.y-negate-2.vert.out +diff -b $BASEDIR/hlsl.y-negate-2.vert.out $TARGETDIR/hlsl.y-negate-2.vert.out || HASERROR=1 +$EXE -H -e main -V -D -H -i --invert-y hlsl.y-negate-3.vert > $TARGETDIR/hlsl.y-negate-3.vert.out +diff -b $BASEDIR/hlsl.y-negate-3.vert.out $TARGETDIR/hlsl.y-negate-3.vert.out || HASERROR=1 + # # Final checking # diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 62e079e55..c92d02391 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -1686,6 +1686,8 @@ void TShader::setShiftUavBinding(unsigned int base) { setShiftBinding(EResUa void TShader::setShiftSsboBinding(unsigned int base) { setShiftBinding(EResSsbo, base); } // Enables binding automapping using TIoMapper void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); } +// Enables position.Y output negation in vertex shader +void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); } // Fragile: currently within one stage: simple auto-assignment of location void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); } // See comment above TDefaultHlslIoMapper in iomapper.cpp: diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 062eb1b08..866517696 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -224,6 +224,7 @@ public: #endif autoMapBindings(false), autoMapLocations(false), + invertY(false), flattenUniformArrays(false), useUnknownFormat(false), hlslOffsets(false), @@ -317,6 +318,14 @@ public: processes.addProcess("auto-map-locations"); } bool getAutoMapLocations() const { return autoMapLocations; } + void setInvertY(bool invert) + { + invertY = invert; + if (invertY) + processes.addProcess("invert-y"); + } + bool getInvertY() const { return invertY; } + void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; @@ -682,6 +691,7 @@ protected: std::vector resourceSetBinding; bool autoMapBindings; bool autoMapLocations; + bool invertY; bool flattenUniformArrays; bool useUnknownFormat; bool hlslOffsets; diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 6e22bdd72..35d846362 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -371,6 +371,7 @@ public: void setResourceSetBinding(const std::vector& base); void setAutoMapBindings(bool map); void setAutoMapLocations(bool map); + void setInvertY(bool invert); void setHlslIoMapping(bool hlslIoMap); void setFlattenUniformArrays(bool flatten); void setNoStorageFormat(bool useUnknownFormat); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 7192747c4..d9f1c2980 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -2301,6 +2301,63 @@ void HlslParseContext::handleFunctionArgument(TFunction* function, arguments = newArg; } +// Position may require special handling: we can optionally invert Y. +// See: https://github.com/KhronosGroup/glslang/issues/1173 +// https://github.com/KhronosGroup/glslang/issues/494 +TIntermTyped* HlslParseContext::assignPosition(const TSourceLoc& loc, TOperator op, + TIntermTyped* left, TIntermTyped* right) +{ + // If we are not asked for Y inversion, use a plain old assign. + if (!intermediate.getInvertY()) + return intermediate.addAssign(op, left, right, loc); + + // If we get here, we should invert Y. + TIntermAggregate* assignList = nullptr; + + // If this is a complex rvalue, we don't want to dereference it many times. Create a temporary. + TVariable* rhsTempVar = nullptr; + rhsTempVar = makeInternalVariable("@position", right->getType()); + rhsTempVar->getWritableType().getQualifier().makeTemporary(); + + { + TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc); + assignList = intermediate.growAggregate(assignList, + intermediate.addAssign(EOpAssign, rhsTempSym, right, loc), loc); + } + + // pos.y = -pos.y + { + const int Y = 1; + + TIntermTyped* tempSymL = intermediate.addSymbol(*rhsTempVar, loc); + TIntermTyped* tempSymR = intermediate.addSymbol(*rhsTempVar, loc); + TIntermTyped* index = intermediate.addConstantUnion(Y, loc); + + TIntermTyped* lhsElement = intermediate.addIndex(EOpIndexDirect, tempSymL, index, loc); + TIntermTyped* rhsElement = intermediate.addIndex(EOpIndexDirect, tempSymR, index, loc); + + const TType derefType(right->getType(), 0); + + lhsElement->setType(derefType); + rhsElement->setType(derefType); + + TIntermTyped* yNeg = intermediate.addUnaryMath(EOpNegative, rhsElement, loc); + + assignList = intermediate.growAggregate(assignList, intermediate.addAssign(EOpAssign, lhsElement, yNeg, loc)); + } + + // Assign the rhs temp (now with Y inversion) to the final output + { + TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc); + assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, rhsTempSym, loc)); + } + + assert(assignList != nullptr); + assignList->setOperator(EOpSequence); + + return assignList; +} + // Clip and cull distance require special handling due to a semantic mismatch. In HLSL, // these can be float scalar, float vector, or arrays of float scalar or float vector. // In SPIR-V, they are arrays of scalar floats in all cases. We must copy individual components @@ -2566,6 +2623,12 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op wasSplit(binaryNode->getLeft()); }; + // Return true if this stage assigns clip position with potentially inverted Y + const auto assignsClipPos = [this](const TIntermTyped* node) -> bool { + return node->getType().getQualifier().builtIn == EbvPosition && + (language == EShLangVertex || language == EShLangGeometry || language == EShLangTessEvaluation); + }; + const bool isSplitLeft = wasSplit(left) || indexesSplit(left); const bool isSplitRight = wasSplit(right) || indexesSplit(right); @@ -2581,6 +2644,9 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op const int semanticId = (isOutput ? left : right)->getType().getQualifier().layoutLocation; return assignClipCullDistance(loc, op, semanticId, left, right); + } else if (assignsClipPos(left)) { + // Position can require special handling: see comment above assignPosition + return assignPosition(loc, op, left, right); } return intermediate.addAssign(op, left, right, loc); @@ -2792,7 +2858,10 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op subSplitLeft, subSplitRight); assignList = intermediate.growAggregate(assignList, clipCullAssign, loc); - + } else if (assignsClipPos(subSplitLeft)) { + // Position can require special handling: see comment above assignPosition + TIntermTyped* positionAssign = assignPosition(loc, op, subSplitLeft, subSplitRight); + assignList = intermediate.growAggregate(assignList, positionAssign, loc); } else if (!shouldFlattenSubsetLeft && !shouldFlattenSubsetRight && !typeL.containsBuiltIn() && !typeR.containsBuiltIn()) { // If this is the final flattening (no nested types below to flatten) diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index 67d192d47..a56fc2e41 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -93,6 +93,7 @@ public: TIntermTyped* handleAssignToMatrixSwizzle(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right); TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermTyped*); TIntermAggregate* assignClipCullDistance(const TSourceLoc&, TOperator, int semanticId, TIntermTyped* left, TIntermTyped* right); + TIntermTyped* assignPosition(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right); void decomposeIntrinsic(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); void decomposeStructBufferMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);