Branimir Karadžić 8 éve
szülő
commit
0e1893f292

+ 14 - 4
3rdparty/glslang/SPIRV/GlslangToSpv.cpp

@@ -2914,6 +2914,13 @@ bool TGlslangToSpvTraverser::isShaderEntryPoint(const glslang::TIntermAggregate*
 // Make all the functions, skeletally, without actually visiting their bodies.
 void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions)
 {
+    const auto getParamDecorations = [](std::vector<spv::Decoration>& decorations, const glslang::TType& type) {
+        spv::Decoration paramPrecision = TranslatePrecisionDecoration(type);
+        if (paramPrecision != spv::NoPrecision)
+            decorations.push_back(paramPrecision);
+        TranslateMemoryDecoration(type.getQualifier(), decorations);
+    };
+
     for (int f = 0; f < (int)glslFunctions.size(); ++f) {
         glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate();
         if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction || isShaderEntryPoint(glslFunction))
@@ -2934,11 +2941,13 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
         //   GLSL has copy-in/copy-out semantics.  They can be handled though with a pointer to a copy.
 
         std::vector<spv::Id> paramTypes;
-        std::vector<spv::Decoration> paramPrecisions;
+        std::vector<std::vector<spv::Decoration>> paramDecorations; // list of decorations per parameter
         glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence();
 
-        bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() == glslangIntermediate->implicitThisName;
+        bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() ==
+                                                          glslangIntermediate->implicitThisName;
 
+        paramDecorations.resize(parameters.size());
         for (int p = 0; p < (int)parameters.size(); ++p) {
             const glslang::TType& paramType = parameters[p]->getAsTyped()->getType();
             spv::Id typeId = convertGlslangToSpvType(paramType);
@@ -2952,14 +2961,15 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
                 typeId = builder.makePointer(spv::StorageClassFunction, typeId);
             else
                 rValueParameters.insert(parameters[p]->getAsSymbolNode()->getId());
-            paramPrecisions.push_back(TranslatePrecisionDecoration(paramType));
+            getParamDecorations(paramDecorations[p], paramType);
             paramTypes.push_back(typeId);
         }
 
         spv::Block* functionBlock;
         spv::Function *function = builder.makeFunctionEntry(TranslatePrecisionDecoration(glslFunction->getType()),
                                                             convertGlslangToSpvType(glslFunction->getType()),
-                                                            glslFunction->getName().c_str(), paramTypes, paramPrecisions, &functionBlock);
+                                                            glslFunction->getName().c_str(), paramTypes,
+                                                            paramDecorations, &functionBlock);
         if (implicitThis)
             function->setImplicitThis();
 

+ 7 - 5
3rdparty/glslang/SPIRV/SpvBuilder.cpp

@@ -983,16 +983,16 @@ Function* Builder::makeEntryPoint(const char* entryPoint)
 
     Block* entry;
     std::vector<Id> params;
-    std::vector<Decoration> precisions;
+    std::vector<std::vector<Decoration>> decorations;
 
-    entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, precisions, &entry);
+    entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, decorations, &entry);
 
     return entryPointFunction;
 }
 
 // Comments in header
 Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
-                                     const std::vector<Id>& paramTypes, const std::vector<Decoration>& precisions, Block **entry)
+                                     const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry)
 {
     // Make the function and initial instructions in it
     Id typeId = makeFunctionType(returnType, paramTypes);
@@ -1001,8 +1001,10 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
 
     // Set up the precisions
     setPrecision(function->getId(), precision);
-    for (unsigned p = 0; p < (unsigned)precisions.size(); ++p)
-        setPrecision(firstParamId + p, precisions[p]);
+    for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) {
+        for (int d = 0; d < (int)decorations[p].size(); ++d)
+            addDecoration(firstParamId + p, decorations[p][d]);
+    }
 
     // CFG
     if (entry) {

+ 1 - 1
3rdparty/glslang/SPIRV/SpvBuilder.h

@@ -247,7 +247,7 @@ public:
     // Return the function, pass back the entry.
     // The returned pointer is only valid for the lifetime of this builder.
     Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
-                                const std::vector<Decoration>& precisions, Block **entry = 0);
+                                const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
 
     // Create a return. An 'implicit' return is one not appearing in the source
     // code.  In the case of an implicit return, no post-return block is inserted.

