Fix crash with --resource-set-binding [n] (common set form, not per-register form)

--resource-set-binding has a mode which allows per-register assignments of
bindings and descriptor sets on the command line, and another accepting a
single descriptor set value to assign to all variables.

The former worked, but the latter would crash when assigning the values.
This fixes it, and makes the former case a bit more robust against premature
termination of the pre-register values, which must come in (regname,set,binding)
triples.

This also allows the form "--resource-set-binding stage setnum", which was
mentioned in the usage message, but did not parse.

The operation of the per-register form of this option is unchanged.
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index 1089432..3301df4 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -289,31 +289,29 @@
         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 @@
            "  --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"
diff --git a/Test/baseResults/hlsl.explicitDescriptorSet-2.frag.out b/Test/baseResults/hlsl.explicitDescriptorSet-2.frag.out
new file mode 100644
index 0000000..4ff69a4
--- /dev/null
+++ b/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
diff --git a/Test/baseResults/hlsl.explicitDescriptorSet.frag.out b/Test/baseResults/hlsl.explicitDescriptorSet.frag.out
new file mode 100644
index 0000000..e33f9d6
--- /dev/null
+++ b/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
diff --git a/Test/hlsl.explicitDescriptorSet.frag b/Test/hlsl.explicitDescriptorSet.frag
new file mode 100644
index 0000000..1cff8d3
--- /dev/null
+++ b/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;
+}
diff --git a/Test/runtests b/Test/runtests
index 2a8542f..c5a9337 100755
--- a/Test/runtests
+++ b/Test/runtests
@@ -97,6 +97,12 @@
 $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
 #
diff --git a/glslang/MachineIndependent/iomapper.cpp b/glslang/MachineIndependent/iomapper.cpp
index ea5f161..9585627 100644
--- a/glslang/MachineIndependent/iomapper.cpp
+++ b/glslang/MachineIndependent/iomapper.cpp
@@ -404,6 +404,11 @@
     {
         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;
     }
 
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index 50d88d2..0c64c71 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -5370,7 +5370,7 @@
     }
 
     // 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':
@@ -5378,11 +5378,17 @@
     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;