From 4d65ee31a6ffc5abc862211af323b2e858a29f89 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Sat, 12 Mar 2016 18:17:47 -0700 Subject: [PATCH] Generalize "main" to a settable entry point name. --- SPIRV/GlslangToSpv.cpp | 8 +++++--- SPIRV/SpvBuilder.cpp | 4 ++-- SPIRV/SpvBuilder.h | 4 ++-- StandAlone/StandAlone.cpp | 18 ++++++++++++++++++ glslang/MachineIndependent/ParseHelper.cpp | 2 +- glslang/MachineIndependent/ShaderLang.cpp | 6 ++++++ glslang/MachineIndependent/localintermediate.h | 3 +++ glslang/Public/ShaderLang.h | 1 + 8 files changed, 38 insertions(+), 8 deletions(-) diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 8c1c84f9..7a7baa2b 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -590,8 +590,8 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls builder.setSource(TranslateSourceLanguage(glslangIntermediate->getProfile()), glslangIntermediate->getVersion()); stdBuiltins = builder.import("GLSL.std.450"); builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); - shaderEntry = builder.makeMain(); - entryPoint = builder.addEntryPoint(executionModel, shaderEntry, "main"); + shaderEntry = builder.makeEntrypoint(glslangIntermediate->getEntryPoint().c_str()); + entryPoint = builder.addEntryPoint(executionModel, shaderEntry, glslangIntermediate->getEntryPoint().c_str()); // Add the source extensions const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); @@ -2082,7 +2082,9 @@ void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& /*structTy bool TGlslangToSpvTraverser::isShaderEntrypoint(const glslang::TIntermAggregate* node) { - return node->getName() == "main("; + // have to ignore mangling and just look at the base name + int firstOpen = node->getName().find('('); + return node->getName().compare(0, firstOpen, glslangIntermediate->getEntryPoint()) == 0; } // Make all the functions, skeletally, without actually visiting their bodies. diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 336d3de3..06d7a02a 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -893,7 +893,7 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat } // Comments in header -Function* Builder::makeMain() +Function* Builder::makeEntrypoint(const char* entryPoint) { assert(! mainFunction); @@ -901,7 +901,7 @@ Function* Builder::makeMain() std::vector params; std::vector precisions; - mainFunction = makeFunctionEntry(NoPrecision, makeVoidType(), "main", params, precisions, &entry); + mainFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, precisions, &entry); return mainFunction; } diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index e16ba38c..162e79ef 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -205,9 +205,9 @@ public: void setBuildPoint(Block* bp) { buildPoint = bp; } Block* getBuildPoint() const { return buildPoint; } - // Make the main function. The returned pointer is only valid + // Make the entry-point function. The returned pointer is only valid // for the lifetime of this builder. - Function* makeMain(); + Function* makeEntrypoint(const char*); // Make a shader-style function, and create its entry block if entry is non-zero. // Return the function, pass back the entry. diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index cc59d389..408f114e 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -449,6 +449,7 @@ int NumWorkItems = 0; int Options = 0; const char* ExecutableName = nullptr; const char* binaryFileName = nullptr; +const char* entryPointName = nullptr; // // Create the default name for saving a binary if -o is not provided. @@ -537,6 +538,16 @@ void ProcessArguments(int argc, char* argv[]) case 'd': Options |= EOptionDefaultDesktop; break; + case 'e': + // HLSL todo: entry point handle needs much more sophistication. + // This is okay for one compilation unit with one entry point. + entryPointName = argv[1]; + if (argc > 0) { + argc--; + argv++; + } else + Error("no provided for -e"); + break; case 'h': usage(); break; @@ -693,6 +704,8 @@ void CompileAndLinkShaderUnits(std::vector compUnits) const auto &compUnit = *it; glslang::TShader* shader = new glslang::TShader(compUnit.stage); shader->setStrings(compUnit.text, 1); + if (entryPointName) // HLSL todo: this needs to be tracked per compUnits + shader->setEntryPoint(entryPointName); shaders.push_back(shader); const int defaultVersion = Options & EOptionDefaultDesktop? 110: 100; @@ -726,20 +739,24 @@ void CompileAndLinkShaderUnits(std::vector compUnits) // Program-level processing... // + // Link if (! (Options & EOptionOutputPreprocessed) && ! program.link(messages)) LinkFailed = true; + // Report if (! (Options & EOptionSuppressInfolog) && ! (Options & EOptionMemoryLeakMode)) { PutsIfNonEmpty(program.getInfoLog()); PutsIfNonEmpty(program.getInfoDebugLog()); } + // Reflect if (Options & EOptionDumpReflection) { program.buildReflection(); program.dumpReflection(); } + // Dump SPIR-V if (Options & EOptionSpv) { if (CompileFailed || LinkFailed) printf("SPIR-V is not generated for failed compile or link\n"); @@ -1030,6 +1047,7 @@ void usage() " creates the default configuration file (redirect to a .conf file)\n" " -d default to desktop (#version 110) when there is no shader #version\n" " (default is ES version 100)\n" + " -e specify entry-point name\n" " -h print this usage message\n" " -i intermediate tree (glslang AST) is printed out\n" " -l link all input files together to form a single module\n" diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 8cee3e4b..a43df95b 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -975,7 +975,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, // // Raise error message if main function takes any parameters or returns anything other than void // - if (function.getName() == "main") { + if (function.getName() == intermediate.getEntryPoint()) { if (function.getParamCount() > 0) error(loc, "function cannot take any parameter(s)", function.getName().c_str(), ""); if (function.getType().getBasicType() != EbtVoid) diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 1f835539..4b2bf832 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -588,6 +588,7 @@ bool ProcessDeferred( // Now we can process the full shader under proper symbols and rules. // + intermediate.setEntryPoint("main"); TParseContext parseContext(symbolTable, intermediate, false, version, profile, spv, vulkan, compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages); glslang::TScanContext scanContext(parseContext); TPpContext ppContext(parseContext, includer); @@ -1355,6 +1356,11 @@ void TShader::setStringsWithLengthsAndNames( stringNames = names; } +void TShader::setEntryPoint(const char* entryPoint) +{ + intermediate->setEntryPoint(entryPoint); +} + // // Turn the shader strings into a parse tree in the TIntermediate. // diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 99267475..b1e833ba 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -145,6 +145,8 @@ public: void output(TInfoSink&, bool tree); void removeTree(); + void setEntryPoint(const char* ep) { entryPoint = ep; } + const TString& getEntryPoint() const { return entryPoint; } void setVersion(int v) { version = v; } int getVersion() const { return version; } void setProfile(EProfile p) { profile = p; } @@ -338,6 +340,7 @@ protected: static int getBaseAlignmentScalar(const TType&, int& size); const EShLanguage language; + TString entryPoint; TIntermNode* treeRoot; EProfile profile; int version; diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 702b66f4..7a708f2b 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -290,6 +290,7 @@ public: void setStringsWithLengthsAndNames( const char* const* s, const int* l, const char* const* names, int n); void setPreamble(const char* s) { preamble = s; } + void setEntryPoint(const char* entryPoint); // Interface to #include handlers. class Includer {