+ 21 - 20
3rdparty/glslang/StandAlone/StandAlone.cpp

@@ -289,31 +289,29 @@ void ProcessResourceSetBindingBase(int& argc, char**& argv, std::array<std::vect
         usage();
 
     if (!isdigit(argv[1][0])) {
-        if (argc < 5) // this form needs one more argument
+        if (argc < 3) // this form needs one more argument
             usage();
 
-        // Parse form: --argname stage base
+        // Parse form: --argname stage [regname set base...], or:
+        //             --argname stage set
         const EShLanguage lang = FindLanguage(argv[1], false);
 
-        base[lang].push_back(argv[2]);
-        base[lang].push_back(argv[3]);
-        base[lang].push_back(argv[4]);
-        argc -= 4;
-        argv += 4;
-        while(argv[1] != NULL) {
-            if(argv[1][0] != '-') {
-                base[lang].push_back(argv[1]);
-                base[lang].push_back(argv[2]);
-                base[lang].push_back(argv[3]);
-                argc -= 3;
-                argv += 3;
-            }
-            else {
-                break;
-            }
+        argc--;
+        argv++;
+
+        while (argc > 1 && argv[1] != nullptr && argv[1][0] != '-') {
+            base[lang].push_back(argv[1]);
+
+            argc--;
+            argv++;
         }
+
+        // Must have one arg, or a multiple of three (for [regname set binding] triples)
+        if (base[lang].size() != 1 && (base[lang].size() % 3) != 0)
+            usage();
+
     } else {
-        // Parse form: --argname base
+        // Parse form: --argname set
         for (int lang=0; lang<EShLangCount; ++lang)
             base[lang].push_back(argv[1]);
 
@@ -1187,7 +1185,10 @@ void usage()
            "  --ku                                 synonym for --keep-uncalled\n"
            "  --no-storage-format                  use Unknown image format\n"
            "  --nsf                                synonym for --no-storage-format\n"
-           "  --resource-set-binding [stage] num   descriptor set and binding for resources\n"
+           "  --resource-set-binding [stage] name set binding\n"
+           "              Set descriptor set and binding for individual resources\n"
+           "  --resource-set-binding [stage] set\n"
+           "              Set descriptor set for all resources\n"
            "  --rsb [stage] type set binding       synonym for --resource-set-binding\n"
            "  --shift-image-binding [stage] num    base binding number for images (uav)\n"
            "  --sib [stage] num                    synonym for --shift-image-binding\n"

+ 4 - 3
3rdparty/glslang/Test/baseResults/glspv.frag.out

@@ -1,9 +1,10 @@
 glspv.frag
 ERROR: 0:4: '#error' : GL_SPIRV is set ( correct , not an error )  
 ERROR: 0:6: '#error' : GL_SPIR is 100  
-ERROR: 0:14: 'input_attachment_index' : only allowed when using GLSL for Vulkan 
-ERROR: 0:14: '' :  syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
-ERROR: 4 compilation errors.  No code generated.
+ERROR: 0:14: 'f' : non-opaque uniform variables need a layout(location=L) 
+ERROR: 0:19: 'input_attachment_index' : only allowed when using GLSL for Vulkan 
+ERROR: 0:19: '' :  syntax error, unexpected IDENTIFIER, expecting LEFT_BRACE or COMMA or SEMICOLON
+ERROR: 5 compilation errors.  No code generated.
 
 
 SPIR-V is not generated for failed compile or link

+ 66 - 0
3rdparty/glslang/Test/baseResults/hlsl.explicitDescriptorSet-2.frag.out

@@ -0,0 +1,66 @@
+hlsl.explicitDescriptorSet.frag
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 31
+
+                              Capability Shader
+                              Capability Sampled1D
+                              Capability SampledBuffer
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 19
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 500
+                              Name 4  "main"
+                              Name 9  "@main("
+                              Name 13  "g_sSamp2_amb"
+                              Name 19  "@entryPointOutput"
+                              Name 21  "g_sSamp"
+                              Name 24  "g_tTex1df4"
+                              Name 25  "$Global"
+                              MemberName 25($Global) 0  "floatval_amb"
+                              Name 27  ""
+                              Name 30  "floatbuff"
+                              Decorate 13(g_sSamp2_amb) DescriptorSet 3
+                              Decorate 13(g_sSamp2_amb) Binding 10
+                              Decorate 19(@entryPointOutput) Location 0
+                              Decorate 21(g_sSamp) DescriptorSet 3
+                              Decorate 21(g_sSamp) Binding 11
+                              Decorate 24(g_tTex1df4) DescriptorSet 3
+                              Decorate 24(g_tTex1df4) Binding 20
+                              MemberDecorate 25($Global) 0 Offset 0
+                              Decorate 25($Global) Block
+                              Decorate 27 DescriptorSet 3
+                              Decorate 30(floatbuff) DescriptorSet 3
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeFunction 7(fvec4)
+              11:             TypeSampler
+              12:             TypePointer UniformConstant 11
+13(g_sSamp2_amb):     12(ptr) Variable UniformConstant
+              14:    6(float) Constant 0
+              15:    7(fvec4) ConstantComposite 14 14 14 14
+              18:             TypePointer Output 7(fvec4)
+19(@entryPointOutput):     18(ptr) Variable Output
+     21(g_sSamp):     12(ptr) Variable UniformConstant
+              22:             TypeImage 6(float) 1D sampled format:Unknown
+              23:             TypePointer UniformConstant 22
+  24(g_tTex1df4):     23(ptr) Variable UniformConstant
+     25($Global):             TypeStruct 6(float)
+              26:             TypePointer Uniform 25($Global)
+              27:     26(ptr) Variable Uniform
+              28:             TypeImage 6(float) Buffer sampled format:R32f
+              29:             TypePointer UniformConstant 28
+   30(floatbuff):     29(ptr) Variable UniformConstant
+         4(main):           2 Function None 3
+               5:             Label
+              20:    7(fvec4) FunctionCall 9(@main()
+                              Store 19(@entryPointOutput) 20
+                              Return
+                              FunctionEnd
+       9(@main():    7(fvec4) Function None 8
+              10:             Label
+                              ReturnValue 15
+                              FunctionEnd

+ 66 - 0
3rdparty/glslang/Test/baseResults/hlsl.explicitDescriptorSet.frag.out

@@ -0,0 +1,66 @@
+hlsl.explicitDescriptorSet.frag
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 31
+
+                              Capability Shader
+                              Capability Sampled1D
+                              Capability SampledBuffer
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 19
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 500
+                              Name 4  "main"
+                              Name 9  "@main("
+                              Name 13  "g_sSamp2_amb"
+                              Name 19  "@entryPointOutput"
+                              Name 21  "g_sSamp"
+                              Name 24  "g_tTex1df4"
+                              Name 25  "$Global"
+                              MemberName 25($Global) 0  "floatval_amb"
+                              Name 27  ""
+                              Name 30  "floatbuff"
+                              Decorate 13(g_sSamp2_amb) DescriptorSet 4
+                              Decorate 13(g_sSamp2_amb) Binding 10
+                              Decorate 19(@entryPointOutput) Location 0
+                              Decorate 21(g_sSamp) DescriptorSet 4
+                              Decorate 21(g_sSamp) Binding 11
+                              Decorate 24(g_tTex1df4) DescriptorSet 4
+                              Decorate 24(g_tTex1df4) Binding 20
+                              MemberDecorate 25($Global) 0 Offset 0
+                              Decorate 25($Global) Block
+                              Decorate 27 DescriptorSet 4
+                              Decorate 30(floatbuff) DescriptorSet 4
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeFunction 7(fvec4)
+              11:             TypeSampler
+              12:             TypePointer UniformConstant 11
+13(g_sSamp2_amb):     12(ptr) Variable UniformConstant
+              14:    6(float) Constant 0
+              15:    7(fvec4) ConstantComposite 14 14 14 14
+              18:             TypePointer Output 7(fvec4)
+19(@entryPointOutput):     18(ptr) Variable Output
+     21(g_sSamp):     12(ptr) Variable UniformConstant
+              22:             TypeImage 6(float) 1D sampled format:Unknown
+              23:             TypePointer UniformConstant 22
+  24(g_tTex1df4):     23(ptr) Variable UniformConstant
+     25($Global):             TypeStruct 6(float)
+              26:             TypePointer Uniform 25($Global)
+              27:     26(ptr) Variable Uniform
+              28:             TypeImage 6(float) Buffer sampled format:R32f
+              29:             TypePointer UniformConstant 28
+   30(floatbuff):     29(ptr) Variable UniformConstant
+         4(main):           2 Function None 3
+               5:             Label
+              20:    7(fvec4) FunctionCall 9(@main()
+                              Store 19(@entryPointOutput) 20
+                              Return
+                              FunctionEnd
+       9(@main():    7(fvec4) Function None 8
+              10:             Label
+                              ReturnValue 15
+                              FunctionEnd

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

@@ -184,6 +184,7 @@ gl_FragCoord origin is upper left
                               MemberDecorate 9 0 NonWritable
                               MemberDecorate 9 0 Offset 0
                               Decorate 9 BufferBlock
+                              Decorate 13(sb) NonWritable
                               Decorate 17 ArrayStride 16
                               MemberDecorate 18 0 Offset 0
                               Decorate 18 BufferBlock

+ 1 - 0
3rdparty/glslang/Test/baseResults/hlsl.structbuffer.fn2.comp.out

@@ -166,6 +166,7 @@ local_size = (256, 1, 1)
                               MemberDecorate 9 0 NonWritable
                               MemberDecorate 9 0 Offset 0
                               Decorate 9 BufferBlock
+                              Decorate 14(buffer) NonWritable
                               Decorate 44(g_input) DescriptorSet 0
                               Decorate 44(g_input) Binding 0
                               Decorate 50(g_output) DescriptorSet 0

+ 137 - 0
3rdparty/glslang/Test/baseResults/spv.paramMemory.frag.out

@@ -0,0 +1,137 @@
+spv.paramMemory.frag
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 69
+
+                              Capability Shader
+                              Capability StorageImageReadWithoutFormat
+                              Capability StorageImageWriteWithoutFormat
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 27 66
+                              ExecutionMode 4 OriginUpperLeft
+                              Source ESSL 310
+                              Name 4  "main"
+                              Name 16  "image_load(I21;vi2;"
+                              Name 14  "image"
+                              Name 15  "coords"
+                              Name 23  "image_store(I21;vi2;vf4;"
+                              Name 20  "image"
+                              Name 21  "coords"
+                              Name 22  "data"
+                              Name 27  "in_coords"
+                              Name 35  "read1"
+                              Name 38  "image1"
+                              Name 39  "param"
+                              Name 42  "read2"
+                              Name 45  "image2"
+                              Name 46  "param"
+                              Name 49  "image3"
+                              Name 53  "param"
+                              Name 55  "param"
+                              Name 57  "image4"
+                              Name 61  "param"
+                              Name 63  "param"
+                              Name 66  "out_color"
+                              Decorate 14(image) Coherent
+                              Decorate 14(image) NonWritable
+                              Decorate 20(image) Coherent
+                              Decorate 20(image) NonReadable
+                              Decorate 27(in_coords) Flat
+                              Decorate 27(in_coords) Location 0
+                              Decorate 38(image1) DescriptorSet 0
+                              Decorate 38(image1) Binding 0
+                              Decorate 38(image1) Coherent
+                              Decorate 38(image1) NonWritable
+                              Decorate 45(image2) DescriptorSet 0
+                              Decorate 45(image2) Binding 2
+                              Decorate 45(image2) NonWritable
+                              Decorate 49(image3) DescriptorSet 0
+                              Decorate 49(image3) Binding 1
+                              Decorate 49(image3) Coherent
+                              Decorate 49(image3) NonReadable
+                              Decorate 57(image4) DescriptorSet 0
+                              Decorate 57(image4) Binding 3
+                              Decorate 57(image4) NonReadable
+                              Decorate 66(out_color) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeImage 6(float) 2D nonsampled format:Unknown
+               8:             TypePointer UniformConstant 7
+               9:             TypeInt 32 1
+              10:             TypeVector 9(int) 2
+              11:             TypePointer Function 10(ivec2)
+              12:             TypeVector 6(float) 4
+              13:             TypeFunction 12(fvec4) 8(ptr) 11(ptr)
+              18:             TypePointer Function 12(fvec4)
+              19:             TypeFunction 2 8(ptr) 11(ptr) 18(ptr)
+              26:             TypePointer Input 10(ivec2)
+   27(in_coords):     26(ptr) Variable Input
+              36:             TypeImage 6(float) 2D nonsampled format:Rgba32f
+              37:             TypePointer UniformConstant 36
+      38(image1):     37(ptr) Variable UniformConstant
+              43:             TypeImage 6(float) 2D nonsampled format:Rgba16f
+              44:             TypePointer UniformConstant 43
+      45(image2):     44(ptr) Variable UniformConstant
+      49(image3):     37(ptr) Variable UniformConstant
+              51:    6(float) Constant 1056964608
+      57(image4):     44(ptr) Variable UniformConstant
+              59:    6(float) Constant 1073741824
+              65:             TypePointer Output 12(fvec4)
+   66(out_color):     65(ptr) Variable Output
+              67:    6(float) Constant 0
+              68:   12(fvec4) ConstantComposite 67 67 67 67
+         4(main):           2 Function None 3
+               5:             Label
+       35(read1):     18(ptr) Variable Function
+       39(param):     11(ptr) Variable Function
+       42(read2):     18(ptr) Variable Function
+       46(param):     11(ptr) Variable Function
+       53(param):     11(ptr) Variable Function
+       55(param):     18(ptr) Variable Function
+       61(param):     11(ptr) Variable Function
+       63(param):     18(ptr) Variable Function
+              40:   10(ivec2) Load 27(in_coords)
+                              Store 39(param) 40
+              41:   12(fvec4) FunctionCall 16(image_load(I21;vi2;) 38(image1) 39(param)
+                              Store 35(read1) 41
+              47:   10(ivec2) Load 27(in_coords)
+                              Store 46(param) 47
+              48:   12(fvec4) FunctionCall 16(image_load(I21;vi2;) 45(image2) 46(param)
+                              Store 42(read2) 48
+              50:   12(fvec4) Load 35(read1)
+              52:   12(fvec4) VectorTimesScalar 50 51
+              54:   10(ivec2) Load 27(in_coords)
+                              Store 53(param) 54
+                              Store 55(param) 52
+              56:           2 FunctionCall 23(image_store(I21;vi2;vf4;) 49(image3) 53(param) 55(param)
+              58:   12(fvec4) Load 42(read2)
+              60:   12(fvec4) VectorTimesScalar 58 59
+              62:   10(ivec2) Load 27(in_coords)
+                              Store 61(param) 62
+                              Store 63(param) 60
+              64:           2 FunctionCall 23(image_store(I21;vi2;vf4;) 57(image4) 61(param) 63(param)
+                              Store 66(out_color) 68
+                              Return
+                              FunctionEnd
+16(image_load(I21;vi2;):   12(fvec4) Function None 13
+       14(image):      8(ptr) FunctionParameter
+      15(coords):     11(ptr) FunctionParameter
+              17:             Label
+              25:           7 Load 14(image)
+              28:   10(ivec2) Load 27(in_coords)
+              29:   12(fvec4) ImageRead 25 28
+                              ReturnValue 29
+                              FunctionEnd
+23(image_store(I21;vi2;vf4;):           2 Function None 19
+       20(image):      8(ptr) FunctionParameter
+      21(coords):     11(ptr) FunctionParameter
+        22(data):     18(ptr) FunctionParameter
+              24:             Label
+              32:           7 Load 20(image)
+              33:   10(ivec2) Load 27(in_coords)
+              34:   12(fvec4) Load 22(data)
+                              ImageWrite 32 33 34
+                              Return
+                              FunctionEnd

+ 6 - 1
3rdparty/glslang/Test/glspv.frag

@@ -1,4 +1,4 @@
-#version 330
+#version 450
 
 #ifdef GL_SPIRV
 #error GL_SPIRV is set ( correct, not an error )
@@ -11,4 +11,9 @@ void main()
 {
 }
 
+uniform float f; // ERROR, no location
+layout(location = 2) uniform float g;
+uniform sampler2D s1;
+layout(location = 3) uniform sampler2D s2;
+
 layout(input_attachment_index = 1) uniform subpassInput sub; // ERROR, no inputs

+ 15 - 0
3rdparty/glslang/Test/hlsl.explicitDescriptorSet.frag

@@ -0,0 +1,15 @@
+SamplerState       g_sSamp : register(s1);
+
+Texture1D <float4> g_tTex1df4 : register(t0);
+
+SamplerState       g_sSamp2_amb;
+uniform float      floatval_amb;
+
+Buffer<float>      floatbuff;
+
+float4 main() : SV_Target0
+{
+    g_sSamp2_amb;
+
+    return 0;
+}

+ 6 - 0
3rdparty/glslang/Test/runtests

@@ -97,6 +97,12 @@ 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 || HASERROR=1
 
+$EXE -V -D -e main -H hlsl.explicitDescriptorSet.frag --hlsl-iomap --amb --ssb 10 --stb 20 --rsb 4 > $TARGETDIR/hlsl.explicitDescriptorSet.frag.out
+diff -b $BASEDIR/hlsl.explicitDescriptorSet.frag.out $TARGETDIR/hlsl.explicitDescriptorSet.frag.out || HASERROR=1
+
+$EXE -V -D -e main -H hlsl.explicitDescriptorSet.frag --hlsl-iomap --amb --ssb 10 --stb 20 --rsb frag 3 > $TARGETDIR/hlsl.explicitDescriptorSet-2.frag.out
+diff -b $BASEDIR/hlsl.explicitDescriptorSet-2.frag.out $TARGETDIR/hlsl.explicitDescriptorSet-2.frag.out || HASERROR=1
+
 #
 # Testing location error
 #

+ 30 - 0
3rdparty/glslang/Test/spv.paramMemory.frag

@@ -0,0 +1,30 @@
+#version 310 es
+
+readonly coherent uniform layout(set = 0, binding = 0, rgba32f) highp image2D image1;
+readonly uniform layout(set = 0, binding = 2, rgba16f) highp image2D image2;
+writeonly coherent uniform layout(set = 0, binding = 1, rgba32f) highp image2D image3;
+writeonly uniform layout(set = 0, binding = 3, rgba16f) highp image2D image4;
+
+flat in layout(location = 0) highp ivec2 in_coords;
+out layout(location = 0) highp vec4 out_color;
+
+highp vec4 image_load(readonly coherent highp image2D image, highp ivec2 coords)
+{
+	return imageLoad(image, in_coords);
+}
+
+void image_store(writeonly coherent highp image2D image, highp ivec2 coords, highp vec4 data)
+{
+	imageStore(image, in_coords, data);
+}
+
+void main()
+{
+	highp vec4 read1 = image_load(image1, in_coords);
+	highp vec4 read2 = image_load(image2, in_coords);
+	
+	image_store(image3, in_coords, read1*0.5);
+	image_store(image4, in_coords, read2*2.0);
+
+	out_color = vec4(0.0);
+}

+ 3 - 2
3rdparty/glslang/Test/spv.targetOpenGL.vert

@@ -1,8 +1,9 @@
 #version 450
 
 layout(constant_id = 3) const int a = 2;
-
-uniform float f;
+layout(location = 2) uniform float f;
+layout(location = 4) uniform sampler2D s1;
+uniform sampler2D s2;
 
 void main()
 {

+ 12 - 6
3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp

@@ -2472,16 +2472,22 @@ void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, co
         error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str());
 }
 
-void TParseContext::transparentCheck(const TSourceLoc& loc, const TType& type, const TString& /*identifier*/)
+void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& type, const TString& identifier)
 {
     if (parsingBuiltins)
         return;
 
-    // Vulkan doesn't allow transparent uniforms outside of blocks
-    if (spvVersion.vulkan == 0 || type.getQualifier().storage != EvqUniform)
+    if (type.getQualifier().storage != EvqUniform)
         return;
-    if (type.containsNonOpaque())
-        vulkanRemoved(loc, "non-opaque uniforms outside a block");
+
+    if (type.containsNonOpaque()) {
+        // Vulkan doesn't allow transparent uniforms outside of blocks
+        if (spvVersion.vulkan > 0)
+            vulkanRemoved(loc, "non-opaque uniforms outside a block");
+        // OpenGL wants locations on these
+        if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation())
+            error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), "");
+    }
 }
 
 //
@@ -5107,7 +5113,7 @@ TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& iden
 
     samplerCheck(loc, type, identifier, initializer);
     atomicUintCheck(loc, type, identifier);
-    transparentCheck(loc, type, identifier);
+    transparentOpaqueCheck(loc, type, identifier);
 
     if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger))
         error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", "");

+ 1 - 1
3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h

@@ -327,7 +327,7 @@ public:
     void boolCheck(const TSourceLoc&, const TPublicType&);
     void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
     void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
-    void transparentCheck(const TSourceLoc&, const TType&, const TString& identifier);
+    void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
     void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
     void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
     bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);

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

@@ -1836,6 +1836,7 @@ const char* TProgram::getUniformName(int index) const        { return reflection
 const char* TProgram::getUniformBlockName(int index) const   { return reflection->getUniformBlock(index).name.c_str(); }
 int TProgram::getUniformBlockSize(int index) const           { return reflection->getUniformBlock(index).size; }
 int TProgram::getUniformIndex(const char* name) const        { return reflection->getIndex(name); }
+int TProgram::getUniformBinding(int index) const             { return reflection->getUniform(index).getBinding(); }
 int TProgram::getUniformBlockIndex(int index) const          { return reflection->getUniform(index).index; }
 int TProgram::getUniformBlockCounterIndex(int index) const   { return reflection->getUniformBlock(index).counterIndex; }
 int TProgram::getUniformType(int index) const                { return reflection->getUniform(index).glDefineType; }

+ 5 - 0
3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp

@@ -404,6 +404,11 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
     {
         if (type.getQualifier().hasSet())
             return type.getQualifier().layoutSet;
+
+        // If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN)
+        if (baseResourceSetBinding.size() == 1)
+            return atoi(baseResourceSetBinding[0].c_str());
+
         return 0;
     }
 

+ 10 - 11
3rdparty/glslang/glslang/MachineIndependent/reflection.h

@@ -59,7 +59,15 @@ public:
         name(pName), offset(pOffset),
         glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1), type(pType.clone()) { }
 
-    void dump() const {
+    const TType* const getType() const { return type; }
+    int getBinding() const
+    {
+        if (type == nullptr || !type->getQualifier().hasBinding())
+            return -1;
+        return type->getQualifier().layoutBinding;
+    }
+    void dump() const
+    {
         printf("%s: offset %d, type %x, size %d, index %d, binding %d",
                name.c_str(), offset, glDefineType, size, index, getBinding() );
 
@@ -68,8 +76,7 @@ public:
 
         printf("\n");
     }
-
-    const TType* const getType() const { return type; }
+    static TObjectReflection badReflection() { return TObjectReflection(); }
 
     TString name;
     int offset;
@@ -78,15 +85,7 @@ public:
     int index;
     int counterIndex;
 
-    static TObjectReflection badReflection() { return TObjectReflection(); }
-
 protected:
-    int getBinding() const {
-        if (type == nullptr || type->getQualifier().layoutBinding == TQualifier::layoutBindingEnd)
-            return -1;
-        return type->getQualifier().layoutBinding;
-    }
-
     TObjectReflection() : offset(-1), glDefineType(-1), size(-1), index(-1), type(nullptr) { }
 
     const TType* type;

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

@@ -619,6 +619,7 @@ public:
     const char* getUniformBlockName(int blockIndex) const; // can be used for glGetActiveUniformBlockName()
     int getUniformBlockSize(int blockIndex) const;         // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE)
     int getUniformIndex(const char* name) const;           // can be used for glGetUniformIndices()
+    int getUniformBinding(int index) const;                // returns the binding number
     int getUniformBlockIndex(int index) const;             // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX)
     int getUniformBlockCounterIndex(int index) const;      // returns block index of associated counter.
     int getUniformType(int index) const;                   // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE)

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

@@ -275,6 +275,7 @@ INSTANTIATE_TEST_CASE_P(
         "spv.noWorkgroup.comp",
         "spv.offsets.frag",
         "spv.Operations.frag",
+        "spv.paramMemory.frag",
         "spv.precision.frag",
         "spv.prepost.frag",
         "spv.qualifiers.vert",

+ 12 - 6
3rdparty/glslang/hlsl/hlslParseHelper.cpp

@@ -5411,7 +5411,7 @@ void HlslParseContext::handleRegister(const TSourceLoc& loc, TQualifier& qualifi
     }
 
     // TODO: learn what all these really mean and how they interact with regNumber and subComponent
-    std::vector<std::string> resourceInfo = intermediate.getResourceSetBinding();
+    const std::vector<std::string>& resourceInfo = intermediate.getResourceSetBinding();
     switch (std::tolower(desc[0])) {
     case 'b':
     case 't':
@@ -5419,11 +5419,17 @@ void HlslParseContext::handleRegister(const TSourceLoc& loc, TQualifier& qualifi
     case 's':
     case 'u':
         qualifier.layoutBinding = regNumber + subComponent;
-        for (auto it = resourceInfo.cbegin(); it != resourceInfo.cend(); it = it + 3) {
-            if (strcmp(desc.c_str(), it[0].c_str()) == 0) {
-                qualifier.layoutSet = atoi(it[1].c_str());
-                qualifier.layoutBinding = atoi(it[2].c_str()) + subComponent;
-                break;
+
+        // This handles per-register layout sets numbers.  For the global mode which sets
+        // every symbol to the same value, see setLinkageLayoutSets().
+        if ((resourceInfo.size() % 3) == 0) {
+            // Apply per-symbol resource set and binding.
+            for (auto it = resourceInfo.cbegin(); it != resourceInfo.cend(); it = it + 3) {
+                if (strcmp(desc.c_str(), it[0].c_str()) == 0) {
+                    qualifier.layoutSet = atoi(it[1].c_str());
+                    qualifier.layoutBinding = atoi(it[2].c_str()) + subComponent;
+                    break;
+                }
             }
         }
         break;