diff options
| author | Yong He <yonghe@outlook.com> | 2023-11-14 17:46:05 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-14 17:46:05 -0800 |
| commit | 12f7237e4060388494c549623f4a640327b7ca08 (patch) | |
| tree | 407c0f8d20b4ccd49ae5df57f84c8f9a310f7055 /source/slang/slang-parser.cpp | |
| parent | c71b12775c8b13ea2b181e42c04b8db55b10fb2f (diff) | |
Add GLSL Compatibility. (#3321)
* Parse glsl buffer blocks to GLSLInterfaceBlockDecl
* Parse glsl local size layout declarations
* Parse (and ignore) glsl version directives
* spelling
* Better l-value interpretation for glsl interface blocks
* Better l-value interpretation for glsl interface blocks
* Add compile flag for enabling glsl
* Parse and ignore precision modifiers.
* Automatically import `glsl` module for compatiblity.
* Complete vector and matrix types for glsl
* Remove generated file from repo
* Bump .gitignore
* do not mark out globals as params
* Synthesize entrypoint layout from global inout vars.
* update test result.
* Allow HLSL semantic on global variables.
* Fix.
* Fix test.
* Fix win32 compile error.
* Add more builtin input/output and texture intrinsics.
* Add struct/array constructor syntax.
* Skip `#extension` lines.
* overide operator * for matrix/vector multiplication.
* Add `matrixCompMult`.
* Parse modifiers in for loop init var declr.
* Add more glsl intrinsics, add stage into to var layout.
* Allow `int[3] x` syntax.
* Fix array type syntax.
---------
Co-authored-by: Ellie Hermaszewska <ellieh@nvidia.com>
Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-parser.cpp')
| -rw-r--r-- | source/slang/slang-parser.cpp | 205 |
1 files changed, 182 insertions, 23 deletions
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index 8c9604df6..0a2076fd0 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -82,6 +82,7 @@ namespace Slang struct ParserOptions { bool enableEffectAnnotations = false; + bool allowGLSLInput = false; }; // TODO: implement two pass parsing for file reference and struct type recognition @@ -186,6 +187,7 @@ namespace Slang void parseSourceFile(ModuleDecl* program); Decl* ParseStruct(); ClassDecl* ParseClass(); + GLSLInterfaceBlockDecl* ParseGLSLInterfaceBlock(); Stmt* ParseStatement(Stmt* parentStmt = nullptr); Stmt* parseBlockStatement(); Stmt* parseLabelStatement(); @@ -1161,7 +1163,17 @@ namespace Slang AddModifier(&modifierLink, parsedModifier); continue; } - + else if (parser->options.allowGLSLInput) + { + if (AdvanceIf(parser, "flat")) + { + parsedModifier = parser->astBuilder->create<HLSLNoInterpolationModifier>(); + parsedModifier->keywordName = nameToken.getName(); + parsedModifier->loc = nameToken.loc; + AddModifier(&modifierLink, parsedModifier); + continue; + } + } // If there was no match for a modifier keyword, then we // must be at the end of the modifier sequence return modifiers; @@ -2135,8 +2147,34 @@ namespace Slang memberExpr->name = expectIdentifier(parser).name; return memberExpr; } + + // Parse optional `[]` braces after a type expression, that indicate an array type + static Expr* parseBracketTypeSuffix(Parser* parser, Expr* inTypeExpr) + { + auto typeExpr = inTypeExpr; + for (;;) + { + Token token; + if (parser->LookAheadToken(TokenType::LBracket)) + { + IndexExpr* arrType = parser->astBuilder->create<IndexExpr>(); + arrType->loc = typeExpr->loc; + arrType->baseExpression = typeExpr; + parser->ReadToken(TokenType::LBracket); + if (!parser->LookAheadToken(TokenType::RBracket)) + { + arrType->indexExprs.add(parser->ParseExpression()); + } + parser->ReadToken(TokenType::RBracket); + typeExpr = arrType; + } + else + break; + } + return typeExpr; + } - // Parse option `[]` braces after a type expression, that indicate an array type + // Parse option `[]` or `*` braces after a type expression, that indicate an array or pointer type static Expr* parsePostfixTypeSuffix( Parser* parser, Expr* inTypeExpr) @@ -2400,7 +2438,7 @@ namespace Slang } /// Parse a type specifier, without dealing with modifiers. - static TypeSpec _parseSimpleTypeSpec(Parser* parser) + static TypeSpec _parseSimpleTypeSpec(Parser* parser, bool mightBeGLSLInterfaceBlock) { TypeSpec typeSpec; @@ -2436,6 +2474,15 @@ namespace Slang typeSpec.expr = createDeclRefType(parser, decl); return typeSpec; } + else if( mightBeGLSLInterfaceBlock + && parser->LookAheadToken(TokenType::Identifier) + && parser->LookAheadToken(TokenType::LBrace,1) ) + { + auto decl = parser->ParseGLSLInterfaceBlock(); + typeSpec.decl = decl; + typeSpec.expr = createDeclRefType(parser, decl); + return typeSpec; + } else if(parser->LookAheadToken("enum")) { auto decl = parseEnumDecl(parser); @@ -2493,6 +2540,19 @@ namespace Slang return typeSpec; } + static bool hasPotentialGLSLInterfaceBlockModifier(Parser* parser, Modifiers& mods) + { + if (!parser->options.allowGLSLInput) + return false; + + for (auto mod : mods) + { + if (as<GLSLBufferModifier>(mod) || as<InModifier>(mod) || as<OutModifier>(mod)) + return true; + } + return false; + } + /// Parse a type specifier, following the given list of modifiers. /// /// If there are any modifiers in `ioModifiers`, this function may modify it @@ -2501,7 +2561,7 @@ namespace Slang /// static TypeSpec _parseTypeSpec(Parser* parser, Modifiers& ioModifiers) { - TypeSpec typeSpec = _parseSimpleTypeSpec(parser); + TypeSpec typeSpec = _parseSimpleTypeSpec(parser, hasPotentialGLSLInterfaceBlockModifier(parser, ioModifiers)); // We don't know whether `ioModifiers` has any modifiers in it, // or which of them might be type modifiers, so we will delegate @@ -2526,7 +2586,7 @@ namespace Slang static TypeSpec _parseTypeSpec(Parser* parser) { Modifiers modifiers = ParseModifiers(parser); - TypeSpec typeSpec = _parseSimpleTypeSpec(parser); + TypeSpec typeSpec = _parseSimpleTypeSpec(parser, hasPotentialGLSLInterfaceBlockModifier(parser, modifiers)); typeSpec = _applyModifiersToTypeSpec(parser, typeSpec, modifiers); @@ -2549,6 +2609,7 @@ namespace Slang return nullptr; } + // We may need to build up multiple declarations in a group, // but the common case will be when we have just a single // declaration @@ -2560,6 +2621,11 @@ namespace Slang // it might declare a `struct` type. if(typeSpec.decl) declGroupBuilder.addDecl(typeSpec.decl); + else + { + // Allow using brackets directly after type name to declare an array typed variable. + typeSpec.expr = parseBracketTypeSuffix(parser, typeSpec.expr); + } if( AdvanceIf(parser, TokenType::Semicolon) ) { @@ -2960,12 +3026,9 @@ namespace Slang reflectionNameModifier->nameAndLoc = NameLoc(reflectionNameToken); addModifier(bufferVarDecl, reflectionNameModifier); - // Both the buffer variable and its type need to have names generated - bufferVarDecl->nameAndLoc.name = generateName(parser, "parameterGroup_" + String(reflectionNameToken.getContent())); + // The parameter group type need to have its name generated. bufferDataTypeDecl->nameAndLoc.name = generateName(parser, "ParameterGroup_" + String(reflectionNameToken.getContent())); - addModifier(bufferDataTypeDecl, parser->astBuilder->create<ImplicitParameterGroupElementTypeModifier>()); - addModifier(bufferVarDecl, parser->astBuilder->create<ImplicitParameterGroupVariableModifier>()); // TODO(tfoley): We end up constructing unchecked syntax here that // is expected to type check into the right form, but it might be @@ -3003,12 +3066,28 @@ namespace Slang // The declarations in the body belong to the data type. parseDeclBody(parser, bufferDataTypeDecl); - // All HLSL buffer declarations are "transparent" in that their - // members are implicitly made visible in the parent scope. - // We achieve this by applying the transparent modifier to the variable. - auto transparentModifier = parser->astBuilder->create<TransparentModifier>(); - transparentModifier->next = bufferVarDecl->modifiers.first; - bufferVarDecl->modifiers.first = transparentModifier; + if (parser->LookAheadToken(TokenType::Identifier) && + parser->LookAheadToken(TokenType::Semicolon, 1)) + { + // If the user specified an explicit name of the buffer var, use it. + bufferVarDecl->nameAndLoc = ParseDeclName(parser); + parser->ReadToken(TokenType::Semicolon); + } + else + { + // Otherwise, we need to generate a name for the buffer variable. + bufferVarDecl->nameAndLoc.name = generateName(parser, "parameterGroup_" + String(reflectionNameToken.getContent())); + + // We also need to make the declaration "transparent" so that their + // members are implicitly made visible in the parent scope. + // We achieve this by applying the transparent modifier to the variable. + auto transparentModifier = parser->astBuilder->create<TransparentModifier>(); + transparentModifier->next = bufferVarDecl->modifiers.first; + bufferVarDecl->modifiers.first = transparentModifier; + + addModifier(bufferVarDecl, parser->astBuilder->create<ImplicitParameterGroupVariableModifier>()); + addModifier(bufferDataTypeDecl, parser->astBuilder->create<ImplicitParameterGroupElementTypeModifier>()); + } // Because we are constructing two declarations, we have a thorny // issue that were are only supposed to return one. @@ -4026,6 +4105,48 @@ namespace Slang return nullptr; } + static bool parseGLSLGlobalDecl(Parser* parser, ContainerDecl* containerDecl) + { + SLANG_UNUSED(containerDecl); + + if (AdvanceIf(parser, "precision")) + { + // skip global precision declarations. + parser->ReadToken(); + parser->ReadToken(); + 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; + } static void parseDecls( Parser* parser, @@ -4035,6 +4156,11 @@ namespace Slang Token closingBraceToken; while (!AdvanceIfMatch(parser, matchType, &closingBraceToken)) { + if (parser->options.allowGLSLInput) + { + if (parseGLSLGlobalDecl(parser, containerDecl)) + continue; + } ParseDecl(parser, containerDecl); } containerDecl->closingSourceLoc = closingBraceToken.loc; @@ -4081,6 +4207,18 @@ namespace Slang program->loc = tokenReader.peekLoc(); } + if (options.allowGLSLInput) + { + auto glslName = getName(this, "glsl"); + if (program->nameAndLoc.name != glslName) + { + auto importDecl = astBuilder->create<ImportDecl>(); + importDecl->moduleNameAndLoc.name = glslName; + importDecl->scope = currentScope; + AddMember(currentScope, importDecl); + } + } + parseDecls(this, program, MatchedTokenType::File); PopScope(); @@ -4140,6 +4278,23 @@ namespace Slang return rs; } + GLSLInterfaceBlockDecl* Parser::ParseGLSLInterfaceBlock() + { + // + // MyBlockName { float myData[]; } myBufferName; + // + + auto* rs = astBuilder->create<GLSLInterfaceBlockDecl>(); + FillPosition(rs); + + // As for struct, skip completion request token to prevent producing a + // block named completion request. + AdvanceIf(this, TokenType::CompletionRequest); + rs->nameAndLoc = expectIdentifier(this); + parseDeclBody(this, rs); + return rs; + } + static EnumCaseDecl* parseEnumCaseDecl(Parser* parser) { EnumCaseDecl* decl = parser->astBuilder->create<EnumCaseDecl>(); @@ -4841,9 +4996,10 @@ namespace Slang FillPosition(stmt); ReadToken("for"); ReadToken(TokenType::LParent); - if (peekTypeName(this)) + auto modifiers = ParseModifiers(this); + if (peekTypeName(this) || !modifiers.isEmpty()) { - stmt->initialStatement = parseVarDeclrStatement(Modifiers()); + stmt->initialStatement = parseVarDeclrStatement(modifiers); } else { @@ -6703,7 +6859,7 @@ namespace Slang // If there are any modifiers, then we know that we are actually // in the type case. // - auto typeSpec = _parseSimpleTypeSpec(parser); + auto typeSpec = _parseSimpleTypeSpec(parser, false); typeSpec = _applyModifiersToTypeSpec(parser, typeSpec, modifiers); auto typeExpr = typeSpec.expr; @@ -6742,6 +6898,7 @@ namespace Slang { ParserOptions options = {}; options.enableEffectAnnotations = translationUnit->compileRequest->getLinkage()->getEnableEffectAnnotations(); + options.allowGLSLInput = translationUnit->compileRequest->getLinkage()->getAllowGLSLInput(); Parser parser(astBuilder, tokens, sink, outerScope, options); parser.namePool = translationUnit->getNamePool(); @@ -6924,7 +7081,6 @@ namespace Slang return modifier; } - static SlangResult parseSemanticVersion(Parser* parser, Token& outToken, SemanticVersion& outVersion) { parser->ReadToken(TokenType::LParent); @@ -6981,12 +7137,12 @@ namespace Slang parser->sink->diagnose(token, Diagnostics::invalidCUDASMVersion); return nullptr; } - + static NodeBase* parseLayoutModifier(Parser* parser, void* /*userData*/) { ModifierListBuilder listBuilder; - UncheckedAttribute* numThreadsAttrib = nullptr; + GLSLLayoutLocalSizeAttribute* numThreadsAttrib = nullptr; listBuilder.add(parser->astBuilder->create<GLSLLayoutModifierGroupBegin>()); @@ -7009,13 +7165,12 @@ namespace Slang { if (!numThreadsAttrib) { - numThreadsAttrib = parser->astBuilder->create<UncheckedAttribute>(); + numThreadsAttrib = parser->astBuilder->create<GLSLLayoutLocalSizeAttribute>(); numThreadsAttrib->args.setCount(3); // Just mark the loc and name from the first in the list numThreadsAttrib->keywordName = getName(parser, "numthreads"); numThreadsAttrib->loc = nameAndLoc.loc; - numThreadsAttrib->scope = parser->currentScope; } if (AdvanceIf(parser, TokenType::OpAssign)) @@ -7272,6 +7427,9 @@ namespace Slang _makeParseModifier("const", ConstModifier::kReflectClassInfo), _makeParseModifier("instance", InstanceModifier::kReflectClassInfo), _makeParseModifier("__builtin", BuiltinModifier::kReflectClassInfo), + _makeParseModifier("highp", GLSLPrecisionModifier::kReflectClassInfo), + _makeParseModifier("lowp", GLSLPrecisionModifier::kReflectClassInfo), + _makeParseModifier("mediump", GLSLPrecisionModifier::kReflectClassInfo), _makeParseModifier("__global", ActualGlobalModifier::kReflectClassInfo), @@ -7296,6 +7454,7 @@ 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), |
