Add grammar productions for adding 'invariant' to already declared variables.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22083 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-06-19 20:44:17 +00:00
parent 41a36bbb2f
commit 60d9f7a881
6 changed files with 60 additions and 12 deletions

View File

@ -8,8 +8,9 @@ attribute vec4 attv4;
uniform sampler2D s2D; uniform sampler2D s2D;
invariant varying vec2 centTexCoord; invariant varying vec2 centTexCoord;
invariant gl_Position; invariant gl_Position;
centroid gl_Position;
centroid centroid foo; centroid centroid foo;
invariant gl_Position, gl_PointSize;
void main() void main()
{ {
@ -22,6 +23,8 @@ void main()
float f[]; float f[];
int a = f.length(); int a = f.length();
gl_PointSize = 3.8;
} }
uniform float initted = 3.4; uniform float initted = 3.4;

View File

@ -97,8 +97,8 @@ layout (binding=3) uniform atomic_uint c2; // offset = 8
layout (binding=2) uniform atomic_uint d2; // offset = 4 layout (binding=2) uniform atomic_uint d2; // offset = 4
//layout (offset=4) // error, must include binding //layout (offset=4) // error, must include binding
layout (binding=1, offset=0) a; // okay //layout (binding=1, offset=0) a; // okay
layout (binding=2, offset=0) b; // okay //layout (binding=2, offset=0) b; // okay
//layout (binding=1, offset=0) c; // error, offsets must not be shared //layout (binding=1, offset=0) c; // error, offsets must not be shared
// // between a and c // // between a and c
//layout (binding=1, offset=2) d; // error, overlaps offset 0 of a //layout (binding=1, offset=2) d; // error, overlaps offset 0 of a

View File

