Merge pull request #576 from steve-lunarg/uav-registers

Add UAV (image) binding offset and HLSL register class support
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index 0ac72d3..377e7cb 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -164,6 +164,7 @@
 
 std::array<unsigned int, EShLangCount> baseSamplerBinding;
 std::array<unsigned int, EShLangCount> baseTextureBinding;
+std::array<unsigned int, EShLangCount> baseImageBinding;
 std::array<unsigned int, EShLangCount> baseUboBinding;
 
 //
@@ -252,6 +253,7 @@
 {
     baseSamplerBinding.fill(0);
     baseTextureBinding.fill(0);
+    baseImageBinding.fill(0);
     baseUboBinding.fill(0);
 
     ExecutableName = argv[0];
@@ -279,6 +281,10 @@
                                lowerword == "shift-texture-binding"  ||
                                lowerword == "stb") {
                         ProcessBindingBase(argc, argv, baseTextureBinding);
+                    } else if (lowerword == "shift-image-bindings" ||  // synonyms
+                               lowerword == "shift-image-binding"  ||
+                               lowerword == "sib") {
+                        ProcessBindingBase(argc, argv, baseImageBinding);
                     } else if (lowerword == "shift-ubo-bindings" ||  // synonyms
                                lowerword == "shift-ubo-binding"  ||
                                lowerword == "sub") {
@@ -544,6 +550,7 @@
 
         shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]);
         shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]);
+        shader->setShiftImageBinding(baseImageBinding[compUnit.stage]);
         shader->setShiftUboBinding(baseUboBinding[compUnit.stage]);
         shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0);
         shader->setNoStorageFormat((Options & EOptionNoStorageFormat) != 0);
@@ -941,6 +948,9 @@
            "  --shift-texture-binding [stage] num     set base binding number for textures\n"
            "  --stb [stage] num                       synonym for --shift-texture-binding\n"
            "\n"
+           "  --shift-image-binding [stage] num       set base binding number for images (uav)\n"
+           "  --sib [stage] num                       synonym for --shift-image-binding\n"
+           "\n"
            "  --shift-UBO-binding [stage] num         set base binding number for UBOs\n"
            "  --sub [stage] num                       synonym for --shift-UBO-binding\n"
            "\n"
