summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/core/token-reader.h2
-rw-r--r--source/slang/check.cpp9
-rw-r--r--source/slang/core.meta.slang9
-rw-r--r--source/slang/core.meta.slang.h9
-rw-r--r--source/slang/lexer.cpp11
-rw-r--r--source/slang/modifier-defs.h8
-rw-r--r--source/slang/parameter-binding.cpp9
-rw-r--r--source/slang/parser.cpp194
-rw-r--r--source/slang/token-defs.h2
-rw-r--r--source/slang/token.h16
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;
}