From 46eaf4939e090758e7de1b6704f6629c3de1fabf Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Wed, 6 Feb 2013 23:06:52 +0000 Subject: [PATCH] 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 --- glslang/MachineIndependent/ParseHelper.cpp | 69 +++++++++++++++++++++- glslang/MachineIndependent/ParseHelper.h | 5 +- glslang/MachineIndependent/ShaderLang.cpp | 9 ++- glslang/MachineIndependent/glslang.l | 57 +----------------- glslang/Public/ShaderLang.h | 3 +- 5 files changed, 79 insertions(+), 64 deletions(-) diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index ccc7d28c..92d2e54a 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -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), recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0), switchNestingLevel(0), inTypeParen(false), - version(110), profile(ENoProfile), futureCompatibility(false), + futureCompatibility(false), contextPragma(true, false) { // Default precisions for version 110, to be overridden for // other versions/profiles/stage combinations for (int type = 0; type < EbtNumTypes; ++type) 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; + } + } + } } // diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 3017e1b2..6af1c95b 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -67,7 +67,7 @@ struct TPragma { // they can be passed to the parser without needing a global. // 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 TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed TInfoSink& infoSink; @@ -92,6 +92,9 @@ struct TParseContext { TString HashErrMsg; bool AfterEOF; + void setVersion(int); + void setProfile(EProfile); + void initializeExtensionBehavior(); void C_DECL error(TSourceLoc, const char *szReason, const char *szToken, diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index dc899f5a..f95445d9 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -190,7 +190,7 @@ bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language else symbolTable = &symbolTables[language]; - TParseContext parseContext(*symbolTable, intermediate, language, infoSink); + TParseContext parseContext(*symbolTable, intermediate, language, infoSink, 110); GlobalParseContext = &parseContext; @@ -255,7 +255,8 @@ int ShCompile( const int numStrings, const EShOptimizationLevel optLevel, const TBuiltInResource* resources, - int debugOptions + int debugOptions, + int defaultVersion ) { if (!InitThread()) @@ -281,9 +282,7 @@ int ShCompile( GenerateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage()); - // TODO: this is happening *after* initialization, which already parsed some things... what parse context was that? - // what extensions did it have? - TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink); + TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink, defaultVersion); parseContext.initializeExtensionBehavior(); GlobalParseContext = &parseContext; diff --git a/glslang/MachineIndependent/glslang.l b/glslang/MachineIndependent/glslang.l index 0719a6a4..52488cbf 100644 --- a/glslang/MachineIndependent/glslang.l +++ b/glslang/MachineIndependent/glslang.l @@ -798,66 +798,13 @@ void ResetTString(void) void SetVersion(int version) { TParseContext& parseContext = *((TParseContext *)cpp->pC); - parseContext.version = 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; - } - } + parseContext.setVersion(version); } -// 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) { - const int FirstProfileVersion = 150; TParseContext& parseContext = *((TParseContext *)cpp->pC); - - 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; - } - } - } + parseContext.setProfile(profile); } TBehavior GetBehavior(const char* behavior) diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index e3ff76d0..b97261aa 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -154,7 +154,8 @@ SH_IMPORT_EXPORT int ShCompile( const int numStrings, const EShOptimizationLevel, const TBuiltInResource *resources, - int debugOptions + int debugOptions, + int defaultVersion = 110 // use 100 for ES environment );