From 046bae0babd17ecc19fc7cbe40c35aa13ac2ee65 Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Sat, 23 Dec 2017 17:29:45 -0700
Subject: [PATCH] HLSL: Attributes: Add [[vk::constant_id()]] and
 [[vk::push_constant]]

---
 Test/baseResults/hlsl.attributeC11.frag.out | 123 +++++++++++---------
 Test/hlsl.attributeC11.frag                 |   6 +-
 hlsl/hlslAttributes.cpp                     |   4 +
 hlsl/hlslAttributes.h                       |   4 +-
 hlsl/hlslGrammar.cpp                        |  31 ++---
 hlsl/hlslGrammar.h                          |   4 +-
 hlsl/hlslParseHelper.cpp                    |  34 ++++--
 hlsl/hlslParseHelper.h                      |   1 +
 8 files changed, 127 insertions(+), 80 deletions(-)

diff --git a/Test/baseResults/hlsl.attributeC11.frag.out b/Test/baseResults/hlsl.attributeC11.frag.out
index 905f049c2..b507abac0 100755
--- a/Test/baseResults/hlsl.attributeC11.frag.out
+++ b/Test/baseResults/hlsl.attributeC11.frag.out
@@ -2,42 +2,45 @@ hlsl.attributeC11.frag
 Shader version: 500
 gl_FragCoord origin is upper left
 0:? Sequence
