allow renaming of shader entry point when creating SPIR-V

Use "--source-entrypoint name" on the command line, or the
TShader::setSourceEntryPoint(char*) API.

When the name given to the above interfaces is detected in the
shader source, it will be renamed to the entry point name supplied
to the -e option or the TShader::setEntryPoint() method.
This commit is contained in:
steve-lunarg 2016-10-31 15:13:43 -06:00
parent 8ce6e2ba49
commit f1e0c87127
9 changed files with 199 additions and 10 deletions

View File

@ -160,6 +160,7 @@ int Options = 0;
const char* ExecutableName = nullptr; const char* ExecutableName = nullptr;
const char* binaryFileName = nullptr; const char* binaryFileName = nullptr;
const char* entryPointName = nullptr; const char* entryPointName = nullptr;
const char* sourceEntryPointName = nullptr;
const char* shaderStageName = nullptr; const char* shaderStageName = nullptr;
std::array<unsigned int, EShLangCount> baseSamplerBinding; std::array<unsigned int, EShLangCount> baseSamplerBinding;
@ -300,6 +301,15 @@ void ProcessArguments(int argc, char* argv[])
} else if (lowerword == "no-storage-format" || // synonyms } else if (lowerword == "no-storage-format" || // synonyms
lowerword == "nsf") { lowerword == "nsf") {
Options |= EOptionNoStorageFormat; Options |= EOptionNoStorageFormat;
} else if (lowerword == "source-entrypoint" || // synonyms
lowerword == "sep") {
sourceEntryPointName = argv[1];
if (argc > 0) {
argc--;
argv++;
} else
Error("no <entry-point> provided for --source-entrypoint");
break;
} else { } else {
usage(); usage();
} }
@ -547,6 +557,8 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, 1); shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, 1);
if (entryPointName) // HLSL todo: this needs to be tracked per compUnits if (entryPointName) // HLSL todo: this needs to be tracked per compUnits
shader->setEntryPoint(entryPointName); shader->setEntryPoint(entryPointName);
if (sourceEntryPointName)
shader->setSourceEntryPoint(sourceEntryPointName);
shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]); shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]);
shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]); shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]);
@ -963,6 +975,9 @@ void usage()
"\n" "\n"
" --no-storage-format use Unknown image format\n" " --no-storage-format use Unknown image format\n"
" --nsf synonym for --no-storage-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); exit(EFailUsage);

View File

@ -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

View File

@ -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;
}

View File

@ -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 $EXE -i -C *.vert *.geom *.frag *.tes* *.comp -t > multiThread.out
diff singleThread.out multiThread.out || HASERROR=1 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 ] if [ $HASERROR -eq 0 ]
then then
echo Tests Succeeded. echo Tests Succeeded.

View File

@ -86,7 +86,7 @@ TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate&
int version, EProfile profile, EShSource source, int version, EProfile profile, EShSource source,
EShLanguage language, TInfoSink& infoSink, EShLanguage language, TInfoSink& infoSink,
SpvVersion spvVersion, bool forwardCompatible, EShMessages messages, SpvVersion spvVersion, bool forwardCompatible, EShMessages messages,
bool parsingBuiltIns) bool parsingBuiltIns, const std::string sourceEntryPointName = "")
{ {
switch (source) { switch (source) {
case EShSourceGlsl: case EShSourceGlsl:
@ -96,7 +96,7 @@ TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate&
case EShSourceHlsl: case EShSourceHlsl:
return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion, return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
language, infoSink, forwardCompatible, messages); language, infoSink, sourceEntryPointName.c_str(), forwardCompatible, messages);
default: default:
infoSink.info.message(EPrefixInternalError, "Unable to determine source language"); infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
return nullptr; return nullptr;
@ -616,7 +616,8 @@ bool ProcessDeferred(
TIntermediate& intermediate, // returned tree, etc. TIntermediate& intermediate, // returned tree, etc.
ProcessingContext& processingContext, ProcessingContext& processingContext,
bool requireNonempty, bool requireNonempty,
TShader::Includer& includer TShader::Includer& includer,
const std::string sourceEntryPointName = ""
) )
{ {
if (! InitThread()) if (! InitThread())
@ -733,7 +734,7 @@ bool ProcessDeferred(
TParseContextBase* parseContext = CreateParseContext(symbolTable, intermediate, version, profile, source, TParseContextBase* parseContext = CreateParseContext(symbolTable, intermediate, version, profile, source,
compiler->getLanguage(), compiler->infoSink, compiler->getLanguage(), compiler->infoSink,
spvVersion, forwardCompatible, messages, false); spvVersion, forwardCompatible, messages, false, sourceEntryPointName);
TPpContext ppContext(*parseContext, names[numPre]? names[numPre]: "", includer); TPpContext ppContext(*parseContext, names[numPre]? names[numPre]: "", includer);
@ -1054,14 +1055,15 @@ bool CompileDeferred(
bool forwardCompatible, // give errors for use of deprecated features bool forwardCompatible, // give errors for use of deprecated features
EShMessages messages, // warnings/errors/AST; things to print out EShMessages messages, // warnings/errors/AST; things to print out
TIntermediate& intermediate,// returned tree, etc. TIntermediate& intermediate,// returned tree, etc.
TShader::Includer& includer) TShader::Includer& includer,
const std::string sourceEntryPointName = "")
{ {
DoFullParse parser; DoFullParse parser;
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
preamble, optLevel, resources, defaultVersion, preamble, optLevel, resources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile, defaultProfile, forceDefaultVersionAndProfile,
forwardCompatible, messages, intermediate, parser, forwardCompatible, messages, intermediate, parser,
true, includer); true, includer, sourceEntryPointName);
} }
} // end anonymous namespace for local functions } // end anonymous namespace for local functions
@ -1479,7 +1481,7 @@ public:
virtual bool compile(TIntermNode*, int = 0, EProfile = ENoProfile) { return true; } 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("") : pool(0), stage(s), lengths(nullptr), stringNames(nullptr), preamble("")
{ {
infoSink = new TInfoSink; infoSink = new TInfoSink;
@ -1523,6 +1525,11 @@ void TShader::setEntryPoint(const char* entryPoint)
intermediate->setEntryPointName(entryPoint); intermediate->setEntryPointName(entryPoint);
} }
void TShader::setSourceEntryPoint(const char* name)
{
sourceEntryPointName = name;
}
void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); } void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); }
void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); } void TShader::setShiftTextureBinding(unsigned int base) { intermediate->setShiftTextureBinding(base); }
void TShader::setShiftImageBinding(unsigned int base) { intermediate->setShiftImageBinding(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, return CompileDeferred(compiler, strings, numStrings, lengths, stringNames,
preamble, EShOptNone, builtInResources, defaultVersion, preamble, EShOptNone, builtInResources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile, defaultProfile, forceDefaultVersionAndProfile,
forwardCompatible, messages, *intermediate, includer); forwardCompatible, messages, *intermediate, includer, sourceEntryPointName);
} }
bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages)

View File

@ -304,6 +304,7 @@ public:
const char* const* s, const int* l, const char* const* names, int n); const char* const* s, const int* l, const char* const* names, int n);
void setPreamble(const char* s) { preamble = s; } void setPreamble(const char* s) { preamble = s; }
void setEntryPoint(const char* entryPoint); void setEntryPoint(const char* entryPoint);
void setSourceEntryPoint(const char* sourceEntryPointName);
void setShiftSamplerBinding(unsigned int base); void setShiftSamplerBinding(unsigned int base);
void setShiftTextureBinding(unsigned int base); void setShiftTextureBinding(unsigned int base);
void setShiftImageBinding(unsigned int base); void setShiftImageBinding(unsigned int base);
@ -437,6 +438,9 @@ protected:
const char* preamble; const char* preamble;
int numStrings; 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; friend class TProgram;
private: private:

View File

@ -308,8 +308,13 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
// identifier // identifier
HlslToken idToken; HlslToken idToken;
while (acceptIdentifier(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 // function_parameters
TFunction& function = *new TFunction(idToken.string, declaredType); TFunction& function = *new TFunction(fnName, declaredType);
if (acceptFunctionParameters(function)) { if (acceptFunctionParameters(function)) {
// post_decls // post_decls
acceptPostDecls(function.getWritableType().getQualifier()); acceptPostDecls(function.getWritableType().getQualifier());

View File

@ -51,6 +51,7 @@ namespace glslang {
HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins,
int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink,
const TString sourceEntryPointName,
bool forwardCompatible, EShMessages messages) : bool forwardCompatible, EShMessages messages) :
TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
contextPragma(true, false), contextPragma(true, false),
@ -58,7 +59,8 @@ HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& int
postEntryPointReturn(false), postEntryPointReturn(false),
limits(resources.limits), limits(resources.limits),
entryPointOutput(nullptr), entryPointOutput(nullptr),
nextInLocation(0), nextOutLocation(0) nextInLocation(0), nextOutLocation(0),
sourceEntryPointName(sourceEntryPointName)
{ {
globalUniformDefaults.clear(); globalUniformDefaults.clear();
globalUniformDefaults.layoutMatrix = ElmRowMajor; globalUniformDefaults.layoutMatrix = ElmRowMajor;
@ -5539,4 +5541,13 @@ TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* ex
return switchNode; 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 } // end namespace glslang

View File

@ -47,6 +47,7 @@ class HlslParseContext : public TParseContextBase {
public: public:
HlslParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, HlslParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins,
int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&,
const TString sourceEntryPointName,
bool forwardCompatible = false, EShMessages messages = EShMsgDefault); bool forwardCompatible = false, EShMessages messages = EShMsgDefault);
virtual ~HlslParseContext(); virtual ~HlslParseContext();
void initializeExtensionBehavior(); void initializeExtensionBehavior();
@ -165,6 +166,9 @@ public:
bool handleOutputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry); bool handleOutputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry); bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry);
// Potentially rename shader entry point function
void renameShaderFunction(TString*& name) const;
protected: protected:
void inheritGlobalDefaults(TQualifier& dst) const; void inheritGlobalDefaults(TQualifier& dst) const;
TVariable* makeInternalVariable(const char* name, const TType&) const; TVariable* makeInternalVariable(const char* name, const TType&) const;
@ -251,6 +255,8 @@ protected:
TMap<int, TVector<TVariable*>> flattenMap; TMap<int, TVector<TVariable*>> flattenMap;
unsigned int nextInLocation; unsigned int nextInLocation;
unsigned int nextOutLocation; unsigned int nextOutLocation;
TString sourceEntryPointName;
}; };
} // end namespace glslang } // end namespace glslang