From 3d157c510fc3bfefe675edf124633212b82d4845 Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Mon, 25 Jul 2016 16:05:33 -0600 Subject: [PATCH] HLSL: cbuffer and tbuffer grammar and production. --- Test/baseResults/hlsl.buffer.frag.out | 153 ++++++++++++++++++++++++++ Test/hlsl.buffer.frag | 22 ++++ glslang/Include/revision.h | 4 +- gtests/Hlsl.FromFile.cpp | 1 + hlsl/hlslGrammar.cpp | 55 +++++++-- hlsl/hlslParseHelper.cpp | 70 ++++++------ hlsl/hlslParseHelper.h | 4 +- hlsl/hlslScanContext.cpp | 5 + hlsl/hlslTokens.h | 2 + 9 files changed, 269 insertions(+), 47 deletions(-) create mode 100755 Test/baseResults/hlsl.buffer.frag.out create mode 100644 Test/hlsl.buffer.frag diff --git a/Test/baseResults/hlsl.buffer.frag.out b/Test/baseResults/hlsl.buffer.frag.out new file mode 100755 index 000000000..a14521974 --- /dev/null +++ b/Test/baseResults/hlsl.buffer.frag.out @@ -0,0 +1,153 @@ +hlsl.buffer.frag +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:23 Function Definition: PixelShaderFunction(vf4; (global 4-component vector of float) +0:20 Function Parameters: +0:20 'input' (in 4-component vector of float) +0:? Sequence +0:21 Branch: Return with expression +0:21 add (temp 4-component vector of float) +0:21 add (temp 4-component vector of float) +0:21 add (temp 4-component vector of float) +0:21 'input' (in 4-component vector of float) +0:21 v1: direct index for structure (layout(column_major std140 ) uniform 4-component vector of float) +0:21 'anon@0' (layout(column_major std140 ) uniform block{layout(column_major std140 ) uniform 4-component vector of float v1}) +0:21 Constant: +0:21 0 (const uint) +0:21 add (temp 4-component vector of float) +0:21 v2: direct index for structure (layout(column_major std430 ) buffer 4-component vector of float) +0:21 'anon@1' (layout(column_major std430 ) buffer block{layout(column_major std430 ) buffer 4-component vector of float v2}) +0:21 Constant: +0:21 0 (const uint) +0:21 v3: direct index for structure (layout(column_major std140 ) uniform 4-component vector of float) +0:21 'anon@2' (layout(column_major std140 ) uniform block{layout(column_major std140 ) uniform 4-component vector of float v3, layout(column_major std140 ) uniform int i3}) +0:21 Constant: +0:21 0 (const uint) +0:21 v4: direct index for structure (layout(column_major std430 ) buffer 4-component vector of float) +0:21 'anon@3' (layout(column_major std430 ) buffer block{layout(column_major std430 ) buffer 4-component vector of float v4, layout(column_major std430 ) buffer int i4}) +0:21 Constant: +0:21 0 (const uint) +0:? Linker Objects +0:? 'anon@0' (layout(column_major std140 ) uniform block{layout(column_major std140 ) uniform 4-component vector of float v1}) +0:? 'anon@1' (layout(column_major std430 ) buffer block{layout(column_major std430 ) buffer 4-component vector of float v2}) +0:? 'anon@2' (layout(column_major std140 ) uniform block{layout(column_major std140 ) uniform 4-component vector of float v3, layout(column_major std140 ) uniform int i3}) +0:? 'anon@3' (layout(column_major std430 ) buffer block{layout(column_major std430 ) buffer 4-component vector of float v4, layout(column_major std430 ) buffer int i4}) + + +Linked fragment stage: + + +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:23 Function Definition: PixelShaderFunction(vf4; (global 4-component vector of float) +0:20 Function Parameters: +0:20 'input' (in 4-component vector of float) +0:? Sequence +0:21 Branch: Return with expression +0:21 add (temp 4-component vector of float) +0:21 add (temp 4-component vector of float) +0:21 add (temp 4-component vector of float) +0:21 'input' (in 4-component vector of float) +0:21 v1: direct index for structure (layout(column_major std140 ) uniform 4-component vector of float) +0:21 'anon@0' (layout(column_major std140 ) uniform block{layout(column_major std140 ) uniform 4-component vector of float v1}) +0:21 Constant: +0:21 0 (const uint) +0:21 add (temp 4-component vector of float) +0:21 v2: direct index for structure (layout(column_major std430 ) buffer 4-component vector of float) +0:21 'anon@1' (layout(column_major std430 ) buffer block{layout(column_major std430 ) buffer 4-component vector of float v2}) +0:21 Constant: +0:21 0 (const uint) +0:21 v3: direct index for structure (layout(column_major std140 ) uniform 4-component vector of float) +0:21 'anon@2' (layout(column_major std140 ) uniform block{layout(column_major std140 ) uniform 4-component vector of float v3, layout(column_major std140 ) uniform int i3}) +0:21 Constant: +0:21 0 (const uint) +0:21 v4: direct index for structure (layout(column_major std430 ) buffer 4-component vector of float) +0:21 'anon@3' (layout(column_major std430 ) buffer block{layout(column_major std430 ) buffer 4-component vector of float v4, layout(column_major std430 ) buffer int i4}) +0:21 Constant: +0:21 0 (const uint) +0:? Linker Objects +0:? 'anon@0' (layout(column_major std140 ) uniform block{layout(column_major std140 ) uniform 4-component vector of float v1}) +0:? 'anon@1' (layout(column_major std430 ) buffer block{layout(column_major std430 ) buffer 4-component vector of float v2}) +0:? 'anon@2' (layout(column_major std140 ) uniform block{layout(column_major std140 ) uniform 4-component vector of float v3, layout(column_major std140 ) uniform int i3}) +0:? 'anon@3' (layout(column_major std430 ) buffer block{layout(column_major std430 ) buffer 4-component vector of float v4, layout(column_major std430 ) buffer int i4}) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 39 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "PixelShaderFunction" 9 + ExecutionMode 4 OriginUpperLeft + Source HLSL 450 + Name 4 "PixelShaderFunction" + Name 9 "input" + Name 11 "" + MemberName 11 0 "v1" + Name 13 "" + Name 20 "" + MemberName 20 0 "v2" + Name 22 "" + Name 25 "" + MemberName 25 0 "v3" + MemberName 25 1 "i3" + Name 27 "" + Name 32 "" + MemberName 32 0 "v4" + MemberName 32 1 "i4" + Name 34 "" + MemberDecorate 11 0 Offset 0 + Decorate 11 Block + Decorate 13 DescriptorSet 0 + MemberDecorate 20 0 Offset 0 + Decorate 20 BufferBlock + Decorate 22 DescriptorSet 0 + MemberDecorate 25 0 Offset 0 + MemberDecorate 25 1 Offset 16 + Decorate 25 Block + Decorate 27 DescriptorSet 0 + MemberDecorate 32 0 Offset 0 + MemberDecorate 32 1 Offset 16 + Decorate 32 BufferBlock + Decorate 34 DescriptorSet 0 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeVector 6(float) 4 + 8: TypePointer Input 7(fvec4) + 9(input): 8(ptr) Variable Input + 11: TypeStruct 7(fvec4) + 12: TypePointer Uniform 11(struct) + 13: 12(ptr) Variable Uniform + 14: TypeInt 32 1 + 15: 14(int) Constant 0 + 16: TypePointer Uniform 7(fvec4) + 20: TypeStruct 7(fvec4) + 21: TypePointer Uniform 20(struct) + 22: 21(ptr) Variable Uniform + 25: TypeStruct 7(fvec4) 14(int) + 26: TypePointer Uniform 25(struct) + 27: 26(ptr) Variable Uniform + 32: TypeStruct 7(fvec4) 14(int) + 33: TypePointer Uniform 32(struct) + 34: 33(ptr) Variable Uniform +4(PixelShaderFunction): 2 Function None 3 + 5: Label + 10: 7(fvec4) Load 9(input) + 17: 16(ptr) AccessChain 13 15 + 18: 7(fvec4) Load 17 + 19: 7(fvec4) FAdd 10 18 + 23: 16(ptr) AccessChain 22 15 + 24: 7(fvec4) Load 23 + 28: 16(ptr) AccessChain 27 15 + 29: 7(fvec4) Load 28 + 30: 7(fvec4) FAdd 24 29 + 31: 7(fvec4) FAdd 19 30 + 35: 16(ptr) AccessChain 34 15 + 36: 7(fvec4) Load 35 + 37: 7(fvec4) FAdd 31 36 + ReturnValue 37 + FunctionEnd diff --git a/Test/hlsl.buffer.frag b/Test/hlsl.buffer.frag new file mode 100644 index 000000000..fbfdc3165 --- /dev/null +++ b/Test/hlsl.buffer.frag @@ -0,0 +1,22 @@ +cbuffer { + float4 v1; +}; + +tbuffer { + float4 v2; +}; + +cbuffer cbufName : register(b2) { + float4 v3; + int i3 : packoffset(c1.y); +}; + +tbuffer tbufName : register(b8) { + float4 v4 : packoffset(c1); + int i4 : packoffset(c3); +}; + +float4 PixelShaderFunction(float4 input) : COLOR0 +{ + return input + v1 + v2 + v3 + v4; +} diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 8bc17dd41..4a4361b62 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // For the version, it uses the latest git tag followed by the number of commits. // For the date, it uses the current date (when then script is run). -#define GLSLANG_REVISION "SPIRV99.1332" -#define GLSLANG_DATE "21-Jul-2016" +#define GLSLANG_REVISION "SPIRV99.1337" +#define GLSLANG_DATE "25-Jul-2016" diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 900aee7f6..0be8850cf 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -75,6 +75,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.array.frag", "PixelShaderFunction"}, {"hlsl.assoc.frag", "PixelShaderFunction"}, {"hlsl.attribute.frag", "PixelShaderFunction"}, + {"hlsl.buffer.frag", "PixelShaderFunction"}, {"hlsl.cast.frag", "PixelShaderFunction"}, {"hlsl.discard.frag", "PixelShaderFunction"}, {"hlsl.doLoop.frag", "PixelShaderFunction"}, diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index fc8360c84..37c8635c9 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -337,6 +337,8 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node) if (typedefDecl) parseContext.declareTypedef(idToken.loc, *idToken.string, type, arraySizes); + else if (type.getBasicType() == EbtBlock) + parseContext.declareBlock(idToken.loc, type, idToken.string); else { // Declare the variable and add any initializer code to the AST. // The top-level node is always made into an aggregate, as that's @@ -414,11 +416,19 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type) TQualifier qualifier; qualifier.clear(); acceptQualifier(qualifier); + TSourceLoc loc = token.loc; // type_specifier if (! acceptType(type)) return false; - type.getQualifier() = qualifier; + if (type.getBasicType() == EbtBlock) { + // the type was a block, which set some parts of the qualifier + parseContext.mergeQualifiers(loc, type.getQualifier(), qualifier, true); + // further, it can create an anonymous instance of the block + if (peekTokenClass(EHTokSemicolon)) + parseContext.declareBlock(loc, type); + } else + type.getQualifier() = qualifier; return true; } @@ -825,6 +835,8 @@ bool HlslGrammar::acceptType(TType& type) break; case EHTokStruct: + case EHTokCBuffer: + case EHTokTBuffer: return acceptStruct(type); break; @@ -1186,13 +1198,29 @@ bool HlslGrammar::acceptType(TType& type) } // struct -// : STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE -// | STRUCT LEFT_BRACE struct_declaration_list RIGHT_BRACE +// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE +// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE +// +// struct_type +// : STRUCT +// | CBUFFER +// | TBUFFER // bool HlslGrammar::acceptStruct(TType& type) { + // This qualifier.storage will tell us whether it's an AST block or + // just a struct. + TQualifier qualifier; + qualifier.clear(); + + // CBUFFER + if (acceptTokenClass(EHTokCBuffer)) + qualifier.storage = EvqUniform; + // TBUFFER + else if (acceptTokenClass(EHTokTBuffer)) + qualifier.storage = EvqBuffer; // STRUCT - if (! acceptTokenClass(EHTokStruct)) + else if (! acceptTokenClass(EHTokStruct)) return false; // IDENTIFIER @@ -1202,6 +1230,9 @@ bool HlslGrammar::acceptStruct(TType& type) advanceToken(); } + // post_decls + acceptPostDecls(type); + // LEFT_BRACE if (! acceptTokenClass(EHTokLeftBrace)) { expected("{"); @@ -1222,11 +1253,15 @@ bool HlslGrammar::acceptStruct(TType& type) } // create the user-defined type - new(&type) TType(typeList, structName); - - // If it was named, which means it can be reused later, add - // it to the symbol table. - if (structName.size() > 0) { + if (qualifier.storage == EvqTemporary) + new(&type) TType(typeList, structName); + else + new(&type) TType(typeList, structName, qualifier); // sets EbtBlock + + // If it was named, which means the type can be reused later, add + // it to the symbol table. (Unless it's a block, in which + // case the name is not a type.) + if (type.getBasicType() != EbtBlock && structName.size() > 0) { TVariable* userTypeDef = new TVariable(&structName, type, true); if (! parseContext.symbolTable.insert(*userTypeDef)) parseContext.error(token.loc, "redefinition", structName.c_str(), "struct"); @@ -2442,6 +2477,7 @@ void HlslGrammar::acceptPostDecls(TType& type) break; } // TODO: process the packoffset information + // c1.y means component y of location slot 1 } else if (! acceptIdentifier(idToken)) { expected("semantic or packoffset or register"); return; @@ -2462,6 +2498,7 @@ void HlslGrammar::acceptPostDecls(TType& type) break; } // TODO: process the register information + // b2 means buffer 2 } else { // semantic, in idToken.string parseContext.handleSemantic(type, *idToken.string); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 83817eaaf..5b265f1b5 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -2533,10 +2533,10 @@ void HlslParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, c if (dst.storage == EvqTemporary || dst.storage == EvqGlobal) dst.storage = src.storage; else if ((dst.storage == EvqIn && src.storage == EvqOut) || - (dst.storage == EvqOut && src.storage == EvqIn)) + (dst.storage == EvqOut && src.storage == EvqIn)) dst.storage = EvqInOut; else if ((dst.storage == EvqIn && src.storage == EvqConst) || - (dst.storage == EvqConst && src.storage == EvqIn)) + (dst.storage == EvqConst && src.storage == EvqIn)) dst.storage = EvqConstReadOnly; else if (src.storage != EvqTemporary && src.storage != EvqGlobal) error(loc, "too many storage qualifiers", GetStorageQualifierString(src.storage), ""); @@ -3898,28 +3898,31 @@ TIntermTyped* HlslParseContext::constructAggregate(TIntermNode* node, const TTyp // // Do everything needed to add an interface block. // -void HlslParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes) +void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TString* instanceName, TArraySizes* arraySizes) { + assert(type.getWritableStruct() != nullptr); + + TTypeList& typeList = *type.getWritableStruct(); // fix and check for member storage qualifiers and types that don't belong within a block for (unsigned int member = 0; member < typeList.size(); ++member) { TType& memberType = *typeList[member].type; TQualifier& memberQualifier = memberType.getQualifier(); const TSourceLoc& memberLoc = typeList[member].loc; globalQualifierFix(memberLoc, memberQualifier); - memberQualifier.storage = currentBlockQualifier.storage; + memberQualifier.storage = type.getQualifier().storage; } // This might be a redeclaration of a built-in block. If so, redeclareBuiltinBlock() will // do all the rest. - if (! symbolTable.atBuiltInLevel() && builtInName(*blockName)) { - redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes); - return; - } + //if (! symbolTable.atBuiltInLevel() && builtInName(*blockName)) { + // redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes); + // return; + //} // Make default block qualification, and adjust the member qualifications TQualifier defaultQualification; - switch (currentBlockQualifier.storage) { + switch (type.getQualifier().storage) { case EvqUniform: defaultQualification = globalUniformDefaults; break; case EvqBuffer: defaultQualification = globalBufferDefaults; break; case EvqVaryingIn: defaultQualification = globalInputDefaults; break; @@ -3929,12 +3932,12 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, // Special case for "push_constant uniform", which has a default of std430, // contrary to normal uniform defaults, and can't have a default tracked for it. - if (currentBlockQualifier.layoutPushConstant && ! currentBlockQualifier.hasPacking()) - currentBlockQualifier.layoutPacking = ElpStd430; + if (type.getQualifier().layoutPushConstant && ! type.getQualifier().hasPacking()) + type.getQualifier().layoutPacking = ElpStd430; // fix and check for member layout qualifiers - mergeObjectLayoutQualifiers(defaultQualification, currentBlockQualifier, true); + mergeObjectLayoutQualifiers(defaultQualification, type.getQualifier(), true); bool memberWithLocation = false; bool memberWithoutLocation = false; @@ -3958,7 +3961,7 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, if (memberQualifier.hasPacking()) error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), ""); if (memberQualifier.hasLocation()) { - switch (currentBlockQualifier.storage) { + switch (type.getQualifier().storage) { case EvqVaryingIn: case EvqVaryingOut: memberWithLocation = true; @@ -3979,19 +3982,20 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, } // Process the members - fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation); - fixBlockXfbOffsets(currentBlockQualifier, typeList); - fixBlockUniformOffsets(currentBlockQualifier, typeList); + fixBlockLocations(loc, type.getQualifier(), typeList, memberWithLocation, memberWithoutLocation); + fixBlockXfbOffsets(type.getQualifier(), typeList); + fixBlockUniformOffsets(type.getQualifier(), typeList); // reverse merge, so that currentBlockQualifier now has all layout information // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers) - mergeObjectLayoutQualifiers(currentBlockQualifier, defaultQualification, true); + mergeObjectLayoutQualifiers(type.getQualifier(), defaultQualification, true); // // Build and add the interface block as a new type named 'blockName' // - TType blockType(&typeList, *blockName, currentBlockQualifier); + //?? need the block name to be a typename? + TType blockType(&typeList, "" /* *blockName */, type.getQualifier()); if (arraySizes) blockType.newArraySizes(*arraySizes); @@ -4008,20 +4012,20 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, // whose type is EbtBlock, but without all the structure; that will come from the type // the instances point to. // - TType blockNameType(EbtBlock, blockType.getQualifier().storage); - TVariable* blockNameVar = new TVariable(blockName, blockNameType); - if (! symbolTable.insert(*blockNameVar)) { - TSymbol* existingName = symbolTable.find(*blockName); - if (existingName->getType().getBasicType() == EbtBlock) { - if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) { - error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString()); - return; - } - } else { - error(loc, "block name cannot redefine a non-block name", blockName->c_str(), ""); - return; - } - } + //??TType blockNameType(EbtBlock, blockType.getQualifier().storage); + //??TVariable* blockNameVar = new TVariable(blockName, blockNameType); + //if (! symbolTable.insert(*blockNameVar)) { + // TSymbol* existingName = symbolTable.find(*blockName); + // if (existingName->getType().getBasicType() == EbtBlock) { + // if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) { + // error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString()); + // return; + // } + // } else { + // error(loc, "block name cannot redefine a non-block name", blockName->c_str(), ""); + // return; + // } + //} // Add the variable, as anonymous or named instanceName. // Make an anonymous variable if no name was provided. @@ -4031,7 +4035,7 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, TVariable& variable = *new TVariable(instanceName, blockType); if (! symbolTable.insert(variable)) { if (*instanceName == "") - error(loc, "nameless block contains a member that already has a name at global scope", blockName->c_str(), ""); + error(loc, "nameless block contains a member that already has a name at global scope", "" /* blockName->c_str() */, ""); else error(loc, "block instance name redefinition", variable.getName().c_str(), ""); diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index f12813194..9c404ae46 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -133,7 +133,7 @@ public: TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&, TOperator); TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); - void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); + void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0, TArraySizes* arraySizes = 0); void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); void fixBlockXfbOffsets(TQualifier&, TTypeList&); void fixBlockUniformOffsets(TQualifier&, TTypeList&); @@ -176,8 +176,6 @@ protected: bool postMainReturn; // if inside a function, true if the function is the entry point and this is after a return statement const TType* currentFunctionType; // the return type of the function that's currently being parsed bool functionReturnsValue; // true if a non-void function has a return - const TString* blockName; - TQualifier currentBlockQualifier; TBuiltInResource resources; TLimits& limits; diff --git a/hlsl/hlslScanContext.cpp b/hlsl/hlslScanContext.cpp index 8a4eb736b..da393211f 100755 --- a/hlsl/hlslScanContext.cpp +++ b/hlsl/hlslScanContext.cpp @@ -258,6 +258,8 @@ void HlslScanContext::fillInKeywordMap() (*KeywordMap)["Texture2DMSArray"] = EHTokTexture2DMSarray; (*KeywordMap)["struct"] = EHTokStruct; + (*KeywordMap)["cbuffer"] = EHTokCBuffer; + (*KeywordMap)["tbuffer"] = EHTokTBuffer; (*KeywordMap)["typedef"] = EHTokTypedef; (*KeywordMap)["true"] = EHTokBoolConstant; @@ -574,6 +576,9 @@ EHlslTokenClass HlslScanContext::tokenizeIdentifier() // variable, user type, ... case EHTokStruct: case EHTokTypedef: + case EHTokCBuffer: + case EHTokTBuffer: + return keyword; case EHTokBoolConstant: if (strcmp("true", tokenText) == 0) diff --git a/hlsl/hlslTokens.h b/hlsl/hlslTokens.h index 5a5266ae3..d72b2cd99 100755 --- a/hlsl/hlslTokens.h +++ b/hlsl/hlslTokens.h @@ -212,6 +212,8 @@ enum EHlslTokenClass { EHTokIdentifier, EHTokTypeName, EHTokStruct, + EHTokCBuffer, + EHTokTBuffer, EHTokTypedef, // constant -- GitLab