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/core.meta.slang | 5 - source/slang/hlsl.meta.slang | 5 + source/slang/slang-ast-modifier.h | 20 +++ source/slang/slang-check-modifier.cpp | 3 +- source/slang/slang-emit-glsl.cpp | 34 +++- source/slang/slang-ir-lower-glsl-ssbo-types.cpp | 6 +- source/slang/slang-ir.h | 8 +- source/slang/slang-lower-to-ir.cpp | 2 + source/slang/slang-parser.cpp | 212 ++++++++++++------------ source/slang/slang-parser.h | 1 + source/slang/slang-preprocessor.cpp | 12 +- source/slang/slang-preprocessor.h | 6 +- source/slang/slang.cpp | 48 ++++-- tests/glsl/ssbo-scalar.slang | 26 +++ 14 files changed, 255 insertions(+), 133 deletions(-) create mode 100644 tests/glsl/ssbo-scalar.slang diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 3961403e7..f3ab38582 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -1296,11 +1296,6 @@ struct Primitives } }; -__generic -__intrinsic_type($(kIROp_GLSLShaderStorageBufferType)) -__magic_type(GLSLShaderStorageBufferType) -struct GLSLShaderStorageBuffer {} - //@ hidden: // Need to add constructors to the types above diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang index a485c6514..273cfdc4f 100644 --- a/source/slang/hlsl.meta.slang +++ b/source/slang/hlsl.meta.slang @@ -27,6 +27,11 @@ __intrinsic_type($(kIROp_ScalarBufferLayoutType)) struct ScalarDataLayout : IBufferDataLayout {}; +__generic +__intrinsic_type($(kIROp_GLSLShaderStorageBufferType)) +__magic_type(GLSLShaderStorageBufferType) +struct GLSLShaderStorageBuffer {} + __generic __intrinsic_op($(kIROp_StructuredBufferGetDimensions)) uint2 __structuredBufferGetDimensions(AppendStructuredBuffer buffer); diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index dae8966de..155363e0c 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -243,6 +243,26 @@ class GLSLLocationLayoutModifier : public GLSLParsedLayoutModifier SLANG_AST_CLASS(GLSLLocationLayoutModifier) }; +class GLSLBufferDataLayoutModifier : public GLSLParsedLayoutModifier +{ + SLANG_AST_CLASS(GLSLBufferDataLayoutModifier) +}; + +class GLSLStd140Modifier : public GLSLBufferDataLayoutModifier +{ + SLANG_AST_CLASS(GLSLStd140Modifier) +}; + +class GLSLStd430Modifier : public GLSLBufferDataLayoutModifier +{ + SLANG_AST_CLASS(GLSLStd430Modifier) +}; + +class GLSLScalarModifier : public GLSLBufferDataLayoutModifier +{ + SLANG_AST_CLASS(GLSLScalarModifier) +}; + // A catch-all for single-keyword modifiers class SimpleModifier : public Modifier diff --git a/source/slang/slang-check-modifier.cpp b/source/slang/slang-check-modifier.cpp index 51cb5346a..2627ab8e8 100644 --- a/source/slang/slang-check-modifier.cpp +++ b/source/slang/slang-check-modifier.cpp @@ -1045,6 +1045,7 @@ namespace Slang // layout(local_size_x=1) in; case ASTNodeType::InModifier: case ASTNodeType::InOutModifier: + case ASTNodeType::OutModifier: case ASTNodeType::GLSLLayoutModifier: case ASTNodeType::GLSLParsedLayoutModifier: case ASTNodeType::GLSLConstantIDLayoutModifier: @@ -1059,8 +1060,6 @@ namespace Slang return true; [[fallthrough]]; - // Allowed only on parameters and global variables. - case ASTNodeType::OutModifier: case ASTNodeType::RefModifier: case ASTNodeType::ConstRefModifier: case ASTNodeType::GLSLBufferModifier: diff --git a/source/slang/slang-emit-glsl.cpp b/source/slang/slang-emit-glsl.cpp index bae34b6fa..e394804c7 100644 --- a/source/slang/slang-emit-glsl.cpp +++ b/source/slang/slang-emit-glsl.cpp @@ -229,7 +229,39 @@ void GLSLSourceEmitter::emitSSBOHeader(IRGlobalParam* varDecl, IRType* bufferTyp _requireGLSLVersion(430); m_writer->emit("layout("); - m_writer->emit(getTargetReq()->getForceGLSLScalarBufferLayout() ? "scalar" : "std430"); + IROp layoutOp = kIROp_DefaultBufferLayoutType; + if (auto structBufferType = as(bufferType)) + { + layoutOp = structBufferType->getDataLayout()? structBufferType->getDataLayout()->getOp() : kIROp_DefaultBufferLayoutType; + } + else if (auto ssboType = as(bufferType)) + { + layoutOp = ssboType->getDataLayout() ? ssboType->getDataLayout()->getOp() : kIROp_DefaultBufferLayoutType; + } + + if (layoutOp == kIROp_DefaultBufferLayoutType) + { + m_writer->emit(getTargetReq()->getForceGLSLScalarBufferLayout() ? "scalar" : "std430"); + } + else + { + switch (layoutOp) + { + case kIROp_DefaultBufferLayoutType: + m_writer->emit(getTargetReq()->getForceGLSLScalarBufferLayout() ? "scalar" : "std430"); + break; + case kIROp_Std430BufferLayoutType: + m_writer->emit("std430"); + break; + case kIROp_Std140BufferLayoutType: + m_writer->emit("std140"); + break; + case kIROp_ScalarBufferLayoutType: + _requireGLSLExtension(toSlice("GL_EXT_scalar_block_layout")); + m_writer->emit("scalar"); + break; + } + } auto layout = getVarLayout(varDecl); if (layout) diff --git a/source/slang/slang-ir-lower-glsl-ssbo-types.cpp b/source/slang/slang-ir-lower-glsl-ssbo-types.cpp index f0bdb7e83..a511c1c06 100644 --- a/source/slang/slang-ir-lower-glsl-ssbo-types.cpp +++ b/source/slang/slang-ir-lower-glsl-ssbo-types.cpp @@ -81,11 +81,11 @@ namespace Slang for(const auto& [ssbo, info] : arrayLikeSSBOTypes) { builder.setInsertAfter(ssbo); - IRInst* operands = info.elementType; + IRInst* operands[2] = { info.elementType, ssbo->getDataLayout() }; const auto sb = builder.getType( kIROp_HLSLRWStructuredBufferType, - 1, - &operands + 2, + operands ); ssbo->replaceUsesWith(sb); ssbo->removeAndDeallocate(); diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h index 2193e0351..0766bb168 100644 --- a/source/slang/slang-ir.h +++ b/source/slang/slang-ir.h @@ -1526,9 +1526,15 @@ SIMPLE_IR_TYPE(ConstantBufferType, UniformParameterGroupType) SIMPLE_IR_TYPE(TextureBufferType, UniformParameterGroupType) SIMPLE_IR_TYPE(GLSLInputParameterGroupType, VaryingParameterGroupType) SIMPLE_IR_TYPE(GLSLOutputParameterGroupType, VaryingParameterGroupType) -SIMPLE_IR_TYPE(GLSLShaderStorageBufferType, ParameterGroupType) SIMPLE_IR_TYPE(ParameterBlockType, UniformParameterGroupType) +struct IRGLSLShaderStorageBufferType : IRBuiltinGenericType +{ + IRType* getDataLayout() { return (IRType*)getOperand(1); } + + IR_LEAF_ISA(GLSLShaderStorageBufferType) +}; + struct IRArrayTypeBase : IRType { IRType* getElementType() { return (IRType*)getOperand(0); } diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index e0bf72f7d..427fe1cf0 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -2317,6 +2317,8 @@ static void addNameHint( String name = getNameForNameHint(context, decl); if(name.getLength() == 0) return; + if (name == "MyBlockName2") + printf("break"); context->irBuilder->addNameHintDecoration(inst, name.getUnownedSlice()); } 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), diff --git a/source/slang/slang-parser.h b/source/slang/slang-parser.h index 9933f6839..22b3e73ce 100644 --- a/source/slang/slang-parser.h +++ b/source/slang/slang-parser.h @@ -12,6 +12,7 @@ namespace Slang void parseSourceFile( ASTBuilder* astBuilder, TranslationUnitRequest* translationUnit, + SourceLanguage sourceLanguage, TokenSpan const& tokens, DiagnosticSink* sink, Scope* outerScope, diff --git a/source/slang/slang-preprocessor.cpp b/source/slang/slang-preprocessor.cpp index 02f46103b..9586088a1 100644 --- a/source/slang/slang-preprocessor.cpp +++ b/source/slang/slang-preprocessor.cpp @@ -1015,6 +1015,9 @@ struct Preprocessor /// Stores the initiating macro source location. SourceLoc initiatingMacroSourceLoc; + /// Detected source language. + SourceLanguage language = SourceLanguage::Unknown; + /// Stores macro definition and invocation info for language server. PreprocessorContentAssistInfo* contentAssistInfo = nullptr; @@ -3655,6 +3658,7 @@ static void HandleVersionDirective(PreprocessorDirectiveContext* context) } SkipToEndOfLine(context); + context->m_preprocessor->language = SourceLanguage::GLSL; // TODO, just skip the version for now } @@ -4022,6 +4026,7 @@ TokenList preprocessSource( IncludeSystem* includeSystem, Dictionary const& defines, Linkage* linkage, + SourceLanguage& outDetectedLanguage, PreprocessorHandler* handler) { PreprocessorDesc desc; @@ -4040,12 +4045,13 @@ TokenList preprocessSource( { desc.contentAssistInfo = &linkage->contentAssistInfo.preprocessorInfo; } - return preprocessSource(file, desc); + return preprocessSource(file, desc, outDetectedLanguage); } TokenList preprocessSource( SourceFile* file, - PreprocessorDesc const& desc) + PreprocessorDesc const& desc, + SourceLanguage &outDetectedLanguage) { using namespace preprocessor; @@ -4132,6 +4138,8 @@ TokenList preprocessSource( String s = sb.produceString(); #endif + outDetectedLanguage = preprocessor.language; + return tokens; } diff --git a/source/slang/slang-preprocessor.h b/source/slang/slang-preprocessor.h index c37fd1607..d8698cd01 100644 --- a/source/slang/slang-preprocessor.h +++ b/source/slang/slang-preprocessor.h @@ -13,6 +13,8 @@ class DiagnosticSink; class Linkage; struct PreprocessorContentAssistInfo; +enum class SourceLanguage : SlangSourceLanguageIntegral; + namespace preprocessor { struct Preprocessor; @@ -62,7 +64,8 @@ struct PreprocessorDesc /// Take a source `file` and preprocess it into a list of tokens. TokenList preprocessSource( SourceFile* file, - PreprocessorDesc const& desc); + PreprocessorDesc const& desc, + SourceLanguage& outDetectedLanguage); /// Convenience wrapper for `preprocessSource` when a `Linkage` is available TokenList preprocessSource( @@ -71,6 +74,7 @@ TokenList preprocessSource( IncludeSystem* includeSystem, Dictionary const& defines, Linkage* linkage, + SourceLanguage& outDetectedLanguage, PreprocessorHandler* handler = nullptr); // The following functions are intended to be used inside of implementations diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index e99f94484..267d91173 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -1984,17 +1984,23 @@ Expr* Linkage::parseTermString(String typeStr, Scope* scope) // We need to temporarily replace the SourceManager for this CompileRequest ScopeReplaceSourceManager scopeReplaceSourceManager(this, &localSourceManager); + + SourceLanguage sourceLanguage; auto tokens = preprocessSource( srcFile, &sink, nullptr, Dictionary(), - this); + this, + sourceLanguage); + + if (sourceLanguage == SourceLanguage::Unknown) + sourceLanguage = SourceLanguage::Slang; return parseTermFromSourceFile( getASTBuilder(), - tokens, &sink, scope, getNamePool(), SourceLanguage::Slang); + tokens, &sink, scope, getNamePool(), sourceLanguage); } Type* checkProperType( @@ -2349,19 +2355,6 @@ void FrontEndCompileRequest::parseTranslationUnit( // would be checked too (after those on the FrontEndCompileRequest). IncludeSystem includeSystem(&linkage->searchDirectories, linkage->getFileSystemExt(), linkage->getSourceManager()); - Scope* languageScope = nullptr; - switch (translationUnit->sourceLanguage) - { - case SourceLanguage::HLSL: - languageScope = getSession()->hlslLanguageScope; - break; - - case SourceLanguage::Slang: - default: - languageScope = getSession()->slangLanguageScope; - break; - } - auto combinedPreprocessorDefinitions = translationUnit->getCombinedPreprocessorDefinitions(); auto module = translationUnit->getModule(); @@ -2406,14 +2399,32 @@ void FrontEndCompileRequest::parseTranslationUnit( for (auto sourceFile : translationUnit->getSourceFiles()) { + SourceLanguage sourceLanguage = SourceLanguage::Unknown; auto tokens = preprocessSource( sourceFile, getSink(), &includeSystem, combinedPreprocessorDefinitions, getLinkage(), + sourceLanguage, &preprocessorHandler); + if (sourceLanguage == SourceLanguage::Unknown) + sourceLanguage = translationUnit->sourceLanguage; + + Scope* languageScope = nullptr; + switch (sourceLanguage) + { + case SourceLanguage::HLSL: + languageScope = getSession()->hlslLanguageScope; + break; + + case SourceLanguage::Slang: + default: + languageScope = getSession()->slangLanguageScope; + break; + } + if (outputIncludes) { _outputIncludes(translationUnit->getSourceFiles(), getSink()->getSourceManager(), getSink()); @@ -2432,6 +2443,7 @@ void FrontEndCompileRequest::parseTranslationUnit( parseSourceFile( astBuilder, translationUnit, + sourceLanguage, tokens, getSink(), languageScope, @@ -3420,18 +3432,24 @@ Linkage::IncludeResult Linkage::findAndIncludeFile(Module* module, TranslationUn FrontEndPreprocessorHandler preprocessorHandler(module, module->getASTBuilder(), sink); auto combinedPreprocessorDefinitions = translationUnit->getCombinedPreprocessorDefinitions(); + SourceLanguage sourceLanguage = SourceLanguage::Unknown; auto tokens = preprocessSource( sourceFile, sink, &includeSystem, combinedPreprocessorDefinitions, this, + sourceLanguage, &preprocessorHandler); + + if (sourceLanguage == SourceLanguage::Unknown) + sourceLanguage = translationUnit->sourceLanguage; auto outerScope = module->getModuleDecl()->ownedScope; parseSourceFile( module->getASTBuilder(), translationUnit, + sourceLanguage, tokens, sink, outerScope, diff --git a/tests/glsl/ssbo-scalar.slang b/tests/glsl/ssbo-scalar.slang new file mode 100644 index 000000000..4d3583383 --- /dev/null +++ b/tests/glsl/ssbo-scalar.slang @@ -0,0 +1,26 @@ +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=BUF):-vk -compute -entry computeMain -allow-glsl + +#version 430 +precision highp float; +precision highp int; + +//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0], stride=4):out,name=outputBuffer +layout(scalar) buffer MyBlockName2 +{ + ivec3 data0; + ivec3 data1; +} outputBuffer; + +layout(local_size_x = 1) in; +void computeMain() +{ + outputBuffer.data0 = ivec3(1,2,3); + outputBuffer.data1 = ivec3(4,5,6); + + // BUF: 1 + // BUF-NEXT: 2 + // BUF-NEXT: 3 + // BUF-NEXT: 4 + // BUF-NEXT: 5 + // BUF-NEXT: 6 +} -- cgit v1.2.3