@ -154,6 +154,14 @@ inline TTypeList* NewPoolTTypeList()
return new(memory) TTypeList; return new(memory) TTypeList;
} }
typedef TVector<TString*> TIdentifierList;
inline TIdentifierList* NewPoolTIdentifierList()
{
void* memory = GlobalPoolAllocator.allocate(sizeof(TIdentifierList));
return new(memory) TIdentifierList;
}
// //
// TODO: memory: TArraySizes can be replaced by something smaller. // TODO: memory: TArraySizes can be replaced by something smaller.
// Almost all arrays could be handled by two sizes each fitting // Almost all arrays could be handled by two sizes each fitting
@ -236,7 +244,7 @@ public:
bool isMemory() const bool isMemory() const
{ {
return coherent || volatil || restrict || readonly || writeonly; return shared || coherent || volatil || restrict || readonly || writeonly;
} }
bool isInterpolation() const bool isInterpolation() const
{ {

View File

@ -48,12 +48,15 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, E
version(v), profile(p), forwardCompatible(fc), messages(m), version(v), profile(p), forwardCompatible(fc), messages(m),
contextPragma(true, false) contextPragma(true, false)
{ {
// set all precision defaults to EpqNone, which is correct for all desktop types
// and for ES types that don't have defaults (thus getting an error on use)
for (int type = 0; type < EbtNumTypes; ++type) for (int type = 0; type < EbtNumTypes; ++type)
defaultPrecision[type] = EpqNone; defaultPrecision[type] = EpqNone;
for (int type = 0; type < maxSamplerIndex; ++type) for (int type = 0; type < maxSamplerIndex; ++type)
defaultSamplerPrecision[type] = EpqNone; defaultSamplerPrecision[type] = EpqNone;
// replace with real defaults for those that have them
if (profile == EEsProfile) { if (profile == EEsProfile) {
TSampler sampler; TSampler sampler;
sampler.set(EbtFloat, Esd2D); sampler.set(EbtFloat, Esd2D);
@ -67,13 +70,11 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, E
defaultPrecision[EbtUint] = EpqHigh; defaultPrecision[EbtUint] = EpqHigh;
defaultPrecision[EbtFloat] = EpqHigh; defaultPrecision[EbtFloat] = EpqHigh;
defaultPrecision[EbtSampler] = EpqLow; defaultPrecision[EbtSampler] = EpqLow;
// TODO: functionality: need default precisions per sampler type
break; break;
case EShLangFragment: case EShLangFragment:
defaultPrecision[EbtInt] = EpqMedium; defaultPrecision[EbtInt] = EpqMedium;
defaultPrecision[EbtUint] = EpqMedium; defaultPrecision[EbtUint] = EpqMedium;
defaultPrecision[EbtSampler] = EpqLow; defaultPrecision[EbtSampler] = EpqLow;
// TODO: semantics: give error when using float in frag shader without default precision
break; break;
default: default:
error(1, "INTERNAL ERROR", "unexpected language", ""); error(1, "INTERNAL ERROR", "unexpected language", "");
@ -1607,6 +1608,36 @@ void TParseContext::addBlock(int line, TTypeList& typeList, const TString* insta
} }
} }
// For an identifier that is already declared, add more qualification to it.
void TParseContext::addQualifierToExisting(int line, TQualifier qualifier, const TString& identifier)
{
TSymbol* existing = symbolTable.find(identifier);
TVariable* variable = existing ? existing->getAsVariable() : 0;
if (! variable) {
error(line, "identifier not previously declared", identifier.c_str(), "");
return;
}
if (qualifier.isAuxillary() ||
qualifier.isMemory() ||
qualifier.isInterpolation() ||
qualifier.storage != EvqTemporary ||
qualifier.precision != EpqNone) {
error(line, "cannot add this qualifier to an existing variable", identifier.c_str(), "");
return;
}
variable->getType().getQualifier().invariant = true;
}
void TParseContext::addQualifierToExisting(int line, TQualifier qualifier, TIdentifierList& identifiers)
{
for (unsigned int i = 0; i < identifiers.size(); ++i)
addQualifierToExisting(line, qualifier, *identifiers[i]);
}
// //
// Take the sequence of statements that has been built up since the last case/default, // Take the sequence of statements that has been built up since the last case/default,
// put it on the list of top-level nodes for the current (inner-most) switch statement, // put it on the list of top-level nodes for the current (inner-most) switch statement,

View File

@ -154,6 +154,8 @@ struct TParseContext {
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc); TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
void addBlock(int line, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0); void addBlock(int line, TTypeList& typeList, const TString* instanceName = 0, TArraySizes arraySizes = 0);
void addQualifierToExisting(int line, TQualifier, const TString& identifier);
void addQualifierToExisting(int line, TQualifier, TIdentifierList&);
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
TIntermNode* addSwitch(int line, TIntermTyped* expression, TIntermAggregate* body); TIntermNode* addSwitch(int line, TIntermTyped* expression, TIntermAggregate* body);
void updateDefaults(int line, const TPublicType&, const TString* id); void updateDefaults(int line, const TPublicType&, const TString* id);

View File

@ -103,6 +103,7 @@ extern void yyerror(const char*);
TTypeLine typeLine; TTypeLine typeLine;
TTypeList* typeList; TTypeList* typeList;
TArraySizes arraySizes; TArraySizes arraySizes;
TIdentifierList* identifierList;
}; };
} interm; } interm;
} }
@ -214,6 +215,8 @@ extern void yyerror(const char*);
%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype %type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
%type <interm> function_call_or_method function_identifier function_call_header %type <interm> function_call_or_method function_identifier function_call_header
%type <interm.identifierList> identifier_list
%start translation_unit %start translation_unit
%% %%
@ -1120,15 +1123,12 @@ declaration
$$ = 0; $$ = 0;
} }
| type_qualifier IDENTIFIER SEMICOLON { | type_qualifier IDENTIFIER SEMICOLON {
// TODO: functionality: track what variables are declared with INVARIANT parseContext.addQualifierToExisting($1.line, $1.qualifier, *$2.string);
// precise foo;
// invariant foo;
$$ = 0; $$ = 0;
} }
| type_qualifier IDENTIFIER identifier_list SEMICOLON { | type_qualifier IDENTIFIER identifier_list SEMICOLON {
// TODO: functionality: track what variables are declared with INVARIANT $3->push_back($2.string);
// precise foo, bar; parseContext.addQualifierToExisting($1.line, $1.qualifier, *$3);
// invariant foo, bar;
$$ = 0; $$ = 0;
} }
; ;
@ -1144,8 +1144,12 @@ block_structure
identifier_list identifier_list
: COMMA IDENTIFIER { : COMMA IDENTIFIER {
$$ = NewPoolTIdentifierList();
$$->push_back($2.string);
} }
| identifier_list COMMA IDENTIFIER { | identifier_list COMMA IDENTIFIER {
$$ = $1;
$$->push_back($3.string);
} }
; ;