From b301c93753eaddb4571999f209cb8c1faa2fe205 Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 6 Feb 2024 01:03:42 -0800 Subject: Unify GLSL and HLSL buffer block parsing. (#3552) * Unify GLSL and HLSL buffer block parsing. Automatic GLSL module recognition. * Fix. --- source/slang/slang-parser.cpp | 212 ++++++++++++++++++++++-------------------- 1 file changed, 109 insertions(+), 103 deletions(-) (limited to 'source/slang/slang-parser.cpp') 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(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(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(); - bufferWrapperTypeExpr->loc = wrappingTypeModifier->loc; - bufferWrapperTypeExpr->name = getName(parser, _wrappingModifierType(wrappingTypeModifier)); - bufferWrapperTypeExpr->scope = parser->outerScope; - - // Apply the wrapper - auto bufferPointerTypeExpr = parser->astBuilder->create(); - 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(mod) || as(mod) || as(mod)) - return true; + if (as(mod) || as(mod) || as(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(); - 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(); - 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(); + 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(); + bufferVarTypeExpr->loc = bufferVarDecl->loc; + bufferVarTypeExpr->functionExpr = bufferWrapperTypeExpr; + bufferVarTypeExpr->arguments.add(bufferDataTypeExpr); + if (additionalTypeArg) + { + auto additionalArgExpr = parser->astBuilder->create(); + 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()) + { + if (as(dataLayoutMod)) + return "Std140DataLayout"; + else if (as(dataLayoutMod)) + return "Std430DataLayout"; + else if (as(dataLayoutMod)) + return "ScalarDataLayout"; + } + return defaultLayout; + }; + if (AdvanceIf(parser, "buffer")) + { + decl = as(parseGLSLShaderStorageBufferDecl(parser, getLayoutArg("Std430DataLayout"))); + break; + } + else if (auto mod = findPotentialGLSLInterfaceBlockModifier(parser, modifiers)) + { + if (!parser->LookAheadToken(TokenType::LBrace, 1)) + { + goto endOfGlslBufferBlock; + } + + if (as(mod)) + { + decl = as(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(); + 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(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(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(); } 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(); @@ -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), -- cgit v1.2.3