HLSL: use HLSL parser to parse HLSL intrinsic prototypes, enable int/bool mats
This PR adds a CreateParseContext() fn analogous to CreateBuiltInParseables(), to create a language specific built in parser. (This code was present before but not encapsualted in a fn). This can now be used to create a source language specific parser for builtins. Along with this, the code creating HLSL intrinsic prototypes can now produce them in HLSL syntax, rather than GLSL syntax. This relaxes certain prior restrictions at the parser level. Lower layers (e.g, SPIR-V) may still have such restrictions, such as around Nx1 matrices: this code does not impact that. This PR also fleshes out matrix types for bools and ints, both of which were partially in place before. This was easier than maintaining the restrictions in the HLSL prototype generator to avoid creating protoypes with those types. Many tests change because the result type from intrinsics moves from "global" to "temp". Several new tests are added for the new types.
This commit is contained in:
parent
fabe7d6a61
commit
0842dbb39a
43 changed files with 3729 additions and 2033 deletions
|
|
@ -81,6 +81,28 @@ TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink, EShSource sourc
|
|||
}
|
||||
}
|
||||
|
||||
// Create a language specific version of a parse context.
|
||||
TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& intermediate,
|
||||
int version, EProfile profile, EShSource source,
|
||||
EShLanguage language, TInfoSink& infoSink,
|
||||
SpvVersion spvVersion, bool forwardCompatible, EShMessages messages,
|
||||
bool parsingBuiltIns)
|
||||
{
|
||||
switch (source) {
|
||||
case EShSourceGlsl:
|
||||
intermediate.setEntryPointName("main");
|
||||
return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
|
||||
language, infoSink, forwardCompatible, messages);
|
||||
|
||||
case EShSourceHlsl:
|
||||
return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion,
|
||||
language, infoSink, forwardCompatible, messages);
|
||||
default:
|
||||
infoSink.info.message(EPrefixInternalError, "Unable to determine source language");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Local mapping functions for making arrays of symbol tables....
|
||||
|
||||
const int VersionCount = 15; // index range in MapVersionToIndex
|
||||
|
|
@ -188,17 +210,22 @@ TPoolAllocator* PerProcessGPA = 0;
|
|||
//
|
||||
// Parse and add to the given symbol table the content of the given shader string.
|
||||
//
|
||||
bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink,
|
||||
TSymbolTable& symbolTable)
|
||||
bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
|
||||
EShSource source, TInfoSink& infoSink, TSymbolTable& symbolTable)
|
||||
{
|
||||
TIntermediate intermediate(language, version, profile);
|
||||
|
||||
TParseContext parseContext(symbolTable, intermediate, true, version, profile, spvVersion, language, infoSink);
|
||||
intermediate.setSource(source);
|
||||
|
||||
std::unique_ptr<TParseContextBase> parseContext(CreateParseContext(symbolTable, intermediate, version, profile, source,
|
||||
language, infoSink, spvVersion, true, EShMsgDefault,
|
||||
true));
|
||||
|
||||
TShader::ForbidInclude includer;
|
||||
TPpContext ppContext(parseContext, "", includer);
|
||||
TScanContext scanContext(parseContext);
|
||||
parseContext.setScanContext(&scanContext);
|
||||
parseContext.setPpContext(&ppContext);
|
||||
TPpContext ppContext(*parseContext, "", includer);
|
||||
TScanContext scanContext(*parseContext);
|
||||
parseContext->setScanContext(&scanContext);
|
||||
parseContext->setPpContext(&ppContext);
|
||||
|
||||
//
|
||||
// Push the symbol table to give it an initial scope. This
|
||||
|
|
@ -217,7 +244,7 @@ bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profil
|
|||
return true;
|
||||
|
||||
TInputScanner input(1, builtInShaders, builtInLengths);
|
||||
if (! parseContext.parseShaderStrings(ppContext, input) != 0) {
|
||||
if (! parseContext->parseShaderStrings(ppContext, input) != 0) {
|
||||
infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins");
|
||||
printf("Unable to parse built-ins\n%s\n", infoSink.info.c_str());
|
||||
printf("%s\n", builtInShaders[0]);
|
||||
|
|
@ -237,10 +264,12 @@ int CommonIndex(EProfile profile, EShLanguage language)
|
|||
// To initialize per-stage shared tables, with the common table already complete.
|
||||
//
|
||||
void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int version, EProfile profile, const SpvVersion& spvVersion,
|
||||
EShLanguage language, TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables)
|
||||
EShLanguage language, EShSource source, TInfoSink& infoSink, TSymbolTable** commonTable,
|
||||
TSymbolTable** symbolTables)
|
||||
{
|
||||
(*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]);
|
||||
InitializeSymbolTable(builtInParseables.getStageString(language), version, profile, spvVersion, language, infoSink, *symbolTables[language]);
|
||||
InitializeSymbolTable(builtInParseables.getStageString(language), version, profile, spvVersion, language, source,
|
||||
infoSink, *symbolTables[language]);
|
||||
builtInParseables.identifyBuiltIns(version, profile, spvVersion, language, *symbolTables[language]);
|
||||
if (profile == EEsProfile && version >= 300)
|
||||
(*symbolTables[language]).setNoBuiltInRedeclarations();
|
||||
|
|
@ -259,32 +288,40 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
|
|||
builtInParseables->initialize(version, profile, spvVersion);
|
||||
|
||||
// do the common tables
|
||||
InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangVertex, infoSink, *commonTable[EPcGeneral]);
|
||||
InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangVertex, source,
|
||||
infoSink, *commonTable[EPcGeneral]);
|
||||
if (profile == EEsProfile)
|
||||
InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangFragment, infoSink, *commonTable[EPcFragment]);
|
||||
InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangFragment, source,
|
||||
infoSink, *commonTable[EPcFragment]);
|
||||
|
||||
// do the per-stage tables
|
||||
|
||||
// always have vertex and fragment
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangVertex, infoSink, commonTable, symbolTables);
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangFragment, infoSink, commonTable, symbolTables);
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangVertex, source,
|
||||
infoSink, commonTable, symbolTables);
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangFragment, source,
|
||||
infoSink, commonTable, symbolTables);
|
||||
|
||||
// check for tessellation
|
||||
if ((profile != EEsProfile && version >= 150) ||
|
||||
(profile == EEsProfile && version >= 310)) {
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessControl, infoSink, commonTable, symbolTables);
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessEvaluation, infoSink, commonTable, symbolTables);
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessControl, source,
|
||||
infoSink, commonTable, symbolTables);
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessEvaluation, source,
|
||||
infoSink, commonTable, symbolTables);
|
||||
}
|
||||
|
||||
// check for geometry
|
||||
if ((profile != EEsProfile && version >= 150) ||
|
||||
(profile == EEsProfile && version >= 310))
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, infoSink, commonTable, symbolTables);
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source,
|
||||
infoSink, commonTable, symbolTables);
|
||||
|
||||
// check for compute
|
||||
if ((profile != EEsProfile && version >= 420) ||
|
||||
(profile == EEsProfile && version >= 310))
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, infoSink, commonTable, symbolTables);
|
||||
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source,
|
||||
infoSink, commonTable, symbolTables);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -295,7 +332,7 @@ bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& inf
|
|||
std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
|
||||
|
||||
builtInParseables->initialize(*resources, version, profile, spvVersion, language);
|
||||
InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, language, infoSink, symbolTable);
|
||||
InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, language, source, infoSink, symbolTable);
|
||||
builtInParseables->identifyBuiltIns(version, profile, spvVersion, language, symbolTable, *resources);
|
||||
|
||||
return true;
|
||||
|
|
@ -694,15 +731,10 @@ bool ProcessDeferred(
|
|||
// Now we can process the full shader under proper symbols and rules.
|
||||
//
|
||||
|
||||
TParseContextBase* parseContext;
|
||||
if (source == EShSourceHlsl) {
|
||||
parseContext = new HlslParseContext(symbolTable, intermediate, false, version, profile, spvVersion,
|
||||
compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
|
||||
} else {
|
||||
intermediate.setEntryPointName("main");
|
||||
parseContext = new TParseContext(symbolTable, intermediate, false, version, profile, spvVersion,
|
||||
compiler->getLanguage(), compiler->infoSink, forwardCompatible, messages);
|
||||
}
|
||||
TParseContextBase* parseContext = CreateParseContext(symbolTable, intermediate, version, profile, source,
|
||||
compiler->getLanguage(), compiler->infoSink,
|
||||
spvVersion, forwardCompatible, messages, false);
|
||||
|
||||
TPpContext ppContext(*parseContext, names[numPre]? names[numPre]: "", includer);
|
||||
|
||||
// only GLSL (bison triggered, really) needs an externally set scan context
|
||||
|
|
@ -940,7 +972,7 @@ struct DoPreprocessing {
|
|||
struct DoFullParse{
|
||||
bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
|
||||
TInputScanner& fullInput, bool versionWillBeError,
|
||||
TSymbolTable& symbolTable, TIntermediate& intermediate,
|
||||
TSymbolTable&, TIntermediate& intermediate,
|
||||
EShOptimizationLevel optLevel, EShMessages messages)
|
||||
{
|
||||
bool success = true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue