Merge pull request #855 from steve-lunarg/constantbuffer

HLSL: Add ConstantBuffer<T> syntax
diff --git a/Test/baseResults/hlsl.constantbuffer.frag.out b/Test/baseResults/hlsl.constantbuffer.frag.out
new file mode 100644
index 0000000..2c7dafe
--- /dev/null
+++ b/Test/baseResults/hlsl.constantbuffer.frag.out
@@ -0,0 +1,241 @@
+hlsl.constantbuffer.frag
+Shader version: 500
+gl_FragCoord origin is upper left
+0:? Sequence
+0:20  Function Definition: @main( ( temp 4-component vector of float)
+0:20    Function Parameters: 
+0:?     Sequence
+0:21      Test condition and select ( temp void)
+0:21        Condition
+0:21        x: direct index for structure (layout( row_major std140) uniform bool)
+0:21          direct index (layout( row_major std140) temp block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:21            direct index (layout( row_major std140) temp 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:21              'cb3' (layout( row_major std140) uniform 2-element array of 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:21              Constant:
+0:21                1 (const int)
+0:21            Constant:
+0:21              2 (const int)
+0:21          Constant:
+0:21            0 (const int)
+0:21        true case
+0:22        Branch: Return with expression
+0:22          add ( temp 4-component vector of float)
+0:22            add ( temp 4-component vector of float)
+0:22              x: direct index for structure (layout( row_major std140) uniform 4-component vector of float)
+0:22                'cb1' (layout( binding=12 row_major std140) uniform block{layout( row_major std140) uniform 4-component vector of float x})
+0:22                Constant:
+0:22                  0 (const int)
+0:22              y: direct index for structure (layout( row_major std140) uniform float)
+0:22                direct index (layout( row_major std140) temp block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:22                  'cb2' (layout( row_major std140) uniform 3-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:22                  Constant:
+0:22                    1 (const int)
+0:22                Constant:
+0:22                  1 (const int)
+0:22            Convert int to float ( temp float)
+0:22              c1: direct index for structure (layout( row_major std140) uniform int)
+0:22                'anon@0' (layout( row_major std140) uniform block{layout( row_major std140) uniform int c1})
+0:22                Constant:
+0:22                  0 (const uint)
+0:21        false case
+0:24        Branch: Return with expression
+0:24          Construct vec4 ( temp 4-component vector of float)
+0:24            y: direct index for structure (layout( row_major std140) uniform float)
+0:24              direct index (layout( row_major std140) temp block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:24                direct index (layout( row_major std140) temp 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:24                  'cb3' (layout( row_major std140) uniform 2-element array of 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:24                  Constant:
+0:24                    2 (const int)
+0:24                Constant:
+0:24                  3 (const int)
+0:24              Constant:
+0:24                1 (const int)
+0:20  Function Definition: main( ( temp void)
+0:20    Function Parameters: 
+0:?     Sequence
+0:20      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:20        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'cb1' (layout( binding=12 row_major std140) uniform block{layout( row_major std140) uniform 4-component vector of float x})
+0:?     'cb2' (layout( row_major std140) uniform 3-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:?     'cb3' (layout( row_major std140) uniform 2-element array of 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:?     'anon@0' (layout( row_major std140) uniform block{layout( row_major std140) uniform int c1})
+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:20  Function Definition: @main( ( temp 4-component vector of float)
+0:20    Function Parameters: 
+0:?     Sequence
+0:21      Test condition and select ( temp void)
+0:21        Condition
+0:21        x: direct index for structure (layout( row_major std140) uniform bool)
+0:21          direct index (layout( row_major std140) temp block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:21            direct index (layout( row_major std140) temp 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:21              'cb3' (layout( row_major std140) uniform 2-element array of 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:21              Constant:
+0:21                1 (const int)
+0:21            Constant:
+0:21              2 (const int)
+0:21          Constant:
+0:21            0 (const int)
+0:21        true case
+0:22        Branch: Return with expression
+0:22          add ( temp 4-component vector of float)
+0:22            add ( temp 4-component vector of float)
+0:22              x: direct index for structure (layout( row_major std140) uniform 4-component vector of float)
+0:22                'cb1' (layout( binding=12 row_major std140) uniform block{layout( row_major std140) uniform 4-component vector of float x})
+0:22                Constant:
+0:22                  0 (const int)
+0:22              y: direct index for structure (layout( row_major std140) uniform float)
+0:22                direct index (layout( row_major std140) temp block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:22                  'cb2' (layout( row_major std140) uniform 3-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:22                  Constant:
+0:22                    1 (const int)
+0:22                Constant:
+0:22                  1 (const int)
+0:22            Convert int to float ( temp float)
+0:22              c1: direct index for structure (layout( row_major std140) uniform int)
+0:22                'anon@0' (layout( row_major std140) uniform block{layout( row_major std140) uniform int c1})
+0:22                Constant:
+0:22                  0 (const uint)
+0:21        false case
+0:24        Branch: Return with expression
+0:24          Construct vec4 ( temp 4-component vector of float)
+0:24            y: direct index for structure (layout( row_major std140) uniform float)
+0:24              direct index (layout( row_major std140) temp block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:24                direct index (layout( row_major std140) temp 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:24                  'cb3' (layout( row_major std140) uniform 2-element array of 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:24                  Constant:
+0:24                    2 (const int)
+0:24                Constant:
+0:24                  3 (const int)
+0:24              Constant:
+0:24                1 (const int)
+0:20  Function Definition: main( ( temp void)
+0:20    Function Parameters: 
+0:?     Sequence
+0:20      move second child to first child ( temp 4-component vector of float)
+0:?         '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+0:20        Function Call: @main( ( temp 4-component vector of float)
+0:?   Linker Objects
+0:?     'cb1' (layout( binding=12 row_major std140) uniform block{layout( row_major std140) uniform 4-component vector of float x})
+0:?     'cb2' (layout( row_major std140) uniform 3-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:?     'cb3' (layout( row_major std140) uniform 2-element array of 4-element array of block{layout( row_major std140) uniform bool x, layout( row_major std140) uniform float y})
+0:?     'anon@0' (layout( row_major std140) uniform block{layout( row_major std140) uniform int c1})
+0:?     '@entryPointOutput' (layout( location=0) out 4-component vector of float)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 66
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main" 64
+                              ExecutionMode 4 OriginUpperLeft
+                              Source HLSL 500
+                              Name 4  "main"
+                              Name 9  "@main("
+                              Name 12  "cb3"
+                              MemberName 12(cb3) 0  "x"
+                              MemberName 12(cb3) 1  "y"
+                              Name 18  "cb3"
+                              Name 31  "cb1"
+                              MemberName 31(cb1) 0  "x"
+                              Name 33  "cb1"
+                              Name 40  "cb2"
+                              Name 46  "cbuff"
+                              MemberName 46(cbuff) 0  "c1"
+                              Name 48  ""
+                              Name 64  "@entryPointOutput"
+                              MemberDecorate 12(cb3) 0 Offset 0
+                              MemberDecorate 12(cb3) 1 Offset 4
+                              Decorate 12(cb3) Block
+                              Decorate 18(cb3) DescriptorSet 0
+                              MemberDecorate 31(cb1) 0 Offset 0
+                              Decorate 31(cb1) Block
+                              Decorate 33(cb1) DescriptorSet 0
+                              Decorate 33(cb1) Binding 12
+                              Decorate 40(cb2) DescriptorSet 0
+                              MemberDecorate 46(cbuff) 0 Offset 0
+                              Decorate 46(cbuff) Block
+                              Decorate 48 DescriptorSet 0
+                              Decorate 64(@entryPointOutput) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeFunction 7(fvec4)
+              11:             TypeInt 32 0
+         12(cb3):             TypeStruct 11(int) 6(float)
+              13:     11(int) Constant 4
+              14:             TypeArray 12(cb3) 13
+              15:     11(int) Constant 2
+              16:             TypeArray 14 15
+              17:             TypePointer Uniform 16
+         18(cb3):     17(ptr) Variable Uniform
+              19:             TypeInt 32 1
+              20:     19(int) Constant 1
+              21:     19(int) Constant 2
+              22:     19(int) Constant 0
+              23:             TypePointer Uniform 11(int)
+              26:             TypeBool
+              27:     11(int) Constant 0
+         31(cb1):             TypeStruct 7(fvec4)
+              32:             TypePointer Uniform 31(cb1)
+         33(cb1):     32(ptr) Variable Uniform
+              34:             TypePointer Uniform 7(fvec4)
+              37:     11(int) Constant 3
+              38:             TypeArray 12(cb3) 37
+              39:             TypePointer Uniform 38
+         40(cb2):     39(ptr) Variable Uniform
+              41:             TypePointer Uniform 6(float)
+       46(cbuff):             TypeStruct 19(int)
+              47:             TypePointer Uniform 46(cbuff)
+              48:     47(ptr) Variable Uniform
+              49:             TypePointer Uniform 19(int)
+              57:     19(int) Constant 3
+              63:             TypePointer Output 7(fvec4)
+64(@entryPointOutput):     63(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+              65:    7(fvec4) FunctionCall 9(@main()
+                              Store 64(@entryPointOutput) 65
+                              Return
+                              FunctionEnd
+       9(@main():    7(fvec4) Function None 8
+              10:             Label
+              24:     23(ptr) AccessChain 18(cb3) 20 21 22
+              25:     11(int) Load 24
+              28:    26(bool) INotEqual 25 27
+                              SelectionMerge 30 None
+                              BranchConditional 28 29 56
+              29:               Label
+              35:     34(ptr)   AccessChain 33(cb1) 22
+              36:    7(fvec4)   Load 35
+              42:     41(ptr)   AccessChain 40(cb2) 20 20
+              43:    6(float)   Load 42
+              44:    7(fvec4)   CompositeConstruct 43 43 43 43
+              45:    7(fvec4)   FAdd 36 44
+              50:     49(ptr)   AccessChain 48 22
+              51:     19(int)   Load 50
+              52:    6(float)   ConvertSToF 51
+              53:    7(fvec4)   CompositeConstruct 52 52 52 52
+              54:    7(fvec4)   FAdd 45 53
+                                ReturnValue 54
+              56:               Label
+              58:     41(ptr)   AccessChain 18(cb3) 21 57 20
+              59:    6(float)   Load 58
+              60:    7(fvec4)   CompositeConstruct 59 59 59 59
+                                ReturnValue 60
+              30:             Label
+              62:    7(fvec4) Undef
+                              ReturnValue 62
+                              FunctionEnd
diff --git a/Test/hlsl.constantbuffer.frag b/Test/hlsl.constantbuffer.frag
new file mode 100644
index 0000000..d7a6ef5
--- /dev/null
+++ b/Test/hlsl.constantbuffer.frag
@@ -0,0 +1,26 @@
+
+struct c1_t {
+    float4 x;
+};
+
+struct c2_t {
+    bool x;
+    float y;
+};
+
+ConstantBuffer<c1_t> cb1 : register(b12);
+ConstantBuffer<c2_t> cb2[3];
+ConstantBuffer<c2_t> cb3[2][4];
+
+cbuffer cbuff {
+    int c1;
+};
+
+float4 main() : SV_Target0
+{
+    if (cb3[1][2].x)
+        return cb1.x + cb2[1].y + c1;
+    else
+        return cb3[2][3].y;
+}
+
diff --git a/glslang/MachineIndependent/iomapper.cpp b/glslang/MachineIndependent/iomapper.cpp
index 920ed0c..8b80cbe 100644
--- a/glslang/MachineIndependent/iomapper.cpp
+++ b/glslang/MachineIndependent/iomapper.cpp
@@ -532,6 +532,7 @@
 
 b – for constant buffer views (CBV)
    CBUFFER
+   CONSTANTBUFFER
  ********************************************************************************/
 struct TDefaultHlslIoResolver : public TDefaultIoResolverBase
 {
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index b23674e..5dcc095 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -98,6 +98,7 @@
         {"hlsl.clip.frag", "main"},
         {"hlsl.comparison.vec.frag", "main"},
         {"hlsl.conditional.frag", "PixelShaderFunction"},
+        {"hlsl.constantbuffer.frag", "main"},
         {"hlsl.constructexpr.frag", "main"},
         {"hlsl.depthGreater.frag", "PixelShaderFunction"},
         {"hlsl.depthLess.frag", "PixelShaderFunction"},
diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp
index 63b78bf..a9743c2 100755
--- a/hlsl/hlslGrammar.cpp
+++ b/hlsl/hlslGrammar.cpp
@@ -476,7 +476,8 @@
                 if (typedefDecl)
                     parseContext.declareTypedef(idToken.loc, *fullName, variableType);
                 else if (variableType.getBasicType() == EbtBlock) {
-                    parseContext.declareBlock(idToken.loc, variableType, fullName);
+                    parseContext.declareBlock(idToken.loc, variableType, fullName,
+                                              variableType.isArray() ? &variableType.getArraySizes() : nullptr);
                     parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName);
                 } else {
                     if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
@@ -1364,6 +1365,9 @@
         return acceptStructBufferType(type);
         break;
 
+    case EHTokConstantBuffer:
+        return acceptConstantBufferType(type);
+
     case EHTokClass:
     case EHTokStruct:
     case EHTokCBuffer:
@@ -1944,6 +1948,47 @@
     return deferredSuccess;
 }
 
+// constantbuffer
+//    : CONSTANTBUFFER LEFT_ANGLE type RIGHT_ANGLE
+bool HlslGrammar::acceptConstantBufferType(TType& type)
+{
+    if (! acceptTokenClass(EHTokConstantBuffer))
+        return false;
+
+    if (! acceptTokenClass(EHTokLeftAngle)) {
+        expected("left angle bracket");
+        return false;
+    }
+    
+    TType templateType;
+    if (! acceptType(templateType)) {
+        expected("type");
+        return false;
+    }
+
+    if (! acceptTokenClass(EHTokRightAngle)) {
+        expected("right angle bracket");
+        return false;
+    }
+
+    TQualifier postDeclQualifier;
+    postDeclQualifier.clear();
+    postDeclQualifier.storage = EvqUniform;
+
+    if (templateType.isStruct()) {
+        // Make a block from the type parsed as the template argument
+        TTypeList* typeList = templateType.getWritableStruct();
+        new(&type) TType(typeList, "", postDeclQualifier); // sets EbtBlock
+
+        type.getQualifier().storage = EvqUniform;
+
+        return true;
+    } else {
+        parseContext.error(token.loc, "non-structure type in ConstantBuffer", "", "");
+        return false;
+    }
+}
+
 // struct_buffer
 //    : APPENDSTRUCTUREDBUFFER
 //    | BYTEADDRESSBUFFER
diff --git a/hlsl/hlslGrammar.h b/hlsl/hlslGrammar.h
index 6d8ed8f..f1ff1c6 100755
--- a/hlsl/hlslGrammar.h
+++ b/hlsl/hlslGrammar.h
@@ -87,6 +87,7 @@
         bool acceptSamplerType(TType&);
         bool acceptTextureType(TType&);
         bool acceptStructBufferType(TType&);
+        bool acceptConstantBufferType(TType&);
         bool acceptStruct(TType&, TIntermNode*& nodeList);
         bool acceptStructDeclarationList(TTypeList*&, TIntermNode*& nodeList, TVector<TFunctionDeclarator>&);
         bool acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType&, const TString& memberName,
diff --git a/hlsl/hlslScanContext.cpp b/hlsl/hlslScanContext.cpp
index 55304a0..0eb5bf5 100755
--- a/hlsl/hlslScanContext.cpp
+++ b/hlsl/hlslScanContext.cpp
@@ -331,6 +331,7 @@
     (*KeywordMap)["class"] =                   EHTokClass;
     (*KeywordMap)["struct"] =                  EHTokStruct;
     (*KeywordMap)["cbuffer"] =                 EHTokCBuffer;
+    (*KeywordMap)["ConstantBuffer"] =          EHTokConstantBuffer;
     (*KeywordMap)["tbuffer"] =                 EHTokTBuffer;
     (*KeywordMap)["typedef"] =                 EHTokTypedef;
     (*KeywordMap)["this"] =                    EHTokThis;
@@ -827,6 +828,7 @@
     case EHTokStruct:
     case EHTokTypedef:
     case EHTokCBuffer:
+    case EHTokConstantBuffer:
     case EHTokTBuffer:
     case EHTokThis:
     case EHTokNamespace:
diff --git a/hlsl/hlslTokens.h b/hlsl/hlslTokens.h
index cba0b96..f6a2c96 100755
--- a/hlsl/hlslTokens.h
+++ b/hlsl/hlslTokens.h
@@ -275,6 +275,7 @@
     EHTokTypedef,
     EHTokThis,
     EHTokNamespace,
+    EHTokConstantBuffer,
 
     // constant
     EHTokFloatConstant,