uniform sampler2D s2D;
invariant varying vec2 centTexCoord;
invariant gl_Position;
-
+centroid gl_Position;
centroid centroid foo;
+invariant gl_Position, gl_PointSize;
void main()
{
float f[];
int a = f.length();
+
+ gl_PointSize = 3.8;
}
uniform float initted = 3.4;
layout (binding=2) uniform atomic_uint d2; // offset = 4\r
\r
//layout (offset=4) // error, must include binding\r
-layout (binding=1, offset=0) a; // okay\r
-layout (binding=2, offset=0) b; // okay\r
+//layout (binding=1, offset=0) a; // okay\r
+//layout (binding=2, offset=0) b; // okay\r
//layout (binding=1, offset=0) c; // error, offsets must not be shared\r
// // between a and c\r
//layout (binding=1, offset=2) d; // error, overlaps offset 0 of a\r
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.
// Almost all arrays could be handled by two sizes each fitting
bool isMemory() const
{
- return coherent || volatil || restrict || readonly || writeonly;
+ return shared || coherent || volatil || restrict || readonly || writeonly;
}
bool isInterpolation() const
{
version(v), profile(p), forwardCompatible(fc), messages(m),
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)
defaultPrecision[type] = EpqNone;
for (int type = 0; type < maxSamplerIndex; ++type)
defaultSamplerPrecision[type] = EpqNone;
+ // replace with real defaults for those that have them
if (profile == EEsProfile) {
TSampler sampler;
sampler.set(EbtFloat, Esd2D);
defaultPrecision[EbtUint] = EpqHigh;
defaultPrecision[EbtFloat] = EpqHigh;
defaultPrecision[EbtSampler] = EpqLow;
- // TODO: functionality: need default precisions per sampler type
break;
case EShLangFragment:
defaultPrecision[EbtInt] = EpqMedium;
defaultPrecision[EbtUint] = EpqMedium;
defaultPrecision[EbtSampler] = EpqLow;
- // TODO: semantics: give error when using float in frag shader without default precision
break;
default:
error(1, "INTERNAL ERROR", "unexpected language", "");
}
}
+// 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,
// put it on the list of top-level nodes for the current (inner-most) switch statement,
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
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);
TIntermNode* addSwitch(int line, TIntermTyped* expression, TIntermAggregate* body);
void updateDefaults(int line, const TPublicType&, const TString* id);
TTypeLine typeLine;\r
TTypeList* typeList;\r
TArraySizes arraySizes;\r
+ TIdentifierList* identifierList;\r
};\r
} interm;\r
}\r
%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype\r
%type <interm> function_call_or_method function_identifier function_call_header\r
\r
+%type <interm.identifierList> identifier_list\r
+\r
%start translation_unit\r
%%\r
\r
$$ = 0;\r
}\r
| type_qualifier IDENTIFIER SEMICOLON {\r
- // TODO: functionality: track what variables are declared with INVARIANT\r
- // precise foo;\r
- // invariant foo;\r
+ parseContext.addQualifierToExisting($1.line, $1.qualifier, *$2.string);\r
$$ = 0;\r
}\r
| type_qualifier IDENTIFIER identifier_list SEMICOLON {\r
- // TODO: functionality: track what variables are declared with INVARIANT\r
- // precise foo, bar;\r
- // invariant foo, bar;\r
+ $3->push_back($2.string);\r
+ parseContext.addQualifierToExisting($1.line, $1.qualifier, *$3);\r
$$ = 0;\r
}\r
;\r
\r
identifier_list\r
: COMMA IDENTIFIER {\r
+ $$ = NewPoolTIdentifierList();\r
+ $$->push_back($2.string);\r
}\r
| identifier_list COMMA IDENTIFIER {\r
+ $$ = $1;\r
+ $$->push_back($3.string);\r
}\r
;\r
\r