summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-parser.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-02-06 01:03:42 -0800
committerGitHub <noreply@github.com>2024-02-06 01:03:42 -0800
commitb301c93753eaddb4571999f209cb8c1faa2fe205 (patch)
tree72fef2e499abecad0dda5ba2347e5890346ac173 /source/slang/slang-parser.cpp
parent23c65b873f8002b74d60f61cacb3614da60e078d (diff)
Unify GLSL and HLSL buffer block parsing. (#3552)
* Unify GLSL and HLSL buffer block parsing. Automatic GLSL module recognition. * Fix.
Diffstat (limited to 'source/slang/slang-parser.cpp')
-rw-r--r--source/slang/slang-parser.cpp212
1 files changed, 109 insertions, 103 deletions
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index 3940e59cf..4b6d9b2d0 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -2379,15 +2379,6 @@ namespace Slang
}
}
- static String _wrappingModifierType(const WrappingTypeModifier* mod)
- {
- if(as<GLSLBufferModifier>(mod))
- {
- return "GLSLShaderStorageBuffer";
- }
- SLANG_UNREACHABLE("unhandled wrapping type modifier");
- }
-
/// Apply any type modifier in `ioBaseModifiers` to the given `typeExpr`.
///
/// If any type modifiers were present, `ioBaseModifiers` will be updated
@@ -2433,30 +2424,6 @@ namespace Slang
//
baseModifierLink = &baseModifier->next;
}
- else if(const auto wrappingTypeModifier = as<WrappingTypeModifier>(typeModifier))
- {
- // This is where we match things which are modifiers in the
- // syntax, but we match conceptually as wrappers around a type
- // expression
-
- // Firstly, disptach the modifier, we don't need it again
- baseModifierLink = &baseModifier->next;
-
- // Conjure up the generic wrapper type
- // Make sure to use the outer scope, to avoid user name shadowing
- auto bufferWrapperTypeExpr = parser->astBuilder->create<VarExpr>();
- bufferWrapperTypeExpr->loc = wrappingTypeModifier->loc;
- bufferWrapperTypeExpr->name = getName(parser, _wrappingModifierType(wrappingTypeModifier));
- bufferWrapperTypeExpr->scope = parser->outerScope;
-
- // Apply the wrapper
- auto bufferPointerTypeExpr = parser->astBuilder->create<GenericAppExpr>();
- bufferPointerTypeExpr->loc = wrappingTypeModifier->loc;
- bufferPointerTypeExpr->functionExpr = bufferWrapperTypeExpr;
- bufferPointerTypeExpr->arguments.add(typeExpr);
-
- typeExpr = bufferPointerTypeExpr;
- }
else
{
// If we have a type modifier, we need to graft it onto
@@ -2526,7 +2493,7 @@ namespace Slang
}
/// Parse a type specifier, without dealing with modifiers.
- static TypeSpec _parseSimpleTypeSpec(Parser* parser, bool mightBeGLSLInterfaceBlock)
+ static TypeSpec _parseSimpleTypeSpec(Parser* parser)
{
TypeSpec typeSpec;
@@ -2562,16 +2529,6 @@ namespace Slang
typeSpec.expr = createDeclRefType(parser, decl);
return typeSpec;
}
- else if( mightBeGLSLInterfaceBlock
- && parser->LookAheadToken(TokenType::Identifier)
- && parser->LookAheadToken(TokenType::LBrace,1) )
- {
- // Parse the struct-like part
- auto innerStructDecl = parser->ParseGLSLInterfaceBlock();
- typeSpec.decl = innerStructDecl;
- typeSpec.expr = createDeclRefType(parser, typeSpec.decl);
- return typeSpec;
- }
else if(parser->LookAheadToken("enum"))
{
auto decl = parseEnumDecl(parser);
@@ -2629,17 +2586,17 @@ namespace Slang
return typeSpec;
}
- static bool hasPotentialGLSLInterfaceBlockModifier(Parser* parser, Modifiers& mods)
+ static Modifier* findPotentialGLSLInterfaceBlockModifier(Parser* parser, Modifiers& mods)
{
if (!parser->options.allowGLSLInput)
- return false;
+ return nullptr;
for (auto mod : mods)
{
- if (as<GLSLBufferModifier>(mod) || as<InModifier>(mod) || as<OutModifier>(mod))
- return true;
+ if (as<HLSLUniformModifier>(mod) || as<InModifier>(mod) || as<OutModifier>(mod))
+ return mod;
}
- return false;
+ return nullptr;
}
/// Parse a type specifier, following the given list of modifiers.
@@ -2650,7 +2607,7 @@ namespace Slang
///
static TypeSpec _parseTypeSpec(Parser* parser, Modifiers& ioModifiers)
{
- TypeSpec typeSpec = _parseSimpleTypeSpec(parser, hasPotentialGLSLInterfaceBlockModifier(parser, ioModifiers));
+ TypeSpec typeSpec = _parseSimpleTypeSpec(parser);
// We don't know whether `ioModifiers` has any modifiers in it,
// or which of them might be type modifiers, so we will delegate
@@ -2675,7 +2632,7 @@ namespace Slang
static TypeSpec _parseTypeSpec(Parser* parser)
{
Modifiers modifiers = ParseModifiers(parser);
- TypeSpec typeSpec = _parseSimpleTypeSpec(parser, hasPotentialGLSLInterfaceBlockModifier(parser, modifiers));
+ TypeSpec typeSpec = _parseSimpleTypeSpec(parser);
typeSpec = _applyModifiersToTypeSpec(parser, typeSpec, modifiers);
@@ -3094,9 +3051,10 @@ namespace Slang
_addModifiers(decl, _parseOptSemantics(parser));
}
- static Decl* ParseHLSLBufferDecl(
+ static Decl* ParseBufferBlockDecl(
Parser* parser,
- String bufferWrapperTypeName)
+ String bufferWrapperTypeName,
+ String *additionalTypeArg = nullptr)
{
// An HLSL declaration of a constant buffer like this:
//
@@ -3161,23 +3119,37 @@ namespace Slang
bufferDataTypeExpr->name = bufferDataTypeDecl->nameAndLoc.name;
bufferDataTypeExpr->scope = parser->currentScope;
- // Construct a type expression to reference the type constructor
- auto bufferWrapperTypeExpr = parser->astBuilder->create<VarExpr>();
- bufferWrapperTypeExpr->loc = bufferWrapperTypeNamePos;
- bufferWrapperTypeExpr->name = getName(parser, bufferWrapperTypeName);
-
- // Always need to look this up in the outer scope,
- // so that it won't collide with, e.g., a local variable called `ConstantBuffer`
- bufferWrapperTypeExpr->scope = parser->outerScope;
-
// Construct a type expression that represents the type for the variable,
// which is the wrapper type applied to the data type
- auto bufferVarTypeExpr = parser->astBuilder->create<GenericAppExpr>();
- bufferVarTypeExpr->loc = bufferVarDecl->loc;
- bufferVarTypeExpr->functionExpr = bufferWrapperTypeExpr;
- bufferVarTypeExpr->arguments.add(bufferDataTypeExpr);
+ if (bufferWrapperTypeName.getLength())
+ {
+ // Construct a type expression to reference the type constructor
+ auto bufferWrapperTypeExpr = parser->astBuilder->create<VarExpr>();
+ bufferWrapperTypeExpr->loc = bufferWrapperTypeNamePos;
+ bufferWrapperTypeExpr->name = getName(parser, bufferWrapperTypeName);
+
+ // Always need to look this up in the outer scope,
+ // so that it won't collide with, e.g., a local variable called `ConstantBuffer`
+ bufferWrapperTypeExpr->scope = parser->outerScope;
- bufferVarDecl->type.exp = bufferVarTypeExpr;
+ auto bufferVarTypeExpr = parser->astBuilder->create<GenericAppExpr>();
+ bufferVarTypeExpr->loc = bufferVarDecl->loc;
+ bufferVarTypeExpr->functionExpr = bufferWrapperTypeExpr;
+ bufferVarTypeExpr->arguments.add(bufferDataTypeExpr);
+ if (additionalTypeArg)
+ {
+ auto additionalArgExpr = parser->astBuilder->create<VarExpr>();
+ additionalArgExpr->scope = parser->outerScope;
+ additionalArgExpr->loc = SourceLoc();
+ additionalArgExpr->name = getName(parser, *additionalTypeArg);
+ bufferVarTypeExpr->arguments.add(additionalArgExpr);
+ }
+ bufferVarDecl->type.exp = bufferVarTypeExpr;
+ }
+ else
+ {
+ bufferVarDecl->type.exp = bufferDataTypeExpr;
+ }
// Any semantics applied to the buffer declaration are taken as applying
// to the variable instead.
@@ -3191,6 +3163,7 @@ namespace Slang
{
// If the user specified an explicit name of the buffer var, use it.
bufferVarDecl->nameAndLoc = ParseDeclName(parser);
+ reflectionNameModifier->nameAndLoc = bufferVarDecl->nameAndLoc;
parser->ReadToken(TokenType::Semicolon);
}
else
@@ -3227,13 +3200,19 @@ namespace Slang
static NodeBase* parseHLSLCBufferDecl(
Parser* parser, void* /*userData*/)
{
- return ParseHLSLBufferDecl(parser, "ConstantBuffer");
+ return ParseBufferBlockDecl(parser, "ConstantBuffer");
}
static NodeBase* parseHLSLTBufferDecl(
Parser* parser, void* /*userData*/)
{
- return ParseHLSLBufferDecl(parser, "TextureBuffer");
+ return ParseBufferBlockDecl(parser, "TextureBuffer");
+ }
+
+ static NodeBase* parseGLSLShaderStorageBufferDecl(
+ Parser* parser, String layoutType)
+ {
+ return ParseBufferBlockDecl(parser, "GLSLShaderStorageBuffer", &layoutType);
}
static void parseOptionalInheritanceClause(Parser* parser, AggTypeDeclBase* decl)
@@ -4442,6 +4421,55 @@ namespace Slang
break;
}
+ // This can also be a GLSL style buffer block declaration.
+ if (parser->options.allowGLSLInput)
+ {
+ auto getLayoutArg = [&](const char* defaultLayout)
+ {
+ if (auto dataLayoutMod = modifiers.findModifier<GLSLBufferDataLayoutModifier>())
+ {
+ if (as<GLSLStd140Modifier>(dataLayoutMod))
+ return "Std140DataLayout";
+ else if (as<GLSLStd430Modifier>(dataLayoutMod))
+ return "Std430DataLayout";
+ else if (as<GLSLScalarModifier>(dataLayoutMod))
+ return "ScalarDataLayout";
+ }
+ return defaultLayout;
+ };
+ if (AdvanceIf(parser, "buffer"))
+ {
+ decl = as<Decl>(parseGLSLShaderStorageBufferDecl(parser, getLayoutArg("Std430DataLayout")));
+ break;
+ }
+ else if (auto mod = findPotentialGLSLInterfaceBlockModifier(parser, modifiers))
+ {
+ if (!parser->LookAheadToken(TokenType::LBrace, 1))
+ {
+ goto endOfGlslBufferBlock;
+ }
+
+ if (as<HLSLUniformModifier>(mod))
+ {
+ decl = as<Decl>(parseHLSLCBufferDecl(parser, nullptr));
+ break;
+ }
+ else
+ {
+ bool isGLSLBuiltinRedeclaration = parser->tokenReader.peekToken().getContent().startsWith("gl_");
+ decl = ParseBufferBlockDecl(parser, "", nullptr);
+ if (isGLSLBuiltinRedeclaration)
+ {
+ // Ignore builtin redeclaration.
+ decl = parser->astBuilder->create<EmptyDecl>();
+ decl->loc = loc;
+ }
+ break;
+ }
+ }
+ endOfGlslBufferBlock:;
+ }
+
// Our final fallback case is to assume that the user is
// probably writing a C-style declarator-based declaration.
decl = ParseDeclaratorDecl(parser, containerDecl, modifiers);
@@ -4548,34 +4576,6 @@ namespace Slang
parser->ReadToken(TokenType::Semicolon);
return true;
}
-
- Modifier* layoutModifier = nullptr;
- if (parser->LookAheadToken("layout"))
- {
- tryParseUsingSyntaxDecl<Modifier>(parser, &layoutModifier);
- }
-
- DeclBase* decl = nullptr;
- if (parser->LookAheadToken("uniform", 0) &&
- (parser->LookAheadToken(TokenType::LBrace, 1) ||
- parser->LookAheadToken(TokenType::Identifier, 1) &&
- parser->LookAheadToken(TokenType::LBrace, 2)))
- {
- parser->ReadToken();
- decl = as<Decl>(parseHLSLCBufferDecl(parser, containerDecl));
- if (decl)
- AddMember(parser->currentScope, (Decl*)decl);
- }
- else if (layoutModifier)
- {
- decl = ParseDecl(parser, containerDecl);
- }
-
- if (decl)
- {
- addModifier(decl, layoutModifier);
- return true;
- }
return false;
}
@@ -7333,7 +7333,7 @@ namespace Slang
// If there are any modifiers, then we know that we are actually
// in the type case.
//
- auto typeSpec = _parseSimpleTypeSpec(parser, false);
+ auto typeSpec = _parseSimpleTypeSpec(parser);
typeSpec = _applyModifiersToTypeSpec(parser, typeSpec, modifiers);
auto typeExpr = typeSpec.expr;
@@ -7355,7 +7355,9 @@ namespace Slang
NamePool* namePool,
SourceLanguage sourceLanguage)
{
- Parser parser(astBuilder, tokens, sink, outerScope, ParserOptions{});
+ ParserOptions options;
+ options.allowGLSLInput = sourceLanguage == SourceLanguage::GLSL;
+ Parser parser(astBuilder, tokens, sink, outerScope, options);
parser.currentScope = outerScope;
parser.namePool = namePool;
parser.sourceLanguage = sourceLanguage;
@@ -7366,6 +7368,7 @@ namespace Slang
void parseSourceFile(
ASTBuilder* astBuilder,
TranslationUnitRequest* translationUnit,
+ SourceLanguage sourceLanguage,
TokenSpan const& tokens,
DiagnosticSink* sink,
Scope* outerScope,
@@ -7373,8 +7376,9 @@ namespace Slang
{
ParserOptions options = {};
options.enableEffectAnnotations = translationUnit->compileRequest->getLinkage()->getEnableEffectAnnotations();
- options.allowGLSLInput = translationUnit->compileRequest->getLinkage()->getAllowGLSLInput() ||
- translationUnit->sourceLanguage == SourceLanguage::GLSL;
+ options.allowGLSLInput =
+ translationUnit->compileRequest->getLinkage()->getAllowGLSLInput() ||
+ sourceLanguage == SourceLanguage::GLSL;
options.isInLanguageServer = translationUnit->compileRequest->getLinkage()->isInLanguageServer();
Parser parser(astBuilder, tokens, sink, outerScope, options);
@@ -7701,7 +7705,10 @@ namespace Slang
#define CASE(key, type) if (nameText == #key) { modifier = parser->astBuilder->create<type>(); } else
CASE(push_constant, PushConstantAttribute)
CASE(shaderRecordNV, ShaderRecordAttribute)
- CASE(constant_id, GLSLConstantIDLayoutModifier)
+ CASE(constant_id, GLSLConstantIDLayoutModifier)
+ CASE(std140, GLSLStd140Modifier)
+ CASE(std430, GLSLStd430Modifier)
+ CASE(scalar, GLSLScalarModifier)
CASE(location, GLSLLocationLayoutModifier)
{
modifier = parser->astBuilder->create<GLSLUnparsedLayoutModifier>();
@@ -7941,7 +7948,6 @@ namespace Slang
_makeParseModifier("uniform", HLSLUniformModifier::kReflectClassInfo),
_makeParseModifier("volatile", HLSLVolatileModifier::kReflectClassInfo),
_makeParseModifier("export", HLSLExportModifier::kReflectClassInfo),
- _makeParseModifier("buffer", GLSLBufferModifier::kReflectClassInfo),
// Modifiers for geometry shader input
_makeParseModifier("point", HLSLPointModifier::kReflectClassInfo),