Commit 19571818 by Jamie Madill

Add more robust support for interpolation and storage qualifiers with varyings for GLSL ES 3.00.

This fixes some conformance failures in the dEQP varying link tests, particularly with ints and the flat keyword. TRAC #23745 Signed-off-by: Nicolas Capens Signed-off-by: Shannon Woods
parent f2e0f9bb
...@@ -301,8 +301,11 @@ enum TQualifier ...@@ -301,8 +301,11 @@ enum TQualifier
EvqInvariantVaryingIn, // readonly, fragment shaders only EvqInvariantVaryingIn, // readonly, fragment shaders only
EvqInvariantVaryingOut, // vertex shaders only read/write EvqInvariantVaryingOut, // vertex shaders only read/write
EvqUniform, // Readonly, vertex and fragment EvqUniform, // Readonly, vertex and fragment
EvqVertexInput, // Vertex shader input
EvqFragmentOutput, // Fragment shader output EvqVertexIn, // Vertex shader input
EvqFragmentOut, // Fragment shader output
EvqVertexOut, // Vertex shader output
EvqFragmentIn, // Fragment shader input
// parameters // parameters
EvqIn, EvqIn,
...@@ -393,8 +396,10 @@ inline const char* getQualifierString(TQualifier q) ...@@ -393,8 +396,10 @@ inline const char* getQualifierString(TQualifier q)
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 EvqVertexInput: return "in"; break; case EvqVertexIn: return "in"; break;
case EvqFragmentOutput: return "out"; 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;
......
...@@ -1549,7 +1549,7 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) ...@@ -1549,7 +1549,7 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
out << decorateUniform(name, nodeType); out << decorateUniform(name, nodeType);
} }
else if (qualifier == EvqAttribute || qualifier == EvqVertexInput) else if (qualifier == EvqAttribute || qualifier == EvqVertexIn)
{ {
mReferencedAttributes[name] = node; mReferencedAttributes[name] = node;
out << decorate(name); out << decorate(name);
...@@ -1559,7 +1559,7 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) ...@@ -1559,7 +1559,7 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
mReferencedVaryings[name] = node; mReferencedVaryings[name] = node;
out << decorate(name); out << decorate(name);
} }
else if (qualifier == EvqFragmentOutput) else if (qualifier == EvqFragmentOut)
{ {
mReferencedOutputVariables[name] = node; mReferencedOutputVariables[name] = node;
out << "out_" << name; out << "out_" << name;
...@@ -2924,11 +2924,13 @@ TString OutputHLSL::interpolationString(TQualifier qualifier) ...@@ -2924,11 +2924,13 @@ TString OutputHLSL::interpolationString(TQualifier qualifier)
switch(qualifier) switch(qualifier)
{ {
case EvqVaryingIn: return ""; case EvqVaryingIn: return "";
case EvqFragmentIn: return "";
case EvqInvariantVaryingIn: return ""; case EvqInvariantVaryingIn: return "";
case EvqSmoothIn: return "linear"; case EvqSmoothIn: return "linear";
case EvqFlatIn: return "nointerpolation"; case EvqFlatIn: return "nointerpolation";
case EvqCentroidIn: return "centroid"; case EvqCentroidIn: return "centroid";
case EvqVaryingOut: return ""; case EvqVaryingOut: return "";
case EvqVertexOut: return "";
case EvqInvariantVaryingOut: return ""; case EvqInvariantVaryingOut: return "";
case EvqSmoothOut: return "linear"; case EvqSmoothOut: return "linear";
case EvqFlatOut: return "nointerpolation"; case EvqFlatOut: return "nointerpolation";
...@@ -3772,6 +3774,7 @@ bool OutputHLSL::isVaryingOut(TQualifier qualifier) ...@@ -3772,6 +3774,7 @@ bool OutputHLSL::isVaryingOut(TQualifier qualifier)
case EvqSmoothOut: case EvqSmoothOut:
case EvqFlatOut: case EvqFlatOut:
case EvqCentroidOut: case EvqCentroidOut:
case EvqVertexOut:
return true; return true;
} }
...@@ -3787,6 +3790,7 @@ bool OutputHLSL::isVaryingIn(TQualifier qualifier) ...@@ -3787,6 +3790,7 @@ bool OutputHLSL::isVaryingIn(TQualifier qualifier)
case EvqSmoothIn: case EvqSmoothIn:
case EvqFlatIn: case EvqFlatIn:
case EvqCentroidIn: case EvqCentroidIn:
case EvqFragmentIn:
return true; return true;
} }
......
...@@ -318,7 +318,8 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIn ...@@ -318,7 +318,8 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIn
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 EvqAttribute: message = "can't modify an attribute"; break;
case EvqVertexInput: message = "can't modify an input"; 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 EvqVaryingIn: message = "can't modify a varying"; break; case EvqVaryingIn: message = "can't modify a varying"; break;
case EvqFragCoord: message = "can't modify gl_FragCoord"; break; case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
...@@ -630,8 +631,8 @@ bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPub ...@@ -630,8 +631,8 @@ bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPub
case EvqVaryingIn: case EvqVaryingIn:
case EvqVaryingOut: case EvqVaryingOut:
case EvqAttribute: case EvqAttribute:
case EvqVertexInput: case EvqVertexIn:
case EvqFragmentOutput: 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));
...@@ -732,7 +733,7 @@ bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* ex ...@@ -732,7 +733,7 @@ bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* ex
// //
bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type) bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type)
{ {
if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexInput) || (type.qualifier == EvqConst)) { if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConst)) {
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;
} }
...@@ -938,7 +939,7 @@ bool TParseContext::singleDeclarationErrorCheck(TPublicType &publicType, const T ...@@ -938,7 +939,7 @@ bool TParseContext::singleDeclarationErrorCheck(TPublicType &publicType, const T
return true; return true;
} }
if (publicType.qualifier != EvqVertexInput && publicType.qualifier != EvqFragmentOutput && layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier)) if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut && layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
{ {
return true; return true;
} }
...@@ -1164,10 +1165,28 @@ TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, TLayoutQu ...@@ -1164,10 +1165,28 @@ TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, TLayoutQu
{ {
switch (qualifier) switch (qualifier)
{ {
case EvqVertexInput: case EvqSmoothIn:
case EvqFragmentOutput: case EvqSmoothOut:
case EvqVaryingIn: case EvqVertexOut:
case EvqVaryingOut: 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) if (typeSpecifier.type == EbtBool)
{ {
error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier)); error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
...@@ -2123,12 +2142,12 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co ...@@ -2123,12 +2142,12 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co
{ {
if (baseExpression->isInterfaceBlock()) if (baseExpression->isInterfaceBlock())
{ {
error(location, "", "[", "array indexes for interface blocks arrays must be constant integeral expressions"); error(location, "", "[", "array indexes for interface blocks arrays must be constant integral expressions");
recover(); recover();
} }
else if (baseExpression->getQualifier() == EvqFragmentOutput) else if (baseExpression->getQualifier() == EvqFragmentOut)
{ {
error(location, "", "[", "array indexes for output variables must be constant integeral expressions"); error(location, "", "[", "array indexes for fragment outputs must be constant integral expressions");
recover(); recover();
} }
...@@ -2462,7 +2481,7 @@ TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpo ...@@ -2462,7 +2481,7 @@ TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpo
{ {
TQualifier mergedQualifier = EvqSmoothIn; TQualifier mergedQualifier = EvqSmoothIn;
if (storageQualifier == EvqSmoothIn) { if (storageQualifier == EvqFragmentIn) {
if (interpolationQualifier == EvqSmooth) if (interpolationQualifier == EvqSmooth)
mergedQualifier = EvqSmoothIn; mergedQualifier = EvqSmoothIn;
else if (interpolationQualifier == EvqFlat) else if (interpolationQualifier == EvqFlat)
...@@ -2476,7 +2495,7 @@ TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpo ...@@ -2476,7 +2495,7 @@ TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpo
mergedQualifier = EvqFlatIn; mergedQualifier = EvqFlatIn;
else UNREACHABLE(); else UNREACHABLE();
} }
else if (storageQualifier == EvqSmoothOut) { else if (storageQualifier == EvqVertexOut) {
if (interpolationQualifier == EvqSmooth) if (interpolationQualifier == EvqSmooth)
mergedQualifier = EvqSmoothOut; mergedQualifier = EvqSmoothOut;
else if (interpolationQualifier == EvqFlat) else if (interpolationQualifier == EvqFlat)
......
...@@ -27,7 +27,7 @@ void ValidateOutputs::visitSymbol(TIntermSymbol *symbol) ...@@ -27,7 +27,7 @@ void ValidateOutputs::visitSymbol(TIntermSymbol *symbol)
mVisitedSymbols.insert(name); mVisitedSymbols.insert(name);
if (qualifier == EvqFragmentOutput) if (qualifier == EvqFragmentOut)
{ {
const TType &type = symbol->getType(); const TType &type = symbol->getType();
const int location = type.getLayoutQualifier().location; const int location = type.getLayoutQualifier().location;
......
...@@ -246,9 +246,9 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node) ...@@ -246,9 +246,9 @@ bool CollectAttribsUniforms::visitAggregate(Visit, TIntermAggregate* node)
case EOpDeclaration: { case EOpDeclaration: {
const TIntermSequence& sequence = node->getSequence(); const TIntermSequence& sequence = node->getSequence();
TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
if (qualifier == EvqAttribute || qualifier == EvqVertexInput || qualifier == EvqUniform) if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqUniform)
{ {
TVariableInfoList& infoList = (qualifier == EvqAttribute || qualifier == EvqVertexInput) ? TVariableInfoList& infoList = (qualifier == EvqAttribute || qualifier == EvqVertexIn) ?
mAttribs : mUniforms; mAttribs : mUniforms;
for (TIntermSequence::const_iterator i = sequence.begin(); for (TIntermSequence::const_iterator i = sequence.begin();
i != sequence.end(); ++i) i != sequence.end(); ++i)
......
...@@ -1190,11 +1190,11 @@ storage_qualifier ...@@ -1190,11 +1190,11 @@ storage_qualifier
} }
| IN_QUAL { | IN_QUAL {
ES3_ONLY("in", @1, "storage qualifier"); ES3_ONLY("in", @1, "storage qualifier");
$$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqSmoothIn : EvqVertexInput; $$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn;
} }
| OUT_QUAL { | OUT_QUAL {
ES3_ONLY("out", @1, "storage qualifier"); ES3_ONLY("out", @1, "storage qualifier");
$$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOutput : EvqSmoothOut; $$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut;
} }
| CENTROID IN_QUAL { | CENTROID IN_QUAL {
ES3_ONLY("centroid in", @1, "storage qualifier"); ES3_ONLY("centroid in", @1, "storage qualifier");
...@@ -1203,7 +1203,7 @@ storage_qualifier ...@@ -1203,7 +1203,7 @@ storage_qualifier
context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader"); context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader");
context->recover(); context->recover();
} }
$$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexInput; $$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn;
} }
| CENTROID OUT_QUAL { | CENTROID OUT_QUAL {
ES3_ONLY("centroid out", @1, "storage qualifier"); ES3_ONLY("centroid out", @1, "storage qualifier");
...@@ -1212,7 +1212,7 @@ storage_qualifier ...@@ -1212,7 +1212,7 @@ storage_qualifier
context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader"); context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader");
context->recover(); context->recover();
} }
$$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOutput : EvqCentroidOut; $$.qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut;
} }
| UNIFORM { | UNIFORM {
if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform")) if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform"))
......
...@@ -3852,7 +3852,7 @@ yyreduce: ...@@ -3852,7 +3852,7 @@ yyreduce:
{ {
ES3_ONLY("in", (yylsp[(1) - (1)]), "storage qualifier"); ES3_ONLY("in", (yylsp[(1) - (1)]), "storage qualifier");
(yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqSmoothIn : EvqVertexInput; (yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn;
} }
break; break;
...@@ -3860,7 +3860,7 @@ yyreduce: ...@@ -3860,7 +3860,7 @@ yyreduce:
{ {
ES3_ONLY("out", (yylsp[(1) - (1)]), "storage qualifier"); ES3_ONLY("out", (yylsp[(1) - (1)]), "storage qualifier");
(yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOutput : EvqSmoothOut; (yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut;
} }
break; break;
...@@ -3873,7 +3873,7 @@ yyreduce: ...@@ -3873,7 +3873,7 @@ yyreduce:
context->error((yylsp[(1) - (2)]), "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader"); context->error((yylsp[(1) - (2)]), "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader");
context->recover(); context->recover();
} }
(yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexInput; (yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn;
} }
break; break;
...@@ -3886,7 +3886,7 @@ yyreduce: ...@@ -3886,7 +3886,7 @@ yyreduce:
context->error((yylsp[(1) - (2)]), "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader"); context->error((yylsp[(1) - (2)]), "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader");
context->recover(); context->recover();
} }
(yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOutput : EvqCentroidOut; (yyval.interm.type).qualifier = (context->shaderType == SH_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut;
} }
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