Support multiple default versions, to enable ES vs. desktop contexts, for shaders missing a #version statement.

This also moved some parseContext code from the flex file to the proper C++ file.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@20501 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-02-06 23:06:52 +00:00
parent c435c71d87
commit 46eaf4939e
5 changed files with 79 additions and 64 deletions

View File

@ -45,17 +45,82 @@
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is) : TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is, int defaultVersion) :
intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0), intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0), recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
switchNestingLevel(0), inTypeParen(false), switchNestingLevel(0), inTypeParen(false),
version(110), profile(ENoProfile), futureCompatibility(false), futureCompatibility(false),
contextPragma(true, false) contextPragma(true, false)
{ {
// Default precisions for version 110, to be overridden for // Default precisions for version 110, to be overridden for
// other versions/profiles/stage combinations // other versions/profiles/stage combinations
for (int type = 0; type < EbtNumTypes; ++type) for (int type = 0; type < EbtNumTypes; ++type)
defaultPrecision[type] = EpqNone; defaultPrecision[type] = EpqNone;
setVersion(defaultVersion);
setProfile(ENoProfile);
}
void TParseContext::setVersion(int newVersion)
{
version = newVersion;
if (version == 100 || version == 300) {
if (language == EShLangVertex) {
defaultPrecision[EbtInt] = EpqHigh;
defaultPrecision[EbtFloat] = EpqHigh;
defaultPrecision[EbtSampler2D] = EpqLow;
defaultPrecision[EbtSamplerCube] = EpqLow;
}
if (language == EShLangFragment) {
defaultPrecision[EbtInt] = EpqMedium;
defaultPrecision[EbtSampler2D] = EpqLow;
defaultPrecision[EbtSamplerCube] = EpqLow;
}
}
}
// Important assumption: SetVersion() is called before SetProfile(), and is always called
// if there is a version, sending in a ENoProfile if there is no profile given.
void TParseContext::setProfile(EProfile newProfile)
{
const int FirstProfileVersion = 150;
if (newProfile == ENoProfile) {
if (version == 300) {
error(1, "version 300 requires specifying the 'es' profile", "#version", "");
profile = EEsProfile;
} else if (version == 100)
profile = EEsProfile;
else if (version >= FirstProfileVersion)
profile = ECoreProfile;
else
profile = ENoProfile;
} else {
// a profile was provided...
if (version < 150) {
error(1, "versions before 150 do not allow a profile token", "#version", "");
if (version == 100)
profile = EEsProfile;
else
profile = ENoProfile;
} else if (version == 300) {
if (newProfile != EEsProfile)
error(1, "only version 300 supports the es profile", "#version", "");
profile = EEsProfile;
} else {
if (newProfile == EEsProfile) {
error(1, "only version 300 supports the es profile", "#version", "");
if (version >= FirstProfileVersion)
profile = ECoreProfile;
else
profile = ENoProfile;
} else {
// typical desktop case... e.g., "#version 410 core"
profile = newProfile;
}
}
}
} }
// //

View File

@ -67,7 +67,7 @@ struct TPragma {
// they can be passed to the parser without needing a global. // they can be passed to the parser without needing a global.
// //
struct TParseContext { struct TParseContext {
TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is); TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is, int defaultVersion);
TIntermediate& intermediate; // to hold and build a parse tree TIntermediate& intermediate; // to hold and build a parse tree
TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed
TInfoSink& infoSink; TInfoSink& infoSink;
@ -92,6 +92,9 @@ struct TParseContext {
TString HashErrMsg; TString HashErrMsg;
bool AfterEOF; bool AfterEOF;
void setVersion(int);
void setProfile(EProfile);
void initializeExtensionBehavior(); void initializeExtensionBehavior();
void C_DECL error(TSourceLoc, const char *szReason, const char *szToken, void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,

View File

@ -190,7 +190,7 @@ bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language
else else
symbolTable = &symbolTables[language]; symbolTable = &symbolTables[language];
TParseContext parseContext(*symbolTable, intermediate, language, infoSink); TParseContext parseContext(*symbolTable, intermediate, language, infoSink, 110);
GlobalParseContext = &parseContext; GlobalParseContext = &parseContext;
@ -255,7 +255,8 @@ int ShCompile(
const int numStrings, const int numStrings,
const EShOptimizationLevel optLevel, const EShOptimizationLevel optLevel,
const TBuiltInResource* resources, const TBuiltInResource* resources,
int debugOptions int debugOptions,
int defaultVersion
) )
{ {
if (!InitThread()) if (!InitThread())
@ -281,9 +282,7 @@ int ShCompile(
GenerateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage()); GenerateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage());
// TODO: this is happening *after* initialization, which already parsed some things... what parse context was that? TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink, defaultVersion);
// what extensions did it have?
TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink);
parseContext.initializeExtensionBehavior(); parseContext.initializeExtensionBehavior();
GlobalParseContext = &parseContext; GlobalParseContext = &parseContext;

View File

@ -798,66 +798,13 @@ void ResetTString(void)
void SetVersion(int version) void SetVersion(int version)
{ {
TParseContext& parseContext = *((TParseContext *)cpp->pC); TParseContext& parseContext = *((TParseContext *)cpp->pC);
parseContext.version = version; parseContext.setVersion(version);
if (version == 100 || version == 300) {
if (parseContext.language == EShLangVertex) {
parseContext.defaultPrecision[EbtInt] = EpqHigh;
parseContext.defaultPrecision[EbtFloat] = EpqHigh;
parseContext.defaultPrecision[EbtSampler2D] = EpqLow;
parseContext.defaultPrecision[EbtSamplerCube] = EpqLow;
} }
if (parseContext.language == EShLangFragment) {
parseContext.defaultPrecision[EbtInt] = EpqMedium;
parseContext.defaultPrecision[EbtSampler2D] = EpqLow;
parseContext.defaultPrecision[EbtSamplerCube] = EpqLow;
}
}
}
// Important assumption: SetVersion() is called before SetProfile(), and is always called
// if there is a version, sending in a ENoProfile if there is no profile given.
void SetProfile(EProfile profile) void SetProfile(EProfile profile)
{ {
const int FirstProfileVersion = 150;
TParseContext& parseContext = *((TParseContext *)cpp->pC); TParseContext& parseContext = *((TParseContext *)cpp->pC);
parseContext.setProfile(profile);
if (profile == ENoProfile) {
if (parseContext.version == 300) {
CPPErrorToInfoLog("version 300 requires specifying the 'es' profile");
parseContext.profile = EEsProfile;
} else if (parseContext.version == 100)
parseContext.profile = EEsProfile;
else if (parseContext.version >= FirstProfileVersion)
parseContext.profile = ECoreProfile;
else
parseContext.profile = ENoProfile;
} else {
// a profile was provided...
if (parseContext.version < 150) {
CPPErrorToInfoLog("versions before 150 do not allow a profile token");
if (parseContext.version == 100)
parseContext.profile = EEsProfile;
else
parseContext.profile = ENoProfile;
} else if (parseContext.version == 300) {
if (profile != EEsProfile)
CPPErrorToInfoLog("only version 300 supports the es profile");
parseContext.profile = EEsProfile;
} else {
if (profile == EEsProfile) {
CPPErrorToInfoLog("only version 300 supports the es profile");
if (parseContext.version >= FirstProfileVersion)
parseContext.profile = ECoreProfile;
else
parseContext.profile = ENoProfile;
} else {
// typical desktop case... e.g., "#version 410 core"
parseContext.profile = profile;
}
}
}
} }
TBehavior GetBehavior(const char* behavior) TBehavior GetBehavior(const char* behavior)

View File

@ -154,7 +154,8 @@ SH_IMPORT_EXPORT int ShCompile(
const int numStrings, const int numStrings,
const EShOptimizationLevel, const EShOptimizationLevel,
const TBuiltInResource *resources, const TBuiltInResource *resources,
int debugOptions int debugOptions,
int defaultVersion = 110 // use 100 for ES environment
); );