Răsfoiți Sursa

Updated glslang.

Branimir Karadžić 8 ani în urmă
părinte
comite
4a3d221a2b
38 a modificat fișierele cu 1669 adăugiri și 195 ștergeri
  1. 30 9
      3rdparty/glslang/.travis.yml
  2. 13 1
      3rdparty/glslang/SPIRV/SPVRemapper.cpp
  3. 12 0
      3rdparty/glslang/StandAlone/StandAlone.cpp
  4. 112 0
      3rdparty/glslang/Test/baseResults/hlsl.fraggeom.frag.out
  5. 264 0
      3rdparty/glslang/Test/baseResults/hlsl.memberFunCall.frag.out
  6. 68 0
      3rdparty/glslang/Test/baseResults/hlsl.mip.negative.frag.out
  7. 74 0
      3rdparty/glslang/Test/baseResults/hlsl.mip.negative2.frag.out
  8. 209 0
      3rdparty/glslang/Test/baseResults/hlsl.mip.operator.frag.out
  9. 275 0
      3rdparty/glslang/Test/baseResults/hlsl.structbuffer.append.fn.frag.out
  10. 112 87
      3rdparty/glslang/Test/baseResults/hlsl.structbuffer.fn.frag.out
  11. 33 0
      3rdparty/glslang/Test/baseResults/remap.specconst.comp.out
  12. 1 0
      3rdparty/glslang/Test/baseResults/spv.glsl.register.autoassign.frag.out
  13. 1 0
      3rdparty/glslang/Test/baseResults/spv.glsl.register.noautoassign.frag.out
  14. 8 0
      3rdparty/glslang/Test/baseResults/spv.noLocation.vert.out
  15. 17 0
      3rdparty/glslang/Test/hlsl.fraggeom.frag
  16. 16 0
      3rdparty/glslang/Test/hlsl.memberFunCall.frag
  17. 9 0
      3rdparty/glslang/Test/hlsl.mip.negative.frag
  18. 9 0
      3rdparty/glslang/Test/hlsl.mip.negative2.frag
  19. 14 0
      3rdparty/glslang/Test/hlsl.mip.operator.frag
  20. 23 0
      3rdparty/glslang/Test/hlsl.structbuffer.append.fn.frag
  21. 7 0
      3rdparty/glslang/Test/remap.specconst.comp
  22. 8 1
      3rdparty/glslang/Test/runtests
  23. 14 0
      3rdparty/glslang/Test/spv.noLocation.vert
  24. 2 0
      3rdparty/glslang/glslang/Include/Types.h
  25. 15 0
      3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp
  26. 2 0
      3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp
  27. 17 5
      3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h
  28. 23 6
      3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp
  29. 1 1
      3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp
  30. 6 2
      3rdparty/glslang/glslang/MachineIndependent/localintermediate.h
  31. 1 0
      3rdparty/glslang/glslang/Public/ShaderLang.h
  32. 6 0
      3rdparty/glslang/gtests/Hlsl.FromFile.cpp
  33. 1 0
      3rdparty/glslang/gtests/Link.FromFile.Vk.cpp
  34. 1 0
      3rdparty/glslang/gtests/Remap.FromFile.cpp
  35. 4 0
      3rdparty/glslang/gtests/TestFixture.h
  36. 1 1
      3rdparty/glslang/hlsl/hlslGrammar.cpp
  37. 240 78
      3rdparty/glslang/hlsl/hlslParseHelper.cpp
  38. 20 4
      3rdparty/glslang/hlsl/hlslParseHelper.h

+ 30 - 9
3rdparty/glslang/.travis.yml

@@ -7,7 +7,7 @@ os:
   - osx
 
 # Use Ubuntu 14.04 LTS (Trusty) as the Linux testing environment.
-sudo: required
+sudo: false
 dist: trusty
 
 env:
@@ -24,6 +24,9 @@ matrix:
     # Skip GCC builds on Mac OS X.
     - os: osx
       compiler: gcc
+  include:
+    # Additional build using Android NDK.
+    - env: BUILD_NDK=ON
 
 cache:
   apt: true
@@ -41,20 +44,38 @@ addons:
 install:
   # Install ninja on Mac OS X.
   - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update && brew install ninja; fi
-  # Make sure that clang-3.6 is selected.
+  # Make sure that clang-3.6 is selected on Linux.
   - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CC" == "clang" ]]; then
       export CC=clang-3.6 CXX=clang++-3.6;
     fi
+  # Download Android NDK and Android CMake toolchain file.
+  - if [[ "$BUILD_NDK" == "ON" ]]; then
+      git clone --depth=1 https://github.com/urho3d/android-ndk.git $HOME/android-ndk;
+      export ANDROID_NDK=$HOME/android-ndk;
+      git clone --depth=1 https://github.com/taka-no-me/android-cmake.git $HOME/android-cmake;
+      export TOOLCHAIN_PATH=$HOME/android-cmake/android.toolchain.cmake;
+    fi
 
 before_script:
   - git clone https://github.com/google/googletest.git External/googletest
 
 script:
   - mkdir build && cd build
-  # We need to install the compiled binaries so the paths in the runtests script can resolve correctly.
-  - cmake -GNinja -DCMAKE_BUILD_TYPE=${GLSLANG_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=`pwd`/install ..
-  - ninja install
-  # Run Google-Test-based tests.
-  - ctest --output-on-failure
-  # Run runtests-based tests.
-  - cd ../Test && ./runtests
+  # For Android, do release building using NDK without testing.
+  # For Linux and macOS, do debug/release building with testing.
+  - if [[ "$BUILD_NDK" == "ON" ]]; then
+      cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_PATH}
+            -DANDROID_NATIVE_API_LEVEL=android-12
+            -DCMAKE_BUILD_TYPE=Release
+            -DANDROID_ABI="armeabi-v7a with NEON"
+            -DBUILD_TESTING=OFF
+            -GNinja ..;
+      ninja;
+    else
+      cmake -DCMAKE_BUILD_TYPE=${GLSLANG_BUILD_TYPE}
+            -DCMAKE_INSTALL_PREFIX=`pwd`/install
+            -GNinja ..;
+      ninja install;
+      ctest --output-on-failure &&
+      cd ../Test && ./runtests;
+    fi

+ 13 - 1
3rdparty/glslang/SPIRV/SPVRemapper.cpp

