diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2018-07-31 11:03:53 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-07-31 11:03:53 -0400 |
| commit | 9914ca800c92e9b3fe768dec4e913a302f3d678d (patch) | |
| tree | 49544fb2c0387f39876fd99e112cfc32ed05302d /source | |
| parent | 171f524d7ca2922084a33f50c77a1e8797e80949 (diff) | |
Feature/attributed binding (#621)
* Typo fix, and added dxc to command line documentation.
* Fix small typos.
Added support for Scope to lexer.
Fix bug in Token ctor.
* Add support for attribute names that are scoped.
* Added GLSLBindingAttribute. Make binding work through core.met.slang.
* Allow [[gl::binding(binding, set)]]
[[vk::binding(binding,set)]]
Diffstat (limited to 'source')
| -rw-r--r-- | source/core/token-reader.h | 2 | ||||
| -rw-r--r-- | source/slang/check.cpp | 9 | ||||
| -rw-r--r-- | source/slang/core.meta.slang | 9 | ||||
| -rw-r--r-- | source/slang/core.meta.slang.h | 9 | ||||
| -rw-r--r-- | source/slang/lexer.cpp | 11 | ||||
| -rw-r--r-- | source/slang/modifier-defs.h | 8 | ||||
| -rw-r--r-- | source/slang/parameter-binding.cpp | 9 | ||||
| -rw-r--r-- | source/slang/parser.cpp | 194 | ||||
| -rw-r--r-- | source/slang/token-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/token.h | 16 |
10 files changed, 221 insertions, 48 deletions
diff --git a/source/core/token-reader.h b/source/core/token-reader.h index aaebad756..48391738c 100644 --- a/source/core/token-reader.h +++ b/source/core/token-reader.h @@ -22,7 +22,7 @@ namespace Slang OpInc, OpDec, OpAddAssign, OpSubAssign, OpMulAssign, OpDivAssign, OpModAssign, OpShlAssign, OpShrAssign, OpOrAssign, OpAndAssign, OpXorAssign, - QuestionMark, Colon, RightArrow, At, Pound, PoundPound, + QuestionMark, Colon, RightArrow, At, Pound, PoundPound, Scope, }; class CodePosition diff --git a/source/slang/check.cpp b/source/slang/check.cpp index 1fa7f9b01..3c7bcaf84 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -1894,6 +1894,15 @@ namespace Slang numThreadsAttr->y = (int32_t) yVal->value; numThreadsAttr->z = (int32_t) zVal->value; } + else if (auto bindingAttr = attr.As<GLSLBindingAttribute>()) + { + SLANG_ASSERT(attr->args.Count() == 2); + auto binding = checkConstantIntVal(attr->args[0]); + auto set = checkConstantIntVal(attr->args[1]); + + bindingAttr->binding = int32_t(binding->value); + bindingAttr->set = int32_t(set->value); + } else if (auto maxVertexCountAttr = attr.As<MaxVertexCountAttribute>()) { SLANG_ASSERT(attr->args.Count() == 1); diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 836af1a87..899c24539 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -1114,6 +1114,14 @@ __generic<E : __EnumType> __intrinsic_op($(kIROp_Eql)) bool operator==(E left, E right); +// Binding Attributes + +__attributeTarget(DeclBase) +attribute_syntax [vk_binding(binding: int, set: int = 0)] : GLSLBindingAttribute; + +__attributeTarget(DeclBase) +attribute_syntax [gl_binding(binding: int, set: int = 0)] : GLSLBindingAttribute; + // Statement Attributes __attributeTarget(LoopStmt) @@ -1181,3 +1189,4 @@ attribute_syntax [earlydepthstencil] : EarlyDepthStencilAttribute; // Compute Shader __attributeTarget(FuncDecl) attribute_syntax [numthreads(x: int, y: int = 1, z: int = 1)] : NumThreadsAttribute; + diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h index d6c742321..555353c92 100644 --- a/source/slang/core.meta.slang.h +++ b/source/slang/core.meta.slang.h @@ -1132,6 +1132,14 @@ SLANG_SPLICE(kIROp_Eql SLANG_RAW(")\n") SLANG_RAW("bool operator==(E left, E right);\n") SLANG_RAW("\n") +SLANG_RAW("// Binding Attributes\n") +SLANG_RAW("\n") +SLANG_RAW("__attributeTarget(DeclBase)\n") +SLANG_RAW("attribute_syntax [vk_binding(binding: int, set: int = 0)]\t\t\t: GLSLBindingAttribute;\n") +SLANG_RAW("\n") +SLANG_RAW("__attributeTarget(DeclBase)\n") +SLANG_RAW("attribute_syntax [gl_binding(binding: int, set: int = 0)]\t\t\t: GLSLBindingAttribute;\n") +SLANG_RAW("\n") SLANG_RAW("// Statement Attributes\n") SLANG_RAW("\n") SLANG_RAW("__attributeTarget(LoopStmt)\n") @@ -1199,3 +1207,4 @@ SLANG_RAW("\n") SLANG_RAW("// Compute Shader\n") SLANG_RAW("__attributeTarget(FuncDecl)\n") SLANG_RAW("attribute_syntax [numthreads(x: int, y: int = 1, z: int = 1)] : NumThreadsAttribute;\n") +SLANG_RAW("\n") diff --git a/source/slang/lexer.cpp b/source/slang/lexer.cpp index 87ad6bd5c..5e6d15384 100644 --- a/source/slang/lexer.cpp +++ b/source/slang/lexer.cpp @@ -1192,7 +1192,16 @@ namespace Slang case '~': advance(lexer); return TokenType::OpBitNot; - case ':': advance(lexer); return TokenType::Colon; + case ':': + { + advance(lexer); + if (peek(lexer) == ':') + { + advance(lexer); + return TokenType::Scope; + } + return TokenType::Colon; + } case ';': advance(lexer); return TokenType::Semicolon; case ',': advance(lexer); return TokenType::Comma; diff --git a/source/slang/modifier-defs.h b/source/slang/modifier-defs.h index f0443c501..70c26568d 100644 --- a/source/slang/modifier-defs.h +++ b/source/slang/modifier-defs.h @@ -128,8 +128,6 @@ SIMPLE_SYNTAX_CLASS(GLSLUnparsedLayoutModifier , GLSLLayoutModifier) // Specific cases for known GLSL `layout` modifiers that we need to work with SIMPLE_SYNTAX_CLASS(GLSLConstantIDLayoutModifier , GLSLParsedLayoutModifier) -SIMPLE_SYNTAX_CLASS(GLSLBindingLayoutModifier , GLSLParsedLayoutModifier) -SIMPLE_SYNTAX_CLASS(GLSLSetLayoutModifier , GLSLParsedLayoutModifier) SIMPLE_SYNTAX_CLASS(GLSLLocationLayoutModifier , GLSLParsedLayoutModifier) SIMPLE_SYNTAX_CLASS(GLSLPushConstantLayoutModifier, GLSLParsedLayoutModifier) @@ -330,6 +328,12 @@ SIMPLE_SYNTAX_CLASS(FlattenAttribute, Attribute) // `[flatten]` SIMPLE_SYNTAX_CLASS(ForceCaseAttribute, Attribute) // `[forcecase]` SIMPLE_SYNTAX_CLASS(CallAttribute, Attribute) // `[call]` +// [[vk_binding]] +SYNTAX_CLASS(GLSLBindingAttribute, Attribute) + FIELD(int32_t, binding = 0) + FIELD(int32_t, set = 0) +END_SYNTAX_CLASS() + // TODO: for attributes that take arguments, the syntax node // classes should provide accessors for the values of those arguments. diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp index e5fddac02..ced8d7af2 100644 --- a/source/slang/parameter-binding.cpp +++ b/source/slang/parameter-binding.cpp @@ -1413,10 +1413,13 @@ static void addExplicitParameterBindings_GLSL( if( (resInfo = typeLayout->FindResourceInfo(LayoutResourceKind::DescriptorTableSlot)) != nullptr ) { // Try to find `binding` and `set` - if(!findLayoutArg<GLSLBindingLayoutModifier>(varDecl, &semanticInfo.index)) + auto attr = varDecl.getDecl()->FindModifier<GLSLBindingAttribute>(); + if (!attr) + { return; - - findLayoutArg<GLSLSetLayoutModifier>(varDecl, &semanticInfo.space); + } + semanticInfo.index = attr->binding; + semanticInfo.space = attr->set; } else if( (resInfo = typeLayout->FindResourceInfo(LayoutResourceKind::VertexInput)) != nullptr ) { diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index fee5d04b6..62fed75cc 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -8,6 +8,52 @@ namespace Slang { + // Pre-declare + static Name* getName(Parser* parser, String const& text); + + // Helper class useful to build a list of modifiers. + struct ModifierListBuilder + { + ModifierListBuilder() + { + m_next = &m_result; + } + void add(Modifier* modifier) + { + // Doesn't handle SharedModifiers + SLANG_ASSERT(modifier->As<SharedModifiers>() == nullptr); + + // Splice at end + *m_next = modifier; + m_next = &modifier->next; + } + template <typename T> + T* find() const + { + Modifier* cur = m_result; + while (cur) + { + T* castCur = cur->As<T>(); + if (castCur) + { + return castCur; + } + cur = cur->next; + } + return nullptr; + } + template <typename T> + bool hasType() const + { + return find<T>() != nullptr; + } + RefPtr<Modifier> getFirst() { return m_result; }; + protected: + + RefPtr<Modifier> m_result; + RefPtr<Modifier>* m_next; + }; + enum Precedence : int { Invalid = -1, @@ -567,7 +613,9 @@ namespace Slang // About to look at shared modifiers? Done. RefPtr<Modifier> linkMod = *modifierLink; if(linkMod.As<SharedModifiers>()) + { break; + } // Otherwise: keep traversing the modifier list. modifierLink = &(*modifierLink)->next; @@ -575,7 +623,7 @@ namespace Slang // Splice the modifier into the linked list - // We need to deal with the case where the modifeir to + // We need to deal with the case where the modifier to // be spliced in might actually be a modifier *list*, // so that we actually want to splice in at the // end of the new list... @@ -598,10 +646,57 @@ namespace Slang AddModifier(&modifierLink, modifier); } + // + // '::'? identifier ('::' identifier)* + static Token parseAttributeName(Parser* parser) + { + const SourceLoc scopedIdSourceLoc = parser->tokenReader.PeekLoc(); + + // Strip initial :: if there is one + const TokenType initialTokenType = parser->tokenReader.PeekTokenType(); + if (initialTokenType == TokenType::Scope) + { + parser->ReadToken(TokenType::Scope); + } + + const Token firstIdentifier = parser->ReadToken(TokenType::Identifier); + if (initialTokenType != TokenType::Scope && parser->tokenReader.PeekTokenType() != TokenType::Scope) + { + return firstIdentifier; + } + + // Build up scoped string + StringBuilder scopedIdentifierBuilder; + if (initialTokenType == TokenType::Scope) + { + scopedIdentifierBuilder.Append('_'); + } + scopedIdentifierBuilder.Append(firstIdentifier.Content); + + while (parser->tokenReader.PeekTokenType() == TokenType::Scope) + { + parser->ReadToken(TokenType::Scope); + scopedIdentifierBuilder.Append('_'); + + const Token nextIdentifier(parser->ReadToken(TokenType::Identifier)); + scopedIdentifierBuilder.Append(nextIdentifier.Content); + } + + // Make a 'token' + const String scopedIdentifier(scopedIdentifierBuilder.ToString()); + Token token(TokenType::Identifier, scopedIdentifier, scopedIdSourceLoc); + token.ptrValue = getName(parser, token.Content); + + return token; + } + // Parse HLSL-style `[name(arg, ...)]` style "attribute" modifiers static void ParseSquareBracketAttributes(Parser* parser, RefPtr<Modifier>** ioModifierLink) { parser->ReadToken(TokenType::LBracket); + + const bool hasDoubleBracket = AdvanceIf(parser, TokenType::LBracket); + for(;;) { // Note: When parsing we just construct an AST node for an @@ -613,7 +708,8 @@ namespace Slang // seems better to not complicate the parsing process any more. // - auto nameToken = parser->ReadToken(TokenType::Identifier); + Token nameToken = parseAttributeName(parser); + RefPtr<UncheckedAttribute> modifier = new UncheckedAttribute(); modifier->name = nameToken.getName(); modifier->loc = nameToken.getLoc(); @@ -645,6 +741,12 @@ namespace Slang parser->ReadToken(TokenType::Comma); } + + if (hasDoubleBracket) + { + // Read the second ] + parser->ReadToken(TokenType::RBracket); + } } static TokenType peekTokenType(Parser* parser) @@ -4368,60 +4470,86 @@ namespace Slang return modifier; } + + static RefPtr<RefObject> parseLayoutModifier(Parser* parser, void* /*userData*/) { - Modifiers modifiers; - RefPtr<Modifier>* modifierLink = &modifiers.first; - - auto beginMarker = new GLSLLayoutModifierGroupBegin(); - AddModifier(&modifierLink, beginMarker); + ModifierListBuilder listBuilder; + listBuilder.add(new GLSLLayoutModifierGroupBegin()); + parser->ReadToken(TokenType::LParent); while (!AdvanceIfMatch(parser, TokenType::RParent)) { auto nameAndLoc = expectIdentifier(parser); + const String& nameText = nameAndLoc.name->text; - RefPtr<GLSLLayoutModifier> modifier; + if (nameText == "binding" || + nameText == "set") + { + GLSLBindingAttribute* attr = listBuilder.find<GLSLBindingAttribute>(); + if (!attr) + { + attr = new GLSLBindingAttribute(); + listBuilder.add(attr); + } - // TODO: better handling of this choise (e.g., lookup in scope) - if(0) {} - #define CASE(KEYWORD, CLASS) \ - else if(getText(nameAndLoc.name) == #KEYWORD) modifier = new CLASS() + parser->ReadToken(TokenType::OpAssign); - CASE(constant_id, GLSLConstantIDLayoutModifier); - CASE(binding, GLSLBindingLayoutModifier); - CASE(set, GLSLSetLayoutModifier); - CASE(location, GLSLLocationLayoutModifier); - CASE(push_constant, GLSLPushConstantLayoutModifier); - CASE(local_size_x, GLSLLocalSizeXLayoutModifier); - CASE(local_size_y, GLSLLocalSizeYLayoutModifier); - CASE(local_size_z, GLSLLocalSizeZLayoutModifier); + Token valToken = parser->ReadToken(TokenType::IntegerLiteral); + // Work out the value + auto value = getIntegerLiteralValue(valToken); - #undef CASE + if (nameText == "binding") + { + attr->binding = int32_t(value); + } + else + { + attr->set = int32_t(value); + } + } else { - modifier = new GLSLUnparsedLayoutModifier(); - } + RefPtr<GLSLLayoutModifier> modifier; - modifier->name = nameAndLoc.name; - modifier->loc = nameAndLoc.loc; + // TODO: better handling of this choice (e.g., lookup in scope) + if(0) {} + #define CASE(KEYWORD, CLASS) \ + else if(getText(nameAndLoc.name) == #KEYWORD) modifier = new CLASS() - if(AdvanceIf(parser, TokenType::OpAssign)) - { - modifier->valToken = parser->ReadToken(TokenType::IntegerLiteral); - } + CASE(constant_id, GLSLConstantIDLayoutModifier); + CASE(location, GLSLLocationLayoutModifier); + CASE(push_constant, GLSLPushConstantLayoutModifier); + CASE(local_size_x, GLSLLocalSizeXLayoutModifier); + CASE(local_size_y, GLSLLocalSizeYLayoutModifier); + CASE(local_size_z, GLSLLocalSizeZLayoutModifier); - AddModifier(&modifierLink, modifier); + #undef CASE + else + { + modifier = new GLSLUnparsedLayoutModifier(); + } + + modifier->name = nameAndLoc.name; + modifier->loc = nameAndLoc.loc; + + if(AdvanceIf(parser, TokenType::OpAssign)) + { + modifier->valToken = parser->ReadToken(TokenType::IntegerLiteral); + } + + listBuilder.add(modifier); + } if (AdvanceIf(parser, TokenType::RParent)) break; parser->ReadToken(TokenType::Comma); } - auto endMarker = new GLSLLayoutModifierGroupEnd(); - AddModifier(&modifierLink, endMarker); + listBuilder.add(new GLSLLayoutModifierGroupEnd()); - return modifiers.first; + return listBuilder.getFirst(); } static RefPtr<RefObject> parseBuiltinTypeModifier(Parser* parser, void* /*userData*/) diff --git a/source/slang/token-defs.h b/source/slang/token-defs.h index a08084d85..873a252b4 100644 --- a/source/slang/token-defs.h +++ b/source/slang/token-defs.h @@ -88,6 +88,8 @@ PUNCTUATION(Dollar, "$") PUNCTUATION(Pound, "#") PUNCTUATION(PoundPound, "##") +PUNCTUATION(Scope, "::") + #undef PUNCTUATION // Un-define the `TOKEN` macro so that client doesn't have to diff --git a/source/slang/token.h b/source/slang/token.h index 5967ac49a..e3b6f48ff 100644 --- a/source/slang/token.h +++ b/source/slang/token.h @@ -41,15 +41,15 @@ public: Token() = default; Token( - TokenType type, - const String & content, - SourceLoc loc, - TokenFlags flags = 0) - : flags(flags) + TokenType typeIn, + const String & contentIn, + SourceLoc locIn, + TokenFlags flagsIn = 0) + : flags(flagsIn) { - type = type; - Content = content; - loc = loc; + type = typeIn; + Content = contentIn; + loc = locIn; ptrValue = nullptr; } |
