diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 377e7cb3..e6c0ab70 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -160,6 +160,7 @@ int Options = 0; const char* ExecutableName = nullptr; const char* binaryFileName = nullptr; const char* entryPointName = nullptr; +const char* sourceEntryPointName = nullptr; const char* shaderStageName = nullptr; std::array baseSamplerBinding; @@ -300,6 +301,15 @@ void ProcessArguments(int argc, char* argv[]) } else if (lowerword == "no-storage-format" || // synonyms lowerword == "nsf") { Options |= EOptionNoStorageFormat; + } else if (lowerword == "source-entrypoint" || // synonyms + lowerword == "sep") { + sourceEntryPointName = argv[1]; + if (argc > 0) { + argc--; + argv++; + } else + Error("no provided for --source-entrypoint"); + break; } else { usage(); } @@ -547,6 +557,8 @@ void CompileAndLinkShaderUnits(std::vector compUnits) shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, 1); if (entryPointName) // HLSL todo: this needs to be tracked per compUnits shader->setEntryPoint(entryPointName); + if (sourceEntryPointName) + shader->setSourceEntryPoint(sourceEntryPointName); shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]); shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]); @@ -963,6 +975,9 @@ void usage() "\n" " --no-storage-format use Unknown image format\n" " --nsf synonym for --no-storage-format\n" + "\n" + " --source-entrypoint name the given shader source function is renamed to be the entry point given in -e\n" + " --sep synonym for --source-entrypoint\n" ); exit(EFailUsage); diff --git a/Test/baseResults/hlsl.entry.rename.frag.out b/Test/baseResults/hlsl.entry.rename.frag.out new file mode 100644 index 00000000..0cfc9254 --- /dev/null +++ b/Test/baseResults/hlsl.entry.rename.frag.out @@ -0,0 +1,119 @@ +../Test/hlsl.entry.rename.frag +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:7 Function Definition: not_the_entry_point( (temp void) +0:7 Function Parameters: +0:11 Function Definition: main_in_spv( (temp structure{temp 4-component vector of float Color}) +0:11 Function Parameters: +0:? Sequence +0:13 move second child to first child (temp 4-component vector of float) +0:13 Color: direct index for structure (temp 4-component vector of float) +0:13 'psout' (temp structure{temp 4-component vector of float Color}) +0:13 Constant: +0:13 0 (const int) +0:13 Constant: +0:13 0.000000 +0:13 0.000000 +0:13 0.000000 +0:13 0.000000 +0:14 Sequence +0:14 Sequence +0:14 move second child to first child (temp 4-component vector of float) +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:14 Color: direct index for structure (temp 4-component vector of float) +0:14 'psout' (temp structure{temp 4-component vector of float Color}) +0:14 Constant: +0:14 0 (const int) +0:14 Branch: Return +0:? Linker Objects +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:? 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int also_not_the_entry_point}) + + +Linked fragment stage: + + +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:7 Function Definition: not_the_entry_point( (temp void) +0:7 Function Parameters: +0:11 Function Definition: main_in_spv( (temp structure{temp 4-component vector of float Color}) +0:11 Function Parameters: +0:? Sequence +0:13 move second child to first child (temp 4-component vector of float) +0:13 Color: direct index for structure (temp 4-component vector of float) +0:13 'psout' (temp structure{temp 4-component vector of float Color}) +0:13 Constant: +0:13 0 (const int) +0:13 Constant: +0:13 0.000000 +0:13 0.000000 +0:13 0.000000 +0:13 0.000000 +0:14 Sequence +0:14 Sequence +0:14 move second child to first child (temp 4-component vector of float) +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:14 Color: direct index for structure (temp 4-component vector of float) +0:14 'psout' (temp structure{temp 4-component vector of float Color}) +0:14 Constant: +0:14 0 (const int) +0:14 Branch: Return +0:? Linker Objects +0:? 'Color' (layout(location=0 ) out 4-component vector of float) +0:? 'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int also_not_the_entry_point}) + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 27 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "main_in_spv" 20 + ExecutionMode 4 OriginUpperLeft + Name 4 "main_in_spv" + Name 6 "not_the_entry_point(" + Name 10 "PS_OUTPUT" + MemberName 10(PS_OUTPUT) 0 "Color" + Name 12 "psout" + Name 20 "Color" + Name 24 "$Global" + MemberName 24($Global) 0 "also_not_the_entry_point" + Name 26 "" + Decorate 20(Color) Location 0 + MemberDecorate 24($Global) 0 Offset 0 + Decorate 24($Global) Block + Decorate 26 DescriptorSet 0 + 2: TypeVoid + 3: TypeFunction 2 + 8: TypeFloat 32 + 9: TypeVector 8(float) 4 + 10(PS_OUTPUT): TypeStruct 9(fvec4) + 11: TypePointer Function 10(PS_OUTPUT) + 13: TypeInt 32 1 + 14: 13(int) Constant 0 + 15: 8(float) Constant 0 + 16: 9(fvec4) ConstantComposite 15 15 15 15 + 17: TypePointer Function 9(fvec4) + 19: TypePointer Output 9(fvec4) + 20(Color): 19(ptr) Variable Output + 24($Global): TypeStruct 13(int) + 25: TypePointer Uniform 24($Global) + 26: 25(ptr) Variable Uniform + 4(main_in_spv): 2 Function None 3 + 5: Label + 12(psout): 11(ptr) Variable Function + 18: 17(ptr) AccessChain 12(psout) 14 + Store 18 16 + 21: 17(ptr) AccessChain 12(psout) 14 + 22: 9(fvec4) Load 21 + Store 20(Color) 22 + Return + FunctionEnd +6(not_the_entry_point(): 2 Function None 3 + 7: Label + Return + FunctionEnd diff --git a/Test/hlsl.entry.rename.frag b/Test/hlsl.entry.rename.frag new file mode 100644 index 00000000..188dfc58 --- /dev/null +++ b/Test/hlsl.entry.rename.frag @@ -0,0 +1,15 @@ + +struct PS_OUTPUT +{ + float4 Color : SV_Target0; +}; + +void not_the_entry_point() { } +int also_not_the_entry_point; + +PS_OUTPUT main() +{ + PS_OUTPUT psout; + psout.Color = 0; + return psout; +} diff --git a/Test/runtests b/Test/runtests index 06403912..78c630c7 100755 --- a/Test/runtests +++ b/Test/runtests @@ -45,6 +45,13 @@ $EXE -i -C *.vert *.geom *.frag *.tes* *.comp > singleThread.out $EXE -i -C *.vert *.geom *.frag *.tes* *.comp -t > multiThread.out diff singleThread.out multiThread.out || HASERROR=1 + +# +# entry point renaming tests +# +$EXE -i -H -V -D -e main_in_spv --source-entrypoint main ../Test/hlsl.entry.rename.frag > $TARGETDIR/hlsl.entry.rename.frag.out +diff -b $BASEDIR/hlsl.entry.rename.frag.out $TARGETDIR/hlsl.entry.rename.frag.out || HASERROR=1 + if [ $HASERROR -eq 0 ] then echo Tests Succeeded. diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index cc21b2ef..ef459879 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -86,7 +86,7 @@ TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& int version, EProfile profile, EShSource source, EShLanguage language, TInfoSink& infoSink, SpvVersion spvVersion, bool forwardCompatible, EShMessages messages, - bool parsingBuiltIns) + bool parsingBuiltIns, const std::string sourceEntryPointName = "") { switch (source) { case EShSourceGlsl: @@ -96,7 +96,7 @@ TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& case EShSourceHlsl: return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion, - language, infoSink, forwardCompatible, messages); + language, infoSink, sourceEntryPointName.c_str(), forwardCompatible, messages); default: infoSink.info.message(EPrefixInternalError, "Unable to determine source language"); return nullptr; @@ -616,7 +616,8 @@ bool ProcessDeferred( TIntermediate& intermediate, // returned tree, etc. ProcessingContext& processingContext, bool requireNonempty, - TShader::Includer& includer + TShader::Includer& includer, + const std::string sourceEntryPointName = "" ) { if (! InitThread()) @@ -733,7 +734,7 @@ bool ProcessDeferred( TParseContextBase* parseContext = CreateParseContext(symbolTable, intermediate, version, profile, source, compiler->getLanguage(), compiler->infoSink, - spvVersion, forwardCompatible, messages, false); + spvVersion, forwardCompatible, messages, false, sourceEntryPointName); TPpContext ppContext(*parseContext, names[numPre]? names[numPre]: "", includer); @@ -1054,14 +1055,15 @@ bool CompileDeferred( bool forwardCompatible, // give errors for use of deprecated features EShMessages messages, // warnings/errors/AST; things to print out TIntermediate& intermediate,// returned tree, etc. - TShader::Includer& includer) + TShader::Includer& includer, + const std::string sourceEntryPointName = "") { DoFullParse parser; return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, preamble, optLevel, resources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, intermediate, parser, - true, includer); + true, includer, sourceEntryPointName); } } // end anonymous namespace for local functions @@ -1479,7 +1481,7 @@ public: virtual bool compile(TIntermNode*, int = 0, EProfile = ENoProfile) { return true; } }; -TShader::TShader(EShLanguage s) +TShader::TShader(EShLanguage s) : pool(0), stage(s), lengths(nullptr), stringNames(nullptr), preamble("") { infoSink = new TInfoSink; @@ -1523,6 +1525,11 @@ void TShader::setEntryPoint(const char* entryPoint) intermediate->setEntryPointName(entryPoint); } +void TShader::setSourceEntryPoint(const char* name) +{ + sourceEntryPointName = name; +} + void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); } void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); } void TShader::setShiftImageBinding(unsigned int base) { intermediate->setShiftImageBinding(base); } @@ -1550,7 +1557,7 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion return CompileDeferred(compiler, strings, numStrings, lengths, stringNames, preamble, EShOptNone, builtInResources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, - forwardCompatible, messages, *intermediate, includer); + forwardCompatible, messages, *intermediate, includer, sourceEntryPointName); } bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 6793cdd3..851e115e 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -304,6 +304,7 @@ public: 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); + void setSourceEntryPoint(const char* sourceEntryPointName); void setShiftSamplerBinding(unsigned int base); void setShiftTextureBinding(unsigned int base); void setShiftImageBinding(unsigned int base); @@ -437,6 +438,9 @@ protected: const char* preamble; int numStrings; + // a function in the source string can be renamed FROM this TO the name given in setEntryPoint. + std::string sourceEntryPointName; + friend class TProgram; private: diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 10dfcc83..61fb4dd9 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -308,8 +308,13 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node) // identifier HlslToken idToken; while (acceptIdentifier(idToken)) { + TString* fnName = idToken.string; + + // Potentially rename shader entry point function. No-op most of the time. + parseContext.renameShaderFunction(fnName); + // function_parameters - TFunction& function = *new TFunction(idToken.string, declaredType); + TFunction& function = *new TFunction(fnName, declaredType); if (acceptFunctionParameters(function)) { // post_decls acceptPostDecls(function.getWritableType().getQualifier()); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 8685dcd8..c3074087 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -51,6 +51,7 @@ namespace glslang { HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, + const TString sourceEntryPointName, bool forwardCompatible, EShMessages messages) : TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), contextPragma(true, false), @@ -58,7 +59,8 @@ HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& int postEntryPointReturn(false), limits(resources.limits), entryPointOutput(nullptr), - nextInLocation(0), nextOutLocation(0) + nextInLocation(0), nextOutLocation(0), + sourceEntryPointName(sourceEntryPointName) { globalUniformDefaults.clear(); globalUniformDefaults.layoutMatrix = ElmRowMajor; @@ -5539,4 +5541,13 @@ TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* ex return switchNode; } +// Potentially rename shader entry point function +void HlslParseContext::renameShaderFunction(TString*& name) const +{ + // Replace the entry point name given in the shader with the real entry point name, + // if there is a substitution. + if (name != nullptr && *name == sourceEntryPointName) + name = new TString(intermediate.getEntryPointName().c_str()); +} + } // end namespace glslang diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index 246c7c49..f9cb0d32 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -47,6 +47,7 @@ class HlslParseContext : public TParseContextBase { public: HlslParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, + const TString sourceEntryPointName, bool forwardCompatible = false, EShMessages messages = EShMsgDefault); virtual ~HlslParseContext(); void initializeExtensionBehavior(); @@ -165,6 +166,9 @@ public: bool handleOutputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry); bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry); + // Potentially rename shader entry point function + void renameShaderFunction(TString*& name) const; + protected: void inheritGlobalDefaults(TQualifier& dst) const; TVariable* makeInternalVariable(const char* name, const TType&) const; @@ -251,6 +255,8 @@ protected: TMap> flattenMap; unsigned int nextInLocation; unsigned int nextOutLocation; + + TString sourceEntryPointName; }; } // end namespace glslang