-0:16  Function Definition: @main(vf4; ( temp 4-component vector of float)
-0:16    Function Parameters: 
-0:16      'input' ( in 4-component vector of float)
+0:20  Function Definition: @main(vf4; ( temp 4-component vector of float)
+0:20    Function Parameters: 
+0:20      'input' ( in 4-component vector of float)
 0:?     Sequence
-0:17      Branch: Return with expression
-0:17        add ( temp 4-component vector of float)
-0:17          'input' ( in 4-component vector of float)
-0:17          textureFetch ( temp 4-component vector of float)
-0:17            'attach' ( uniform texture2D)
-0:17            vector swizzle ( temp int)
-0:17              Constant:
-0:17                0 (const int)
-0:17                0 (const int)
-0:17              Sequence
-0:17                Constant:
-0:17                  0 (const int)
-0:17            direct index ( temp int)
-0:17              Constant:
-0:17                0 (const int)
-0:17                0 (const int)
-0:17              Constant:
-0:17                1 (const int)
-0:16  Function Definition: main( ( temp void)
-0:16    Function Parameters: 
+0:21      Branch: Return with expression
+0:21        add ( temp 4-component vector of float)
+0:21          'input' ( in 4-component vector of float)
+0:21          textureFetch ( temp 4-component vector of float)
+0:21            'attach' ( uniform texture2D)
+0:21            vector swizzle ( temp int)
+0:21              Constant:
+0:21                0 (const int)
+0:21                0 (const int)
+0:21              Sequence
+0:21                Constant:
+0:21                  0 (const int)
+0:21            direct index ( temp int)
+0:21              Constant:
+0:21                0 (const int)
+0:21                0 (const int)
+0:21              Constant:
+0:21                1 (const int)
+0:20  Function Definition: main( ( temp void)
+0:20    Function Parameters: 
 0:?     Sequence
-0:16      move second child to first child ( temp 4-component vector of float)
+0:20      move second child to first child ( temp 4-component vector of float)
 0:?         'input' ( temp 4-component vector of float)
 0:?         'input' (layout( location=8) in 4-component vector of float)
-0:16      move second child to first child ( temp 4-component vector of float)
+0:20      move second child to first child ( temp 4-component vector of float)
 0:?         '@entryPointOutput' (layout( location=7) out 4-component vector of float)
-0:16        Function Call: @main(vf4; ( temp 4-component vector of float)
+0:20        Function Call: @main(vf4; ( temp 4-component vector of float)
 0:?           'input' ( temp 4-component vector of float)
 0:?   Linker Objects
 0:?     'buffer1' (layout( set=0 binding=1 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of structure{ temp 2-component vector of float f} @data})
 0:?     'buffer3' (layout( set=2 binding=3 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of structure{ temp 2-component vector of float f} @data})
 0:?     'attach' ( uniform texture2D)
+0:?     'ci' ( specialization-constant const int)
+0:?       11 (const int)
+0:?     'anon@0' (layout( row_major std430 push_constant) uniform block{layout( row_major std430 offset=0) uniform int a})
 0:?     '@entryPointOutput' (layout( location=7) out 4-component vector of float)
 0:?     'input' (layout( location=8) in 4-component vector of float)
 
@@ -48,48 +51,51 @@ Linked fragment stage:
 Shader version: 500
 gl_FragCoord origin is upper left
 0:? Sequence
-0:16  Function Definition: @main(vf4; ( temp 4-component vector of float)
-0:16    Function Parameters: 
-0:16      'input' ( in 4-component vector of float)
+0:20  Function Definition: @main(vf4; ( temp 4-component vector of float)
+0:20    Function Parameters: 
+0:20      'input' ( in 4-component vector of float)
 0:?     Sequence
-0:17      Branch: Return with expression
-0:17        add ( temp 4-component vector of float)
-0:17          'input' ( in 4-component vector of float)
-0:17          textureFetch ( temp 4-component vector of float)
-0:17            'attach' ( uniform texture2D)
-0:17            vector swizzle ( temp int)
-0:17              Constant:
-0:17                0 (const int)
-0:17                0 (const int)
-0:17              Sequence
-0:17                Constant:
-0:17                  0 (const int)
-0:17            direct index ( temp int)
-0:17              Constant:
-0:17                0 (const int)
-0:17                0 (const int)
-0:17              Constant:
-0:17                1 (const int)
-0:16  Function Definition: main( ( temp void)
-0:16    Function Parameters: 
+0:21      Branch: Return with expression
+0:21        add ( temp 4-component vector of float)
+0:21          'input' ( in 4-component vector of float)
+0:21          textureFetch ( temp 4-component vector of float)
+0:21            'attach' ( uniform texture2D)
+0:21            vector swizzle ( temp int)
+0:21              Constant:
+0:21                0 (const int)
+0:21                0 (const int)
+0:21              Sequence
+0:21                Constant:
+0:21                  0 (const int)
+0:21            direct index ( temp int)
+0:21              Constant:
+0:21                0 (const int)
+0:21                0 (const int)
+0:21              Constant:
+0:21                1 (const int)
+0:20  Function Definition: main( ( temp void)
+0:20    Function Parameters: 
 0:?     Sequence
-0:16      move second child to first child ( temp 4-component vector of float)
+0:20      move second child to first child ( temp 4-component vector of float)
 0:?         'input' ( temp 4-component vector of float)
 0:?         'input' (layout( location=8) in 4-component vector of float)
-0:16      move second child to first child ( temp 4-component vector of float)
+0:20      move second child to first child ( temp 4-component vector of float)
 0:?         '@entryPointOutput' (layout( location=7) out 4-component vector of float)
-0:16        Function Call: @main(vf4; ( temp 4-component vector of float)
+0:20        Function Call: @main(vf4; ( temp 4-component vector of float)
 0:?           'input' ( temp 4-component vector of float)
 0:?   Linker Objects
 0:?     'buffer1' (layout( set=0 binding=1 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of structure{ temp 2-component vector of float f} @data})
 0:?     'buffer3' (layout( set=2 binding=3 row_major std430) readonly buffer block{layout( row_major std430) buffer implicitly-sized array of structure{ temp 2-component vector of float f} @data})
 0:?     'attach' ( uniform texture2D)
+0:?     'ci' ( specialization-constant const int)
+0:?       11 (const int)
+0:?     'anon@0' (layout( row_major std430 push_constant) uniform block{layout( row_major std430 offset=0) uniform int a})
 0:?     '@entryPointOutput' (layout( location=7) out 4-component vector of float)
 0:?     'input' (layout( location=8) in 4-component vector of float)
 
 // Module Version 10000
 // Generated by (magic number): 80003
-// Id's are bound by 47
+// Id's are bound by 51
 
                               Capability Shader
                1:             ExtInstImport  "GLSL.std.450"
@@ -111,6 +117,10 @@ gl_FragCoord origin is upper left
                               MemberName 43(buffer1) 0  "@data"
                               Name 45  "buffer1"
                               Name 46  "buffer3"
+                              Name 47  "ci"
+                              Name 48  "pcBuf"
+                              MemberName 48(pcBuf) 0  "a"
+                              Name 50  ""
                               Decorate 16(attach) DescriptorSet 0
                               Decorate 16(attach) InputAttachmentIndex 4
                               Decorate 33(input) Location 8
@@ -124,6 +134,9 @@ gl_FragCoord origin is upper left
                               Decorate 45(buffer1) Binding 1
                               Decorate 46(buffer3) DescriptorSet 2
                               Decorate 46(buffer3) Binding 3
+                              Decorate 47(ci) SpecId 13
+                              MemberDecorate 48(pcBuf) 0 Offset 0
+                              Decorate 48(pcBuf) Block
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeFloat 32
@@ -151,6 +164,10 @@ gl_FragCoord origin is upper left
               44:             TypePointer Uniform 43(buffer1)
      45(buffer1):     44(ptr) Variable Uniform
      46(buffer3):     44(ptr) Variable Uniform
+          47(ci):     18(int) SpecConstant 11
+       48(pcBuf):             TypeStruct 18(int)
+              49:             TypePointer PushConstant 48(pcBuf)
+              50:     49(ptr) Variable PushConstant
          4(main):           2 Function None 3
                5:             Label
        31(input):      8(ptr) Variable Function
diff --git a/Test/hlsl.attributeC11.frag b/Test/hlsl.attributeC11.frag
index 4fe663a2a..336511f92 100644
--- a/Test/hlsl.attributeC11.frag
+++ b/Test/hlsl.attributeC11.frag
@@ -11,8 +11,12 @@ StructuredBuffer<S> buffer3;
 [[vk::input_attachment_index(4)]]
 Texture2D<float4> attach;
 
+[[vk::constant_id(13)]] const int ci = 11;
+
+[[vk::push_constant]] cbuffer pcBuf { int a; };
+
 [[vk::location(7)]] float4
 main([[vk::location(8)]] float4 input: A) : B
 {
-    return input + attach.Load(float2(0.5));
+    return input + attach.Load(float2(0.5));// * a;
 }
diff --git a/hlsl/hlslAttributes.cpp b/hlsl/hlslAttributes.cpp
index a7840da14..2d204d315 100644
--- a/hlsl/hlslAttributes.cpp
+++ b/hlsl/hlslAttributes.cpp
@@ -62,6 +62,10 @@ namespace glslang {
                 return EatGlobalBinding;
             else if (lowername == "builtin")
                 return EatBuiltIn;
+            else if (lowername == "constant_id")
+                return EatConstantId;
+            else if (lowername == "push_constant")
+                return EatPushConstant;
         } else if (lowernameSpace.size() > 0)
             return EatNone;
 
diff --git a/hlsl/hlslAttributes.h b/hlsl/hlslAttributes.h
index 5210ca3b8..2c3cf76e6 100644
--- a/hlsl/hlslAttributes.h
+++ b/hlsl/hlslAttributes.h
@@ -67,7 +67,9 @@ namespace glslang {
         EatGlobalBinding,
         EatLocation,
         EatInputAttachment,
-        EatBuiltIn
+        EatBuiltIn,
+        EatPushConstant,
+        EatConstantId
     };
 }
 
diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp
index db7397cfd..c71ba165f 100755
--- a/hlsl/hlslGrammar.cpp
+++ b/hlsl/hlslGrammar.cpp
@@ -376,11 +376,9 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
 
     bool forbidDeclarators = (peekTokenClass(EHTokCBuffer) || peekTokenClass(EHTokTBuffer));
     // fully_specified_type
-    if (! acceptFullySpecifiedType(declaredType, nodeList))
+    if (! acceptFullySpecifiedType(declaredType, nodeList, declarator.attributes))
         return false;
 
-    parseContext.transferTypeAttributes(declarator.attributes, declaredType);
-
     // cbuffer and tbuffer end with the closing '}'.
     // No semicolon is included.
     if (forbidDeclarators)
@@ -538,10 +536,11 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
 bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
 {
     node = nullptr;
+    TAttributeMap attributes;
 
     // fully_specified_type
     TType type;
-    if (! acceptFullySpecifiedType(type))
+    if (! acceptFullySpecifiedType(type, attributes))
         return false;
 
     // filter out type casts
@@ -579,12 +578,12 @@ bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
 //      : type_specifier
 //      | type_qualifier type_specifier
 //
-bool HlslGrammar::acceptFullySpecifiedType(TType& type)
+bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributeMap& attributes)
 {
     TIntermNode* nodeList = nullptr;
-    return acceptFullySpecifiedType(type, nodeList);
+    return acceptFullySpecifiedType(type, nodeList, attributes);
 }
-bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList)
+bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributeMap& attributes)
 {
     // type_qualifier
     TQualifier qualifier;
@@ -603,9 +602,14 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList)
 
         return false;
     }
+
     if (type.getBasicType() == EbtBlock) {
         // the type was a block, which set some parts of the qualifier
         parseContext.mergeQualifiers(type.getQualifier(), qualifier);
+    
+        // merge in the attributes
+        parseContext.transferTypeAttributes(attributes, type);
+
         // further, it can create an anonymous instance of the block
         if (peek() != EHTokIdentifier)
             parseContext.declareBlock(loc, type);
@@ -626,7 +630,10 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList)
         if (type.isBuiltIn())
             qualifier.builtIn = type.getQualifier().builtIn;
 
-        type.getQualifier()    = qualifier;
+        type.getQualifier() = qualifier;
+
+        // merge in the attributes
+        parseContext.transferTypeAttributes(attributes, type);
     }
 
     return true;
@@ -2333,13 +2340,11 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
 
         // fully_specified_type
         TType memberType;
-        if (! acceptFullySpecifiedType(memberType, nodeList)) {
+        if (! acceptFullySpecifiedType(memberType, nodeList, attributes)) {
             expected("member type");
             return false;
         }
 
-        parseContext.transferTypeAttributes(attributes, memberType);
-
         // struct_declarator COMMA struct_declarator ...
         bool functionDefinitionAccepted = false;
         do {
@@ -2540,11 +2545,9 @@ bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
 
     // fully_specified_type
     TType* type = new TType;
-    if (! acceptFullySpecifiedType(*type))
+    if (! acceptFullySpecifiedType(*type, attributes))
         return false;
 
-    parseContext.transferTypeAttributes(attributes, *type);
-
     // identifier
     HlslToken idToken;
     acceptIdentifier(idToken);
diff --git a/hlsl/hlslGrammar.h b/hlsl/hlslGrammar.h
index 9d5380c10..f5613d907 100755
--- a/hlsl/hlslGrammar.h
+++ b/hlsl/hlslGrammar.h
@@ -71,8 +71,8 @@ namespace glslang {
         bool acceptControlDeclaration(TIntermNode*& node);
         bool acceptSamplerDeclarationDX9(TType&);
         bool acceptSamplerState();
-        bool acceptFullySpecifiedType(TType&);
-        bool acceptFullySpecifiedType(TType&, TIntermNode*& nodeList);
+        bool acceptFullySpecifiedType(TType&, const TAttributeMap&);
+        bool acceptFullySpecifiedType(TType&, TIntermNode*& nodeList, const TAttributeMap&);
         bool acceptQualifier(TQualifier&);
         bool acceptLayoutQualifierList(TQualifier&);
         bool acceptType(TType&);
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index 7e401fd6f..ac72e2700 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -1890,6 +1890,17 @@ void HlslParseContext::transferTypeAttributes(const TAttributeMap& attributes, T
         if (builtInString == "PointSize")
             type.getQualifier().builtIn = EbvPointSize;
     }
+
+    // push_constant
+    if (attributes.contains(EatPushConstant))
+        type.getQualifier().layoutPushConstant = true;
+
+    // specialization constant
+    if (attributes.getInt(EatConstantId, value)) {
+        TSourceLoc loc;
+        loc.init();
+        setSpecConstantId(loc, type.getQualifier(), value);
+    }
 }
 
 //
@@ -7041,15 +7052,7 @@ void HlslParseContext::setLayoutQualifier(const TSourceLoc& loc, TQualifier& qua
         return;
     }
     if (id == "constant_id") {
-        requireSpv(loc, "constant_id");
-        if (value >= (int)TQualifier::layoutSpecConstantIdEnd) {
-            error(loc, "specialization-constant id is too large", id.c_str(), "");
-        } else {
-            qualifier.layoutSpecConstantId = value;
-            qualifier.specConstant = true;
-            if (! intermediate.addUsedConstantId(value))
-                error(loc, "specialization-constant id already used", id.c_str(), "");
-        }
+        setSpecConstantId(loc, qualifier, value);
         return;
     }
 
@@ -7144,6 +7147,19 @@ void HlslParseContext::setLayoutQualifier(const TSourceLoc& loc, TQualifier& qua
     error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), "");
 }
 
+void HlslParseContext::setSpecConstantId(const TSourceLoc& loc, TQualifier& qualifier, int value)
+{
+    if (value >= (int)TQualifier::layoutSpecConstantIdEnd) {
+        error(loc, "specialization-constant id is too large", "constant_id", "");
+    } else {
+        qualifier.layoutSpecConstantId = value;
+        qualifier.specConstant = true;
+        if (! intermediate.addUsedConstantId(value))
+            error(loc, "specialization-constant id already used", "constant_id", "");
+    }
+    return;
+}
+
 // Merge any layout qualifier information from src into dst, leaving everything else in dst alone
 //
 // "More than one layout qualifier may appear in a single declaration.
diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h
index a56fc2e41..833eb8e5b 100755
--- a/hlsl/hlslParseHelper.h
+++ b/hlsl/hlslParseHelper.h
@@ -138,6 +138,7 @@ public:
 
     void setLayoutQualifier(const TSourceLoc&, TQualifier&, TString&);
     void setLayoutQualifier(const TSourceLoc&, TQualifier&, TString&, const TIntermTyped*);
+    void setSpecConstantId(const TSourceLoc&, TQualifier&, int value);
     void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
     void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
 
-- 
GitLab