Commit bd0747d6 by John Kessenich

Built-in symbol tables now lazily evaluated, and driven by per version, per…

Built-in symbol tables now lazily evaluated, and driven by per version, per profile input. Got all ES 100 and ES 300 built-in symbols correct. This includes - doing prescan of shader to know version/profile before parsing it - putting precision qualifiers on built-in ES symbols - getting most built-in state correct for core/compatibility/missing profile - adding gl_VertexID and gl_InstanceID, among other ES 300 built-in symbols - adding the ES 300 gl_Max/Min constants - accepting shaders that contain nothing but whitespace without generating an error git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@20627 e7fa87d3-cd2b-0410-9028-fcbf551c1848
parent fb5f7ead
// //
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. //Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
//Copyright (C) 2013 LunarG, Inc.
//
//All rights reserved. //All rights reserved.
// //
//Redistribution and use in source and binary forms, with or without //Redistribution and use in source and binary forms, with or without
...@@ -99,6 +101,12 @@ void GenerateResources(TBuiltInResource& resources) ...@@ -99,6 +101,12 @@ void GenerateResources(TBuiltInResource& resources)
resources.maxTextureImageUnits = 32; resources.maxTextureImageUnits = 32;
resources.maxFragmentUniformComponents = 4096; resources.maxFragmentUniformComponents = 4096;
resources.maxDrawBuffers = 32; resources.maxDrawBuffers = 32;
resources.maxVertexUniformVectors = 128;
resources.maxVaryingVectors = 8;
resources.maxFragmentUniformVectors = 16;
resources.maxVertexOutputVectors = 16;
resources.minProgramTexelOffset = -8;
resources.maxProgramTexelOffset = 7;
} }
int C_DECL main(int argc, char* argv[]) int C_DECL main(int argc, char* argv[])
......
//
/* anotehn t* ontuh * / tnoahnt /* oo */
/* multi line...
ao */
/* no escape \
oanot */
// escape nothing \o oeu
// escape newline \
still in a comment
precision mediump float; precision highp float;
uniform sampler2D sampler; uniform sampler2D sampler;
......
...@@ -18,4 +18,5 @@ cppNest.vert ...@@ -18,4 +18,5 @@ cppNest.vert
cppComplexExpr.vert cppComplexExpr.vert
pointCoord.frag pointCoord.frag
array.frag array.frag
array100.frag array100.frag
\ No newline at end of file comment.frag
...@@ -86,6 +86,10 @@ enum TStorageQualifier { ...@@ -86,6 +86,10 @@ enum TStorageQualifier {
EvqInOut, EvqInOut,
EvqConstReadOnly, EvqConstReadOnly,
// built-ins read by vertex shader
EvqVertexId,
EvqInstanceId,
// built-ins written by vertex shader // built-ins written by vertex shader
EvqPosition, EvqPosition,
EvqPointSize, EvqPointSize,
...@@ -119,6 +123,8 @@ __inline const char* getStorageQualifierString(TStorageQualifier q) ...@@ -119,6 +123,8 @@ __inline const char* getStorageQualifierString(TStorageQualifier q)
case EvqIn: return "in"; break; case EvqIn: return "in"; break;
case EvqOut: return "out"; break; case EvqOut: return "out"; break;
case EvqInOut: return "inout"; break; case EvqInOut: return "inout"; break;
case EvqVertexId: return "gl_VertexId"; break;
case EvqInstanceId: return "gl_InstanceId"; break;
case EvqPosition: return "gl_Position"; break; case EvqPosition: return "gl_Position"; break;
case EvqPointSize: return "gl_PointSize"; break; case EvqPointSize: return "gl_PointSize"; break;
case EvqClipVertex: return "gl_ClipVertex"; break; case EvqClipVertex: return "gl_ClipVertex"; break;
......
...@@ -257,7 +257,7 @@ struct TThreadGlobalPools ...@@ -257,7 +257,7 @@ struct TThreadGlobalPools
TPoolAllocator* globalPoolAllocator; TPoolAllocator* globalPoolAllocator;
}; };
void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator); void SetGlobalPoolAllocatorPtr(TPoolAllocator& poolAllocator);
// //
// This STL compatible allocator is intended to be used as the allocator // This STL compatible allocator is intended to be used as the allocator
......
// //
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. //Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
//Copyright (C) 2013 LunarG, Inc.
//
//All rights reserved. //All rights reserved.
// //
//Redistribution and use in source and binary forms, with or without //Redistribution and use in source and binary forms, with or without
...@@ -48,5 +50,11 @@ struct TBuiltInResource { ...@@ -48,5 +50,11 @@ struct TBuiltInResource {
int maxTextureImageUnits; int maxTextureImageUnits;
int maxFragmentUniformComponents; int maxFragmentUniformComponents;
int maxDrawBuffers; int maxDrawBuffers;
int maxVertexUniformVectors;
int maxVaryingVectors;
int maxFragmentUniformVectors;
int maxVertexOutputVectors;
int minProgramTexelOffset;
int maxProgramTexelOffset;
}; };
#endif // _RESOURCE_LIMITS_INCLUDED_ #endif // _RESOURCE_LIMITS_INCLUDED_
...@@ -155,6 +155,15 @@ public: ...@@ -155,6 +155,15 @@ public:
qualifier.storage = q; qualifier.storage = q;
qualifier.precision = EpqNone; qualifier.precision = EpqNone;
} }
TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0) :
type(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0),
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
fieldName(0), mangled(0), typeName(0)
{
qualifier.storage = q;
qualifier.precision = p;
assert(p >= 0 && p <= EpqHigh);
}
explicit TType(const TPublicType &p) : explicit TType(const TPublicType &p) :
type(p.type), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), arraySizes(p.arraySizes), type(p.type), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), arraySizes(p.arraySizes),
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0) structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
......
// //
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd. //Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
//Copyright (C) 2013 LunarG, Inc.
//
//All rights reserved. //All rights reserved.
// //
//Redistribution and use in source and binary forms, with or without //Redistribution and use in source and binary forms, with or without
...@@ -39,23 +41,22 @@ ...@@ -39,23 +41,22 @@
#include "../Include/Common.h" #include "../Include/Common.h"
#include "../Include/ShHandle.h" #include "../Include/ShHandle.h"
#include "SymbolTable.h" #include "SymbolTable.h"
#include "Versions.h"
typedef TVector<TString> TBuiltInStrings; typedef TVector<TString> TBuiltInStrings;
class TBuiltIns { class TBuiltIns {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
void initialize(); void initialize(int version, EProfile);
void initialize(const TBuiltInResource& resources); void initialize(const TBuiltInResource& resources, int version, EProfile, EShLanguage);
TBuiltInStrings* getBuiltInStrings() { return builtInStrings; } TBuiltInStrings* getBuiltInStrings() { return builtInStrings; }
protected: protected:
TBuiltInStrings builtInStrings[EShLangCount]; TBuiltInStrings builtInStrings[EShLangCount];
}; };
void IdentifyBuiltIns(EShLanguage, TSymbolTable&); void IdentifyBuiltIns(int version, EProfile profile, EShLanguage, TSymbolTable&);
void IdentifyBuiltIns(EShLanguage, TSymbolTable&, const TBuiltInResource &resources); void IdentifyBuiltIns(int version, EProfile profile, EShLanguage, TSymbolTable&, const TBuiltInResource &resources);
bool GenerateBuiltInSymbolTable(const TBuiltInResource* resources, TInfoSink&, TSymbolTable*, EShLanguage language = EShLangCount);
bool InitializeSymbolTable(TBuiltInStrings* BuiltInStrings, EShLanguage language, TInfoSink& infoSink, const TBuiltInResource *resources, TSymbolTable*);
extern "C" int InitPreprocessor(void); extern "C" int InitPreprocessor(void);
extern "C" int FinalizePreprocessor(void); extern "C" int FinalizePreprocessor(void);
......
...@@ -38,94 +38,42 @@ ...@@ -38,94 +38,42 @@
#include "Include/InitializeParseContext.h" #include "Include/InitializeParseContext.h"
#include "osinclude.h" #include "osinclude.h"
#include <stdarg.h> #include <stdarg.h>
///////////////////////////////////////////////////////////////////////
//
// Sub- vector and matrix fields
//
////////////////////////////////////////////////////////////////////////
TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, EShLanguage L, TInfoSink& is, int defaultVersion) : TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, EProfile p, EShLanguage L, TInfoSink& is) :
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),
futureCompatibility(false), version(v), profile(p), futureCompatibility(false),
contextPragma(true, 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) for (int type = 0; type < EbtNumTypes; ++type)
defaultPrecision[type] = EpqNone; defaultPrecision[type] = EpqNone;
setVersion(defaultVersion); if (profile == EEsProfile) {
setProfile(ENoProfile); switch (language) {
} case EShLangVertex:
defaultPrecision[EbtInt] = EpqHigh;
void TParseContext::setVersion(int newVersion) defaultPrecision[EbtFloat] = EpqHigh;
{ defaultPrecision[EbtSampler2D] = EpqLow;
version = newVersion; defaultPrecision[EbtSamplerCube] = EpqLow;
if (version == 100 || version == 300) { break;
if (language == EShLangVertex) { case EShLangFragment:
defaultPrecision[EbtInt] = EpqHigh; defaultPrecision[EbtInt] = EpqMedium;
defaultPrecision[EbtFloat] = EpqHigh; defaultPrecision[EbtSampler2D] = EpqLow;
defaultPrecision[EbtSampler2D] = EpqLow; defaultPrecision[EbtSamplerCube] = EpqLow;
defaultPrecision[EbtSamplerCube] = EpqLow;
}
if (language == EShLangFragment) {
defaultPrecision[EbtInt] = EpqMedium;
defaultPrecision[EbtSampler2D] = EpqLow;
defaultPrecision[EbtSamplerCube] = EpqLow;
// TODO: give error when using float in frag shader without default precision // TODO: give error when using float in frag shader without default precision
break;
default:
error(1, "INTERNAL ERROR", "unexpected language", "");
} }
} else {
for (int type = 0; type < EbtNumTypes; ++type)
defaultPrecision[type] = EpqNone;
} }
} }
// 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) // Sub- vector and matrix fields
{ //
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;
}
}
}
}
// //
// Look at a '.' field selector string and change it into offsets // Look at a '.' field selector string and change it into offsets
...@@ -380,6 +328,8 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod ...@@ -380,6 +328,8 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod
case EvqAttribute: message = "can't modify an attribute"; break; case EvqAttribute: message = "can't modify an attribute"; break;
case EvqUniform: message = "can't modify a uniform"; break; case EvqUniform: message = "can't modify a uniform"; break;
case EvqVaryingIn: message = "can't modify a varying"; break; case EvqVaryingIn: message = "can't modify a varying"; break;
case EvqInstanceId: message = "can't modify gl_InstanceID"; break;
case EvqVertexId: message = "can't modify gl_VertexID"; break;
case EvqFace: message = "can't modify gl_FrontFace"; break; case EvqFace: message = "can't modify gl_FrontFace"; break;
case EvqFragCoord: message = "can't modify gl_FragCoord"; break; case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
case EvqPointCoord: message = "can't modify gl_PointCoord"; break; case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
...@@ -767,9 +717,10 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel() ...@@ -767,9 +717,10 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel()
{ {
TString *name = NewPoolTString("gl_TexCoord"); TString *name = NewPoolTString("gl_TexCoord");
TSymbol* symbol = symbolTable.find(*name); TSymbol* symbol = symbolTable.find(*name);
if (!symbol) { if (! symbol) {
error(0, "INTERNAL ERROR finding symbol", name->c_str(), ""); // assume it was not added due to version/profile
return true;
return false;
} }
TVariable* variable = symbol->getAsVariable(); TVariable* variable = symbol->getAsVariable();
......
...@@ -67,9 +67,9 @@ struct TPragma { ...@@ -67,9 +67,9 @@ 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, int defaultVersion); TParseContext(TSymbolTable&, TIntermediate&, int version, EProfile, EShLanguage, TInfoSink&);
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 current language, version, and profile
TInfoSink& infoSink; TInfoSink& infoSink;
EShLanguage language; // vertex or fragment language EShLanguage language; // vertex or fragment language
TIntermNode* treeRoot; // root of parse tree being created TIntermNode* treeRoot; // root of parse tree being created
...@@ -92,9 +92,6 @@ struct TParseContext { ...@@ -92,9 +92,6 @@ 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,
......
...@@ -52,8 +52,7 @@ void InitializeGlobalPools() ...@@ -52,8 +52,7 @@ void InitializeGlobalPools()
threadData->globalPoolAllocator = globalPoolAllocator; threadData->globalPoolAllocator = globalPoolAllocator;
OS_SetTLSValue(PoolIndex, threadData); OS_SetTLSValue(PoolIndex, threadData);
globalPoolAllocator->push();
} }
void FreeGlobalPools() void FreeGlobalPools()
...@@ -90,11 +89,11 @@ TPoolAllocator& GetGlobalPoolAllocator() ...@@ -90,11 +89,11 @@ TPoolAllocator& GetGlobalPoolAllocator()
return *threadData->globalPoolAllocator; return *threadData->globalPoolAllocator;
} }
void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator) void SetGlobalPoolAllocatorPtr(TPoolAllocator& poolAllocator)
{ {
TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex)); TThreadGlobalPools* threadData = static_cast<TThreadGlobalPools*>(OS_GetTLSValue(PoolIndex));
threadData->globalPoolAllocator = poolAllocator; threadData->globalPoolAllocator = &poolAllocator;
} }
// //
...@@ -143,6 +142,8 @@ TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignm ...@@ -143,6 +142,8 @@ TPoolAllocator::TPoolAllocator(bool g, int growthIncrement, int allocationAlignm
if (headerSkip < sizeof(tHeader)) { if (headerSkip < sizeof(tHeader)) {
headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
} }
push();
} }
TPoolAllocator::~TPoolAllocator() TPoolAllocator::~TPoolAllocator()
......
...@@ -479,14 +479,14 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon ...@@ -479,14 +479,14 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
return 1; return 1;
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
if (!argv[i]) { if (! argv[i]) {
parseContextLocal.error(0, "Null shader source string", "", ""); parseContextLocal.error(0, "Null shader source string", "", "");
parseContextLocal.recover(); parseContextLocal.recover();
return 1; return 1;
} }
} }
if (!strLen) { if (! strLen) {
argv0len = (int) strlen(argv[0]); argv0len = (int) strlen(argv[0]);
strLen = &argv0len; strLen = &argv0len;
} }
...@@ -499,7 +499,16 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon ...@@ -499,7 +499,16 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
cpp->notAVersionToken = 0; cpp->notAVersionToken = 0;
yylineno = 1; yylineno = 1;
if (*cpp->PaStrLen >= 0) { // TODO: CPP: a shader containing nothing but white space and comments is valid, even though it has no parse tokens
int len = 0;
while (argv[0][len] == ' ' ||
argv[0][len] == '\t' ||
argv[0][len] == '\n' ||
argv[0][len] == '\r')
if (++len >= strLen[0])
return 0;
if (*cpp->PaStrLen > 0) {
int ret; int ret;
#ifdef _WIN32 #ifdef _WIN32
ret = yyparse(parseContextLocal); ret = yyparse(parseContextLocal);
...@@ -510,8 +519,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon ...@@ -510,8 +519,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
return 1; return 1;
else else
return 0; return 0;
} } else
else
return 0; return 0;
} }
...@@ -838,14 +846,18 @@ void ResetTString(void) ...@@ -838,14 +846,18 @@ void ResetTString(void)
void SetVersion(int version) void SetVersion(int version)
{ {
TParseContext& pc = *((TParseContext *)cpp->pC); // called by the CPP, but this functionality is currently
pc.setVersion(version); // taken over by ScanVersion() before parsing starts
// CPP should still report errors in semantics
} }
void SetProfile(EProfile profile) void SetProfile(EProfile profile)
{ {
TParseContext& pc = *((TParseContext *)cpp->pC); // called by the CPP, but this functionality is currently
pc.setProfile(profile); // taken over by ScanVersion() before parsing starts
// CPP should still report errors in semantics
} }
TBehavior GetBehavior(const char* behavior) TBehavior GetBehavior(const char* behavior)
......
...@@ -78,6 +78,8 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -78,6 +78,8 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// cpp.c // cpp.c
// //
// TODO: CPP handle escaped newlines in a // style comment, correctly done in ConsumeWhitespaceComment()
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#include <stdarg.h> #include <stdarg.h>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment