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
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index e7844eb..6b09c8b 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -98,6 +98,7 @@
     EOptionStdin                = (1 << 27),
     EOptionOptimizeDisable      = (1 << 28),
     EOptionOptimizeSize         = (1 << 29),
+    EOptionInvertY              = (1 << 30),
 };
 
 //
@@ -519,6 +520,9 @@
                         variableName = argv[1];
                         bumpArg();
                         break;
+                    } else if (lowerword == "invert-y" ||  // synonyms
+                               lowerword == "iy") {
+                        Options |= EOptionInvertY;
                     } else {
                         usage();
                     }
@@ -840,6 +844,9 @@
         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 @@
            "                                       uint32_t array named <name>\n"
            "                                       initialized with the shader binary code.\n"
            "  --vn <name>                          synonym for --variable-name <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 0000000..332339e
--- /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 0000000..57f8e01
--- /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 0000000..5983c2b
--- /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 0000000..ee62ec2
--- /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 0000000..01fa6ce
--- /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 0000000..a0c4a8d
--- /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 814210b..3a5b175 100755
--- a/Test/runtests
+++ b/Test/runtests
@@ -187,6 +187,17 @@
 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
 #
 if [ $HASERROR -eq 0 ]
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index 62e079e..c92d023 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -1686,6 +1686,8 @@
 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 062eb1b..8665176 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -224,6 +224,7 @@
 #endif
         autoMapBindings(false),
         autoMapLocations(false),
+        invertY(false),
         flattenUniformArrays(false),
         useUnknownFormat(false),
         hlslOffsets(false),
@@ -317,6 +318,14 @@
             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 @@
     std::vector<std::string> 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 6e22bdd..35d8463 100644
--- a/glslang/Public/ShaderLang.h
+++ b/glslang/Public/ShaderLang.h
@@ -371,6 +371,7 @@
     void setResourceSetBinding(const std::vector<std::string>& 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 7192747..d9f1c29 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -2301,6 +2301,63 @@
         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 @@
                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 @@
 
             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 @@
                                                                               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 67d192d..a56fc2e 100755
--- a/hlsl/hlslParseHelper.h
+++ b/hlsl/hlslParseHelper.h
@@ -93,6 +93,7 @@
     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);