Commit 42ff6b15 by Alexis Hetu Committed by Alexis Hétu

Add proper in/out shader types

Fragment and Vertex inputs and outputs were treated as OpenGL ES2.0 attributes and varyings, but OpenGL ES3.0 inputs and outputs have different limitations and must be treated differently. This cl simply introduces the new types, without modifying the ES2.0 behavior and only modifying ES3.0 to allow integer varyings when they are flat. Change-Id: I965cb576bab3f505602af9e055438bcc7c18cdfd Reviewed-on: https://swiftshader-review.googlesource.com/3371Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent bb7a1730
...@@ -342,6 +342,11 @@ enum TQualifier : unsigned char ...@@ -342,6 +342,11 @@ enum TQualifier : unsigned char
EvqInvariantVaryingOut, // vertex shaders only read/write EvqInvariantVaryingOut, // vertex shaders only read/write
EvqUniform, // Readonly, vertex and fragment EvqUniform, // Readonly, vertex and fragment
EvqVertexIn, // Vertex shader input
EvqFragmentOut, // Fragment shader output
EvqVertexOut, // Vertex shader output
EvqFragmentIn, // Fragment shader input
// pack/unpack input and output // pack/unpack input and output
EvqInput, EvqInput,
EvqOutput, EvqOutput,
...@@ -420,6 +425,10 @@ inline const char *getQualifierString(TQualifier qualifier) ...@@ -420,6 +425,10 @@ inline const char *getQualifierString(TQualifier qualifier)
case EvqInvariantVaryingIn: return "invariant varying"; break; case EvqInvariantVaryingIn: return "invariant varying"; break;
case EvqInvariantVaryingOut:return "invariant varying"; break; case EvqInvariantVaryingOut:return "invariant varying"; break;
case EvqUniform: return "uniform"; break; case EvqUniform: return "uniform"; break;
case EvqVertexIn: return "in"; break;
case EvqFragmentOut: return "out"; break;
case EvqVertexOut: return "out"; break;
case EvqFragmentIn: return "in"; break;
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;
......
...@@ -166,7 +166,7 @@ namespace glsl ...@@ -166,7 +166,7 @@ namespace glsl
{ {
// Vertex varyings don't have to be actively used to successfully link // Vertex varyings don't have to be actively used to successfully link
// against pixel shaders that use them. So make sure they're declared. // against pixel shaders that use them. So make sure they're declared.
if(symbol->getQualifier() == EvqVaryingOut || symbol->getQualifier() == EvqInvariantVaryingOut) if(symbol->getQualifier() == EvqVaryingOut || symbol->getQualifier() == EvqInvariantVaryingOut || symbol->getQualifier() == EvqVertexOut)
{ {
if(symbol->getBasicType() != EbtInvariant) // Typeless declarations are not new varyings if(symbol->getBasicType() != EbtInvariant) // Typeless declarations are not new varyings
{ {
...@@ -1857,6 +1857,10 @@ namespace glsl ...@@ -1857,6 +1857,10 @@ namespace glsl
case EvqAttribute: return sw::Shader::PARAMETER_INPUT; case EvqAttribute: return sw::Shader::PARAMETER_INPUT;
case EvqVaryingIn: return sw::Shader::PARAMETER_INPUT; case EvqVaryingIn: return sw::Shader::PARAMETER_INPUT;
case EvqVaryingOut: return sw::Shader::PARAMETER_OUTPUT; case EvqVaryingOut: return sw::Shader::PARAMETER_OUTPUT;
case EvqVertexIn: return sw::Shader::PARAMETER_INPUT;
case EvqFragmentOut: return sw::Shader::PARAMETER_COLOROUT;
case EvqVertexOut: return sw::Shader::PARAMETER_OUTPUT;
case EvqFragmentIn: return sw::Shader::PARAMETER_INPUT;
case EvqInvariantVaryingIn: return sw::Shader::PARAMETER_INPUT; // FIXME: Guarantee invariance at the backend case EvqInvariantVaryingIn: return sw::Shader::PARAMETER_INPUT; // FIXME: Guarantee invariance at the backend
case EvqInvariantVaryingOut: return sw::Shader::PARAMETER_OUTPUT; // FIXME: Guarantee invariance at the backend case EvqInvariantVaryingOut: return sw::Shader::PARAMETER_OUTPUT; // FIXME: Guarantee invariance at the backend
case EvqUniform: return sw::Shader::PARAMETER_CONST; case EvqUniform: return sw::Shader::PARAMETER_CONST;
...@@ -1893,6 +1897,10 @@ namespace glsl ...@@ -1893,6 +1897,10 @@ namespace glsl
case EvqAttribute: return attributeRegister(operand); case EvqAttribute: return attributeRegister(operand);
case EvqVaryingIn: return varyingRegister(operand); case EvqVaryingIn: return varyingRegister(operand);
case EvqVaryingOut: return varyingRegister(operand); case EvqVaryingOut: return varyingRegister(operand);
case EvqVertexIn: return attributeRegister(operand);
case EvqFragmentOut: return 0;
case EvqVertexOut: return varyingRegister(operand);
case EvqFragmentIn: return varyingRegister(operand);
case EvqInvariantVaryingIn: return varyingRegister(operand); case EvqInvariantVaryingIn: return varyingRegister(operand);
case EvqInvariantVaryingOut: return varyingRegister(operand); case EvqInvariantVaryingOut: return varyingRegister(operand);
case EvqUniform: return uniformRegister(operand); case EvqUniform: return uniformRegister(operand);
......
...@@ -314,6 +314,8 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod ...@@ -314,6 +314,8 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod
case EvqConstExpr: message = "can't modify a const"; break; case EvqConstExpr: 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 EvqAttribute: message = "can't modify an attribute"; break;
case EvqFragmentIn: message = "can't modify an input"; break;
case EvqVertexIn: message = "can't modify an input"; break;
case EvqUniform: message = "can't modify a uniform"; break; case EvqUniform: message = "can't modify a uniform"; break;
case EvqSmoothIn: case EvqSmoothIn:
case EvqFlatIn: case EvqFlatIn:
...@@ -624,6 +626,8 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType ...@@ -624,6 +626,8 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType
case EvqFlatIn: case EvqFlatIn:
case EvqCentroidIn: case EvqCentroidIn:
case EvqAttribute: case EvqAttribute:
case EvqVertexIn:
case EvqFragmentOut:
if(pType.type == EbtStruct) if(pType.type == EbtStruct)
{ {
error(line, "cannot be used with a structure", getQualifierString(pType.qualifier)); error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
...@@ -638,9 +642,29 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType ...@@ -638,9 +642,29 @@ bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType
if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform")) if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
return true; return true;
// check for layout qualifier issues
const TLayoutQualifier layoutQualifier = pType.layoutQualifier;
if (pType.qualifier != EvqVertexIn && pType.qualifier != EvqFragmentOut &&
layoutLocationErrorCheck(line, pType.layoutQualifier))
{
return true;
}
return false; return false;
} }
bool TParseContext::layoutLocationErrorCheck(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier)
{
if(layoutQualifier.location != -1)
{
error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs");
return true;
}
return false;
}
bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type) bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
{ {
if ((qualifier == EvqOut || qualifier == EvqInOut) && if ((qualifier == EvqOut || qualifier == EvqInOut) &&
...@@ -717,7 +741,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size) ...@@ -717,7 +741,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
// //
bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type) bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
{ {
if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConstExpr)) { if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConstExpr)) {
error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
return true; return true;
} }
...@@ -1122,6 +1146,75 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) ...@@ -1122,6 +1146,75 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
return allConstant; return allConstant;
} }
TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier)
{
TPublicType returnType = typeSpecifier;
returnType.qualifier = qualifier;
returnType.invariant = invariant;
returnType.layoutQualifier = layoutQualifier;
if(typeSpecifier.array)
{
error(typeSpecifier.line, "not supported", "first-class array");
recover();
returnType.clearArrayness();
}
if(shaderVersion < 300)
{
if(qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
{
error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
recover();
}
if((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
(typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
{
error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
recover();
}
}
else
{
switch(qualifier)
{
case EvqSmoothIn:
case EvqSmoothOut:
case EvqVertexOut:
case EvqFragmentIn:
case EvqCentroidOut:
case EvqCentroidIn:
if(typeSpecifier.type == EbtBool)
{
error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
recover();
}
if(typeSpecifier.type == EbtInt || typeSpecifier.type == EbtUInt)
{
error(typeSpecifier.line, "must use 'flat' interpolation here", getQualifierString(qualifier));
recover();
}
break;
case EvqVertexIn:
case EvqFragmentOut:
case EvqFlatIn:
case EvqFlatOut:
if(typeSpecifier.type == EbtBool)
{
error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
recover();
}
break;
default: break;
}
}
return returnType;
}
// This function is used to test for the correctness of the parameters passed to various constructor functions // This function is used to test for the correctness of the parameters passed to various constructor functions
// and also convert them to the right datatype if it is allowed and required. // and also convert them to the right datatype if it is allowed and required.
// //
...@@ -1406,7 +1499,7 @@ TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpo ...@@ -1406,7 +1499,7 @@ TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpo
{ {
TQualifier mergedQualifier = EvqSmoothIn; TQualifier mergedQualifier = EvqSmoothIn;
if(storageQualifier == EvqVaryingIn) { if(storageQualifier == EvqFragmentIn) {
if(interpolationQualifier == EvqSmooth) if(interpolationQualifier == EvqSmooth)
mergedQualifier = EvqSmoothIn; mergedQualifier = EvqSmoothIn;
else if(interpolationQualifier == EvqFlat) else if(interpolationQualifier == EvqFlat)
...@@ -1420,7 +1513,7 @@ TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpo ...@@ -1420,7 +1513,7 @@ TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpo
mergedQualifier = EvqFlatIn; mergedQualifier = EvqFlatIn;
else UNREACHABLE(); else UNREACHABLE();
} }
else if(storageQualifier == EvqVaryingOut) { else if(storageQualifier == EvqVertexOut) {
if(interpolationQualifier == EvqSmooth) if(interpolationQualifier == EvqSmooth)
mergedQualifier = EvqSmoothOut; mergedQualifier = EvqSmoothOut;
else if(interpolationQualifier == EvqFlat) else if(interpolationQualifier == EvqFlat)
......
...@@ -102,6 +102,7 @@ struct TParseContext { ...@@ -102,6 +102,7 @@ struct TParseContext {
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable); bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable);
bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type); bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
bool extensionErrorCheck(int line, const TString&); bool extensionErrorCheck(int line, const TString&);
bool layoutLocationErrorCheck(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier);
const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
bool supportsExtension(const char* extension); bool supportsExtension(const char* extension);
...@@ -115,6 +116,8 @@ struct TParseContext { ...@@ -115,6 +116,8 @@ struct TParseContext {
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0); const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
TPublicType addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier);
bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc); bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc); TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
......
...@@ -275,6 +275,7 @@ struct TPublicType ...@@ -275,6 +275,7 @@ struct TPublicType
TBasicType type; TBasicType type;
TLayoutQualifier layoutQualifier; TLayoutQualifier layoutQualifier;
TQualifier qualifier; TQualifier qualifier;
bool invariant;
TPrecision precision; TPrecision precision;
int primarySize; // size of vector or matrix, not size of array int primarySize; // size of vector or matrix, not size of array
int secondarySize; // 1 for scalars/vectors, >1 for matrices int secondarySize; // 1 for scalars/vectors, >1 for matrices
...@@ -288,6 +289,7 @@ struct TPublicType ...@@ -288,6 +289,7 @@ struct TPublicType
type = bt; type = bt;
layoutQualifier = TLayoutQualifier::create(); layoutQualifier = TLayoutQualifier::create();
qualifier = q; qualifier = q;
invariant = false;
precision = EbpUndefined; precision = EbpUndefined;
primarySize = 1; primarySize = 1;
secondarySize = 1; secondarySize = 1;
...@@ -315,6 +317,12 @@ struct TPublicType ...@@ -315,6 +317,12 @@ struct TPublicType
arraySize = s; arraySize = s;
} }
void clearArrayness()
{
array = false;
arraySize = 0;
}
bool isStructureContainingArrays() const bool isStructureContainingArrays() const
{ {
if (!userDef) if (!userDef)
......
...@@ -1573,30 +1573,14 @@ fully_specified_type ...@@ -1573,30 +1573,14 @@ fully_specified_type
$$ = $1; $$ = $1;
if ($1.array) { if ($1.array) {
context->error($1.line, "not supported", "first-class array"); ES3_ONLY("[]", $1.line);
context->recover(); if (context->getShaderVersion() != 300) {
$1.setArray(false); $1.clearArrayness();
}
} }
} }
| type_qualifier type_specifier { | type_qualifier type_specifier {
if ($2.array) { $$ = context->addFullySpecifiedType($1.qualifier, $1.invariant, $1.layoutQualifier, $2);
context->error($2.line, "not supported", "first-class array");
context->recover();
$2.setArray(false);
}
if ($1.qualifier == EvqAttribute &&
($2.type == EbtBool || $2.type == EbtInt)) {
context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier));
context->recover();
}
if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
($2.type == EbtBool || $2.type == EbtInt)) {
context->error($2.line, "cannot be bool or int", getQualifierString($1.qualifier));
context->recover();
}
$$ = $2;
$$.qualifier = $1.qualifier;
} }
; ;
...@@ -1671,24 +1655,32 @@ storage_qualifier ...@@ -1671,24 +1655,32 @@ storage_qualifier
} }
| IN_QUAL { | IN_QUAL {
ES3_ONLY("in", $1.line); ES3_ONLY("in", $1.line);
$$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqVaryingIn : EvqAttribute; $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn;
$$.line = $1.line; $$.line = $1.line;
} }
| OUT_QUAL { | OUT_QUAL {
ES3_ONLY("out", $1.line); ES3_ONLY("out", $1.line);
$$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragColor : EvqVaryingOut; $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut;
$$.line = $1.line; $$.line = $1.line;
} }
| CENTROID IN_QUAL { | CENTROID IN_QUAL {
ES3_ONLY("in", $1.line); ES3_ONLY("centroid in", $1.line);
// FIXME: Handle centroid qualifier if (context->shaderType == GL_VERTEX_SHADER)
$$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqVaryingIn : EvqAttribute; {
context->error($1.line, "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader");
context->recover();
}
$$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn;
$$.line = $2.line; $$.line = $2.line;
} }
| CENTROID OUT_QUAL { | CENTROID OUT_QUAL {
ES3_ONLY("out", $1.line); ES3_ONLY("centroid out", $1.line);
// FIXME: Handle centroid qualifier if (context->shaderType == GL_FRAGMENT_SHADER)
$$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragColor : EvqVaryingOut; {
context->error($1.line, "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader");
context->recover();
}
$$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut;
$$.line = $2.line; $$.line = $2.line;
} }
| UNIFORM { | UNIFORM {
......
...@@ -741,21 +741,21 @@ static const yytype_uint16 yyrline[] = ...@@ -741,21 +741,21 @@ static const yytype_uint16 yyrline[] =
1051, 1053, 1058, 1061, 1072, 1080, 1107, 1112, 1122, 1160, 1051, 1053, 1058, 1061, 1072, 1080, 1107, 1112, 1122, 1160,
1163, 1170, 1178, 1199, 1220, 1231, 1260, 1265, 1275, 1280, 1163, 1170, 1178, 1199, 1220, 1231, 1260, 1265, 1275, 1280,
1290, 1293, 1296, 1299, 1305, 1312, 1315, 1337, 1355, 1379, 1290, 1293, 1296, 1299, 1305, 1312, 1315, 1337, 1355, 1379,
1402, 1406, 1424, 1432, 1464, 1484, 1572, 1581, 1604, 1607, 1402, 1406, 1424, 1432, 1464, 1484, 1572, 1582, 1588, 1591,
1613, 1619, 1626, 1635, 1644, 1647, 1650, 1657, 1661, 1668, 1597, 1603, 1610, 1619, 1628, 1631, 1634, 1641, 1645, 1652,
1672, 1677, 1682, 1688, 1694, 1703, 1713, 1720, 1723, 1726, 1656, 1661, 1666, 1676, 1686, 1695, 1705, 1712, 1715, 1718,
1732, 1739, 1742, 1748, 1751, 1754, 1760, 1763, 1778, 1782, 1724, 1731, 1734, 1740, 1743, 1746, 1752, 1755, 1770, 1774,
1786, 1790, 1794, 1798, 1803, 1808, 1813, 1818, 1823, 1828, 1778, 1782, 1786, 1790, 1795, 1800, 1805, 1810, 1815, 1820,
1833, 1838, 1843, 1848, 1853, 1858, 1864, 1870, 1876, 1882, 1825, 1830, 1835, 1840, 1845, 1850, 1856, 1862, 1868, 1874,
1888, 1894, 1900, 1906, 1912, 1917, 1922, 1931, 1936, 1941, 1880, 1886, 1892, 1898, 1904, 1909, 1914, 1923, 1928, 1933,
1946, 1951, 1956, 1961, 1966, 1971, 1976, 1981, 1986, 1991, 1938, 1943, 1948, 1953, 1958, 1963, 1968, 1973, 1978, 1983,
1996, 2001, 2014, 2014, 2028, 2028, 2037, 2040, 2055, 2087, 1988, 1993, 2006, 2006, 2020, 2020, 2029, 2032, 2047, 2079,
2091, 2097, 2105, 2121, 2125, 2129, 2130, 2136, 2137, 2138, 2083, 2089, 2097, 2113, 2117, 2121, 2122, 2128, 2129, 2130,
2139, 2140, 2144, 2145, 2145, 2145, 2155, 2156, 2160, 2160, 2131, 2132, 2136, 2137, 2137, 2137, 2147, 2148, 2152, 2152,
2161, 2161, 2166, 2169, 2179, 2182, 2188, 2189, 2193, 2201, 2153, 2153, 2158, 2161, 2171, 2174, 2180, 2181, 2185, 2193,
2205, 2215, 2220, 2237, 2237, 2242, 2242, 2249, 2249, 2257, 2197, 2207, 2212, 2229, 2229, 2234, 2234, 2241, 2241, 2249,
2260, 2266, 2269, 2275, 2279, 2286, 2293, 2300, 2307, 2318, 2252, 2258, 2261, 2267, 2271, 2278, 2285, 2292, 2299, 2310,
2327, 2331, 2338, 2341, 2347, 2347 2319, 2323, 2330, 2333, 2339, 2339
}; };
#endif #endif
...@@ -3940,9 +3940,10 @@ yyreduce: ...@@ -3940,9 +3940,10 @@ yyreduce:
(yyval.interm.type) = (yyvsp[(1) - (1)].interm.type); (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
if ((yyvsp[(1) - (1)].interm.type).array) { if ((yyvsp[(1) - (1)].interm.type).array) {
context->error((yyvsp[(1) - (1)].interm.type).line, "not supported", "first-class array"); ES3_ONLY("[]", (yyvsp[(1) - (1)].interm.type).line);
context->recover(); if (context->getShaderVersion() != 300) {
(yyvsp[(1) - (1)].interm.type).setArray(false); (yyvsp[(1) - (1)].interm.type).clearArrayness();
}
} }
} }
break; break;
...@@ -3950,24 +3951,7 @@ yyreduce: ...@@ -3950,24 +3951,7 @@ yyreduce:
case 117: case 117:
{ {
if ((yyvsp[(2) - (2)].interm.type).array) { (yyval.interm.type) = context->addFullySpecifiedType((yyvsp[(1) - (2)].interm.type).qualifier, (yyvsp[(1) - (2)].interm.type).invariant, (yyvsp[(1) - (2)].interm.type).layoutQualifier, (yyvsp[(2) - (2)].interm.type));
context->error((yyvsp[(2) - (2)].interm.type).line, "not supported", "first-class array");
context->recover();
(yyvsp[(2) - (2)].interm.type).setArray(false);
}
if ((yyvsp[(1) - (2)].interm.type).qualifier == EvqAttribute &&
((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) {
context->error((yyvsp[(2) - (2)].interm.type).line, "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier));
context->recover();
}
if (((yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingIn || (yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingOut) &&
((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) {
context->error((yyvsp[(2) - (2)].interm.type).line, "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier));
context->recover();
}
(yyval.interm.type) = (yyvsp[(2) - (2)].interm.type);
(yyval.interm.type).qualifier = (yyvsp[(1) - (2)].interm.type).qualifier;
} }
break; break;
...@@ -4082,7 +4066,7 @@ yyreduce: ...@@ -4082,7 +4066,7 @@ yyreduce:
{ {
ES3_ONLY("in", (yyvsp[(1) - (1)].lex).line); ES3_ONLY("in", (yyvsp[(1) - (1)].lex).line);
(yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqVaryingIn : EvqAttribute; (yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn;
(yyval.interm.type).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm.type).line = (yyvsp[(1) - (1)].lex).line;
} }
break; break;
...@@ -4091,7 +4075,7 @@ yyreduce: ...@@ -4091,7 +4075,7 @@ yyreduce:
{ {
ES3_ONLY("out", (yyvsp[(1) - (1)].lex).line); ES3_ONLY("out", (yyvsp[(1) - (1)].lex).line);
(yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragColor : EvqVaryingOut; (yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut;
(yyval.interm.type).line = (yyvsp[(1) - (1)].lex).line; (yyval.interm.type).line = (yyvsp[(1) - (1)].lex).line;
} }
break; break;
...@@ -4099,9 +4083,13 @@ yyreduce: ...@@ -4099,9 +4083,13 @@ yyreduce:
case 132: case 132:
{ {
ES3_ONLY("in", (yyvsp[(1) - (2)].lex).line); ES3_ONLY("centroid in", (yyvsp[(1) - (2)].lex).line);
// FIXME: Handle centroid qualifier if (context->shaderType == GL_VERTEX_SHADER)
(yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqVaryingIn : EvqAttribute; {
context->error((yyvsp[(1) - (2)].lex).line, "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader");
context->recover();
}
(yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn;
(yyval.interm.type).line = (yyvsp[(2) - (2)].lex).line; (yyval.interm.type).line = (yyvsp[(2) - (2)].lex).line;
} }
break; break;
...@@ -4109,9 +4097,13 @@ yyreduce: ...@@ -4109,9 +4097,13 @@ yyreduce:
case 133: case 133:
{ {
ES3_ONLY("out", (yyvsp[(1) - (2)].lex).line); ES3_ONLY("centroid out", (yyvsp[(1) - (2)].lex).line);
// FIXME: Handle centroid qualifier if (context->shaderType == GL_FRAGMENT_SHADER)
(yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragColor : EvqVaryingOut; {
context->error((yyvsp[(1) - (2)].lex).line, "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader");
context->recover();
}
(yyval.interm.type).qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut;
(yyval.interm.type).line = (yyvsp[(2) - (2)].lex).line; (yyval.interm.type).line = (yyvsp[(2) - (2)].lex).line;
} }
break; break;
......
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