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) 2013 LunarG, Inc.
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
......@@ -99,6 +101,12 @@ void GenerateResources(TBuiltInResource& resources)
resources.maxTextureImageUnits = 32;
resources.maxFragmentUniformComponents = 4096;
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[])
......
//
/* 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;
......
......@@ -18,4 +18,5 @@ cppNest.vert
cppComplexExpr.vert
pointCoord.frag
array.frag
array100.frag
\ No newline at end of file
array100.frag
comment.frag
......@@ -86,6 +86,10 @@ enum TStorageQualifier {
EvqInOut,
EvqConstReadOnly,
// built-ins read by vertex shader
EvqVertexId,
EvqInstanceId,
// built-ins written by vertex shader
EvqPosition,
EvqPointSize,
......@@ -119,6 +123,8 @@ __inline const char* getStorageQualifierString(TStorageQualifier q)
case EvqIn: return "in"; break;
case EvqOut: return "out"; 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 EvqPointSize: return "gl_PointSize"; break;
case EvqClipVertex: return "gl_ClipVertex"; break;
......
......@@ -257,7 +257,7 @@ struct TThreadGlobalPools
TPoolAllocator* globalPoolAllocator;
};
void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator);
void SetGlobalPoolAllocatorPtr(TPoolAllocator& poolAllocator);
//
// This STL compatible allocator is intended to be used as the allocator
......
//
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
//Copyright (C) 2013 LunarG, Inc.
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
......@@ -48,5 +50,11 @@ struct TBuiltInResource {
int maxTextureImageUnits;
int maxFragmentUniformComponents;
int maxDrawBuffers;
int maxVertexUniformVectors;
int maxVaryingVectors;
int maxFragmentUniformVectors;
int maxVertexOutputVectors;
int minProgramTexelOffset;
int maxProgramTexelOffset;
};
#endif // _RESOURCE_LIMITS_INCLUDED_
......@@ -155,6 +155,15 @@ public:
qualifier.storage = q;
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) :
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)
......
//
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
//Copyright (C) 2013 LunarG, Inc.
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
......@@ -39,23 +41,22 @@
#include "../Include/Common.h"
#include "../Include/ShHandle.h"
#include "SymbolTable.h"
#include "Versions.h"
typedef TVector<TString> TBuiltInStrings;
class TBuiltIns {
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
void initialize();
void initialize(const TBuiltInResource& resources);
void initialize(int version, EProfile);
void initialize(const TBuiltInResource& resources, int version, EProfile, EShLanguage);
TBuiltInStrings* getBuiltInStrings() { return builtInStrings; }
protected:
TBuiltInStrings builtInStrings[EShLangCount];
};
void IdentifyBuiltIns(EShLanguage, TSymbolTable&);
void IdentifyBuiltIns(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*);
void IdentifyBuiltIns(int version, EProfile profile, EShLanguage, TSymbolTable&);
void IdentifyBuiltIns(int version, EProfile profile, EShLanguage, TSymbolTable&, const TBuiltInResource &resources);
extern "C" int InitPreprocessor(void);
extern "C" int FinalizePreprocessor(void);
......
......@@ -38,94 +38,42 @@
#include "Include/InitializeParseContext.h"
#include "osinclude.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),
recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
switchNestingLevel(0), inTypeParen(false),
futureCompatibility(false),
version(v), profile(p), 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;
if (profile == EEsProfile) {
switch (language) {
case EShLangVertex:
defaultPrecision[EbtInt] = EpqHigh;
defaultPrecision[EbtFloat] = EpqHigh;
defaultPrecision[EbtSampler2D] = EpqLow;
defaultPrecision[EbtSamplerCube] = EpqLow;
break;
case EShLangFragment:
defaultPrecision[EbtInt] = EpqMedium;
defaultPrecision[EbtSampler2D] = EpqLow;
defaultPrecision[EbtSamplerCube] = EpqLow;
// 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)
{
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;
}
}
}
}
///////////////////////////////////////////////////////////////////////
//
// Sub- vector and matrix fields
//
////////////////////////////////////////////////////////////////////////
//
// 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
case EvqAttribute: message = "can't modify an attribute"; break;
case EvqUniform: message = "can't modify a uniform"; 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 EvqFragCoord: message = "can't modify gl_FragCoord"; break;
case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
......@@ -767,9 +717,10 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel()
{
TString *name = NewPoolTString("gl_TexCoord");
TSymbol* symbol = symbolTable.find(*name);
if (!symbol) {
error(0, "INTERNAL ERROR finding symbol", name->c_str(), "");
return true;
if (! symbol) {
// assume it was not added due to version/profile
return false;
}
TVariable* variable = symbol->getAsVariable();
......
......@@ -67,9 +67,9 @@ struct TPragma {
// they can be passed to the parser without needing a global.
//
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
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;
EShLanguage language; // vertex or fragment language
TIntermNode* treeRoot; // root of parse tree being created
......@@ -92,9 +92,6 @@ 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,
......
......@@ -52,8 +52,7 @@ void InitializeGlobalPools()
threadData->globalPoolAllocator = globalPoolAllocator;
OS_SetTLSValue(PoolIndex, threadData);
globalPoolAllocator->push();
OS_SetTLSValue(PoolIndex, threadData);
}
void FreeGlobalPools()
......@@ -90,11 +89,11 @@ TPoolAllocator& GetGlobalPoolAllocator()
return *threadData->globalPoolAllocator;
}
void SetGlobalPoolAllocatorPtr(TPoolAllocator* poolAllocator)
void SetGlobalPoolAllocatorPtr(TPoolAllocator& poolAllocator)
{
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
if (headerSkip < sizeof(tHeader)) {
headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
}
push();
}
TPoolAllocator::~TPoolAllocator()
......
......@@ -479,14 +479,14 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
return 1;
for (int i = 0; i < argc; ++i) {
if (!argv[i]) {
if (! argv[i]) {
parseContextLocal.error(0, "Null shader source string", "", "");
parseContextLocal.recover();
return 1;
}
}
if (!strLen) {
if (! strLen) {
argv0len = (int) strlen(argv[0]);
strLen = &argv0len;
}
......@@ -499,7 +499,16 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
cpp->notAVersionToken = 0;
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;
#ifdef _WIN32
ret = yyparse(parseContextLocal);
......@@ -510,8 +519,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
return 1;
else
return 0;
}
else
} else
return 0;
}
......@@ -838,14 +846,18 @@ void ResetTString(void)
void SetVersion(int version)
{
TParseContext& pc = *((TParseContext *)cpp->pC);
pc.setVersion(version);
// called by the CPP, but this functionality is currently
// taken over by ScanVersion() before parsing starts
// CPP should still report errors in semantics
}
void SetProfile(EProfile profile)
{
TParseContext& pc = *((TParseContext *)cpp->pC);
pc.setProfile(profile);
// called by the CPP, but this functionality is currently
// taken over by ScanVersion() before parsing starts
// CPP should still report errors in semantics
}
TBehavior GetBehavior(const char* behavior)
......
......@@ -78,6 +78,8 @@ NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// cpp.c
//
// TODO: CPP handle escaped newlines in a // style comment, correctly done in ConsumeWhitespaceComment()
#define _CRT_SECURE_NO_WARNINGS
#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