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* binaryFileName = nullptr;
const char* entryPointName = nullptr;
const char* sourceEntryPointName = nullptr;
const char* shaderStageName = nullptr;
std::array<unsigned int, EShLangCount> 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 <entry-point> provided for --source-entrypoint");
break;
} else {
usage();
}
@ -547,6 +557,8 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> 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);

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

View File

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

View File

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

View File

@ -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());

View File

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

View File

@ -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<int, TVector<TVariable*>> flattenMap;
unsigned int nextInLocation;
unsigned int nextOutLocation;
TString sourceEntryPointName;
};
} // end namespace glslang