@@ -464,8 +464,8 @@ namespace spv {
     {
         const auto     instructionStart = word;
         const unsigned wordCount = asWordCount(instructionStart);
-        const spv::Op  opCode    = asOpCode(instructionStart);
         const int      nextInst  = word++ + wordCount;
+        spv::Op  opCode    = asOpCode(instructionStart);
 
         if (nextInst > int(spv.size()))
             error("spir instruction terminated too early");
@@ -506,6 +506,18 @@ namespace spv {
 
         // Store IDs from instruction in our map
         for (int op = 0; numOperands > 0; ++op, --numOperands) {
+            // SpecConstantOp is special: it includes the operands of another opcode which is
+            // given as a literal in the 3rd word.  We will switch over to pretending that the
+            // opcode being processed is the literal opcode value of the SpecConstantOp.  See the
+            // SPIRV spec for details.  This way we will handle IDs and literals as appropriate for
+            // the embedded op.
+            if (opCode == spv::OpSpecConstantOp) {
+                if (op == 0) {
+                    opCode = asOpCode(word++);  // this is the opcode embedded in the SpecConstantOp.
+                    --numOperands;
+                }
+            }
+
             switch (spv::InstructionDesc[opCode].operands.getClass(op)) {
             case spv::OperandId:
             case spv::OperandScope:

+ 12 - 0
3rdparty/glslang/StandAlone/StandAlone.cpp

@@ -90,6 +90,7 @@ enum TOptions {
     EOptionKeepUncalled         = (1 << 22),
     EOptionHlslOffsets          = (1 << 23),
     EOptionHlslIoMapping        = (1 << 24),
+    EOptionAutoMapLocations     = (1 << 25),
 };
 
 //
@@ -386,6 +387,9 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
                                lowerword == "hlsl-iomapper" ||
                                lowerword == "hlsl-iomapping") {
                         Options |= EOptionHlslIoMapping;
+                    } else if (lowerword == "auto-map-locations" || // synonyms
+                               lowerword == "aml") {
+                        Options |= EOptionAutoMapLocations;
                     } else {
                         usage();
                     }
@@ -648,6 +652,9 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
         if (Options & EOptionAutoMapBindings)
             shader->setAutoMapBindings(true);
 
+        if (Options & EOptionAutoMapLocations)
+            shader->setAutoMapLocations(true);
+
         shaders.push_back(shader);
 
         const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100;
@@ -1063,6 +1070,11 @@ void usage()
            "                                          explicit bindings.\n"
            "  --amb                                   synonym for --auto-map-bindings\n"
            "\n"
+           "  --auto-map-locations                    automatically locate input/output lacking 'location'\n"
+           "                                          (fragile, not cross stage: recommend explicit\n"
+           "                                          'location' use in shader)\n"
+           "  --aml                                   synonym for --auto-map-locations\n"
+           "\n"
            "  --flatten-uniform-arrays                flatten uniform texture & sampler arrays to scalars\n"
            "  --fua                                   synonym for --flatten-uniform-arrays\n"
            "\n"

+ 112 - 0
3rdparty/glslang/Test/baseResults/hlsl.fraggeom.frag.out

@@ -0,0 +1,112 @@
+hlsl.fraggeom.frag
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:9  Function Definition: GS_Draw(struct-myVertex-vf41;struct-myVertex-vf41; ( temp void)
+0:9    Function Parameters: 
+0:9      'IN' ( in structure{ temp 4-component vector of float pos})
+0:9      'OutputStream' ( out structure{ temp 4-component vector of float pos})
+0:?     Sequence
+0:10      Constant:
+0:10        0.000000
+0:11      Constant:
+0:11        0.000000
+0:15  Function Definition: @main( ( temp 4-component vector of float)
+0:15    Function Parameters: 
+0:?     Sequence
+0:16      Branch: Return with expression
+0:16        Constant:
+0:16          0.000000
+0:16          0.000000
+0:16          0.000000
+0:16          0.000000
+0:15  Function Definition: main( ( temp void)
+0:15    Function Parameters: 
+0:?     Sequence
+0:15      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:15        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:9  Function Definition: GS_Draw(struct-myVertex-vf41;struct-myVertex-vf41; ( temp void)
+0:9    Function Parameters: 
+0:9      'IN' ( in structure{ temp 4-component vector of float pos})
+0:9      'OutputStream' ( out structure{ temp 4-component vector of float pos})
+0:?     Sequence
+0:10      Constant:
+0:10        0.000000
+0:11      Constant:
+0:11        0.000000
+0:15  Function Definition: @main( ( temp 4-component vector of float)
+0:15    Function Parameters: 
+0:?     Sequence
+0:16      Branch: Return with expression
+0:16        Constant:
+0:16          0.000000
+0:16          0.000000
+0:16          0.000000
+0:16          0.000000
+0:15  Function Definition: main( ( temp void)
+0:15    Function Parameters: 
+0:?     Sequence
+0:15      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:15        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 25
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 23
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 500
+                              Name 4  "main"
+                              Name 8  "myVertex"
+                              MemberName 8(myVertex) 0  "pos"
+                              Name 13  "GS_Draw(struct-myVertex-vf41;struct-myVertex-vf41;"
+                              Name 11  "IN"
+                              Name 12  "OutputStream"
+                              Name 16  "@main("
+                              Name 23  "@entryPointOutput"
+                              Decorate 23(@entryPointOutput) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+     8(myVertex):             TypeStruct 7(fvec4)
+               9:             TypePointer Function 8(myVertex)
+              10:             TypeFunction 2 9(ptr) 9(ptr)
+              15:             TypeFunction 7(fvec4)
+              18:    6(float) Constant 0
+              19:    7(fvec4) ConstantComposite 18 18 18 18
+              22:             TypePointer Output 7(fvec4)
+23(@entryPointOutput):     22(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+              24:    7(fvec4) FunctionCall 16(@main()
+                              Store 23(@entryPointOutput) 24
+                              Return
+                              FunctionEnd
+13(GS_Draw(struct-myVertex-vf41;struct-myVertex-vf41;):           2 Function None 10
+          11(IN):      9(ptr) FunctionParameter
+12(OutputStream):      9(ptr) FunctionParameter
+              14:             Label
+                              Return
+                              FunctionEnd
+      16(@main():    7(fvec4) Function None 15
+              17:             Label
+                              ReturnValue 19
+                              FunctionEnd

+ 264 - 0
3rdparty/glslang/Test/baseResults/hlsl.memberFunCall.frag.out

@@ -0,0 +1,264 @@
+hlsl.memberFunCall.frag
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:1  Function Definition: method3(f1; ( temp float)
+0:1    Function Parameters: 
+0:1      'a' ( in float)
+0:?     Sequence
+0:1      Branch: Return with expression
+0:1        Constant:
+0:1          1.000000
+0:4  Function Definition: myContext::method1( ( temp float)
+0:4    Function Parameters: 
+0:4      '@this' ( temp structure{ temp float f})
+0:?     Sequence
+0:4      Branch: Return with expression
+0:4        Function Call: myContext::method2( ( temp float)
+0:?           '@this' ( temp structure{ temp float f})
+0:5  Function Definition: myContext::method2( ( temp float)
+0:5    Function Parameters: 
+0:5      '@this' ( temp structure{ temp float f})
+0:?     Sequence
+0:5      Branch: Return with expression
+0:5        Function Call: myContext::method3(f1; ( temp float)
+0:?           '@this' ( temp structure{ temp float f})
+0:5          Constant:
+0:5            1.000000
+0:6  Function Definition: myContext::method3(f1; ( temp float)
+0:6    Function Parameters: 
+0:6      '@this' ( temp structure{ temp float f})
+0:6      'a' ( in float)
+0:?     Sequence
+0:6      Branch: Return with expression
+0:6        Function Call: myContext::method4(f1;f1; ( temp float)
+0:?           '@this' ( temp structure{ temp float f})
+0:6          'a' ( in float)
+0:6          'a' ( in float)
+0:7  Function Definition: myContext::method4(f1;f1; ( temp float)
+0:7    Function Parameters: 
+0:7      '@this' ( temp structure{ temp float f})
+0:7      'a' ( in float)
+0:7      'b' ( in float)
+0:?     Sequence
+0:7      Branch: Return with expression
+0:7        add ( temp float)
+0:7          add ( temp float)
+0:7            'a' ( in float)
+0:7            'b' ( in float)
+0:7          f: direct index for structure ( temp float)
+0:7            '@this' ( temp structure{ temp float f})
+0:7            Constant:
+0:7              0 (const uint)
+0:12  Function Definition: @main( ( temp 4-component vector of float)
+0:12    Function Parameters: 
+0:?     Sequence
+0:14      move second child to first child ( temp float)
+0:14        f: direct index for structure ( temp float)
+0:14          'context' ( temp structure{ temp float f})
+0:14          Constant:
+0:14            0 (const int)
+0:14        Constant:
+0:14          3.000000
+0:15      Branch: Return with expression
+0:15        Construct vec4 ( temp 4-component vector of float)
+0:15          Function Call: myContext::method1( ( temp float)
+0:15            'context' ( temp structure{ temp float f})
+0:12  Function Definition: main( ( temp void)
+0:12    Function Parameters: 
+0:?     Sequence
+0:12      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:12        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:1  Function Definition: method3(f1; ( temp float)
+0:1    Function Parameters: 
+0:1      'a' ( in float)
+0:?     Sequence
+0:1      Branch: Return with expression
+0:1        Constant:
+0:1          1.000000
+0:4  Function Definition: myContext::method1( ( temp float)
+0:4    Function Parameters: 
+0:4      '@this' ( temp structure{ temp float f})
+0:?     Sequence
+0:4      Branch: Return with expression
+0:4        Function Call: myContext::method2( ( temp float)
+0:?           '@this' ( temp structure{ temp float f})
+0:5  Function Definition: myContext::method2( ( temp float)
+0:5    Function Parameters: 
+0:5      '@this' ( temp structure{ temp float f})
+0:?     Sequence
+0:5      Branch: Return with expression
+0:5        Function Call: myContext::method3(f1; ( temp float)
+0:?           '@this' ( temp structure{ temp float f})
+0:5          Constant:
+0:5            1.000000
+0:6  Function Definition: myContext::method3(f1; ( temp float)
+0:6    Function Parameters: 
+0:6      '@this' ( temp structure{ temp float f})
+0:6      'a' ( in float)
+0:?     Sequence
+0:6      Branch: Return with expression
+0:6        Function Call: myContext::method4(f1;f1; ( temp float)
+0:?           '@this' ( temp structure{ temp float f})
+0:6          'a' ( in float)
+0:6          'a' ( in float)
+0:7  Function Definition: myContext::method4(f1;f1; ( temp float)
+0:7    Function Parameters: 
+0:7      '@this' ( temp structure{ temp float f})
+0:7      'a' ( in float)
+0:7      'b' ( in float)
+0:?     Sequence
+0:7      Branch: Return with expression
+0:7        add ( temp float)
+0:7          add ( temp float)
+0:7            'a' ( in float)
+0:7            'b' ( in float)
+0:7          f: direct index for structure ( temp float)
+0:7            '@this' ( temp structure{ temp float f})
+0:7            Constant:
+0:7              0 (const uint)
+0:12  Function Definition: @main( ( temp 4-component vector of float)
+0:12    Function Parameters: 
+0:?     Sequence
+0:14      move second child to first child ( temp float)
+0:14        f: direct index for structure ( temp float)
+0:14          'context' ( temp structure{ temp float f})
+0:14          Constant:
+0:14            0 (const int)
+0:14        Constant:
+0:14          3.000000
+0:15      Branch: Return with expression
+0:15        Construct vec4 ( temp 4-component vector of float)
+0:15          Function Call: myContext::method1( ( temp float)
+0:15            'context' ( temp structure{ temp float f})
+0:12  Function Definition: main( ( temp void)
+0:12    Function Parameters: 
+0:?     Sequence
+0:12      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:12        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 73
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 71
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 500
+                              Name 4  "main"
+                              Name 10  "method3(f1;"
+                              Name 9  "a"
+                              Name 12  "myContext"
+                              MemberName 12(myContext) 0  "f"
+                              Name 16  "myContext::method1("
+                              Name 15  "@this"
+                              Name 19  "myContext::method2("
+                              Name 18  "@this"
+                              Name 24  "myContext::method3(f1;"
+                              Name 22  "@this"
+                              Name 23  "a"
+                              Name 30  "myContext::method4(f1;f1;"
+                              Name 27  "@this"
+                              Name 28  "a"
+                              Name 29  "b"
+                              Name 34  "@main("
+                              Name 42  "param"
+                              Name 46  "param"
+                              Name 48  "param"
+                              Name 63  "context"
+                              Name 71  "@entryPointOutput"
+                              Decorate 71(@entryPointOutput) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypePointer Function 6(float)
+               8:             TypeFunction 6(float) 7(ptr)
+   12(myContext):             TypeStruct 6(float)
+              13:             TypePointer Function 12(myContext)
+              14:             TypeFunction 6(float) 13(ptr)
+              21:             TypeFunction 6(float) 13(ptr) 7(ptr)
+              26:             TypeFunction 6(float) 13(ptr) 7(ptr) 7(ptr)
+              32:             TypeVector 6(float) 4
+              33:             TypeFunction 32(fvec4)
+              36:    6(float) Constant 1065353216
+              56:             TypeInt 32 1
+              57:     56(int) Constant 0
+              64:    6(float) Constant 1077936128
+              70:             TypePointer Output 32(fvec4)
+71(@entryPointOutput):     70(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+              72:   32(fvec4) FunctionCall 34(@main()
+                              Store 71(@entryPointOutput) 72
+                              Return
+                              FunctionEnd
+ 10(method3(f1;):    6(float) Function None 8
+            9(a):      7(ptr) FunctionParameter
+              11:             Label
+                              ReturnValue 36
+                              FunctionEnd
+16(myContext::method1():    6(float) Function None 14
+       15(@this):     13(ptr) FunctionParameter
+              17:             Label
+              39:    6(float) FunctionCall 19(myContext::method2() 15(@this)
+                              ReturnValue 39
+                              FunctionEnd
+19(myContext::method2():    6(float) Function None 14
+       18(@this):     13(ptr) FunctionParameter
+              20:             Label
+       42(param):      7(ptr) Variable Function
+                              Store 42(param) 36
+              43:    6(float) FunctionCall 24(myContext::method3(f1;) 18(@this) 42(param)
+                              ReturnValue 43
+                              FunctionEnd
+24(myContext::method3(f1;):    6(float) Function None 21
+       22(@this):     13(ptr) FunctionParameter
+           23(a):      7(ptr) FunctionParameter
+              25:             Label
+       46(param):      7(ptr) Variable Function
+       48(param):      7(ptr) Variable Function
+              47:    6(float) Load 23(a)
+                              Store 46(param) 47
+              49:    6(float) Load 23(a)
+                              Store 48(param) 49
+              50:    6(float) FunctionCall 30(myContext::method4(f1;f1;) 22(@this) 46(param) 48(param)
+                              ReturnValue 50
+                              FunctionEnd
+30(myContext::method4(f1;f1;):    6(float) Function None 26
+       27(@this):     13(ptr) FunctionParameter
+           28(a):      7(ptr) FunctionParameter
+           29(b):      7(ptr) FunctionParameter
+              31:             Label
+              53:    6(float) Load 28(a)
+              54:    6(float) Load 29(b)
+              55:    6(float) FAdd 53 54
+              58:      7(ptr) AccessChain 27(@this) 57
+              59:    6(float) Load 58
+              60:    6(float) FAdd 55 59
+                              ReturnValue 60
+                              FunctionEnd
+      34(@main():   32(fvec4) Function None 33
+              35:             Label
+     63(context):     13(ptr) Variable Function
+              65:      7(ptr) AccessChain 63(context) 57
+                              Store 65 64
+              66:    6(float) FunctionCall 16(myContext::method1() 63(context)
+              67:   32(fvec4) CompositeConstruct 66 66 66 66
+                              ReturnValue 67
+                              FunctionEnd

+ 68 - 0
3rdparty/glslang/Test/baseResults/hlsl.mip.negative.frag.out

@@ -0,0 +1,68 @@
+hlsl.mip.negative.frag
+ERROR: 0:5: '' : unterminated mips operator: 
+ERROR: 1 compilation errors.  No code generated.
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+ERROR: node is still EOpNull!
+0:4  Function Definition: @main( ( temp 4-component vector of float)
+0:4    Function Parameters: 
+0:?     Sequence
+0:?       textureFetch ( temp 4-component vector of float)
+0:5        'g_tTex2df4' ( uniform texture2D)
+0:?         Constant:
+0:?           3 (const uint)
+0:?           4 (const uint)
+0:5        Constant:
+0:5          2 (const int)
+0:7      Branch: Return with expression
+0:7        Constant:
+0:7          0.000000
+0:7          0.000000
+0:7          0.000000
+0:7          0.000000
+0:4  Function Definition: main( ( temp void)
+0:4    Function Parameters: 
+0:?     Sequence
+0:4      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:4        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'g_tTex2df4' ( uniform texture2D)
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+ERROR: node is still EOpNull!
+0:4  Function Definition: @main( ( temp 4-component vector of float)
+0:4    Function Parameters: 
+0:?     Sequence
+0:?       textureFetch ( temp 4-component vector of float)
+0:5        'g_tTex2df4' ( uniform texture2D)
+0:?         Constant:
+0:?           3 (const uint)
+0:?           4 (const uint)
+0:5        Constant:
+0:5          2 (const int)
+0:7      Branch: Return with expression
+0:7        Constant:
+0:7          0.000000
+0:7          0.000000
+0:7          0.000000
+0:7          0.000000
+0:4  Function Definition: main( ( temp void)
+0:4    Function Parameters: 
+0:?     Sequence
+0:4      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:4        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'g_tTex2df4' ( uniform texture2D)
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+SPIR-V is not generated for failed compile or link

+ 74 - 0
3rdparty/glslang/Test/baseResults/hlsl.mip.negative2.frag.out

@@ -0,0 +1,74 @@
+hlsl.mip.negative2.frag
+ERROR: 0:5: 'r' : unexpected operator on texture type:  uniform texture2D
+ERROR: 1 compilation errors.  No code generated.
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+ERROR: node is still EOpNull!
+0:4  Function Definition: @main( ( temp 4-component vector of float)
+0:4    Function Parameters: 
+0:?     Sequence
+0:5      direct index ( temp float)
+0:5        textureFetch ( temp 4-component vector of float)
+0:5          'g_tTex2df4' ( uniform texture2D)
+0:5          Constant:
+0:5            2 (const int)
+0:5          Constant:
+0:5            0 (const int)
+0:?         Constant:
+0:?           3 (const uint)
+0:?           4 (const uint)
+0:7      Branch: Return with expression
+0:7        Constant:
+0:7          0.000000
+0:7          0.000000
+0:7          0.000000
+0:7          0.000000
+0:4  Function Definition: main( ( temp void)
+0:4    Function Parameters: 
+0:?     Sequence
+0:4      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:4        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'g_tTex2df4' ( uniform texture2D)
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+ERROR: node is still EOpNull!
+0:4  Function Definition: @main( ( temp 4-component vector of float)
+0:4    Function Parameters: 
+0:?     Sequence
+0:5      direct index ( temp float)
+0:5        textureFetch ( temp 4-component vector of float)
+0:5          'g_tTex2df4' ( uniform texture2D)
+0:5          Constant:
+0:5            2 (const int)
+0:5          Constant:
+0:5            0 (const int)
+0:?         Constant:
+0:?           3 (const uint)
+0:?           4 (const uint)
+0:7      Branch: Return with expression
+0:7        Constant:
+0:7          0.000000
+0:7          0.000000
+0:7          0.000000
+0:7          0.000000
+0:4  Function Definition: main( ( temp void)
+0:4    Function Parameters: 
+0:?     Sequence
+0:4      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:4        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'g_tTex2df4' ( uniform texture2D)
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+SPIR-V is not generated for failed compile or link

+ 209 - 0
3rdparty/glslang/Test/baseResults/hlsl.mip.operator.frag.out

@@ -0,0 +1,209 @@
+hlsl.mip.operator.frag
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:5  Function Definition: @main( ( temp 4-component vector of float)
+0:5    Function Parameters: 
+0:?     Sequence
+0:13      Branch: Return with expression
+0:9        add ( temp 4-component vector of float)
+0:6          add ( temp 4-component vector of float)
+0:?             textureFetch ( temp 4-component vector of float)
+0:6              'g_tTex2df4' ( uniform texture2D)
+0:?               Constant:
+0:?                 3 (const uint)
+0:?                 4 (const uint)
+0:6              Constant:
+0:6                2 (const int)
+0:?             textureFetch ( temp 4-component vector of float)
+0:9              'g_tTex2df4a' ( uniform texture2DArray)
+0:?               Constant:
+0:?                 6 (const uint)
+0:?                 7 (const uint)
+0:?                 8 (const uint)
+0:9              Constant:
+0:9                5 (const uint)
+0:13          textureFetch ( temp 4-component vector of float)
+0:13            'g_tTex2df4' ( uniform texture2D)
+0:13            Convert float to uint ( temp 2-component vector of uint)
+0:13              vector swizzle ( temp 2-component vector of float)
+0:?                 textureFetch ( temp 4-component vector of float)
+0:13                  'g_tTex2df4' ( uniform texture2D)
+0:?                   Constant:
+0:?                     14 (const uint)
+0:?                     15 (const uint)
+0:13                  Constant:
+0:13                    13 (const int)
+0:13                Sequence
+0:13                  Constant:
+0:13                    0 (const int)
+0:13                  Constant:
+0:13                    1 (const int)
+0:13            Convert float to uint ( temp uint)
+0:13              direct index ( temp float)
+0:?                 textureFetch ( temp 4-component vector of float)
+0:13                  'g_tTex2df4' ( uniform texture2D)
+0:?                   Constant:
+0:?                     10 (const uint)
+0:?                     11 (const uint)
+0:13                  Constant:
+0:13                    9 (const int)
+0:13                Constant:
+0:13                  0 (const int)
+0:5  Function Definition: main( ( temp void)
+0:5    Function Parameters: 
+0:?     Sequence
+0:5      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:5        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'g_tTex2df4a' ( uniform texture2DArray)
+0:?     'g_tTex2df4' ( uniform texture2D)
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:5  Function Definition: @main( ( temp 4-component vector of float)
+0:5    Function Parameters: 
+0:?     Sequence
+0:13      Branch: Return with expression
+0:9        add ( temp 4-component vector of float)
+0:6          add ( temp 4-component vector of float)
+0:?             textureFetch ( temp 4-component vector of float)
+0:6              'g_tTex2df4' ( uniform texture2D)
+0:?               Constant:
+0:?                 3 (const uint)
+0:?                 4 (const uint)
+0:6              Constant:
+0:6                2 (const int)
+0:?             textureFetch ( temp 4-component vector of float)
+0:9              'g_tTex2df4a' ( uniform texture2DArray)
+0:?               Constant:
+0:?                 6 (const uint)
+0:?                 7 (const uint)
+0:?                 8 (const uint)
+0:9              Constant:
+0:9                5 (const uint)
+0:13          textureFetch ( temp 4-component vector of float)
+0:13            'g_tTex2df4' ( uniform texture2D)
+0:13            Convert float to uint ( temp 2-component vector of uint)
+0:13              vector swizzle ( temp 2-component vector of float)
+0:?                 textureFetch ( temp 4-component vector of float)
+0:13                  'g_tTex2df4' ( uniform texture2D)
+0:?                   Constant:
+0:?                     14 (const uint)
+0:?                     15 (const uint)
+0:13                  Constant:
+0:13                    13 (const int)
+0:13                Sequence
+0:13                  Constant:
+0:13                    0 (const int)
+0:13                  Constant:
+0:13                    1 (const int)
+0:13            Convert float to uint ( temp uint)
+0:13              direct index ( temp float)
+0:?                 textureFetch ( temp 4-component vector of float)
+0:13                  'g_tTex2df4' ( uniform texture2D)
+0:?                   Constant:
+0:?                     10 (const uint)
+0:?                     11 (const uint)
+0:13                  Constant:
+0:13                    9 (const int)
+0:13                Constant:
+0:13                  0 (const int)
+0:5  Function Definition: main( ( temp void)
+0:5    Function Parameters: 
+0:?     Sequence
+0:5      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:5        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'g_tTex2df4a' ( uniform texture2DArray)
+0:?     'g_tTex2df4' ( uniform texture2D)
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 61
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 59
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 500
+                              Name 4  "main"
+                              Name 9  "@main("
+                              Name 13  "g_tTex2df4"
+                              Name 25  "g_tTex2df4a"
+                              Name 59  "@entryPointOutput"
+                              Decorate 13(g_tTex2df4) DescriptorSet 0
+                              Decorate 25(g_tTex2df4a) DescriptorSet 0
+                              Decorate 59(@entryPointOutput) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeFunction 7(fvec4)
+              11:             TypeImage 6(float) 2D sampled format:Unknown
+              12:             TypePointer UniformConstant 11
+  13(g_tTex2df4):     12(ptr) Variable UniformConstant
+              15:             TypeInt 32 0
+              16:             TypeVector 15(int) 2
+              17:     15(int) Constant 3
+              18:     15(int) Constant 4
+              19:   16(ivec2) ConstantComposite 17 18
+              20:             TypeInt 32 1
+              21:     20(int) Constant 2
+              23:             TypeImage 6(float) 2D array sampled format:Unknown
+              24:             TypePointer UniformConstant 23
+ 25(g_tTex2df4a):     24(ptr) Variable UniformConstant
+              27:             TypeVector 15(int) 3
+              28:     15(int) Constant 6
+              29:     15(int) Constant 7
+              30:     15(int) Constant 8
+              31:   27(ivec3) ConstantComposite 28 29 30
+              32:     15(int) Constant 5
+              37:     15(int) Constant 14
+              38:     15(int) Constant 15
+              39:   16(ivec2) ConstantComposite 37 38
+              40:     20(int) Constant 13
+              42:             TypeVector 6(float) 2
+              46:     15(int) Constant 10
+              47:     15(int) Constant 11
+              48:   16(ivec2) ConstantComposite 46 47
+              49:     20(int) Constant 9
+              51:     15(int) Constant 0
+              58:             TypePointer Output 7(fvec4)
+59(@entryPointOutput):     58(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+              60:    7(fvec4) FunctionCall 9(@main()
+                              Store 59(@entryPointOutput) 60
+                              Return
+                              FunctionEnd
+       9(@main():    7(fvec4) Function None 8
+              10:             Label
+              14:          11 Load 13(g_tTex2df4)
+              22:    7(fvec4) ImageFetch 14 19 Lod 21
+              26:          23 Load 25(g_tTex2df4a)
+              33:    7(fvec4) ImageFetch 26 31 Lod 32
+              34:    7(fvec4) FAdd 22 33
+              35:          11 Load 13(g_tTex2df4)
+              36:          11 Load 13(g_tTex2df4)
+              41:    7(fvec4) ImageFetch 36 39 Lod 40
+              43:   42(fvec2) VectorShuffle 41 41 0 1
+              44:   16(ivec2) ConvertFToU 43
+              45:          11 Load 13(g_tTex2df4)
+              50:    7(fvec4) ImageFetch 45 48 Lod 49
+              52:    6(float) CompositeExtract 50 0
+              53:     15(int) ConvertFToU 52
+              54:    7(fvec4) ImageFetch 35 44 Lod 53
+              55:    7(fvec4) FAdd 34 54
+                              ReturnValue 55
+                              FunctionEnd

+ 275 - 0
3rdparty/glslang/Test/baseResults/hlsl.structbuffer.append.fn.frag.out

@@ -0,0 +1,275 @@
+hlsl.structbuffer.append.fn.frag
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:8  Function Definition: Fn2(block--vf4[0]1;block--vf4[0]1; ( temp 4-component vector of float)
+0:8    Function Parameters: 
+0:8      'arg_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:8      'arg_a@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:8      'arg_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:8      'arg_c@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:?     Sequence
+0:9      move second child to first child ( temp 4-component vector of float)
+0:9        indirect index ( buffer 4-component vector of float)
+0:9          @data: direct index for structure ( buffer implicitly-sized array of 4-component vector of float)
+0:9            'arg_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:9            Constant:
+0:9              0 (const uint)
+0:9          AtomicAdd ( temp uint)
+0:9            @count: direct index for structure ( temp int)
+0:9              'arg_a@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:9              Constant:
+0:9                0 (const int)
+0:9            Constant:
+0:9              1 (const int)
+0:?         Constant:
+0:?           1.000000
+0:?           2.000000
+0:?           3.000000
+0:?           4.000000
+0:10      Branch: Return with expression
+0:10        indirect index ( buffer 4-component vector of float)
+0:10          @data: direct index for structure ( buffer implicitly-sized array of 4-component vector of float)
+0:10            'arg_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:10            Constant:
+0:10              0 (const uint)
+0:10          add ( temp uint)
+0:10            AtomicAdd ( temp uint)
+0:10              @count: direct index for structure ( temp int)
+0:10                'arg_c@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:10                Constant:
+0:10                  0 (const int)
+0:10              Constant:
+0:10                -1 (const int)
+0:10            Constant:
+0:10              -1 (const int)
+0:19  Function Definition: @main(u1; ( temp 4-component vector of float)
+0:19    Function Parameters: 
+0:19      'pos' ( in uint)
+0:?     Sequence
+0:22      Branch: Return with expression
+0:22        Function Call: Fn2(block--vf4[0]1;block--vf4[0]1; ( temp 4-component vector of float)
+0:22          'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:22          'sbuf_a@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:22          'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:22          'sbuf_c@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:19  Function Definition: main( ( temp void)
+0:19    Function Parameters: 
+0:?     Sequence
+0:19      move second child to first child ( temp uint)
+0:?         'pos' ( temp uint)
+0:?         'pos' (layout( location=0) in uint)
+0:19      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:19        Function Call: @main(u1; ( temp 4-component vector of float)
+0:?           'pos' ( temp uint)
+0:?   Linker Objects
+0:?     'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:?     'sbuf_a@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
+0:?     'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:?     'sbuf_c@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
+0:?     'sbuf_unused' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:?     'pos' (layout( location=0) in uint)
+
+
+Linked fragment stage:
+
+
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:8  Function Definition: Fn2(block--vf4[0]1;block--vf4[0]1; ( temp 4-component vector of float)
+0:8    Function Parameters: 
+0:8      'arg_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:8      'arg_a@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:8      'arg_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:8      'arg_c@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:?     Sequence
+0:9      move second child to first child ( temp 4-component vector of float)
+0:9        indirect index ( buffer 4-component vector of float)
+0:9          @data: direct index for structure ( buffer implicitly-sized array of 4-component vector of float)
+0:9            'arg_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:9            Constant:
+0:9              0 (const uint)
+0:9          AtomicAdd ( temp uint)
+0:9            @count: direct index for structure ( temp int)
+0:9              'arg_a@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:9              Constant:
+0:9                0 (const int)
+0:9            Constant:
+0:9              1 (const int)
+0:?         Constant:
+0:?           1.000000
+0:?           2.000000
+0:?           3.000000
+0:?           4.000000
+0:10      Branch: Return with expression
+0:10        indirect index ( buffer 4-component vector of float)
+0:10          @data: direct index for structure ( buffer implicitly-sized array of 4-component vector of float)
+0:10            'arg_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:10            Constant:
+0:10              0 (const uint)
+0:10          add ( temp uint)
+0:10            AtomicAdd ( temp uint)
+0:10              @count: direct index for structure ( temp int)
+0:10                'arg_c@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:10                Constant:
+0:10                  0 (const int)
+0:10              Constant:
+0:10                -1 (const int)
+0:10            Constant:
+0:10              -1 (const int)
+0:19  Function Definition: @main(u1; ( temp 4-component vector of float)
+0:19    Function Parameters: 
+0:19      'pos' ( in uint)
+0:?     Sequence
+0:22      Branch: Return with expression
+0:22        Function Call: Fn2(block--vf4[0]1;block--vf4[0]1; ( temp 4-component vector of float)
+0:22          'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:22          'sbuf_a@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:22          'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:22          'sbuf_c@count' ( buffer block{layout( row_major std430) buffer int @count})
+0:19  Function Definition: main( ( temp void)
+0:19    Function Parameters: 
+0:?     Sequence
+0:19      move second child to first child ( temp uint)
+0:?         'pos' ( temp uint)
+0:?         'pos' (layout( location=0) in uint)
+0:19      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:19        Function Call: @main(u1; ( temp 4-component vector of float)
+0:?           'pos' ( temp uint)
+0:?   Linker Objects
+0:?     'sbuf_a' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:?     'sbuf_a@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
+0:?     'sbuf_c' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:?     'sbuf_c@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
+0:?     'sbuf_unused' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of float @data})
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:?     'pos' (layout( location=0) in uint)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 70
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 58 61
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 500
+                              Name 4  "main"
+                              Name 9  ""
+                              MemberName 9 0  "@data"
+                              Name 12  ""
+                              MemberName 12 0  "@count"
+                              Name 19  "Fn2(block--vf4[0]1;block--vf4[0]1;"
+                              Name 15  "arg_a"
+                              Name 16  "arg_a@count"
+                              Name 17  "arg_c"
+                              Name 18  "arg_c@count"
+                              Name 25  "@main(u1;"
+                              Name 24  "pos"
+                              Name 49  "sbuf_a"
+                              Name 50  "sbuf_a@count"
+                              Name 51  "sbuf_c"
+                              Name 52  "sbuf_c@count"
+                              Name 56  "pos"
+                              Name 58  "pos"
+                              Name 61  "@entryPointOutput"
+                              Name 62  "param"
+                              Name 65  "sbuf_a@count"
+                              MemberName 65(sbuf_a@count) 0  "@count"
+                              Name 67  "sbuf_a@count"
+                              Name 68  "sbuf_c@count"
+                              Name 69  "sbuf_unused"
+                              Decorate 8 ArrayStride 16
+                              MemberDecorate 9 0 Offset 0
+                              Decorate 9 BufferBlock
+                              Decorate 12 BufferBlock
+                              Decorate 49(sbuf_a) DescriptorSet 0
+                              Decorate 50(sbuf_a@count) DescriptorSet 0
+                              Decorate 51(sbuf_c) DescriptorSet 0
+                              Decorate 52(sbuf_c@count) DescriptorSet 0
+                              Decorate 58(pos) Location 0
+                              Decorate 61(@entryPointOutput) Location 0
+                              MemberDecorate 65(sbuf_a@count) 0 Offset 0
+                              Decorate 65(sbuf_a@count) BufferBlock
+                              Decorate 67(sbuf_a@count) DescriptorSet 0
+                              Decorate 68(sbuf_c@count) DescriptorSet 0
+                              Decorate 69(sbuf_unused) DescriptorSet 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeRuntimeArray 7(fvec4)
+               9:             TypeStruct 8
+              10:             TypePointer Uniform 9(struct)
+              11:             TypeInt 32 1
+              12:             TypeStruct 11(int)
+              13:             TypePointer Uniform 12(struct)
+              14:             TypeFunction 7(fvec4) 10(ptr) 13(ptr) 10(ptr) 13(ptr)
+              21:             TypeInt 32 0
+              22:             TypePointer Function 21(int)
+              23:             TypeFunction 7(fvec4) 22(ptr)
+              27:     11(int) Constant 0
+              28:             TypePointer Uniform 11(int)
+              30:     11(int) Constant 1
+              31:     21(int) Constant 1
+              32:     21(int) Constant 0
+              34:    6(float) Constant 1065353216
+              35:    6(float) Constant 1073741824
+              36:    6(float) Constant 1077936128
+              37:    6(float) Constant 1082130432
+              38:    7(fvec4) ConstantComposite 34 35 36 37
+              39:             TypePointer Uniform 7(fvec4)
+              42:     11(int) Constant 4294967295
+      49(sbuf_a):     10(ptr) Variable Uniform
+50(sbuf_a@count):     13(ptr) Variable Uniform
+      51(sbuf_c):     10(ptr) Variable Uniform
+52(sbuf_c@count):     13(ptr) Variable Uniform
+              57:             TypePointer Input 21(int)
+         58(pos):     57(ptr) Variable Input
+              60:             TypePointer Output 7(fvec4)
+61(@entryPointOutput):     60(ptr) Variable Output
+65(sbuf_a@count):             TypeStruct 11(int)
+              66:             TypePointer Uniform 65(sbuf_a@count)
+67(sbuf_a@count):     66(ptr) Variable Uniform
+68(sbuf_c@count):     66(ptr) Variable Uniform
+ 69(sbuf_unused):     10(ptr) Variable Uniform
+         4(main):           2 Function None 3
+               5:             Label
+         56(pos):     22(ptr) Variable Function
+       62(param):     22(ptr) Variable Function
+              59:     21(int) Load 58(pos)
+                              Store 56(pos) 59
+              63:     21(int) Load 56(pos)
+                              Store 62(param) 63
+              64:    7(fvec4) FunctionCall 25(@main(u1;) 62(param)
+                              Store 61(@entryPointOutput) 64
+                              Return
+                              FunctionEnd
+19(Fn2(block--vf4[0]1;block--vf4[0]1;):    7(fvec4) Function None 14
+       15(arg_a):     10(ptr) FunctionParameter
+ 16(arg_a@count):     13(ptr) FunctionParameter
+       17(arg_c):     10(ptr) FunctionParameter
+ 18(arg_c@count):     13(ptr) FunctionParameter
+              20:             Label
+              29:     28(ptr) AccessChain 16(arg_a@count) 27
+              33:     21(int) AtomicIAdd 29 31 32 30
+              40:     39(ptr) AccessChain 15(arg_a) 27 33
+                              Store 40 38
+              41:     28(ptr) AccessChain 18(arg_c@count) 27
+              43:     21(int) AtomicIAdd 41 31 32 42
+              44:     21(int) IAdd 43 42
+              45:     39(ptr) AccessChain 17(arg_c) 27 44
+              46:    7(fvec4) Load 45
+                              ReturnValue 46
+                              FunctionEnd
+   25(@main(u1;):    7(fvec4) Function None 23
+         24(pos):     22(ptr) FunctionParameter
+              26:             Label
+              53:    7(fvec4) FunctionCall 19(Fn2(block--vf4[0]1;block--vf4[0]1;) 49(sbuf_a) 50(sbuf_a@count) 51(sbuf_c) 52(sbuf_c@count)
+                              ReturnValue 53
+                              FunctionEnd

+ 112 - 87
3rdparty/glslang/Test/baseResults/hlsl.structbuffer.fn.frag.out

@@ -17,6 +17,7 @@ gl_FragCoord origin is upper left
 0:10  Function Definition: set(block--vu4[0]1;u1;vu4; ( temp void)
 0:10    Function Parameters: 
 0:10      'sb' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
+0:10      'sb@count' ( buffer block{layout( row_major std430) buffer int @count})
 0:10      'bufferOffset' ( in uint)
 0:10      'data' ( in 4-component vector of uint)
 0:?     Sequence
@@ -34,6 +35,7 @@ gl_FragCoord origin is upper left
 0:?     Sequence
 0:21      Function Call: set(block--vu4[0]1;u1;vu4; ( temp void)
 0:21        'sbuf2' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
+0:21        'sbuf2@count' ( buffer block{layout( row_major std430) buffer int @count})
 0:21        Constant:
 0:21          2 (const uint)
 0:21        Function Call: get(block--vu4[0]1;u1; ( temp 4-component vector of uint)
@@ -59,6 +61,7 @@ gl_FragCoord origin is upper left
 0:?   Linker Objects
 0:?     'sbuf' (layout( binding=10 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
 0:?     'sbuf2' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
+0:?     'sbuf2@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
 0:?     'sbuf3' (layout( binding=12 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 3-component vector of uint @data})
 0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
 0:?     'pos' (layout( location=0) in uint)
@@ -85,6 +88,7 @@ gl_FragCoord origin is upper left
 0:10  Function Definition: set(block--vu4[0]1;u1;vu4; ( temp void)
 0:10    Function Parameters: 
 0:10      'sb' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
+0:10      'sb@count' ( buffer block{layout( row_major std430) buffer int @count})
 0:10      'bufferOffset' ( in uint)
 0:10      'data' ( in 4-component vector of uint)
 0:?     Sequence
@@ -102,6 +106,7 @@ gl_FragCoord origin is upper left
 0:?     Sequence
 0:21      Function Call: set(block--vu4[0]1;u1;vu4; ( temp void)
 0:21        'sbuf2' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
+0:21        'sbuf2@count' ( buffer block{layout( row_major std430) buffer int @count})
 0:21        Constant:
 0:21          2 (const uint)
 0:21        Function Call: get(block--vu4[0]1;u1; ( temp 4-component vector of uint)
@@ -127,18 +132,19 @@ gl_FragCoord origin is upper left
 0:?   Linker Objects
 0:?     'sbuf' (layout( binding=10 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
 0:?     'sbuf2' (layout( row_major std430) buffer block{layout( row_major std430) buffer implicitly-sized array of 4-component vector of uint @data})
+0:?     'sbuf2@count' (layout( row_major std430) buffer block{layout( row_major std430) buffer int @count})
 0:?     'sbuf3' (layout( binding=12 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of 3-component vector of uint @data})
 0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
 0:?     'pos' (layout( location=0) in uint)
 
 // Module Version 10000
 // Generated by (magic number): 80001
-// Id's are bound by 71
+// Id's are bound by 78
 
                               Capability Shader
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint Fragment 4  "main" 59 62
+                              EntryPoint Fragment 4  "main" 63 66
                               ExecutionMode 4 OriginUpperLeft
                               Source HLSL 500
                               Name 4  "main"
@@ -149,24 +155,31 @@ gl_FragCoord origin is upper left
                               Name 14  "bufferOffset"
                               Name 18  ""
                               MemberName 18 0  "@data"
-                              Name 25  "set(block--vu4[0]1;u1;vu4;"
-                              Name 22  "sb"
-                              Name 23  "bufferOffset"
-                              Name 24  "data"
-                              Name 31  "@main(u1;"
-                              Name 30  "pos"
-                              Name 44  "sbuf2"
-                              Name 46  "sbuf"
-                              Name 48  "param"
-                              Name 50  "param"
-                              Name 51  "param"
-                              Name 57  "pos"
-                              Name 59  "pos"
-                              Name 62  "@entryPointOutput"
-                              Name 63  "param"
-                              Name 68  "sbuf3"
-                              MemberName 68(sbuf3) 0  "@data"
-                              Name 70  "sbuf3"
+                              Name 21  ""
+                              MemberName 21 0  "@count"
+                              Name 29  "set(block--vu4[0]1;u1;vu4;"
+                              Name 25  "sb"
+                              Name 26  "sb@count"
+                              Name 27  "bufferOffset"
+                              Name 28  "data"
+                              Name 35  "@main(u1;"
+                              Name 34  "pos"
+                              Name 47  "sbuf2"
+                              Name 48  "sbuf2@count"
+                              Name 50  "sbuf"
+                              Name 52  "param"
+                              Name 54  "param"
+                              Name 55  "param"
+                              Name 61  "pos"
+                              Name 63  "pos"
+                              Name 66  "@entryPointOutput"
+                              Name 67  "param"
+                              Name 70  "sbuf2@count"
+                              MemberName 70(sbuf2@count) 0  "@count"
+                              Name 72  "sbuf2@count"
+                              Name 75  "sbuf3"
+                              MemberName 75(sbuf3) 0  "@data"
+                              Name 77  "sbuf3"
                               Decorate 8 ArrayStride 16
                               MemberDecorate 9 0 NonWritable
                               MemberDecorate 9 0 Offset 0
@@ -174,17 +187,22 @@ gl_FragCoord origin is upper left
                               Decorate 17 ArrayStride 16
                               MemberDecorate 18 0 Offset 0
                               Decorate 18 BufferBlock
-                              Decorate 44(sbuf2) DescriptorSet 0
-                              Decorate 46(sbuf) DescriptorSet 0
-                              Decorate 46(sbuf) Binding 10
-                              Decorate 59(pos) Location 0
-                              Decorate 62(@entryPointOutput) Location 0
-                              Decorate 67 ArrayStride 16
-                              MemberDecorate 68(sbuf3) 0 NonWritable
-                              MemberDecorate 68(sbuf3) 0 Offset 0
-                              Decorate 68(sbuf3) BufferBlock
-                              Decorate 70(sbuf3) DescriptorSet 0
-                              Decorate 70(sbuf3) Binding 12
+                              Decorate 21 BufferBlock
+                              Decorate 47(sbuf2) DescriptorSet 0
+                              Decorate 48(sbuf2@count) DescriptorSet 0
+                              Decorate 50(sbuf) DescriptorSet 0
+                              Decorate 50(sbuf) Binding 10
+                              Decorate 63(pos) Location 0
+                              Decorate 66(@entryPointOutput) Location 0
+                              MemberDecorate 70(sbuf2@count) 0 Offset 0
+                              Decorate 70(sbuf2@count) BufferBlock
+                              Decorate 72(sbuf2@count) DescriptorSet 0
+                              Decorate 74 ArrayStride 16
+                              MemberDecorate 75(sbuf3) 0 NonWritable
+                              MemberDecorate 75(sbuf3) 0 Offset 0
+                              Decorate 75(sbuf3) BufferBlock
+                              Decorate 77(sbuf3) DescriptorSet 0
+                              Decorate 77(sbuf3) Binding 12
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeInt 32 0
@@ -197,71 +215,78 @@ gl_FragCoord origin is upper left
               17:             TypeRuntimeArray 7(ivec4)
               18:             TypeStruct 17
               19:             TypePointer Uniform 18(struct)
-              20:             TypePointer Function 7(ivec4)
-              21:             TypeFunction 2 19(ptr) 11(ptr) 20(ptr)
-              27:             TypeFloat 32
-              28:             TypeVector 27(float) 4
-              29:             TypeFunction 28(fvec4) 11(ptr)
-              33:             TypeInt 32 1
-              34:     33(int) Constant 0
-              36:             TypePointer Uniform 7(ivec4)
-       44(sbuf2):     19(ptr) Variable Uniform
-              45:      6(int) Constant 2
-        46(sbuf):     10(ptr) Variable Uniform
-              47:      6(int) Constant 3
-              53:   27(float) Constant 0
-              54:   28(fvec4) ConstantComposite 53 53 53 53
-              58:             TypePointer Input 6(int)
-         59(pos):     58(ptr) Variable Input
-              61:             TypePointer Output 28(fvec4)
-62(@entryPointOutput):     61(ptr) Variable Output
-              66:             TypeVector 6(int) 3
-              67:             TypeRuntimeArray 66(ivec3)
-       68(sbuf3):             TypeStruct 67
-              69:             TypePointer Uniform 68(sbuf3)
-       70(sbuf3):     69(ptr) Variable Uniform
+              20:             TypeInt 32 1
+              21:             TypeStruct 20(int)
+              22:             TypePointer Uniform 21(struct)
+              23:             TypePointer Function 7(ivec4)
+              24:             TypeFunction 2 19(ptr) 22(ptr) 11(ptr) 23(ptr)
+              31:             TypeFloat 32
+              32:             TypeVector 31(float) 4
+              33:             TypeFunction 32(fvec4) 11(ptr)
+              37:     20(int) Constant 0
+              39:             TypePointer Uniform 7(ivec4)
+       47(sbuf2):     19(ptr) Variable Uniform
+ 48(sbuf2@count):     22(ptr) Variable Uniform
+              49:      6(int) Constant 2
+        50(sbuf):     10(ptr) Variable Uniform
+              51:      6(int) Constant 3
+              57:   31(float) Constant 0
+              58:   32(fvec4) ConstantComposite 57 57 57 57
+              62:             TypePointer Input 6(int)
+         63(pos):     62(ptr) Variable Input
+              65:             TypePointer Output 32(fvec4)
+66(@entryPointOutput):     65(ptr) Variable Output
+ 70(sbuf2@count):             TypeStruct 20(int)
+              71:             TypePointer Uniform 70(sbuf2@count)
+ 72(sbuf2@count):     71(ptr) Variable Uniform
+              73:             TypeVector 6(int) 3
+              74:             TypeRuntimeArray 73(ivec3)
+       75(sbuf3):             TypeStruct 74
+              76:             TypePointer Uniform 75(sbuf3)
+       77(sbuf3):     76(ptr) Variable Uniform
          4(main):           2 Function None 3
                5:             Label
-         57(pos):     11(ptr) Variable Function
-       63(param):     11(ptr) Variable Function
-              60:      6(int) Load 59(pos)
-                              Store 57(pos) 60
-              64:      6(int) Load 57(pos)
-                              Store 63(param) 64
-              65:   28(fvec4) FunctionCall 31(@main(u1;) 63(param)
-                              Store 62(@entryPointOutput) 65
+         61(pos):     11(ptr) Variable Function
+       67(param):     11(ptr) Variable Function
+              64:      6(int) Load 63(pos)
+                              Store 61(pos) 64
+              68:      6(int) Load 61(pos)
+                              Store 67(param) 68
+              69:   32(fvec4) FunctionCall 35(@main(u1;) 67(param)
+                              Store 66(@entryPointOutput) 69
                               Return
                               FunctionEnd
 15(get(block--vu4[0]1;u1;):    7(ivec4) Function None 12
           13(sb):     10(ptr) FunctionParameter
 14(bufferOffset):     11(ptr) FunctionParameter
               16:             Label
-              35:      6(int) Load 14(bufferOffset)
-              37:     36(ptr) AccessChain 13(sb) 34 35
-              38:    7(ivec4) Load 37
-                              ReturnValue 38
+              38:      6(int) Load 14(bufferOffset)
+              40:     39(ptr) AccessChain 13(sb) 37 38
+              41:    7(ivec4) Load 40
+                              ReturnValue 41
                               FunctionEnd
-25(set(block--vu4[0]1;u1;vu4;):           2 Function None 21
-          22(sb):     19(ptr) FunctionParameter
-23(bufferOffset):     11(ptr) FunctionParameter
-        24(data):     20(ptr) FunctionParameter
-              26:             Label
-              41:      6(int) Load 23(bufferOffset)
-              42:    7(ivec4) Load 24(data)
-              43:     36(ptr) AccessChain 22(sb) 34 41
-                              Store 43 42
+29(set(block--vu4[0]1;u1;vu4;):           2 Function None 24
+          25(sb):     19(ptr) FunctionParameter
+    26(sb@count):     22(ptr) FunctionParameter
+27(bufferOffset):     11(ptr) FunctionParameter
+        28(data):     23(ptr) FunctionParameter
+              30:             Label
+              44:      6(int) Load 27(bufferOffset)
+              45:    7(ivec4) Load 28(data)
+              46:     39(ptr) AccessChain 25(sb) 37 44
+                              Store 46 45
                               Return
                               FunctionEnd
-   31(@main(u1;):   28(fvec4) Function None 29
-         30(pos):     11(ptr) FunctionParameter
-              32:             Label
-       48(param):     11(ptr) Variable Function
-       50(param):     11(ptr) Variable Function
-       51(param):     20(ptr) Variable Function
-                              Store 48(param) 47
-              49:    7(ivec4) FunctionCall 15(get(block--vu4[0]1;u1;) 46(sbuf) 48(param)
-                              Store 50(param) 45
-                              Store 51(param) 49
-              52:           2 FunctionCall 25(set(block--vu4[0]1;u1;vu4;) 44(sbuf2) 50(param) 51(param)
-                              ReturnValue 54
+   35(@main(u1;):   32(fvec4) Function None 33
+         34(pos):     11(ptr) FunctionParameter
+              36:             Label
+       52(param):     11(ptr) Variable Function
+       54(param):     11(ptr) Variable Function
+       55(param):     23(ptr) Variable Function
+                              Store 52(param) 51
+              53:    7(ivec4) FunctionCall 15(get(block--vu4[0]1;u1;) 50(sbuf) 52(param)
+                              Store 54(param) 49
+                              Store 55(param) 53
+              56:           2 FunctionCall 29(set(block--vu4[0]1;u1;vu4;) 47(sbuf2) 48(sbuf2@count) 54(param) 55(param)
+                              ReturnValue 58
                               FunctionEnd

+ 33 - 0
3rdparty/glslang/Test/baseResults/remap.specconst.comp.out

@@ -0,0 +1,33 @@
+remap.specconst.comp
+Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 16104
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint GLCompute 5663  "main"
+                              ExecutionMode 5663 LocalSize 1 1 1
+                              Decorate 2 SpecId 0
+                              Decorate 3 SpecId 1
+                              Decorate 4 SpecId 2
+                              Decorate 5 BuiltIn WorkgroupSize
+               8:             TypeVoid
+            1282:             TypeFunction 8
+              11:             TypeInt 32 0
+               2:     11(int) SpecConstant 1
+               3:     11(int) SpecConstant 1
+               4:     11(int) SpecConstant 1
+              20:             TypeVector 11(int) 3
+               5:   20(ivec3) SpecConstantComposite 2 3 4
+               6:     11(int) SpecConstantOp 81 5 0
+               7:     11(int) SpecConstantOp 81 5 1(GLSL.std.450)
+               9:     11(int) SpecConstantOp 81 5 2
+              10:     11(int) SpecConstantOp 132 7 9
+              12:     11(int) SpecConstantOp 128 6 10
+            5663:           8 Function None 1282
+           16103:             Label
+                              Return
+                              FunctionEnd

+ 1 - 0
3rdparty/glslang/Test/baseResults/spv.glsl.register.autoassign.frag.out

@@ -78,6 +78,7 @@ Warning, version 450 is not yet complete; most version-specific features are pre
                               Decorate 126(g_tTex_unused2) DescriptorSet 0
                               Decorate 126(g_tTex_unused2) Binding 12
                               Decorate 128(g_sSamp_unused2) DescriptorSet 0
+                              Decorate 137(FragColor) Location 0
                               Decorate 141(g_tTex_unused3) DescriptorSet 0
                2:             TypeVoid
                3:             TypeFunction 2

+ 1 - 0
3rdparty/glslang/Test/baseResults/spv.glsl.register.noautoassign.frag.out

@@ -72,6 +72,7 @@ Warning, version 450 is not yet complete; most version-specific features are pre
                               Decorate 126(g_tTex_unused2) DescriptorSet 0
                               Decorate 126(g_tTex_unused2) Binding 12
                               Decorate 128(g_sSamp_unused2) DescriptorSet 0
+                              Decorate 137(FragColor) Location 0
                               Decorate 141(g_tTex_unused3) DescriptorSet 0
                2:             TypeVoid
                3:             TypeFunction 2

+ 8 - 0
3rdparty/glslang/Test/baseResults/spv.noLocation.vert.out

@@ -0,0 +1,8 @@
+spv.noLocation.vert
+Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
+ERROR: spv.noLocation.vert:4: 'location' : SPIR-V requires location for user input/output 
+ERROR: spv.noLocation.vert:8: 'location' : SPIR-V requires location for user input/output 
+ERROR: 2 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link

+ 17 - 0
3rdparty/glslang/Test/hlsl.fraggeom.frag

@@ -0,0 +1,17 @@
+// test geometry shader in fragment shader.  GS attributes should be successfully ignored.
+
+struct myVertex {
+    float4 pos : SV_Position;
+};
+
+[maxvertexcount(1)]
+void GS_Draw(point myVertex IN, inout PointStream<myVertex> OutputStream)
+{
+    OutputStream.Append(IN);
+    OutputStream.RestartStrip();
+}
+
+float4 main() : SV_TARGET
+{
+    return 0;
+}

+ 16 - 0
3rdparty/glslang/Test/hlsl.memberFunCall.frag

@@ -0,0 +1,16 @@
+float method3(float a) { return 1.0; }
+
+struct myContext {
+    float method1() { return method2(); }
+    float method2() { return method3(1.0); }
+    float method3(float a) { return method4(a, a); }
+    float method4(float a, float b) { return a + b + f; }
+    float f;
+};
+
+float4 main() : SV_TARGET0
+{
+    myContext context;
+    context.f = 3.0;
+    return (float4)context.method1();
+}

+ 9 - 0
3rdparty/glslang/Test/hlsl.mip.negative.frag

@@ -0,0 +1,9 @@
+Texture2D          g_tTex2df4;
+
+float4 main() : SV_Target0
+{
+    g_tTex2df4.mips.mips[2][uint2(3, 4)]; // error to chain like this
+
+    return 0;
+}
+    

+ 9 - 0
3rdparty/glslang/Test/hlsl.mip.negative2.frag

@@ -0,0 +1,9 @@
+Texture2D          g_tTex2df4;
+
+float4 main() : SV_Target0
+{
+    g_tTex2df4.r[2][uint2(3, 4)]; // '.r' not valid on texture object
+
+    return 0;
+}
+    

+ 14 - 0
3rdparty/glslang/Test/hlsl.mip.operator.frag

@@ -0,0 +1,14 @@
+Texture2DArray     g_tTex2df4a;
+Texture2D          g_tTex2df4;
+
+float4 main() : SV_Target0
+{
+    return g_tTex2df4.mips[2][uint2(3, 4)] +
+
+        // test float->uint cast on the mip arg
+        g_tTex2df4a.mips[5.2][uint3(6, 7, 8)] +
+
+        // Test nesting involving .mips operators:
+        //               ....outer operator mip level......     .....outer operator coordinate....
+        g_tTex2df4.mips[ g_tTex2df4.mips[9][uint2(10,11)][0] ][ g_tTex2df4.mips[13][uint2(14,15)].xy ];
+}

+ 23 - 0
3rdparty/glslang/Test/hlsl.structbuffer.append.fn.frag

@@ -0,0 +1,23 @@
+
+// float4 Fn1(ConsumeStructuredBuffer<float4> arg_c)
+// {
+//     return arg_c.Consume();
+// }
+
+float4 Fn2(AppendStructuredBuffer<float4> arg_a, ConsumeStructuredBuffer<float4> arg_c)
+{
+    arg_a.Append(float4(1,2,3,4));
+    return arg_c.Consume();
+}
+
+AppendStructuredBuffer<float4>  sbuf_a;
+ConsumeStructuredBuffer<float4> sbuf_c;
+
+AppendStructuredBuffer<float4>  sbuf_unused;
+
+float4 main(uint pos : FOO) : SV_Target0
+{
+    // Fn1(sbuf_c);
+
+    return Fn2(sbuf_a, sbuf_c);
+}

+ 7 - 0
3rdparty/glslang/Test/remap.specconst.comp

@@ -0,0 +1,7 @@
+#version 450
+
+layout (local_size_x_id = 0, local_size_y_id = 1, local_size_z_id = 2) in;
+
+shared int foo[gl_WorkGroupSize.x + gl_WorkGroupSize.y * gl_WorkGroupSize.z];
+
+void main () {}

+ 8 - 1
3rdparty/glslang/Test/runtests

@@ -86,12 +86,19 @@ $EXE -i  --hlsl-offsets -D -e main -H hlsl.hlslOffset.vert > $TARGETDIR/hlsl.hls
 diff -b $BASEDIR/hlsl.hlslOffset.vert.out $TARGETDIR/hlsl.hlslOffset.vert.out || HASERROR=1
 
 #
-# Tesing --resource-set-binding
+# Testing --resource-set-binding
 #
 echo Configuring HLSL descriptor set and binding number manually
 $EXE -V -D -e main -H hlsl.multiDescriptorSet.frag --rsb frag t0 0 0 t1 1 0 s0 0 1 s1 1 1 b0 2 0 b1 2 1 b2 2 2 > $TARGETDIR/hlsl.multiDescriptorSet.frag.out
 diff -b $BASEDIR/hlsl.multiDescriptorSet.frag.out $TARGETDIR/hlsl.multiDescriptorSet.frag.out
 
+#
+# Testing location error
+#
+echo Testing SPV no location
+$EXE -V -C spv.noLocation.vert > $TARGETDIR/spv.noLocation.vert.out
+diff -b $BASEDIR/spv.noLocation.vert.out $TARGETDIR/spv.noLocation.vert.out
+
 #
 # Final checking
 #

+ 14 - 0
3rdparty/glslang/Test/spv.noLocation.vert

@@ -0,0 +1,14 @@
+#version 450
+
+layout(location = 1) in vec4 in1;
+in vec4 in2;
+layout(location = 3) in vec4 in3;
+
+layout(location = 1) out vec4 out1;
+out vec4 out2;
+layout(location = 3) out vec4 out3;
+
+
+void main()
+{
+}

+ 2 - 0
3rdparty/glslang/glslang/Include/Types.h

@@ -400,6 +400,7 @@ public:
         invariant = false;
         noContraction = false;
         makeTemporary();
+        declaredBuiltIn = EbvNone;
     }
 
     // drop qualifiers that don't belong in a temporary variable
@@ -457,6 +458,7 @@ public:
     const char*         semanticName;
     TStorageQualifier   storage   : 6;
     TBuiltInVariable    builtIn   : 8;
+    TBuiltInVariable    declaredBuiltIn : 8;
     TPrecisionQualifier precision : 3;
     bool invariant    : 1; // require canonical treatment for cross-shader invariance
     bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects

+ 15 - 0
3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp

@@ -4332,6 +4332,18 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
         default:
             break;
         }
+    } else if (spvVersion.spv > 0) {
+        switch (qualifier.storage) {
+        case EvqVaryingIn:
+        case EvqVaryingOut:
+            if (! parsingBuiltins && qualifier.builtIn == EbvNone) {
+                if (!intermediate.getAutoMapLocations())
+                    error(loc, "SPIR-V requires location for user input/output", "location", "");
+            }
+            break;
+        default:
+            break;
+        }
     }
 
     // Check packing and matrix
@@ -5022,6 +5034,8 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
 
     // look for errors in layout qualifier use
     layoutObjectCheck(loc, *symbol);
+
+    // fix up
     fixOffset(loc, *symbol);
 
     return initNode;
@@ -5728,6 +5742,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
     // Check for general layout qualifier errors
     layoutObjectCheck(loc, variable);
 
+    // fix up
     if (isIoResizeArray(blockType)) {
         ioArraySymbolResizeList.push_back(&variable);
         checkIoArraysConsistency(loc, true);

+ 2 - 0
3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp

@@ -1571,6 +1571,8 @@ void TShader::setShiftUavBinding(unsigned int base)     { intermediate->setShift
 void TShader::setShiftSsboBinding(unsigned int base)    { intermediate->setShiftSsboBinding(base); }
 // Enables binding automapping using TIoMapper
 void TShader::setAutoMapBindings(bool map)              { intermediate->setAutoMapBindings(map); }
+// 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:
 void TShader::setHlslIoMapping(bool hlslIoMap)          { intermediate->setHlslIoMapping(hlslIoMap); }
 void TShader::setFlattenUniformArrays(bool flatten)     { intermediate->setFlattenUniformArrays(flatten); }

+ 17 - 5
3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h

@@ -198,7 +198,6 @@ struct TParameter {
     TString *name;
     TType* type;
     TIntermTyped* defaultValue;
-    TBuiltInVariable declaredBuiltIn;
     void copyParam(const TParameter& param)
     {
         if (param.name)
@@ -207,8 +206,8 @@ struct TParameter {
             name = 0;
         type = param.type->clone();
         defaultValue = param.defaultValue;
-        declaredBuiltIn = param.declaredBuiltIn;
     }
+    TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; }
 };
 
 //
@@ -241,7 +240,6 @@ public:
     virtual void addParameter(TParameter& p)
     {
         assert(writable);
-        p.declaredBuiltIn = p.type->getQualifier().builtIn;
         parameters.push_back(p);
         p.type->appendMangledName(mangledName);
 
@@ -264,6 +262,12 @@ public:
         mangledName.insert(0, prefix);
     }
 
+    virtual void removePrefix(const TString& prefix)
+    {
+        assert(mangledName.compare(0, prefix.size(), prefix) == 0);
+        mangledName.erase(0, prefix.size());
+    }
+
     virtual const TString& getMangledName() const override { return mangledName; }
     virtual const TType& getType() const override { return returnType; }
     virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; }
@@ -688,19 +692,27 @@ public:
 
     // Normal find of a symbol, that can optionally say whether the symbol was found
     // at a built-in level or the current top-scope level.
-    TSymbol* find(const TString& name, bool* builtIn = 0, bool *currentScope = 0)
+    TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0)
     {
         int level = currentLevel();
         TSymbol* symbol;
+        int thisDepth = 0;
         do {
+            if (table[level]->isThisLevel())
+                ++thisDepth;
             symbol = table[level]->find(name);
             --level;
-        } while (symbol == 0 && level >= 0);
+        } while (symbol == nullptr && level >= 0);
         level++;
         if (builtIn)
             *builtIn = isBuiltInLevel(level);
         if (currentScope)
             *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel();  // consider shared levels as "current scope" WRT user globals
+        if (thisDepthP != nullptr) {
+            if (! table[level]->isThisLevel())
+                thisDepth = 0;
+            *thisDepthP = thisDepth;
+        }
 
         return symbol;
     }

+ 23 - 6
3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp

@@ -214,6 +214,8 @@ struct TNotifyUniformAdaptor
     {
         resolver.notifyBinding(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
     }
+private:
+    TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&);
 };
 
 struct TNotifyInOutAdaptor
@@ -229,6 +231,8 @@ struct TNotifyInOutAdaptor
     {
         resolver.notifyInOut(stage, ent.symbol->getName().c_str(), ent.symbol->getType(), ent.live);
     }
+private:
+    TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&);
 };
 
 struct TResolverUniformAdaptor
@@ -350,7 +354,8 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
     int baseSsboBinding;
     int baseUavBinding;
     std::vector<std::string> baseResourceSetBinding;
-    bool doAutoMapping;
+    bool doAutoBindingMapping;
+    bool doAutoLocationMapping;
     typedef std::vector<int> TSlotSet;
     typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
     TSlotSetMap slots;
@@ -401,9 +406,19 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
     {
         return true;
     }
-    int resolveInOutLocation(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
+    int resolveInOutLocation(EShLanguage /*stage*/, const char* /*name*/, const TType& type, bool /*is_live*/) override
     {
-        return -1;
+        if (!doAutoLocationMapping || type.getQualifier().hasLocation())
+            return -1;
+
+        // Placeholder.
+        // TODO: It would be nice to flesh this out using 
+        // intermediate->computeTypeLocationSize(type), or functions that call it like
+        // intermediate->addUsedLocation()
+        // These in turn would want the intermediate, which is not available here, but
+        // is available in many places, and a lot of copying from it could be saved if
+        // it were just available.
+        return 0;
     }
     int resolveInOutComponent(EShLanguage /*stage*/, const char* /*name*/, const TType& /*type*/, bool /*is_live*/) override
     {
@@ -493,7 +508,7 @@ struct TDefaultIoResolver : public TDefaultIoResolverBase
 
             if (isUboType(type))
                 return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
-        } else if (is_live && doAutoMapping) {
+        } else if (is_live && doAutoBindingMapping) {
             // find free slot, the caller did make sure it passes all vars with binding
             // first and now all are passed that do not have a binding and needs one
 
@@ -607,7 +622,7 @@ struct TDefaultHlslIoResolver : public TDefaultIoResolverBase
 
             if (isUboType(type))
                 return reserveSlot(set, baseUboBinding + type.getQualifier().layoutBinding);
-        } else if (is_live && doAutoMapping) {
+        } else if (is_live && doAutoBindingMapping) {
             // find free slot, the caller did make sure it passes all vars with binding
             // first and now all are passed that do not have a binding and needs one
 
@@ -659,6 +674,7 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
         intermediate.getShiftUavBinding() == 0 &&
         intermediate.getResourceSetBinding().empty() &&
         intermediate.getAutoMapBindings() == false &&
+        intermediate.getAutoMapLocations() == false &&
         resolver == nullptr)
         return true;
 
@@ -689,7 +705,8 @@ bool TIoMapper::addStage(EShLanguage stage, TIntermediate &intermediate, TInfoSi
         resolverBase->baseSsboBinding = intermediate.getShiftSsboBinding();
         resolverBase->baseUavBinding = intermediate.getShiftUavBinding();
         resolverBase->baseResourceSetBinding = intermediate.getResourceSetBinding();
-        resolverBase->doAutoMapping = intermediate.getAutoMapBindings();
+        resolverBase->doAutoBindingMapping = intermediate.getAutoMapBindings();
+        resolverBase->doAutoLocationMapping = intermediate.getAutoMapLocations();
 
         resolver = resolverBase;
     }

+ 1 - 1
3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp

@@ -860,7 +860,7 @@ int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TTyp
     return -1; // no collision
 }
 
-// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions
+// Accumulate bindings and offsets, and check for collisions
 // as the accumulation is done.
 //
 // Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value.

+ 6 - 2
3rdparty/glslang/glslang/MachineIndependent/localintermediate.h

@@ -177,6 +177,7 @@ public:
         shiftSsboBinding(0),
         shiftUavBinding(0),
         autoMapBindings(false),
+        autoMapLocations(false),
         flattenUniformArrays(false),
         useUnknownFormat(false),
         hlslOffsets(false),
@@ -218,9 +219,11 @@ public:
     unsigned int getShiftUavBinding()  const { return shiftUavBinding; }
     void setResourceSetBinding(const std::vector<std::string>& shift) { resourceSetBinding = shift; }
     const std::vector<std::string>& getResourceSetBinding() const { return resourceSetBinding; }
-    void setAutoMapBindings(bool map)               { autoMapBindings = map; }
+    void setAutoMapBindings(bool map)           { autoMapBindings = map; }
     bool getAutoMapBindings()             const { return autoMapBindings; }
-    void setFlattenUniformArrays(bool flatten)      { flattenUniformArrays = flatten; }
+    void setAutoMapLocations(bool map)          { autoMapLocations = map; }
+    bool getAutoMapLocations()            const { return autoMapLocations; }
+    void setFlattenUniformArrays(bool flatten)  { flattenUniformArrays = flatten; }
     bool getFlattenUniformArrays()        const { return flattenUniformArrays; }
     void setNoStorageFormat(bool b)             { useUnknownFormat = b; }
     bool getNoStorageFormat()             const { return useUnknownFormat; }
@@ -516,6 +519,7 @@ protected:
     unsigned int shiftUavBinding;
     std::vector<std::string> resourceSetBinding;
     bool autoMapBindings;
+    bool autoMapLocations;
     bool flattenUniformArrays;
     bool useUnknownFormat;
     bool hlslOffsets;

+ 1 - 0
3rdparty/glslang/glslang/Public/ShaderLang.h

@@ -309,6 +309,7 @@ public:
     void setShiftSsboBinding(unsigned int base);
     void setResourceSetBinding(const std::vector<std::string>& base);
     void setAutoMapBindings(bool map);
+    void setAutoMapLocations(bool map);
     void setHlslIoMapping(bool hlslIoMap);
     void setFlattenUniformArrays(bool flatten);
     void setNoStorageFormat(bool useUnknownFormat);

+ 6 - 0
3rdparty/glslang/gtests/Hlsl.FromFile.cpp

@@ -109,6 +109,7 @@ INSTANTIATE_TEST_CASE_P(
         {"hlsl.emptystruct.init.vert", "main"},
         {"hlsl.entry-in.frag", "PixelShaderFunction"},
         {"hlsl.entry-out.frag", "PixelShaderFunction"},
+        {"hlsl.fraggeom.frag", "main"},
         {"hlsl.float1.frag", "PixelShaderFunction"},
         {"hlsl.float4.frag", "PixelShaderFunction"},
         {"hlsl.flatten.return.frag", "main"},
@@ -176,10 +177,14 @@ INSTANTIATE_TEST_CASE_P(
         {"hlsl.logicalConvert.frag", "main"},
         {"hlsl.logical.unary.frag", "main"},
         {"hlsl.loopattr.frag", "main"},
+        {"hlsl.mip.operator.frag", "main"},
+        {"hlsl.mip.negative.frag", "main"},
+        {"hlsl.mip.negative2.frag", "main"},
         {"hlsl.namespace.frag", "main"},
         {"hlsl.nonint-index.frag", "main"},
         {"hlsl.matNx1.frag", "main"},
         {"hlsl.matrixSwizzle.vert", "ShaderFunction"},
+        {"hlsl.memberFunCall.frag", "main"},
         {"hlsl.mintypes.frag", "main"},
         {"hlsl.multiEntry.vert", "RealEntrypoint"},
         {"hlsl.multiReturn.frag", "main"},
@@ -251,6 +256,7 @@ INSTANTIATE_TEST_CASE_P(
         {"hlsl.structarray.flatten.geom", "main"},
         {"hlsl.structbuffer.frag", "main"},
         {"hlsl.structbuffer.append.frag", "main"},
+        {"hlsl.structbuffer.append.fn.frag", "main"},
         {"hlsl.structbuffer.atomics.frag", "main"},
         {"hlsl.structbuffer.byte.frag", "main"},
         {"hlsl.structbuffer.coherent.frag", "main"},

+ 1 - 0
3rdparty/glslang/gtests/Link.FromFile.Vk.cpp

@@ -60,6 +60,7 @@ TEST_P(LinkTestVulkan, FromFile)
         shaders.emplace_back(
                 new glslang::TShader(GetShaderStage(GetSuffix(fileNames[i]))));
         auto* shader = shaders.back().get();
+        shader->setAutoMapLocations(true);
         compile(shader, contents, "", controls);
         result.shaderResults.push_back(
             {fileNames[i], shader->getInfoLog(), shader->getInfoDebugLog()});

+ 1 - 0
3rdparty/glslang/gtests/Remap.FromFile.cpp

@@ -89,6 +89,7 @@ INSTANTIATE_TEST_CASE_P(
             { "remap.basic.everything.frag",              "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
             { "remap.basic.dcefunc.frag",                 "main", Source::GLSL, spv::spirvbin_t::DCE_FUNCS },
             { "remap.basic.strip.frag",                   "main", Source::GLSL, spv::spirvbin_t::STRIP },
+            { "remap.specconst.comp",                     "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
             { "remap.switch.none.frag",                   "main", Source::GLSL, spv::spirvbin_t::NONE },
             { "remap.switch.everything.frag",             "main", Source::GLSL, spv::spirvbin_t::DO_EVERYTHING },
             { "remap.literal64.none.spv",                 "main", Source::GLSL, spv::spirvbin_t::NONE },

+ 4 - 0
3rdparty/glslang/gtests/TestFixture.h

@@ -202,6 +202,7 @@ public:
         const EShLanguage kind = GetShaderStage(GetSuffix(shaderName));
 
         glslang::TShader shader(kind);
+        shader.setAutoMapLocations(true);
         shader.setFlattenUniformArrays(flattenUniformArrays);
 
         bool success = compile(&shader, code, entryPointName, controls);
@@ -254,6 +255,7 @@ public:
         shader.setShiftUboBinding(baseUboBinding);
         shader.setShiftSsboBinding(baseSsboBinding);
         shader.setAutoMapBindings(autoMapBindings);
+        shader.setAutoMapLocations(true);
         shader.setFlattenUniformArrays(flattenUniformArrays);
 
         bool success = compile(&shader, code, entryPointName, controls);
@@ -295,6 +297,8 @@ public:
         const EShLanguage kind = GetShaderStage(GetSuffix(shaderName));
 
         glslang::TShader shader(kind);
+        shader.setAutoMapLocations(true);
+
         bool success = compile(&shader, code, entryPointName, controls);
 
         glslang::TProgram program;

+ 1 - 1
3rdparty/glslang/hlsl/hlslGrammar.cpp

@@ -1933,7 +1933,7 @@ bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList)
     // All member functions get parsed inside the class/struct namespace and with the
     // class/struct members in a symbol-table level.
     parseContext.pushNamespace(structName);
-    parseContext.pushThisScope(type);
+    parseContext.pushThisScope(type, functionDeclarators);
     bool deferredSuccess = true;
     for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) {
         // parse body

+ 240 - 78
3rdparty/glslang/hlsl/hlslParseHelper.cpp

@@ -677,19 +677,30 @@ TIntermTyped* HlslParseContext::handleBracketOperator(const TSourceLoc& loc, TIn
     if (base->getType().getBasicType() == EbtSampler && !base->isArray()) {
         const TSampler& sampler = base->getType().getSampler();
         if (sampler.isImage() || sampler.isTexture()) {
-            TIntermAggregate* load = new TIntermAggregate(sampler.isImage() ? EOpImageLoad : EOpTextureFetch);
-
-            load->setType(TType(sampler.type, EvqTemporary, sampler.vectorSize));
-            load->setLoc(loc);
-            load->getSequence().push_back(base);
-            load->getSequence().push_back(index);
-
-            // Textures need a MIP.  First indirection is always to mip 0.  If there's another, we'll add it
-            // later.
-            if (sampler.isTexture())
-                load->getSequence().push_back(intermediate.addConstantUnion(0, loc, true));
+            if (! mipsOperatorMipArg.empty() && mipsOperatorMipArg.back().mipLevel == nullptr) {
+                // The first operator[] to a .mips[] sequence is the mip level.  We'll remember it.
+                mipsOperatorMipArg.back().mipLevel = index;
+                return base;  // next [] index is to the same base.
+            } else {
+                TIntermAggregate* load = new TIntermAggregate(sampler.isImage() ? EOpImageLoad : EOpTextureFetch);
+
+                load->setType(TType(sampler.type, EvqTemporary, sampler.vectorSize));
+                load->setLoc(loc);
+                load->getSequence().push_back(base);
+                load->getSequence().push_back(index);
+
+                // Textures need a MIP.  If we saw one go by, use it.  Otherwise, use zero.
+                if (sampler.isTexture()) {
+                    if (! mipsOperatorMipArg.empty()) {
+                        load->getSequence().push_back(mipsOperatorMipArg.back().mipLevel);
+                        mipsOperatorMipArg.pop_back();
+                    } else {
+                        load->getSequence().push_back(intermediate.addConstantUnion(0, loc, true));
+                    }
+                }
 
-            return load;
+                return load;
+            }
         }
     }
 
@@ -874,7 +885,21 @@ TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TInt
     }
 
     TIntermTyped* result = base;
-    if (base->isVector() || base->isScalar()) {
+
+    if (base->getType().getBasicType() == EbtSampler) {
+        // Handle .mips[mipid][pos] operation on textures
+        const TSampler& sampler = base->getType().getSampler();
+        if (sampler.isTexture() && field == "mips") {
+            // Push a null to signify that we expect a mip level under operator[] next.
+            mipsOperatorMipArg.push_back(tMipsOperatorData(loc, nullptr));
+            // Keep 'result' pointing to 'base', since we expect an operator[] to go by next.
+        } else {
+            if (field == "mips")
+                error(loc, "unexpected texture type for .mips[][] operator:", base->getType().getCompleteString().c_str(), "");
+            else
+                error(loc, "unexpected operator on texture type:", field.c_str(), base->getType().getCompleteString().c_str());
+        }
+    } else if (base->isVector() || base->isScalar()) {
         TSwizzleSelectors<TVectorSelector> selectors;
         parseSwizzleSelector(loc, field, base->getVectorSize(), selectors);
 
@@ -1555,6 +1580,28 @@ void HlslParseContext::addInterstageIoToLinkage()
     }
 }
 
+// For struct buffers with counters, we must pass the counter buffer as hidden parameter.
+// This adds the hidden parameter to the parameter list in 'paramNodes' if needed.
+// Otherwise, it's a no-op
+void HlslParseContext::addStructBufferHiddenCounterParam(const TSourceLoc& loc, TParameter& param, TIntermAggregate*& paramNodes)
+{
+    if (! hasStructBuffCounter(*param.type))
+        return;
+
+    const TString counterBlockName(getStructBuffCounterName(*param.name));
+
+    TType counterType;
+    counterBufferType(loc, counterType);
+    TVariable *variable = makeInternalVariable(counterBlockName, counterType);
+
+    if (! symbolTable.insert(*variable))
+        error(loc, "redefinition", variable->getName().c_str(), "");
+
+    paramNodes = intermediate.growAggregate(paramNodes,
+                                            intermediate.addSymbol(*variable, loc),
+                                            loc);
+}
+
 //
 // Handle seeing the function prototype in front of a function definition in the grammar.
 // The body is handled after this function returns.
@@ -1624,7 +1671,8 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
                                                     intermediate.addSymbol(*variable, loc),
                                                     loc);
 
-            // TODO: for struct buffers with counters, pass counter buffer as hidden parameter
+            // Add hidden parameter for struct buffer counters, if needed.
+            addStructBufferHiddenCounterParam(loc, param, paramNodes);
         } else
             paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc);
     }
@@ -1960,7 +2008,7 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
 
         // GS outputs are via emit, so we do not copy them here.
         if (param.type->getQualifier().isParamOutput()) {
-            if (param.declaredBuiltIn == EbvGsOutputStream) {
+            if (param.getDeclaredBuiltIn() == EbvGsOutputStream) {
                 // GS output stream does not assign outputs here: it's the Append() method
                 // which writes to the output, probably multiple times separated by Emit.
                 // We merely remember the output to use, here.
@@ -2067,7 +2115,7 @@ void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& return
             TVariable* argAsGlobal = makeIoVariable(function[i].name->c_str(), paramType, EvqVaryingIn);
             inputs.push_back(argAsGlobal);
 
-            if (function[i].declaredBuiltIn == EbvInputPatch)
+            if (function[i].getDeclaredBuiltIn() == EbvInputPatch)
                 inputPatch = argAsGlobal;
         }
         if (paramType.getQualifier().isParamOutput()) {
@@ -2456,13 +2504,9 @@ TIntermAggregate* HlslParseContext::handleSamplerTextureCombine(const TSourceLoc
 }
 
 // Return true if this a buffer type that has an associated counter buffer.
-bool HlslParseContext::hasStructBuffCounter(const TString& name) const
+bool HlslParseContext::hasStructBuffCounter(const TType& type) const
 {
-    const auto bivIt = structBufferBuiltIn.find(name);
-    if (bivIt == structBufferBuiltIn.end())
-        return false;
-
-    switch (bivIt->second) {
+    switch (type.getQualifier().declaredBuiltIn) {
     case EbvAppendConsume:       // fall through...
     case EbvRWStructuredBuffer:  // ...
         return true;
@@ -2471,6 +2515,29 @@ bool HlslParseContext::hasStructBuffCounter(const TString& name) const
     }
 }
 
+void HlslParseContext::counterBufferType(const TSourceLoc& loc, TType& type)
+{
+    // Counter type
+    TType* counterType = new TType(EbtInt, EvqBuffer);
+    counterType->setFieldName("@count");
+
+    TTypeList* blockStruct = new TTypeList;
+    TTypeLoc  member = { counterType, loc };
+    blockStruct->push_back(member);
+
+    TType blockType(blockStruct, "", counterType->getQualifier());
+    blockType.getQualifier().storage = EvqBuffer;
+
+    type.shallowCopy(blockType);
+    shareStructBufferType(type);
+}
+
+// knowledge of how to construct block name, in one place instead of N places.
+TString HlslParseContext::getStructBuffCounterName(const TString& blockName) const
+{
+    return blockName + "@count";
+}
+
 // declare counter for a structured buffer type
 void HlslParseContext::declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name)
 {
@@ -2478,25 +2545,17 @@ void HlslParseContext::declareStructBufferCounter(const TSourceLoc& loc, const T
     if (! isStructBufferType(bufferType))
         return;
 
-    if (! hasStructBuffCounter(name))
+    if (! hasStructBuffCounter(bufferType))
         return;
 
-    // Counter type
-    TType* counterType = new TType(EbtInt, EvqBuffer);
-    counterType->setFieldName("@count");
-
-    TTypeList* blockStruct = new TTypeList;
-    TTypeLoc  member = { counterType, loc };
-    blockStruct->push_back(member);
+    TType blockType;
+    counterBufferType(loc, blockType);
 
-    TString* blockName = new TString(name);
-    *blockName += "@count";
+    TString* blockName = new TString(getStructBuffCounterName(name));
 
+    // Counter buffer does not have its own counter buffer.  TODO: there should be a better way to track this.
     structBufferCounter[*blockName] = false;
 
-    TType blockType(blockStruct, "", counterType->getQualifier());
-    blockType.getQualifier().storage = EvqBuffer;
-
     shareStructBufferType(blockType);
     declareBlock(loc, blockType, blockName);
 }
@@ -2508,13 +2567,12 @@ TIntermTyped* HlslParseContext::getStructBufferCounter(const TSourceLoc& loc, TI
     if (buffer == nullptr || ! isStructBufferType(buffer->getType()))
         return nullptr;
 
-    TString blockName(buffer->getAsSymbolNode()->getName());
-    blockName += "@count";
+    const TString counterBlockName(getStructBuffCounterName(buffer->getAsSymbolNode()->getName()));
 
     // Mark the counter as being used
-    structBufferCounter[blockName] = true;
+    structBufferCounter[counterBlockName] = true;
 
-    TIntermTyped* counterVar = handleVariable(loc, &blockName);  // find the block structure
+    TIntermTyped* counterVar = handleVariable(loc, &counterBlockName);  // find the block structure
     TIntermTyped* index = intermediate.addConstantUnion(0, loc); // index to counter inside block struct
 
     TIntermTyped* counterMember = intermediate.addIndex(EOpIndexDirectStruct, counterVar, index, loc);
@@ -2549,8 +2607,6 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte
     if (bufferObj == nullptr || bufferObj->getAsSymbolNode() == nullptr)
         return;
 
-    const TString bufferName(bufferObj->getAsSymbolNode()->getName());
-
     // Some methods require a hidden internal counter, obtained via getStructBufferCounter().
     // This lambda adds something to it and returns the old value.
     const auto incDecCounter = [&](int incval) -> TIntermTyped* {
@@ -2579,20 +2635,14 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte
         {
             TIntermTyped* argIndex = makeIntegerIndex(argAggregate->getSequence()[1]->getAsTyped());  // index
 
-            const auto bivIt = structBufferBuiltIn.find(bufferName);
-
-            const TBuiltInVariable builtInType = (bivIt != structBufferBuiltIn.end()) ? bivIt->second : EbvNone;
-
             const TType& bufferType = bufferObj->getType();
 
+            const TBuiltInVariable builtInType = bufferType.getQualifier().declaredBuiltIn;
+
             // Byte address buffers index in bytes (only multiples of 4 permitted... not so much a byte address
             // buffer then, but that's what it calls itself.
-            // TODO: it would be easier to track the declared (pre-sanitized) builtInType in the TType.
-            //       If/when that happens, this should be simplified to look *only* at the builtin type.
             const bool isByteAddressBuffer = (builtInType == EbvByteAddressBuffer   || 
-                                              builtInType == EbvRWByteAddressBuffer ||
-                                              (builtInType == EbvNone && !bufferType.isVector() &&
-                                               bufferType.getBasicType() == EbtUint));
+                                              builtInType == EbvRWByteAddressBuffer);
                 
 
             if (isByteAddressBuffer)
@@ -3660,6 +3710,12 @@ void HlslParseContext::decomposeGeometryMethods(const TSourceLoc& loc, TIntermTy
     switch (op) {
     case EOpMethodAppend:
         if (argAggregate) {
+            // Don't emit these for non-GS stage, since we won't have the gsStreamOutput symbol.
+            if (language != EShLangGeometry) {
+                node = nullptr;
+                return;
+            }
+
             TIntermAggregate* sequence = nullptr;
             TIntermAggregate* emit = new TIntermAggregate(EOpEmitVertex);
 
@@ -3689,6 +3745,12 @@ void HlslParseContext::decomposeGeometryMethods(const TSourceLoc& loc, TIntermTy
 
     case EOpMethodRestartStrip:
         {
+            // Don't emit these for non-GS stage, since we won't have the gsStreamOutput symbol.
+            if (language != EShLangGeometry) {
+                node = nullptr;
+                return;
+            }
+
             TIntermAggregate* cut = new TIntermAggregate(EOpEndPrimitive);
             cut->setLoc(loc);
             cut->setType(TType(EbtVoid));
@@ -4294,6 +4356,9 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
         //
         const TFunction* fnCandidate = nullptr;
         bool builtIn = false;
+        int thisDepth = 0;
+
+        TIntermAggregate* aggregate = arguments ? arguments->getAsAggregate() : nullptr;
 
         // TODO: this needs improvement: there's no way at present to look up a signature in
         // the symbol table for an arbitrary type.  This is a temporary hack until that ability exists.
@@ -4304,14 +4369,12 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
 
             TIntermTyped* arg0 = nullptr;
 
-            if (arguments->getAsAggregate() && arguments->getAsAggregate()->getSequence().size() > 0)
-                arg0 = arguments->getAsAggregate()->getSequence()[0]->getAsTyped();
+            if (aggregate && aggregate->getSequence().size() > 0)
+                arg0 = aggregate->getSequence()[0]->getAsTyped();
             else if (arguments->getAsSymbolNode())
                 arg0 = arguments->getAsSymbolNode();
 
             if (arg0 != nullptr && isStructBufferType(arg0->getType())) {
-                // TODO: for struct buffers with counters, pass counter buffer as hidden parameter
-
                 static const int methodPrefixSize = sizeof(BUILTIN_PREFIX)-1;
 
                 if (function->getName().length() > methodPrefixSize &&
@@ -4326,7 +4389,7 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
         }
 
         if (fnCandidate == nullptr)
-            fnCandidate = findFunction(loc, *function, builtIn, arguments);
+            fnCandidate = findFunction(loc, *function, builtIn, thisDepth, arguments);
 
         if (fnCandidate) {
             // This is a declared function that might map to
@@ -4338,10 +4401,27 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
             if (builtIn && fnCandidate->getNumExtensions())
                 requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str());
 
+            // turn an implicit member-function resolution into an explicit call
+            TString callerName;
+            if (thisDepth == 0)
+                callerName = fnCandidate->getMangledName();
+            else {
+                // get the explicit (full) name of the function
+                callerName = currentTypePrefix[currentTypePrefix.size() - thisDepth];
+                callerName += fnCandidate->getMangledName();
+                // insert the implicit calling argument
+                pushFrontArguments(intermediate.addSymbol(*getImplicitThis(thisDepth)), arguments);
+            }
+
             // Convert 'in' arguments
             if (arguments)
                 addInputArgumentConversions(*fnCandidate, arguments);
 
+            // If any argument is a pass-by-reference struct buffer with an associated counter
+            // buffer, we have to add another hidden parameter for that counter.
+            if (aggregate && !builtIn)
+                addStructBuffArguments(loc, aggregate);
+
             op = fnCandidate->getBuiltInOp();
             if (builtIn && op != EOpNull) {
                 // A function call mapped to a built-in operation.
@@ -4358,14 +4438,14 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
                 // It could still be a built-in function, but only if PureOperatorBuiltins == false.
                 result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc);
                 TIntermAggregate* call = result->getAsAggregate();
-                call->setName(fnCandidate->getMangledName());
+                call->setName(callerName);
 
                 // this is how we know whether the given function is a built-in function or a user-defined function
                 // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also
                 // if builtIn == true, it's definitely a built-in function with EOpNull
                 if (! builtIn) {
                     call->setUserDefined();
-                    intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName());
+                    intermediate.addToCallGraph(infoSink, currentCaller, callerName);
                 }
             }
 
@@ -4388,7 +4468,12 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
                 for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
                     TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage;
                     qualifierList.push_back(qual);
+
+                    // add counter buffer argument qualifier
+                    if (hasStructBuffCounter(*(*fnCandidate)[i].type))
+                        qualifierList.push_back(qual);
                 }
+
                 result = addOutputArgumentConversions(*fnCandidate, *result->getAsOperator());
             }
         }
@@ -4402,6 +4487,19 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
     return result;
 }
 
+// An initial argument list is difficult: it can be null, or a single node,
+// or an aggregate if more than one argument.  Add one to the front, maintaining
+// this lack of uniformity.
+void HlslParseContext::pushFrontArguments(TIntermTyped* front, TIntermTyped*& arguments)
+{
+    if (arguments == nullptr)
+        arguments = front;
+    else if (arguments->getAsAggregate() != nullptr)
+        arguments->getAsAggregate()->getSequence().insert(arguments->getAsAggregate()->getSequence().begin(), front);
+    else
+        arguments = intermediate.growAggregate(front, arguments);
+}
+
 //
 // Add any needed implicit conversions for function-call arguments to input parameters.
 //
@@ -4557,6 +4655,55 @@ TIntermTyped* HlslParseContext::addOutputArgumentConversions(const TFunction& fu
     return conversionTree;
 }
 
+//
+// Add any needed "hidden" counter buffer arguments for function calls.
+//
+// Modifies the 'aggregate' argument if needed.  Otherwise, is no-op.
+//
+void HlslParseContext::addStructBuffArguments(const TSourceLoc& loc, TIntermAggregate*& aggregate)
+{
+    // See if there are any SB types with counters.
+    const bool hasStructBuffArg =
+        std::any_of(aggregate->getSequence().begin(),
+                    aggregate->getSequence().end(),
+                    [this](const TIntermNode* node) {
+                        return (node->getAsTyped() != nullptr) && hasStructBuffCounter(node->getAsTyped()->getType());
+                    });
+
+    // Nothing to do, if we didn't find one.
+    if (! hasStructBuffArg)
+        return;
+
+    TIntermSequence argsWithCounterBuffers;
+
+    for (int param=0; param<int(aggregate->getSequence().size()); ++param) {
+        argsWithCounterBuffers.push_back(aggregate->getSequence()[param]);
+
+        if (hasStructBuffCounter(aggregate->getSequence()[param]->getAsTyped()->getType())) {
+            const TIntermSymbol* blockSym = aggregate->getSequence()[param]->getAsSymbolNode();
+            if (blockSym != nullptr) {
+                TType counterType;
+                counterBufferType(loc, counterType);
+
+                const TString counterBlockName(getStructBuffCounterName(blockSym->getName()));
+
+                TVariable* variable = makeInternalVariable(counterBlockName, counterType);
+
+                // Mark this buffer as requiring a counter block.  TODO: there should be a better
+                // way to track it.
+                structBufferCounter[counterBlockName] = true;
+
+                TIntermSymbol* sym = intermediate.addSymbol(*variable, loc);
+                argsWithCounterBuffers.push_back(sym);
+            }
+        }
+    }
+
+    // Swap with the temp list we've built up.
+    aggregate->getSequence().swap(argsWithCounterBuffers);
+}
+
+
 //
 // Do additional checking of built-in function calls that is not caught
 // by normal semantic checks on argument type, extension tagging, etc.
@@ -5715,6 +5862,7 @@ void HlslParseContext::paramFix(TType& type)
             bufferQualifier.storage = type.getQualifier().storage;
             bufferQualifier.readonly = type.getQualifier().readonly;
             bufferQualifier.coherent = type.getQualifier().coherent;
+            bufferQualifier.declaredBuiltIn = type.getQualifier().declaredBuiltIn;
             type.getQualifier() = bufferQualifier;
             break;
         }
@@ -6159,18 +6307,17 @@ void HlslParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQuali
 //
 // Return the function symbol if found, otherwise nullptr.
 //
-const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn,
+const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, int& thisDepth,
                                                 TIntermTyped*& args)
 {
-    // const TFunction* function = nullptr;
-
     if (symbolTable.isFunctionNameVariable(call.getName())) {
         error(loc, "can't use function syntax on variable", call.getName().c_str(), "");
         return nullptr;
     }
 
     // first, look for an exact match
-    TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn);
+    bool dummyScope;
+    TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn, &dummyScope, &thisDepth);
     if (symbol)
         return symbol->getAsFunction();
 
@@ -6180,7 +6327,7 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction
     TVector<const TFunction*> candidateList;
     symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn);
 
-    // These builtin ops can accept any type, so we bypass the argument selection
+    // These built-in ops can accept any type, so we bypass the argument selection
     if (candidateList.size() == 1 && builtIn &&
         (candidateList[0]->getBuiltInOp() == EOpMethodAppend ||
          candidateList[0]->getBuiltInOp() == EOpMethodRestartStrip ||
@@ -7197,10 +7344,6 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TS
     switch (type.getQualifier().storage) {
     case EvqUniform:
     case EvqBuffer:
-        // remember pre-sanitized builtin type
-        if (type.getQualifier().storage == EvqBuffer && instanceName != nullptr)
-            structBufferBuiltIn[*instanceName] = type.getQualifier().builtIn;
-
         correctUniform(type.getQualifier());
         break;
     case EvqVaryingIn:
@@ -7761,11 +7904,23 @@ TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* ex
 
 // Make a new symbol-table level that is made out of the members of a structure.
 // This should be done as an anonymous struct (name is "") so that the symbol table
-// finds the members with on explicit reference to a 'this' variable.
-void HlslParseContext::pushThisScope(const TType& thisStruct)
+// finds the members with no explicit reference to a 'this' variable.
+void HlslParseContext::pushThisScope(const TType& thisStruct, const TVector<TFunctionDeclarator>& functionDeclarators)
 {
+    // member variables
     TVariable& thisVariable = *new TVariable(NewPoolTString(""), thisStruct);
     symbolTable.pushThis(thisVariable);
+
+    // member functions
+    for (auto it = functionDeclarators.begin(); it != functionDeclarators.end(); ++it) {
+        // member should have a prefix matching currentTypePrefix.back()
+        // but, symbol lookup within the class scope will just use the
+        // unprefixed name. Hence, there are two: one fully prefixed and
+        // one with no prefix.
+        TFunction& member = *it->function->clone();
+        member.removePrefix(currentTypePrefix.back());
+        symbolTable.insert(member);
+    }
 }
 
 // Track levels of class/struct/namespace nesting with a prefix string using
@@ -7780,11 +7935,10 @@ void HlslParseContext::pushNamespace(const TString& typeName)
 {
     // make new type prefix
     TString newPrefix;
-    if (currentTypePrefix.size() > 0) {
+    if (currentTypePrefix.size() > 0)
         newPrefix = currentTypePrefix.back();
-        newPrefix.append(scopeMangler);
-    }
     newPrefix.append(typeName);
+    newPrefix.append(scopeMangler);
     currentTypePrefix.push_back(newPrefix);
 }
 
@@ -7802,7 +7956,6 @@ void HlslParseContext::getFullNamespaceName(const TString*& name) const
         return;
 
     TString* fullName = NewPoolTString(currentTypePrefix.back().c_str());
-    fullName->append(scopeMangler);
     fullName->append(*name);
     name = fullName;
 }
@@ -8006,6 +8159,9 @@ void HlslParseContext::correctOutput(TQualifier& qualifier)
 // Make the IO decorations etc. be appropriate only for uniform type interfaces.
 void HlslParseContext::correctUniform(TQualifier& qualifier)
 {
+    if (qualifier.declaredBuiltIn == EbvNone)
+        qualifier.declaredBuiltIn = qualifier.builtIn;
+
     qualifier.builtIn = EbvNone;
     qualifier.clearInterstage();
     qualifier.clearInterstageLayout();
@@ -8074,8 +8230,8 @@ void HlslParseContext::addPatchConstantInvocation()
             if (storage == EvqConstReadOnly) // treated identically to input
                 storage = EvqIn;
 
-            if (function[p].declaredBuiltIn != EbvNone)
-                builtIns.insert(HlslParseContext::tInterstageIoData(function[p].declaredBuiltIn, storage));
+            if (function[p].getDeclaredBuiltIn() != EbvNone)
+                builtIns.insert(HlslParseContext::tInterstageIoData(function[p].getDeclaredBuiltIn(), storage));
             else
                 builtIns.insert(HlslParseContext::tInterstageIoData(function[p].type->getQualifier().builtIn, storage));
         }
@@ -8105,7 +8261,7 @@ void HlslParseContext::addPatchConstantInvocation()
 
     const auto isOutputPatch = [this](TFunction& patchConstantFunction, int param) {
         const TType& type = *patchConstantFunction[param].type;
-        const TBuiltInVariable biType = patchConstantFunction[param].declaredBuiltIn;
+        const TBuiltInVariable biType = patchConstantFunction[param].getDeclaredBuiltIn();
 
         return type.isArray() && !type.isRuntimeSizedArray() && biType == EbvOutputPatch;
     };
@@ -8161,7 +8317,7 @@ void HlslParseContext::addPatchConstantInvocation()
 
         // Now we'll add those to the entry and to the linkage.
         for (int p=0; p<pcfParamCount; ++p) {
-            const TBuiltInVariable biType   = patchConstantFunction[p].declaredBuiltIn;
+            const TBuiltInVariable biType   = patchConstantFunction[p].getDeclaredBuiltIn();
             TStorageQualifier storage = patchConstantFunction[p].type->getQualifier().storage;
 
             // Track whether there is an output patch param
@@ -8227,7 +8383,7 @@ void HlslParseContext::addPatchConstantInvocation()
                 inputArg = intermediate.addSymbol(*perCtrlPtVar, loc);
             } else {
                 // find which builtin it is
-                const TBuiltInVariable biType = patchConstantFunction[p].declaredBuiltIn;
+                const TBuiltInVariable biType = patchConstantFunction[p].getDeclaredBuiltIn();
                 
                 inputArg = findLinkageSymbol(biType);
 
@@ -8308,7 +8464,7 @@ void HlslParseContext::addPatchConstantInvocation()
 
                 if (paramType.getQualifier().isParamInput())  {
                     TIntermTyped* arg = nullptr;
-                    if ((*entryPointFunction)[i].declaredBuiltIn == EbvInvocationId) {
+                    if ((*entryPointFunction)[i].getDeclaredBuiltIn() == EbvInvocationId) {
                         // substitute invocation ID with the array element ID
                         arg = intermediate.addConstantUnion(cpt, loc);
                     } else {
@@ -8414,6 +8570,12 @@ void HlslParseContext::removeUnusedStructBufferCounters()
 // post-processing
 void HlslParseContext::finish()
 {
+    // Error check: There was a dangling .mips operator.  These are not nested constructs in the grammar, so
+    // cannot be detected there.  This is not strictly needed in a non-validating parser; it's just helpful.
+    if (! mipsOperatorMipArg.empty()) {
+        error(mipsOperatorMipArg.back().loc, "unterminated mips operator:", "", "");
+    }
+
     removeUnusedStructBufferCounters();
     addPatchConstantInvocation();
     addInterstageIoToLinkage();

+ 20 - 4
3rdparty/glslang/hlsl/hlslParseHelper.h

@@ -42,6 +42,7 @@
 namespace glslang {
 
 class TAttributeMap; // forward declare
+class TFunctionDeclarator;
 
 class HlslParseContext : public TParseContextBase {
 public:
@@ -93,6 +94,7 @@ public:
     void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
     void decomposeStructBufferMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
     void decomposeGeometryMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
+    void pushFrontArguments(TIntermTyped* front, TIntermTyped*& arguments);
     void addInputArgumentConversions(const TFunction&, TIntermTyped*&);
     TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&);
     void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
@@ -135,7 +137,7 @@ public:
     void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
     void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
 
-    const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, TIntermTyped*& args);
+    const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, int& thisDepth, TIntermTyped*& args);
     void declareTypedef(const TSourceLoc&, const TString& identifier, const TType&);
     void declareStruct(const TSourceLoc&, TString& structName, TType&);
     TSymbol* lookupUserType(const TString&, TType&);
@@ -166,7 +168,7 @@ public:
     void pushScope()         { symbolTable.push(); }
     void popScope()          { symbolTable.pop(0); }
 
-    void pushThisScope(const TType&);
+    void pushThisScope(const TType&, const TVector<TFunctionDeclarator>&);
     void popThisScope()      { symbolTable.pop(0); }
 
     void pushImplicitThis(TVariable* thisParameter) { implicitThisStack.push_back(thisParameter); }
@@ -275,6 +277,7 @@ protected:
 
     // Test method names
     bool isStructBufferMethod(const TString& name) const;
+    void counterBufferType(const TSourceLoc& loc, TType& type);
 
     // Return standard sample position array
     TIntermConstantUnion* getSamplePosArray(int count);
@@ -283,13 +286,16 @@ protected:
     bool isStructBufferType(const TType& type) const { return getStructBufferContentType(type) != nullptr; }
     TIntermTyped* indexStructBufferContent(const TSourceLoc& loc, TIntermTyped* buffer) const;
     TIntermTyped* getStructBufferCounter(const TSourceLoc& loc, TIntermTyped* buffer);
+    TString getStructBuffCounterName(const TString&) const;
+    void addStructBuffArguments(const TSourceLoc& loc, TIntermAggregate*&);
+    void addStructBufferHiddenCounterParam(const TSourceLoc& loc, TParameter&, TIntermAggregate*&);
 
     // Return true if this type is a reference.  This is not currently a type method in case that's
     // a language specific answer.
     bool isReference(const TType& type) const { return isStructBufferType(type); }
 
     // Return true if this a buffer type that has an associated counter buffer.
-    bool hasStructBuffCounter(const TString& name) const;
+    bool hasStructBuffCounter(const TType&) const;
 
     // Finalization step: remove unused buffer blocks from linkage (we don't know until the
     // shader is entirely compiled)
@@ -383,7 +389,6 @@ protected:
     // Structuredbuffer shared types.  Typically there are only a few.
     TVector<TType*> structBufferTypes;
     
-    TMap<TString, TBuiltInVariable> structBufferBuiltIn;
     TMap<TString, bool> structBufferCounter;
 
     // The builtin interstage IO map considers e.g, EvqPosition on input and output separately, so that we
@@ -429,6 +434,17 @@ protected:
     TVector<TVariable*> implicitThisStack;   // currently active 'this' variables for nested structures
 
     TVariable* gsStreamOutput;               // geometry shader stream outputs, for emit (Append method)
+
+    // This tracks the first (mip level) argument to the .mips[][] operator.  Since this can be nested as
+    // in tx.mips[tx.mips[0][1].x][2], we need a stack.  We also track the TSourceLoc for error reporting 
+    // purposes.
+    struct tMipsOperatorData {
+        tMipsOperatorData(TSourceLoc l, TIntermTyped* m) : loc(l), mipLevel(m) { }
+        TSourceLoc loc;
+        TIntermTyped* mipLevel;
+    };
+
+    TVector<tMipsOperatorData> mipsOperatorMipArg;
 };
 
 // This is the prefix we use for builtin methods to avoid namespace collisions with