Put in correct rules for multiple versions of qualification and typing of inputs and outputs. Also, removed EvqAttribute, merging it with EvqVaryingIn.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21064 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich
2013-04-07 22:43:16 +00:00
parent ad3663be1f
commit 3ed2db58f1
8 changed files with 132 additions and 123 deletions

View File

@@ -23,10 +23,19 @@ in vec2 c2D;
in vec3 c3D; in vec3 c3D;
in vec4 c4D; in vec4 c4D;
in int ic1D; flat in int ic1D;
in ivec2 ic2D; flat in ivec2 ic2D;
in ivec3 ic3D; flat in ivec3 ic3D;
in ivec4 ic4D; flat in ivec4 ic4D;
in sampler2D bads; // ERROR
struct s {
int i;
sampler2D s; // ERROR
};
out s badout; // ERROR
void main() void main()
{ {

View File

@@ -7,6 +7,8 @@ uniform mat4x4 m44;
in vec3 v3; in vec3 v3;
in vec2 v2; in vec2 v2;
in vec4 bad[10];
void main() void main()
{ {
int id = gl_VertexID + gl_InstanceID; int id = gl_VertexID + gl_InstanceID;

View File

@@ -1,9 +1,9 @@
#version 300 es #version 300 es
in uvec2 badu; // ERROR
in uvec2 t; flat in uvec2 t;
in float f; in float f;
in vec2 tc; in vec2 tc;
in bool bad; // ERROR
uniform uvec4 v; uniform uvec4 v;
uniform int i; uniform int i;
uniform bool b; uniform bool b;

View File

@@ -62,9 +62,8 @@ enum TStorageQualifier {
EvqTemporary, // For temporaries (within a function), read/write EvqTemporary, // For temporaries (within a function), read/write
EvqGlobal, // For globals read/write EvqGlobal, // For globals read/write
EvqConst, // User defined constants and non-output parameters in functions EvqConst, // User defined constants and non-output parameters in functions
EvqAttribute, // Readonly EvqVaryingIn, // pipeline input, read only
EvqVaryingIn, // readonly, fragment shaders only EvqVaryingOut, // pipeline ouput, read/write
EvqVaryingOut, // vertex shaders only read/write
EvqUniform, // Readonly, vertex and fragment EvqUniform, // Readonly, vertex and fragment
// parameters // parameters
@@ -103,9 +102,8 @@ __inline const char* getStorageQualifierString(TStorageQualifier q)
case EvqGlobal: return "global"; break; case EvqGlobal: return "global"; break;
case EvqConst: return "const"; break; case EvqConst: return "const"; break;
case EvqConstReadOnly: return "const (read only)"; break; case EvqConstReadOnly: return "const (read only)"; break;
case EvqAttribute: return "attribute"; break; case EvqVaryingIn: return "shader in"; break;
case EvqVaryingIn: return "varying in"; break; case EvqVaryingOut: return "shader out"; break;
case EvqVaryingOut: return "varying out"; break;
case EvqUniform: return "uniform"; break; case EvqUniform: return "uniform"; break;
case EvqIn: return "in"; break; case EvqIn: return "in"; break;
case EvqOut: return "out"; break; case EvqOut: return "out"; break;

View File

@@ -217,6 +217,18 @@ public:
bool restrict : 1; bool restrict : 1;
bool readonly : 1; bool readonly : 1;
bool writeonly : 1; bool writeonly : 1;
bool isMemory()
{
return coherent || volatil || restrict || readonly || writeonly;
}
bool isInterpolation()
{
return flat || smooth || nopersp;
}
bool isAuxillary()
{
return centroid || patch || sample;
}
}; };
class TPublicType { class TPublicType {

View File

@@ -328,9 +328,8 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod
switch (node->getQualifier().storage) { switch (node->getQualifier().storage) {
case EvqConst: message = "can't modify a const"; break; case EvqConst: message = "can't modify a const"; break;
case EvqConstReadOnly: message = "can't modify a const"; break; case EvqConstReadOnly: message = "can't modify a const"; break;
case EvqAttribute: message = "can't modify an attribute"; break; case EvqVaryingIn: message = "can't modify shader input"; 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 EvqInstanceId: message = "can't modify gl_InstanceID"; break; case EvqInstanceId: message = "can't modify gl_InstanceID"; break;
case EvqVertexId: message = "can't modify gl_VertexID"; 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;
@@ -617,7 +616,7 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const
{ {
if (pType.type == EbtStruct) { if (pType.type == EbtStruct) {
if (containsSampler(*pType.userDef)) { if (containsSampler(*pType.userDef)) {
error(line, reason, TType::getBasicString(pType.type), "(structure contains a sampler/image)"); error(line, reason, TType::getBasicString(pType.type), "(structure cannot contain a sampler or image)");
return true; return true;
} }
@@ -632,8 +631,13 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const
return false; return false;
} }
bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualifier) bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualifier, const TPublicType& publicType)
{ {
if (! symbolTable.atGlobalLevel())
return false;
// First, move from parameter qualifiers to shader in/out qualifiers
switch (qualifier.storage) { switch (qualifier.storage) {
case EvqIn: case EvqIn:
profileRequires(line, ENoProfile, 130, 0, "in for stage inputs"); profileRequires(line, ENoProfile, 130, 0, "in for stage inputs");
@@ -645,31 +649,68 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
profileRequires(line, EEsProfile, 300, 0, "out for stage outputs"); profileRequires(line, EEsProfile, 300, 0, "out for stage outputs");
qualifier.storage = EvqVaryingOut; qualifier.storage = EvqVaryingOut;
break; break;
case EvqVaryingIn:
case EvqVaryingOut:
break;
case EvqInOut: case EvqInOut:
qualifier.storage = EvqVaryingIn; qualifier.storage = EvqVaryingIn;
error(line, "cannot use 'inout' at global scope", "", ""); error(line, "cannot use 'inout' at global scope", "", "");
return true; return true;
default: break; // some compilers want this default:
break;
} }
// Do non in/out error checks
if (qualifier.storage != EvqUniform && samplerErrorCheck(line, publicType, "samplers and images must be uniform"))
return true;
if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
return false; return false;
}
bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType) // now, knowing it is a shader in/out, do all the in/out semantic checks
{
if ((pType.qualifier.storage == EvqVaryingIn ||
pType.qualifier.storage == EvqVaryingOut ||
pType.qualifier.storage == EvqAttribute) &&
pType.type == EbtStruct) {
error(line, "cannot be used with a structure", getStorageQualifierString(pType.qualifier.storage), "");
if (publicType.type == EbtBool) {
error(line, "cannot be bool", getStorageQualifierString(qualifier.storage), "");
return true; return true;
} }
if (pType.qualifier.storage != EvqUniform && samplerErrorCheck(line, pType, "samplers and images must be uniform")) if (language == EShLangVertex && qualifier.storage == EvqVaryingIn) {
if (publicType.type == EbtStruct) {
error(line, "cannot be a structure or array", getStorageQualifierString(qualifier.storage), "");
return true; return true;
}
if (publicType.arraySizes) {
requireProfile(line, (EProfileMask)~EEsProfileMask, "vertex input arrays");
profileRequires(line, ENoProfile, 150, 0, "vertex input arrays");
}
}
if (language == EShLangFragment && qualifier.storage == EvqVaryingOut) {
profileRequires(line, EEsProfile, 300, 0, "fragment shader output");
if (publicType.type == EbtStruct) {
error(line, "cannot be a structure", getStorageQualifierString(qualifier.storage), "");
return true;
}
}
if (publicType.type == EbtInt || publicType.type == EbtUint || publicType.type == EbtDouble) {
profileRequires(line, EEsProfile, 300, 0, "shader input/output");
if (language != EShLangVertex && qualifier.storage == EvqVaryingIn && ! qualifier.flat ||
language != EShLangFragment && qualifier.storage == EvqVaryingOut && ! qualifier.flat) {
error(line, "must be qualified as 'flat'", getStorageQualifierString(qualifier.storage), TType::getBasicString(publicType.type));
return true;
}
}
if (language == EShLangVertex && qualifier.storage == EvqVaryingIn &&
(qualifier.isAuxillary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.buffer || qualifier.invariant)) {
error(line, "vertex input cannot be further qualified", "", "");
return true;
}
return false; return false;
} }
@@ -832,13 +873,8 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
// //
// Returns true if there is an error. // Returns true if there is an error.
// //
bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) bool TParseContext::arrayQualifierErrorCheck(int line, const TPublicType& type)
{ {
if (type.qualifier.storage == EvqAttribute) {
error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
return true;
}
if (type.qualifier.storage == EvqConst) if (type.qualifier.storage == EvqConst)
profileRequires(line, ENoProfile, 120, "GL_3DL_array_objects", "const array"); profileRequires(line, ENoProfile, 120, "GL_3DL_array_objects", "const array");
@@ -870,7 +906,7 @@ bool TParseContext::arraySizeRequiredErrorCheck(int line, int& size)
// //
// Returns true if there was an error. // Returns true if there was an error.
// //
bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable) bool TParseContext::arrayErrorCheck(int line, TString& identifier, const TPublicType& type, TVariable*& variable)
{ {
// //
// Don't check for reserved word use until after we know it's not in the symbol table, // Don't check for reserved word use until after we know it's not in the symbol table,

View File

@@ -112,15 +112,15 @@ struct TParseContext {
bool globalErrorCheck(int line, bool global, const char* token); bool globalErrorCheck(int line, bool global, const char* token);
bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*); bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*);
bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size); bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size);
bool arrayQualifierErrorCheck(int line, TPublicType type); bool arrayQualifierErrorCheck(int line, const TPublicType&);
bool arraySizeRequiredErrorCheck(int line, int& size); bool arraySizeRequiredErrorCheck(int line, int& size);
bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable); bool arrayErrorCheck(int line, TString& identifier, const TPublicType&, TVariable*& variable);
bool insertBuiltInArrayAtGlobalLevel(); bool insertBuiltInArrayAtGlobalLevel();
bool voidErrorCheck(int, const TString&, const TPublicType&); bool voidErrorCheck(int, const TString&, const TPublicType&);
bool boolErrorCheck(int, const TIntermTyped*); bool boolErrorCheck(int, const TIntermTyped*);
bool boolErrorCheck(int, const TPublicType&); bool boolErrorCheck(int, const TPublicType&);
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason); bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
bool globalQualifierFixAndErrorCheck(int line, TQualifier&); bool globalQualifierFixAndErrorCheck(int line, TQualifier&, const TPublicType&);
bool structQualifierErrorCheck(int line, const TPublicType& pType); bool structQualifierErrorCheck(int line, const TPublicType& pType);
bool mergeQualifiersErrorCheck(int line, TPublicType& left, const TPublicType& right); bool mergeQualifiersErrorCheck(int line, TPublicType& left, const TPublicType& right);
void setDefaultPrecision(int line, TPublicType&, TPrecisionQualifier); void setDefaultPrecision(int line, TPublicType&, TPrecisionQualifier);

View File

@@ -1302,9 +1302,6 @@ function_header
getStorageQualifierString($1.qualifier.storage), ""); getStorageQualifierString($1.qualifier.storage), "");
parseContext.recover(); parseContext.recover();
} }
// make sure a sampler is not involved as well...
if (parseContext.structQualifierErrorCheck($2.line, $1))
parseContext.recover();
// Add the function as a prototype after parsing it (we do not support recursion) // Add the function as a prototype after parsing it (we do not support recursion)
TFunction *function; TFunction *function;
@@ -1410,9 +1407,6 @@ init_declarator_list
} }
| init_declarator_list COMMA IDENTIFIER { | init_declarator_list COMMA IDENTIFIER {
$$ = $1; $$ = $1;
if (parseContext.structQualifierErrorCheck($3.line, $$.type))
parseContext.recover();
if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $$.type)) if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $$.type))
parseContext.recover(); parseContext.recover();
@@ -1420,9 +1414,6 @@ init_declarator_list
parseContext.recover(); parseContext.recover();
} }
| init_declarator_list COMMA IDENTIFIER array_specifier { | init_declarator_list COMMA IDENTIFIER array_specifier {
if (parseContext.structQualifierErrorCheck($3.line, $1.type))
parseContext.recover();
if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $1.type)) if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $1.type))
parseContext.recover(); parseContext.recover();
@@ -1438,9 +1429,6 @@ init_declarator_list
} }
} }
| init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer { | init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer {
if (parseContext.structQualifierErrorCheck($3.line, $1.type))
parseContext.recover();
$$ = $1; $$ = $1;
TVariable* variable = 0; TVariable* variable = 0;
@@ -1469,9 +1457,6 @@ init_declarator_list
} }
} }
| init_declarator_list COMMA IDENTIFIER EQUAL initializer { | init_declarator_list COMMA IDENTIFIER EQUAL initializer {
if (parseContext.structQualifierErrorCheck($3.line, $1.type))
parseContext.recover();
$$ = $1; $$ = $1;
TIntermNode* intermNode; TIntermNode* intermNode;
@@ -1494,21 +1479,11 @@ single_declaration
: fully_specified_type { : fully_specified_type {
$$.type = $1; $$.type = $1;
$$.intermAggregate = 0; $$.intermAggregate = 0;
if (parseContext.globalQualifierFixAndErrorCheck($1.line, $1.qualifier))
parseContext.recover();
} }
| fully_specified_type IDENTIFIER { | fully_specified_type IDENTIFIER {
$$.intermAggregate = 0; $$.intermAggregate = 0;
if (parseContext.globalQualifierFixAndErrorCheck($1.line, $1.qualifier))
parseContext.recover();
$$.type = $1; $$.type = $1;
if (parseContext.structQualifierErrorCheck($2.line, $$.type))
parseContext.recover();
if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $$.type)) if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $$.type))
parseContext.recover(); parseContext.recover();
@@ -1517,13 +1492,6 @@ single_declaration
} }
| fully_specified_type IDENTIFIER array_specifier { | fully_specified_type IDENTIFIER array_specifier {
$$.intermAggregate = 0; $$.intermAggregate = 0;
if (parseContext.globalQualifierFixAndErrorCheck($1.line, $1.qualifier))
parseContext.recover();
if (parseContext.structQualifierErrorCheck($2.line, $1))
parseContext.recover();
if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $1)) if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $1))
parseContext.recover(); parseContext.recover();
@@ -1540,10 +1508,6 @@ single_declaration
} }
| fully_specified_type IDENTIFIER array_specifier EQUAL initializer { | fully_specified_type IDENTIFIER array_specifier EQUAL initializer {
$$.intermAggregate = 0; $$.intermAggregate = 0;
if (parseContext.structQualifierErrorCheck($2.line, $1))
parseContext.recover();
$$.type = $1; $$.type = $1;
TVariable* variable = 0; TVariable* variable = 0;
@@ -1572,9 +1536,6 @@ single_declaration
} }
} }
| fully_specified_type IDENTIFIER EQUAL initializer { | fully_specified_type IDENTIFIER EQUAL initializer {
if (parseContext.structQualifierErrorCheck($2.line, $1))
parseContext.recover();
$$.type = $1; $$.type = $1;
TIntermNode* intermNode; TIntermNode* intermNode;
@@ -1604,6 +1565,9 @@ fully_specified_type
} }
} }
| type_qualifier type_specifier { | type_qualifier type_specifier {
if (parseContext.globalQualifierFixAndErrorCheck($1.line, $1.qualifier, $2))
parseContext.recover();
if ($2.arraySizes) { if ($2.arraySizes) {
parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type"); parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
parseContext.profileRequires($2.line, EEsProfile, 300, 0, "arrayed type"); parseContext.profileRequires($2.line, EEsProfile, 300, 0, "arrayed type");
@@ -1614,16 +1578,6 @@ fully_specified_type
$2.arraySizes = 0; $2.arraySizes = 0;
} }
if ($1.qualifier.storage == EvqAttribute &&
($2.type == EbtBool || $2.type == EbtInt || $2.type == EbtUint)) {
parseContext.error($2.line, "cannot be bool or int", getStorageQualifierString($1.qualifier.storage), "");
parseContext.recover();
}
if (($1.qualifier.storage == EvqVaryingIn || $1.qualifier.storage == EvqVaryingOut) &&
($2.type == EbtBool || $2.type == EbtInt || $2.type == EbtUint)) {
parseContext.error($2.line, "cannot be bool or int", getStorageQualifierString($1.qualifier.storage), "");
parseContext.recover();
}
$$ = $2; $$ = $2;
$$.qualifier = $1.qualifier; $$.qualifier = $1.qualifier;
if ($$.qualifier.precision == EpqNone) if ($$.qualifier.precision == EpqNone)
@@ -1747,7 +1701,7 @@ storage_qualifier
parseContext.recover(); parseContext.recover();
$$.init($1.line); $$.init($1.line);
$$.qualifier.storage = EvqAttribute; $$.qualifier.storage = EvqVaryingIn;
} }
| VARYING { | VARYING {
parseContext.checkDeprecated($1.line, ENoProfile, 140, "varying"); parseContext.checkDeprecated($1.line, ENoProfile, 140, "varying");
@@ -2790,8 +2744,6 @@ condition
} }
| fully_specified_type IDENTIFIER EQUAL initializer { | fully_specified_type IDENTIFIER EQUAL initializer {
TIntermNode* intermNode; TIntermNode* intermNode;
if (parseContext.structQualifierErrorCheck($2.line, $1))
parseContext.recover();
if (parseContext.boolErrorCheck($2.line, $1)) if (parseContext.boolErrorCheck($2.line, $1))
parseContext.recover(); parseContext.recover();