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;
} 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();
}
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]);
"\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);
--- /dev/null
+../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
--- /dev/null
+
+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;
+}
$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.
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:
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;
TIntermediate& intermediate, // returned tree, etc.
ProcessingContext& processingContext,
bool requireNonempty,
- TShader::Includer& includer
+ TShader::Includer& includer,
+ const std::string sourceEntryPointName = ""
)
{
if (! InitThread())
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);
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
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;
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); }
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)
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);
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:
// 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());
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),
postEntryPointReturn(false),
limits(resources.limits),
entryPointOutput(nullptr),
- nextInLocation(0), nextOutLocation(0)
+ nextInLocation(0), nextOutLocation(0),
+ sourceEntryPointName(sourceEntryPointName)
{
globalUniformDefaults.clear();
globalUniformDefaults.layoutMatrix = ElmRowMajor;
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
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();
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;
TMap<int, TVector<TVariable*>> flattenMap;
unsigned int nextInLocation;
unsigned int nextOutLocation;
+
+ TString sourceEntryPointName;
};
} // end namespace glslang