diff --git a/Test/baseResults/hlsl.rw.register.frag.out b/Test/baseResults/hlsl.rw.register.frag.out
new file mode 100644
index 0000000..b2d8f29
--- /dev/null
+++ b/Test/baseResults/hlsl.rw.register.frag.out
@@ -0,0 +1,158 @@
+hlsl.rw.register.frag
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:11  Function Definition: main( (temp structure{temp 4-component vector of float Color})
+0:11    Function Parameters: 
+0:?     Sequence
+0:12      Sequence
+0:12        move second child to first child (temp float)
+0:12          'r00' (temp float)
+0:12          imageLoad (temp float)
+0:12            'g_tTex1df1' (layout(binding=2 r32f ) uniform image1D)
+0:12            Constant:
+0:12              0 (const int)
+0:13      Sequence
+0:13        move second child to first child (temp uint)
+0:13          'r01' (temp uint)
+0:13          imageLoad (temp uint)
+0:13            'g_tBuf1du1' (layout(binding=3 r32ui ) uniform uimageBuffer)
+0:13            Constant:
+0:13              0 (const int)
+0:16      move second child to first child (temp 4-component vector of float)
+0:16        Color: direct index for structure (temp 4-component vector of float)
+0:16          'psout' (temp structure{temp 4-component vector of float Color})
+0:16          Constant:
+0:16            0 (const int)
+0:16        Constant:
+0:16          1.000000
+0:16          1.000000
+0:16          1.000000
+0:16          1.000000
+0:17      Sequence
+0:17        Sequence
+0:17          move second child to first child (temp 4-component vector of float)
+0:?             'Color' (layout(location=0 ) out 4-component vector of float)
+0:17            Color: direct index for structure (temp 4-component vector of float)
+0:17              'psout' (temp structure{temp 4-component vector of float Color})
+0:17              Constant:
+0:17                0 (const int)
+0:17        Branch: Return
+0:?   Linker Objects
+0:?     'g_tTex1df1' (layout(binding=2 r32f ) uniform image1D)
+0:?     'g_tBuf1du1' (layout(binding=3 r32ui ) uniform uimageBuffer)
+0:?     'Color' (layout(location=0 ) out 4-component vector of float)
+
+
+Linked fragment stage:
+
+
+Shader version: 450
+gl_FragCoord origin is upper left
+0:? Sequence
+0:11  Function Definition: main( (temp structure{temp 4-component vector of float Color})
+0:11    Function Parameters: 
+0:?     Sequence
+0:12      Sequence
+0:12        move second child to first child (temp float)
+0:12          'r00' (temp float)
+0:12          imageLoad (temp float)
+0:12            'g_tTex1df1' (layout(binding=2 r32f ) uniform image1D)
+0:12            Constant:
+0:12              0 (const int)
+0:13      Sequence
+0:13        move second child to first child (temp uint)
+0:13          'r01' (temp uint)
+0:13          imageLoad (temp uint)
+0:13            'g_tBuf1du1' (layout(binding=3 r32ui ) uniform uimageBuffer)
+0:13            Constant:
+0:13              0 (const int)
+0:16      move second child to first child (temp 4-component vector of float)
+0:16        Color: direct index for structure (temp 4-component vector of float)
+0:16          'psout' (temp structure{temp 4-component vector of float Color})
+0:16          Constant:
+0:16            0 (const int)
+0:16        Constant:
+0:16          1.000000
+0:16          1.000000
+0:16          1.000000
+0:16          1.000000
+0:17      Sequence
+0:17        Sequence
+0:17          move second child to first child (temp 4-component vector of float)
+0:?             'Color' (layout(location=0 ) out 4-component vector of float)
+0:17            Color: direct index for structure (temp 4-component vector of float)
+0:17              'psout' (temp structure{temp 4-component vector of float Color})
+0:17              Constant:
+0:17                0 (const int)
+0:17        Branch: Return
+0:?   Linker Objects
+0:?     'g_tTex1df1' (layout(binding=2 r32f ) uniform image1D)
+0:?     'g_tBuf1du1' (layout(binding=3 r32ui ) uniform uimageBuffer)
+0:?     'Color' (layout(location=0 ) out 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 37
+
+                              Capability Shader
+                              Capability Sampled1D
+                              Capability SampledBuffer
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 33
+                              ExecutionMode 4 OriginUpperLeft
+                              Name 4  "main"
+                              Name 8  "r00"
+                              Name 11  "g_tTex1df1"
+                              Name 18  "r01"
+                              Name 21  "g_tBuf1du1"
+                              Name 25  "PS_OUTPUT"
+                              MemberName 25(PS_OUTPUT) 0  "Color"
+                              Name 27  "psout"
+                              Name 33  "Color"
+                              Decorate 11(g_tTex1df1) DescriptorSet 0
+                              Decorate 11(g_tTex1df1) Binding 2
+                              Decorate 21(g_tBuf1du1) DescriptorSet 0
+                              Decorate 21(g_tBuf1du1) Binding 3
+                              Decorate 33(Color) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypePointer Function 6(float)
+               9:             TypeImage 6(float) 1D nonsampled format:R32f
+              10:             TypePointer UniformConstant 9
+  11(g_tTex1df1):     10(ptr) Variable UniformConstant
+              13:             TypeInt 32 1
+              14:     13(int) Constant 0
+              16:             TypeInt 32 0
+              17:             TypePointer Function 16(int)
+              19:             TypeImage 16(int) Buffer nonsampled format:R32ui
+              20:             TypePointer UniformConstant 19
+  21(g_tBuf1du1):     20(ptr) Variable UniformConstant
+              24:             TypeVector 6(float) 4
+   25(PS_OUTPUT):             TypeStruct 24(fvec4)
+              26:             TypePointer Function 25(PS_OUTPUT)
+              28:    6(float) Constant 1065353216
+              29:   24(fvec4) ConstantComposite 28 28 28 28
+              30:             TypePointer Function 24(fvec4)
+              32:             TypePointer Output 24(fvec4)
+       33(Color):     32(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+          8(r00):      7(ptr) Variable Function
+         18(r01):     17(ptr) Variable Function
+       27(psout):     26(ptr) Variable Function
+              12:           9 Load 11(g_tTex1df1)
+              15:    6(float) ImageRead 12 14
+                              Store 8(r00) 15
+              22:          19 Load 21(g_tBuf1du1)
+              23:     16(int) ImageRead 22 14
+                              Store 18(r01) 23
+              31:     30(ptr) AccessChain 27(psout) 14
+                              Store 31 29
+              34:     30(ptr) AccessChain 27(psout) 14
+              35:   24(fvec4) Load 34
+                              Store 33(Color) 35
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.rw.autoassign.frag.out b/Test/baseResults/spv.rw.autoassign.frag.out
new file mode 100644
index 0000000..851ef46
--- /dev/null
+++ b/Test/baseResults/spv.rw.autoassign.frag.out
@@ -0,0 +1,70 @@
+spv.rw.autoassign.frag
+
+Linked fragment stage:
+
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 37
+
+                              Capability Shader
+                              Capability Sampled1D
+                              Capability SampledBuffer
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 33
+                              ExecutionMode 4 OriginUpperLeft
+                              Name 4  "main"
+                              Name 8  "r00"
+                              Name 11  "g_tTex1df1"
+                              Name 18  "r01"
+                              Name 21  "g_tBuf1du1"
+                              Name 25  "PS_OUTPUT"
+                              MemberName 25(PS_OUTPUT) 0  "Color"
+                              Name 27  "psout"
+                              Name 33  "Color"
+                              Decorate 11(g_tTex1df1) DescriptorSet 0
+                              Decorate 11(g_tTex1df1) Binding 20
+                              Decorate 21(g_tBuf1du1) DescriptorSet 0
+                              Decorate 21(g_tBuf1du1) Binding 21
+                              Decorate 33(Color) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypePointer Function 6(float)
+               9:             TypeImage 6(float) 1D nonsampled format:R32f
+              10:             TypePointer UniformConstant 9
+  11(g_tTex1df1):     10(ptr) Variable UniformConstant
+              13:             TypeInt 32 1
+              14:     13(int) Constant 0
+              16:             TypeInt 32 0
+              17:             TypePointer Function 16(int)
+              19:             TypeImage 16(int) Buffer nonsampled format:R32ui
+              20:             TypePointer UniformConstant 19
+  21(g_tBuf1du1):     20(ptr) Variable UniformConstant
+              24:             TypeVector 6(float) 4
+   25(PS_OUTPUT):             TypeStruct 24(fvec4)
+              26:             TypePointer Function 25(PS_OUTPUT)
+              28:    6(float) Constant 0
+              29:   24(fvec4) ConstantComposite 28 28 28 28
+              30:             TypePointer Function 24(fvec4)
+              32:             TypePointer Output 24(fvec4)
+       33(Color):     32(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+          8(r00):      7(ptr) Variable Function
+         18(r01):     17(ptr) Variable Function
+       27(psout):     26(ptr) Variable Function
+              12:           9 Load 11(g_tTex1df1)
+              15:    6(float) ImageRead 12 14
+                              Store 8(r00) 15
+              22:          19 Load 21(g_tBuf1du1)
+              23:     16(int) ImageRead 22 14
+                              Store 18(r01) 23
+              31:     30(ptr) AccessChain 27(psout) 14
+                              Store 31 29
+              34:     30(ptr) AccessChain 27(psout) 14
+              35:   24(fvec4) Load 34
+                              Store 33(Color) 35
+                              Return
+                              FunctionEnd
diff --git a/Test/hlsl.rw.register.frag b/Test/hlsl.rw.register.frag
new file mode 100644
index 0000000..e82e419
--- /dev/null
+++ b/Test/hlsl.rw.register.frag
@@ -0,0 +1,18 @@
+
+RWTexture1D <float> g_tTex1df1 : register(u2);
+RWBuffer <uint>     g_tBuf1du1 : register(U3);
+
+struct PS_OUTPUT
+{
+    float4 Color : SV_Target0;
+};
+
+PS_OUTPUT main()
+{
+   float r00 = g_tTex1df1[0];
+   uint  r01 = g_tBuf1du1[0];
+
+   PS_OUTPUT psout;
+   psout.Color = 1.0;
+   return psout;
+}
diff --git a/Test/spv.rw.autoassign.frag b/Test/spv.rw.autoassign.frag
new file mode 100644
index 0000000..5c7d0d3
--- /dev/null
+++ b/Test/spv.rw.autoassign.frag
@@ -0,0 +1,18 @@
+
+RWTexture1D <float> g_tTex1df1;
+RWBuffer <uint>     g_tBuf1du1;
+
+struct PS_OUTPUT
+{
+    float4 Color : SV_Target0;
+};
+
+PS_OUTPUT main()
+{
+    float r00 = g_tTex1df1[0];
+    uint  r01 = g_tBuf1du1[0];
+
+    PS_OUTPUT psout;
+    psout.Color = 0;
+    return psout;
+}
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index 4d78a70..5b44af5 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -1493,6 +1493,7 @@
 
 void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); }
 void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); }
+void TShader::setShiftImageBinding(unsigned int base)   { intermediate->setShiftImageBinding(base); }
 void TShader::setShiftUboBinding(unsigned int base)     { intermediate->setShiftUboBinding(base); }
 void TShader::setAutoMapBindings(bool map)              { intermediate->setAutoMapBindings(map); }
 void TShader::setFlattenUniformArrays(bool flatten)     { intermediate->setFlattenUniformArrays(flatten); }
diff --git a/glslang/MachineIndependent/iomapper.cpp b/glslang/MachineIndependent/iomapper.cpp
index 2ee6cae..269d654 100644
--- a/glslang/MachineIndependent/iomapper.cpp
+++ b/glslang/MachineIndependent/iomapper.cpp
@@ -222,6 +222,7 @@
 {
     int baseSamplerBinding;
     int baseTextureBinding;
+    int baseImageBinding;
     int baseUboBinding;
     bool doAutoMapping;
     typedef std::vector<int> TSlotSet;
@@ -294,6 +295,9 @@
         if (type.getQualifier().hasBinding()) {
             if (type.getBasicType() == glslang::EbtSampler) {
                 const glslang::TSampler& sampler = type.getSampler();
+                if (sampler.isImage())
+                    return reserveSlot(set, baseImageBinding + type.getQualifier().layoutBinding);
+
                 if (sampler.isPureSampler())
                     return reserveSlot(set, baseSamplerBinding + type.getQualifier().layoutBinding);
 
@@ -308,6 +312,9 @@
             // first and now all are passed that do not have a binding and needs one
             if (type.getBasicType() == glslang::EbtSampler) {
                 const glslang::TSampler& sampler = type.getSampler();
+                if (sampler.isImage())
+                    return getFreeSlot(set, baseImageBinding);
+
                 if (sampler.isPureSampler())
                     return getFreeSlot(set, baseSamplerBinding);
 
@@ -339,9 +346,10 @@
     // Trivial return if there is nothing to do.
     if (intermediate.getShiftSamplerBinding() == 0 &&
         intermediate.getShiftTextureBinding() == 0 &&
+        intermediate.getShiftImageBinding() == 0 &&
         intermediate.getShiftUboBinding() == 0 &&
         intermediate.getAutoMapBindings() == false &&
-        resolver == NULL)
+        resolver == nullptr)
         return true;
 
     if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive())
@@ -353,9 +361,10 @@
 
     // if no resolver is provided, use the default resolver with the given shifts and auto map settings
     TDefaultIoResolver defaultResolver;
-    if (resolver == NULL) {
+    if (resolver == nullptr) {
         defaultResolver.baseSamplerBinding = intermediate.getShiftSamplerBinding();
         defaultResolver.baseTextureBinding = intermediate.getShiftTextureBinding();
+        defaultResolver.baseImageBinding = intermediate.getShiftImageBinding();
         defaultResolver.baseUboBinding = intermediate.getShiftUboBinding();
         defaultResolver.doAutoMapping = intermediate.getAutoMapBindings();
 
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 13e1b14..6a4cfd0 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -144,6 +144,7 @@
         multiStream(false), xfbMode(false),
         shiftSamplerBinding(0),
         shiftTextureBinding(0),
+        shiftImageBinding(0),
         shiftUboBinding(0),
         autoMapBindings(false),
         flattenUniformArrays(false),
@@ -174,6 +175,8 @@
     unsigned int getShiftSamplerBinding() const { return shiftSamplerBinding; }
     void setShiftTextureBinding(unsigned int shift) { shiftTextureBinding = shift; }
     unsigned int getShiftTextureBinding() const { return shiftTextureBinding; }
+    void setShiftImageBinding(unsigned int shift) { shiftImageBinding = shift; }
+    unsigned int getShiftImageBinding() const { return shiftImageBinding; }
     void setShiftUboBinding(unsigned int shift)     { shiftUboBinding = shift; }
     unsigned int getShiftUboBinding()     const { return shiftUboBinding; }
     void setAutoMapBindings(bool map)               { autoMapBindings = map; }
@@ -403,6 +406,7 @@
     std::string entryPointMangledName;
     unsigned int shiftSamplerBinding;
     unsigned int shiftTextureBinding;
+    unsigned int shiftImageBinding;
     unsigned int shiftUboBinding;
     bool autoMapBindings;
     bool flattenUniformArrays;
diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h
index acde8b0..9a76b40 100644
--- a/glslang/Public/ShaderLang.h
+++ b/glslang/Public/ShaderLang.h
@@ -306,6 +306,7 @@
     void setEntryPoint(const char* entryPoint);
     void setShiftSamplerBinding(unsigned int base);
     void setShiftTextureBinding(unsigned int base);
+    void setShiftImageBinding(unsigned int base);
     void setShiftUboBinding(unsigned int base);
     void setAutoMapBindings(bool map);
     void setFlattenUniformArrays(bool flatten);
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index edd7e4d..5487fb9 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -161,6 +161,7 @@
         {"hlsl.promotions.frag", "main"},
         {"hlsl.rw.atomics.frag", "main"},
         {"hlsl.rw.bracket.frag", "main"},
+        {"hlsl.rw.register.frag", "main"},
         {"hlsl.rw.scalar.bracket.frag", "main"},
         {"hlsl.rw.vec2.bracket.frag", "main"},
         {"hlsl.sample.array.dx10.frag", "main"},
diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp
index 9911e0e..414fa7b 100644
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -46,6 +46,7 @@
     const char* entryPoint;
     int baseSamplerBinding;
     int baseTextureBinding;
+    int baseImageBinding;
     int baseUboBinding;
     bool autoMapBindings;
     bool flattenUniforms;
@@ -123,6 +124,7 @@
                                  Target::Spv, GetParam().entryPoint,
                                  GetParam().baseSamplerBinding,
                                  GetParam().baseTextureBinding,
+                                 GetParam().baseImageBinding,
                                  GetParam().baseUboBinding,
                                  GetParam().autoMapBindings,
                                  GetParam().flattenUniforms);
@@ -136,6 +138,7 @@
                                  Target::Spv, GetParam().entryPoint,
                                  GetParam().baseSamplerBinding,
                                  GetParam().baseTextureBinding,
+                                 GetParam().baseImageBinding,
                                  GetParam().baseUboBinding,
                                  GetParam().autoMapBindings,
                                  GetParam().flattenUniforms);
@@ -284,10 +287,11 @@
 INSTANTIATE_TEST_CASE_P(
     Hlsl, HlslIoMap,
     ::testing::ValuesIn(std::vector<IoMapData>{
-        { "spv.register.autoassign.frag", "main_ep", 5, 10, 20, true, false },
-        { "spv.register.noautoassign.frag", "main_ep", 5, 10, 15, false, false },
-        { "spv.register.autoassign-2.frag", "main", 5, 10, 15, true, true },
-        { "spv.buffer.autoassign.frag", "main", 5, 10, 15, true, true },
+        { "spv.register.autoassign.frag", "main_ep", 5, 10, 0, 20, true, false },
+        { "spv.register.noautoassign.frag", "main_ep", 5, 10, 0, 15, false, false },
+        { "spv.register.autoassign-2.frag", "main", 5, 10, 0, 15, true, true },
+        { "spv.buffer.autoassign.frag", "main", 5, 10, 0, 15, true, true },
+        { "spv.rw.autoassign.frag", "main", 5, 10, 20, 15, true, true },
         { "spv.register.autoassign.rangetest.frag", "main", 
                 glslang::TQualifier::layoutBindingEnd-2,
                 glslang::TQualifier::layoutBindingEnd+5,
@@ -300,8 +304,8 @@
 INSTANTIATE_TEST_CASE_P(
     Hlsl, GlslIoMap,
     ::testing::ValuesIn(std::vector<IoMapData>{
-        { "spv.glsl.register.autoassign.frag", "main", 5, 10, 20, true, false },
-        { "spv.glsl.register.noautoassign.frag", "main", 5, 10, 15, false, false },
+        { "spv.glsl.register.autoassign.frag", "main", 5, 10, 0, 20, true, false },
+        { "spv.glsl.register.noautoassign.frag", "main", 5, 10, 0, 15, false, false },
     }),
     FileNameAsCustomTestSuffixIoMap
 );
diff --git a/gtests/TestFixture.h b/gtests/TestFixture.h
index c08c6cc..e795e8d 100644
--- a/gtests/TestFixture.h
+++ b/gtests/TestFixture.h
@@ -239,6 +239,7 @@
             const std::string& entryPointName, EShMessages controls,
             int baseSamplerBinding,
             int baseTextureBinding,
+            int baseImageBinding,
             int baseUboBinding,
             bool autoMapBindings,
             bool flattenUniformArrays)
@@ -248,6 +249,7 @@
         glslang::TShader shader(kind);
         shader.setShiftSamplerBinding(baseSamplerBinding);
         shader.setShiftTextureBinding(baseTextureBinding);
+        shader.setShiftImageBinding(baseImageBinding);
         shader.setShiftUboBinding(baseUboBinding);
         shader.setAutoMapBindings(autoMapBindings);
         shader.setFlattenUniformArrays(flattenUniformArrays);
@@ -426,6 +428,7 @@
                                       const std::string& entryPointName,
                                       int baseSamplerBinding,
                                       int baseTextureBinding,
+                                      int baseImageBinding,
                                       int baseUboBinding,
                                       bool autoMapBindings,
                                       bool flattenUniformArrays)
@@ -440,7 +443,7 @@
 
         const EShMessages controls = DeriveOptions(source, semantics, target);
         GlslangResult result = compileLinkIoMap(testName, input, entryPointName, controls,
-                                                baseSamplerBinding, baseTextureBinding, baseUboBinding,
+                                                baseSamplerBinding, baseTextureBinding, baseImageBinding, baseUboBinding,
                                                 autoMapBindings,
                                                 flattenUniformArrays);
 
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index 31fb0d4..ff2c301 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -45,6 +45,7 @@
 #include "../glslang/OSDependent/osinclude.h"
 
 #include <algorithm>
+#include <cctype>
 
 namespace glslang {
 
@@ -3084,11 +3085,12 @@
     }
 
     // TODO: learn what all these really mean and how they interact with regNumber and subComponent
-    switch (desc[0]) {
+    switch (std::tolower(desc[0])) {
     case 'b':
     case 't':
     case 'c':
     case 's':
+    case 'u':
         qualifier.layoutBinding = regNumber + subComponent;
         break;
     default: