Add a new shader-versioning infrastructure capable of handling multiple profiles, desktop/ES, many versions, features coming and going in different versions across different profiles, and extensions.
NB: *Use* of this infrastructure is so far only skeletal. Fixed a few typos and minor issues along the way. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@19951 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
@@ -739,8 +739,8 @@ bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.qualifier == EvqConst && extensionErrorCheck(line, "GL_3DL_array_objects"))
|
||||
return true;
|
||||
if (type.qualifier == EvqConst)
|
||||
profileRequires(line, ENoProfile, 120, "GL_3DL_array_objects", "const array");
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -948,20 +948,6 @@ bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TType* type)
|
||||
}
|
||||
}
|
||||
|
||||
bool TParseContext::extensionErrorCheck(int line, const char* extension)
|
||||
{
|
||||
if (extensionBehavior[extension] == EBhWarn) {
|
||||
infoSink.info.message(EPrefixWarning, ("extension " + TString(extension) + " is being used").c_str(), line);
|
||||
return false;
|
||||
}
|
||||
if (extensionBehavior[extension] == EBhDisable) {
|
||||
error(line, "extension", extension, "is disabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Non-Errors.
|
||||
@@ -1448,7 +1434,7 @@ void TParseContext::initializeExtensionBehavior()
|
||||
// example code: extensionBehavior["test"] = EBhDisable; // where "test" is the name of
|
||||
// supported extension
|
||||
//
|
||||
extensionBehavior["GL_ARB_texture_rectangle"] = EBhRequire;
|
||||
extensionBehavior["GL_ARB_texture_rectangle"] = EBhDisable;
|
||||
extensionBehavior["GL_3DL_array_objects"] = EBhDisable;
|
||||
}
|
||||
|
||||
@@ -1457,7 +1443,7 @@ OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
|
||||
bool InitializeParseContextIndex()
|
||||
{
|
||||
if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
|
||||
assert(0 && "InitializeParseContextIndex(): Parse Context already initialised");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1467,7 +1453,7 @@ bool InitializeParseContextIndex()
|
||||
GlobalParseContextIndex = OS_AllocTLSIndex();
|
||||
|
||||
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
|
||||
assert(0 && "InitializeParseContextIndex(): Parse Context already initialised");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1477,13 +1463,13 @@ bool InitializeParseContextIndex()
|
||||
bool InitializeGlobalParseContext()
|
||||
{
|
||||
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalised");
|
||||
assert(0 && "InitializeGlobalParseContext(): Parse Context index not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
|
||||
if (lpParseContext != 0) {
|
||||
assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
|
||||
assert(0 && "InitializeParseContextIndex(): Parse Context already initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1513,7 +1499,7 @@ TParseContextPointer& GetGlobalParseContext()
|
||||
bool FreeParseContext()
|
||||
{
|
||||
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "FreeParseContext(): Parse Context index not initalised");
|
||||
assert(0 && "FreeParseContext(): Parse Context index not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1529,7 +1515,7 @@ bool FreeParseContextIndex()
|
||||
OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
|
||||
|
||||
if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
|
||||
assert(0 && "FreeParseContextIndex(): Parse Context index not initalised");
|
||||
assert(0 && "FreeParseContextIndex(): Parse Context index not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
//All rights reserved.
|
||||
//
|
||||
//Copyright (C) 2012 LunarG, Inc.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
@@ -34,6 +36,7 @@
|
||||
#ifndef _PARSER_HELPER_INCLUDED_
|
||||
#define _PARSER_HELPER_INCLUDED_
|
||||
|
||||
#include "Versions.h"
|
||||
#include "../Include/ShHandle.h"
|
||||
#include "SymbolTable.h"
|
||||
#include "localintermediate.h"
|
||||
@@ -67,8 +70,9 @@ struct TParseContext {
|
||||
TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is) :
|
||||
intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
|
||||
recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
|
||||
switchNestingLevel(0),
|
||||
inTypeParen(false), contextPragma(true, false) { }
|
||||
switchNestingLevel(0), inTypeParen(false),
|
||||
version(110), profile(ENoProfile), futureCompatibility(false),
|
||||
contextPragma(true, false) { }
|
||||
TIntermediate& intermediate; // to hold and build a parse tree
|
||||
TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed
|
||||
TInfoSink& infoSink;
|
||||
@@ -82,7 +86,16 @@ struct TParseContext {
|
||||
bool inTypeParen; // true if in parentheses, looking only for an identifier
|
||||
const TType* currentFunctionType; // the return type of the function that's currently being parsed
|
||||
bool functionReturnsValue; // true if a non-void function has a return
|
||||
TMap<TString, TBehavior> extensionBehavior;
|
||||
|
||||
int version; // the declared version in the shader (110 by default)
|
||||
EProfile profile; // the declared profile in the shader (core by default)
|
||||
bool futureCompatibility; // true if requesting errors for future compatibility (false by default)
|
||||
TMap<TString, TBehavior> extensionBehavior; // for each extension string, what it's current enablement is
|
||||
|
||||
struct TPragma contextPragma;
|
||||
TString HashErrMsg;
|
||||
bool AfterEOF;
|
||||
|
||||
void initializeExtensionBehavior();
|
||||
|
||||
void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
|
||||
@@ -117,7 +130,6 @@ struct TParseContext {
|
||||
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
|
||||
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
|
||||
bool paramErrorCheck(int line, TQualifier qualifier, TType* type);
|
||||
bool extensionErrorCheck(int line, const char*);
|
||||
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
|
||||
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
|
||||
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
|
||||
@@ -131,9 +143,12 @@ struct TParseContext {
|
||||
TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line);
|
||||
TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
|
||||
bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
|
||||
struct TPragma contextPragma;
|
||||
TString HashErrMsg;
|
||||
bool AfterEOF;
|
||||
void requireProfile(int line, EProfileMask profileMask, const char *featureDesc);
|
||||
void requireStage(int line, EShLanguageMask languageMask, const char *featureDesc);
|
||||
void profileRequires(int line, EProfile callingProfile, int minVersion, int numExtensions, const char* extensions[], const char *featureDesc);
|
||||
void profileRequires(int line, EProfile callingProfile, int minVersion, const char* extension, const char *featureDesc);
|
||||
void checkDeprecated(int line, EProfile callingProfile, int depVersion, const char *featureDesc);
|
||||
void requireNotRemoved(int line, EProfile callingProfile, int removedVersion, const char *featureDesc);
|
||||
};
|
||||
|
||||
int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext&);
|
||||
|
||||
@@ -282,6 +282,8 @@ 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);
|
||||
parseContext.initializeExtensionBehavior();
|
||||
|
||||
|
||||
161
glslang/MachineIndependent/Versions.cpp
Normal file
161
glslang/MachineIndependent/Versions.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
//
|
||||
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
//All rights reserved.
|
||||
//
|
||||
//Copyright (C) 2012 LunarG, Inc.
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
//
|
||||
// Help manage multiple profiles, versions, extensions etc.
|
||||
//
|
||||
// These don't return error codes, as the presumption is parsing
|
||||
// will always continue as if the feature were present, and there
|
||||
// is no error recovery needed to enable that.
|
||||
//
|
||||
|
||||
#include "ParseHelper.h"
|
||||
|
||||
char* StageName[EShLangCount] = {
|
||||
"vertex",
|
||||
"tessellation control",
|
||||
"tessellation evaluation",
|
||||
"geometry",
|
||||
"fragment"
|
||||
};
|
||||
|
||||
char* ProfileName[EProfileCount] = {
|
||||
"none",
|
||||
"core",
|
||||
"compatibility",
|
||||
"es"
|
||||
};
|
||||
|
||||
//
|
||||
// If only some profiles support a feature, use requireProfile() to specify
|
||||
// which subset allows the feature. If the current profile is not present,
|
||||
// give an error message.
|
||||
//
|
||||
void TParseContext::requireProfile(int line, EProfileMask profileMask, const char *featureDesc)
|
||||
{
|
||||
if (((1 << profile) & profileMask) == 0) {
|
||||
error(line, "not supported with this profile:", featureDesc, ProfileName[profile]);
|
||||
recover();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If only some stages support a feature, use requireStage() to specify
|
||||
// which subset allows the feature. If the current stage is not present,
|
||||
// give an error message.
|
||||
//
|
||||
void TParseContext::requireStage(int line, EShLanguageMask languageMask, const char *featureDesc)
|
||||
{
|
||||
if (((1 << language) & languageMask) == 0) {
|
||||
error(line, "not supported in this stage:", featureDesc, StageName[language]);
|
||||
recover();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Within a profile, if a feature requires a version level or extension, use
|
||||
// ProfileRequires(). This only checks if the current profile matches
|
||||
// the passed-in profile.
|
||||
//
|
||||
|
||||
// one that takes multiple extensions
|
||||
void TParseContext::profileRequires(int line, EProfile callingProfile, int minVersion, int numExtensions, const char* extensions[], const char *featureDesc)
|
||||
{
|
||||
if (profile == callingProfile) {
|
||||
bool okay = false;
|
||||
if (version >= minVersion)
|
||||
okay = true;
|
||||
for (int i = 0; i < numExtensions; ++i) {
|
||||
TBehavior behavior = extensionBehavior[extensions[i]];
|
||||
switch (behavior) {
|
||||
case EBhWarn:
|
||||
infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), line);
|
||||
// fall through
|
||||
case EBhRequire:
|
||||
case EBhEnable:
|
||||
okay = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! okay) {
|
||||
error(line, "not supported for this version or the enabled extensions", featureDesc, "");
|
||||
recover();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// one that takes a single extension
|
||||
void TParseContext::profileRequires(int line, EProfile callingProfile, int minVersion, const char* extension, const char *featureDesc)
|
||||
{
|
||||
profileRequires(line, callingProfile, minVersion, 1, &extension, featureDesc);
|
||||
}
|
||||
|
||||
//
|
||||
// Within a profile, see if a feature is deprecated and error or warn based on whether
|
||||
// a future compatibility context is being use.
|
||||
//
|
||||
void TParseContext::checkDeprecated(int line, EProfile callingProfile, int depVersion, const char *featureDesc)
|
||||
{
|
||||
if (profile == callingProfile) {
|
||||
if (version >= depVersion) {
|
||||
if (futureCompatibility) {
|
||||
error(line, "deprecated, may be removed in future release", featureDesc, "");
|
||||
recover();
|
||||
} else {
|
||||
infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " being used, but may be removed in future release").c_str(), line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Within a profile, see if a feature has now been removed and if so, give an error.
|
||||
// The version argument is the first version no longer having the feature.
|
||||
//
|
||||
void TParseContext::requireNotRemoved(int line, EProfile callingProfile, int removedVersion, const char *featureDesc)
|
||||
{
|
||||
if (profile == callingProfile) {
|
||||
if (version >= removedVersion) {
|
||||
const int maxSize = 60;
|
||||
char buf[maxSize];
|
||||
sprintf_s(buf, maxSize, "%s profile; removed in version %d", ProfileName[profile], removedVersion);
|
||||
error(line, "no longer supported in", featureDesc, buf);
|
||||
recover();
|
||||
}
|
||||
}
|
||||
}
|
||||
59
glslang/MachineIndependent/Versions.h
Normal file
59
glslang/MachineIndependent/Versions.h
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
//All rights reserved.
|
||||
//
|
||||
//Copyright (C) 2012 LunarG, Inc.
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
#ifndef _VERSIONS_INCLUDED_
|
||||
#define _VERSIONS_INCLUDED_
|
||||
|
||||
//
|
||||
// Help manage multiple profiles, versions, extensions etc.
|
||||
//
|
||||
|
||||
typedef enum {
|
||||
ENoProfile, // only for desktop, before profiles showed up
|
||||
ECoreProfile,
|
||||
ECompatibilityProfile,
|
||||
EEsProfile,
|
||||
EProfileCount,
|
||||
} EProfile;
|
||||
|
||||
typedef enum {
|
||||
ENoProfileMask = (1 << ENoProfile),
|
||||
ECoreProfileMask = (1 << ECoreProfile),
|
||||
ECompatibilityProfileMask = (1 << ECompatibilityProfile),
|
||||
EEsProfileMask = (1 << EEsProfile)
|
||||
} EProfileMask;
|
||||
|
||||
#endif // _VERSIONS_INCLUDED_
|
||||
@@ -3,6 +3,8 @@
|
||||
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
//All rights reserved.
|
||||
//
|
||||
//Copyright (C) 2012 LunarG, Inc.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
@@ -568,7 +570,7 @@ void CPPShInfoLogMsg(const char *msg)
|
||||
|
||||
void CPPErrorToInfoLog(char *msg)
|
||||
{
|
||||
((TParseContext *)cpp->pC)->error(yylineno,"syntax error", "",msg,"");
|
||||
((TParseContext *)cpp->pC)->error(yylineno, "CPP error:", "",msg,"");
|
||||
GlobalParseContext->recover();
|
||||
}
|
||||
|
||||
@@ -708,6 +710,48 @@ void ResetTString(void)
|
||||
((TParseContext *)cpp->pC)->HashErrMsg = "";
|
||||
}
|
||||
|
||||
void SetVersion(int version)
|
||||
{
|
||||
((TParseContext *)cpp->pC)->version = version;
|
||||
}
|
||||
|
||||
const int FirstProfileVersion = 150;
|
||||
|
||||
// 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)
|
||||
{
|
||||
int version = ((TParseContext *)cpp->pC)->version;
|
||||
|
||||
if (profile == ENoProfile) {
|
||||
if (version == 100 || version == 300) {
|
||||
CPPErrorToInfoLog("versions 100 and 300 require specifying the es profile");
|
||||
((TParseContext *)cpp->pC)->profile = ENoProfile;
|
||||
} else if (version >= FirstProfileVersion)
|
||||
((TParseContext *)cpp->pC)->profile = ECoreProfile;
|
||||
else
|
||||
((TParseContext *)cpp->pC)->profile = ENoProfile;
|
||||
} else {
|
||||
// a profile was provided...
|
||||
if (version == 100 || version == 300) {
|
||||
if (profile != EEsProfile)
|
||||
CPPErrorToInfoLog("versions 100 and 300 only support the es profile");
|
||||
((TParseContext *)cpp->pC)->profile = EEsProfile;
|
||||
} else {
|
||||
if (profile == EEsProfile) {
|
||||
CPPErrorToInfoLog("only versions 100 and 300 support the es profile");
|
||||
if (version >= FirstProfileVersion)
|
||||
((TParseContext *)cpp->pC)->profile = ECoreProfile;
|
||||
else
|
||||
((TParseContext *)cpp->pC)->profile = ENoProfile;
|
||||
} else {
|
||||
// typical desktop case... e.g., "#version 410 core"
|
||||
((TParseContext *)cpp->pC)->profile = profile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TBehavior GetBehavior(const char* behavior)
|
||||
{
|
||||
if (!strcmp("require", behavior))
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
||||
//All rights reserved.
|
||||
//
|
||||
//Copyright (C) 2012 LunarG, Inc.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
@@ -70,20 +72,6 @@ Jutta Degener, 1995
|
||||
extern void yyerror(char*);
|
||||
#endif
|
||||
|
||||
#define VERTEX_ONLY(S, L) { \
|
||||
if (parseContext.language != EShLangVertex) { \
|
||||
parseContext.error(L, " supported in vertex shaders only ", S, "", ""); \
|
||||
parseContext.recover(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define FRAG_ONLY(S, L) { \
|
||||
if (parseContext.language != EShLangFragment) { \
|
||||
parseContext.error(L, " supported in fragment shaders only ", S, "", "");\
|
||||
parseContext.recover(); \
|
||||
} \
|
||||
}
|
||||
|
||||
%}
|
||||
%union {
|
||||
struct {
|
||||
@@ -384,12 +372,8 @@ postfix_expression
|
||||
// TODO: if next token is not "(", then this is an error
|
||||
|
||||
if (*$3.string == "length") {
|
||||
if (parseContext.extensionErrorCheck($3.line, "GL_3DL_array_objects")) {
|
||||
parseContext.recover();
|
||||
$$ = $1;
|
||||
} else {
|
||||
$$ = parseContext.intermediate.addMethod($1, TType(EbtInt), $3.string, $2.line);
|
||||
}
|
||||
parseContext.profileRequires($3.line, ENoProfile, 120, "GL_3DL_array_objects", ".length");
|
||||
$$ = parseContext.intermediate.addMethod($1, TType(EbtInt), $3.string, $2.line);
|
||||
} else {
|
||||
parseContext.error($3.line, "only the length method is supported for array", $3.string->c_str(), "");
|
||||
parseContext.recover();
|
||||
@@ -695,10 +679,7 @@ function_identifier
|
||||
$$.intermNode = 0;
|
||||
|
||||
if ($1.array) {
|
||||
if (parseContext.extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
|
||||
parseContext.recover();
|
||||
$1.setArray(false);
|
||||
}
|
||||
parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "array");
|
||||
}
|
||||
|
||||
if ($1.userDef) {
|
||||
@@ -966,8 +947,8 @@ equality_expression
|
||||
constUnion *unionArray = new constUnion[1];
|
||||
unionArray->setBConst(false);
|
||||
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
|
||||
} else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects"))
|
||||
parseContext.recover();
|
||||
} else if (($1->isArray() || $3->isArray()))
|
||||
parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "==");
|
||||
}
|
||||
| equality_expression NE_OP relational_expression {
|
||||
$$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, parseContext.symbolTable);
|
||||
@@ -977,8 +958,8 @@ equality_expression
|
||||
constUnion *unionArray = new constUnion[1];
|
||||
unionArray->setBConst(false);
|
||||
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
|
||||
} else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects"))
|
||||
parseContext.recover();
|
||||
} else if (($1->isArray() || $3->isArray()))
|
||||
parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "!=");
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1088,8 +1069,8 @@ assignment_expression
|
||||
parseContext.assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
|
||||
parseContext.recover();
|
||||
$$ = $1;
|
||||
} else if (($1->isArray() || $3->isArray()) && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects"))
|
||||
parseContext.recover();
|
||||
} else if (($1->isArray() || $3->isArray()))
|
||||
parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "=");
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1394,22 +1375,20 @@ init_declarator_list
|
||||
parseContext.recover();
|
||||
}
|
||||
|
||||
if (parseContext.extensionErrorCheck($$.line, "GL_3DL_array_objects"))
|
||||
parseContext.profileRequires($5.line, ENoProfile, 120, "GL_3DL_array_objects", "initializer");
|
||||
|
||||
TIntermNode* intermNode;
|
||||
if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $6, intermNode, variable)) {
|
||||
//
|
||||
// build the intermediate representation
|
||||
//
|
||||
if (intermNode)
|
||||
$$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $5.line);
|
||||
else
|
||||
$$.intermAggregate = $1.intermAggregate;
|
||||
} else {
|
||||
parseContext.recover();
|
||||
else {
|
||||
TIntermNode* intermNode;
|
||||
if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $6, intermNode, variable)) {
|
||||
//
|
||||
// build the intermediate representation
|
||||
//
|
||||
if (intermNode)
|
||||
$$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $5.line);
|
||||
else
|
||||
$$.intermAggregate = $1.intermAggregate;
|
||||
} else {
|
||||
parseContext.recover();
|
||||
$$.intermAggregate = 0;
|
||||
}
|
||||
$$.intermAggregate = 0;
|
||||
}
|
||||
}
|
||||
| init_declarator_list COMMA IDENTIFIER EQUAL initializer {
|
||||
@@ -1492,22 +1471,20 @@ single_declaration
|
||||
parseContext.recover();
|
||||
}
|
||||
|
||||
if (parseContext.extensionErrorCheck($$.line, "GL_3DL_array_objects"))
|
||||
parseContext.recover();
|
||||
else {
|
||||
TIntermNode* intermNode;
|
||||
if (!parseContext.executeInitializer($2.line, *$2.string, $1, $5, intermNode, variable)) {
|
||||
//
|
||||
// Build intermediate representation
|
||||
//
|
||||
if (intermNode)
|
||||
$$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $4.line);
|
||||
else
|
||||
$$.intermAggregate = 0;
|
||||
} else {
|
||||
parseContext.recover();
|
||||
parseContext.profileRequires($4.line, ENoProfile, 120, "GL_3DL_array_objects", "initializer");
|
||||
|
||||
TIntermNode* intermNode;
|
||||
if (!parseContext.executeInitializer($2.line, *$2.string, $1, $5, intermNode, variable)) {
|
||||
//
|
||||
// Build intermediate representation
|
||||
//
|
||||
if (intermNode)
|
||||
$$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $4.line);
|
||||
else
|
||||
$$.intermAggregate = 0;
|
||||
}
|
||||
} else {
|
||||
parseContext.recover();
|
||||
$$.intermAggregate = 0;
|
||||
}
|
||||
}
|
||||
| fully_specified_type IDENTIFIER EQUAL initializer {
|
||||
@@ -1538,17 +1515,13 @@ fully_specified_type
|
||||
$$ = $1;
|
||||
|
||||
if ($1.array) {
|
||||
if (parseContext.extensionErrorCheck($1.line, "GL_3DL_array_objects")) {
|
||||
parseContext.recover();
|
||||
$1.setArray(false);
|
||||
}
|
||||
parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "array");
|
||||
}
|
||||
}
|
||||
| type_qualifier type_specifier {
|
||||
if ($2.array && parseContext.extensionErrorCheck($2.line, "GL_3DL_array_objects")) {
|
||||
parseContext.recover();
|
||||
$2.setArray(false);
|
||||
}
|
||||
if ($2.array)
|
||||
parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "array");
|
||||
|
||||
if ($2.array && parseContext.arrayQualifierErrorCheck($2.line, $1)) {
|
||||
parseContext.recover();
|
||||
$2.setArray(false);
|
||||
@@ -1661,12 +1634,15 @@ storage_qualifier
|
||||
$$.setBasic(EbtVoid, EvqConst, $1.line);
|
||||
}
|
||||
| ATTRIBUTE {
|
||||
VERTEX_ONLY("attribute", $1.line);
|
||||
//parseContext.requireProfile($1.line, (EProfileMask)(ENoProfileMask | ECompatibilityProfileMask), "attribute");
|
||||
parseContext.requireStage($1.line, EShLangVertexMask, "attribute");
|
||||
parseContext.requireNotRemoved($1.line, ECoreProfile, 420, "attribute");
|
||||
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "attribute"))
|
||||
parseContext.recover();
|
||||
$$.setBasic(EbtVoid, EvqAttribute, $1.line);
|
||||
}
|
||||
| VARYING {
|
||||
parseContext.requireNotRemoved($1.line, ECoreProfile, 420, "varying");
|
||||
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying"))
|
||||
parseContext.recover();
|
||||
if (parseContext.language == EShLangVertex)
|
||||
@@ -2162,29 +2138,25 @@ type_specifier_nonarray
|
||||
$$.setBasic(EbtSampler2DShadow, qual, $1.line);
|
||||
}
|
||||
| SAMPLER2DRECT {
|
||||
if (parseContext.extensionErrorCheck($1.line, "GL_ARB_texture_rectangle"))
|
||||
parseContext.recover();
|
||||
parseContext.profileRequires($1.line, ENoProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
|
||||
|
||||
TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
|
||||
$$.setBasic(EbtSamplerRect, qual, $1.line);
|
||||
}
|
||||
| SAMPLER2DRECTSHADOW {
|
||||
if (parseContext.extensionErrorCheck($1.line, "GL_ARB_texture_rectangle"))
|
||||
parseContext.recover();
|
||||
parseContext.profileRequires($1.line, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
|
||||
|
||||
TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
|
||||
$$.setBasic(EbtSamplerRectShadow, qual, $1.line);
|
||||
}
|
||||
| ISAMPLER2DRECT {
|
||||
if (parseContext.extensionErrorCheck($1.line, "GL_ARB_texture_rectangle"))
|
||||
parseContext.recover();
|
||||
parseContext.profileRequires($1.line, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
|
||||
|
||||
TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
|
||||
$$.setBasic(EbtSamplerRect, qual, $1.line);
|
||||
}
|
||||
| USAMPLER2DRECT {
|
||||
if (parseContext.extensionErrorCheck($1.line, "GL_ARB_texture_rectangle"))
|
||||
parseContext.recover();
|
||||
parseContext.profileRequires($1.line, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
|
||||
|
||||
TQualifier qual = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
|
||||
$$.setBasic(EbtSamplerRect, qual, $1.line);
|
||||
@@ -2760,7 +2732,7 @@ jump_statement
|
||||
}
|
||||
}
|
||||
| DISCARD SEMICOLON {
|
||||
FRAG_ONLY("discard", $1.line);
|
||||
parseContext.requireStage($1.line, EShLangFragmentMask, "discard");
|
||||
$$ = parseContext.intermediate.addBranch(EOpKill, $1.line);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -127,10 +127,6 @@ struct CPPStruct_Rec {
|
||||
int PaArgc; // count of strings in the array
|
||||
char** PaArgv; // our array of strings to parse
|
||||
unsigned int tokensBeforeEOF : 1;
|
||||
|
||||
// Declared version of the shader
|
||||
int version;
|
||||
int profileAtom;
|
||||
};
|
||||
|
||||
#endif // !defined(__COMPILE_H)
|
||||
|
||||
@@ -685,18 +685,22 @@ static int CPPversion(yystypepp * yylvalpp)
|
||||
|
||||
yylvalpp->sc_int=atoi(yylvalpp->symbol_name);
|
||||
|
||||
cpp->version = yylvalpp->sc_int;
|
||||
SetVersion(yylvalpp->sc_int);
|
||||
|
||||
token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
|
||||
|
||||
if (token == '\n'){
|
||||
if (token == '\n') {
|
||||
SetProfile(ENoProfile);
|
||||
return token;
|
||||
}
|
||||
else{
|
||||
cpp->profileAtom = yylvalpp->sc_ident;
|
||||
if (cpp->profileAtom != coreAtom &&
|
||||
cpp->profileAtom != compatibilityAtom &&
|
||||
cpp->profileAtom != esAtom)
|
||||
else {
|
||||
if (yylvalpp->sc_ident == coreAtom)
|
||||
SetProfile(ECoreProfile);
|
||||
else if (yylvalpp->sc_ident == compatibilityAtom)
|
||||
SetProfile(ECompatibilityProfile);
|
||||
else if (yylvalpp->sc_ident == esAtom)
|
||||
SetProfile(EEsProfile);
|
||||
else
|
||||
CPPErrorToInfoLog("#version profile name");
|
||||
|
||||
token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
|
||||
|
||||
@@ -83,6 +83,7 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "parser.h"
|
||||
#include "tokens.h"
|
||||
#include "Versions.h"
|
||||
|
||||
int InitCPP(void);
|
||||
int FinalCPP(void);
|
||||
@@ -113,6 +114,8 @@ void SetStringNumber(int); // Set string number.
|
||||
int GetLineNumber(void); // Get the current String Number.
|
||||
int GetStringNumber(void); // Get the current String Number.
|
||||
const char* GetStrfromTStr(void); // Convert TString to String.
|
||||
void SetVersion(int);
|
||||
void SetProfile(EProfile);
|
||||
void updateExtensionBehavior(const char* extName, const char* behavior);
|
||||
int FreeCPP(void);
|
||||
|
||||
|
||||
@@ -132,8 +132,6 @@ int ResetPreprocessor(void)
|
||||
cpp->elsedepth[cpp->elsetracker]=0;
|
||||
cpp->elsetracker=0;
|
||||
cpp->tokensBeforeEOF = 0;
|
||||
cpp->version = 110;
|
||||
cpp->profileAtom = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,10 +71,23 @@ SH_IMPORT_EXPORT int __fastcall ShFinalize();
|
||||
//
|
||||
typedef enum {
|
||||
EShLangVertex,
|
||||
EShLangTessControl,
|
||||
EShLangTessEvaluation,
|
||||
EShLangGeometry,
|
||||
EShLangFragment,
|
||||
EShLangCount,
|
||||
} EShLanguage;
|
||||
|
||||
typedef enum {
|
||||
EShLangVertexMask = (1 << EShLangVertex),
|
||||
EShLangTessControlMask = (1 << EShLangTessControl),
|
||||
EShLangTessEvaluationMask = (1 << EShLangTessEvaluation),
|
||||
EShLangGeometryMask = (1 << EShLangGeometry),
|
||||
EShLangFragmentMask = (1 << EShLangFragment),
|
||||
} EShLanguageMask;
|
||||
|
||||
extern char* StageName[EShLangCount];
|
||||
|
||||
//
|
||||
// Types of output the linker will create.
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user