Commit a82b58e0 by Alexis Hetu Committed by Alexis Hétu

Fixed a WebGL conformance test

It is illegal to use both glFragData and glFragColor in the same shader according to the OpenGL spec, so a check was added to verify that this doesn't happen, and returns an error if it does. BUG=18029434 Change-Id: Ifee14dd539cacc7cd16a2c2634d3e021dbf7ff8e Reviewed-on: https://swiftshader-review.googlesource.com/1430Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent a53bf06c
...@@ -114,6 +114,7 @@ namespace sh ...@@ -114,6 +114,7 @@ namespace sh
functionArray.push_back(Function(0, "main(", 0, 0)); functionArray.push_back(Function(0, "main(", 0, 0));
currentFunction = 0; currentFunction = 0;
outputQualifier = EvqOutput; // Set outputQualifier to any value other than EvqFragColor or EvqFragData
} }
OutputASM::~OutputASM() OutputASM::~OutputASM()
...@@ -1266,7 +1267,7 @@ namespace sh ...@@ -1266,7 +1267,7 @@ namespace sh
Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, int index) Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, int index)
{ {
if(dst && registerType(dst) == sw::Shader::PARAMETER_SAMPLER) if(dst && IsSampler(dst->getBasicType()))
{ {
op = sw::Shader::OPCODE_NULL; // Can't assign to a sampler, but this is hit when indexing sampler arrays op = sw::Shader::OPCODE_NULL; // Can't assign to a sampler, but this is hit when indexing sampler arrays
} }
...@@ -1463,7 +1464,7 @@ namespace sh ...@@ -1463,7 +1464,7 @@ namespace sh
{ {
parameter.index = registerIndex(arg) + index; parameter.index = registerIndex(arg) + index;
if(registerType(arg) == sw::Shader::PARAMETER_SAMPLER) if(IsSampler(arg->getBasicType()))
{ {
TIntermBinary *binary = argument->getAsBinaryNode(); TIntermBinary *binary = argument->getAsBinaryNode();
...@@ -1740,12 +1741,23 @@ namespace sh ...@@ -1740,12 +1741,23 @@ namespace sh
sw::Shader::ParameterType OutputASM::registerType(TIntermTyped *operand) sw::Shader::ParameterType OutputASM::registerType(TIntermTyped *operand)
{ {
if(IsSampler(operand->getBasicType()) && (operand->getQualifier() == EvqUniform || operand->getQualifier() == EvqTemporary)) // Function parameters are temporaries if(IsSampler(operand->getBasicType()))
{ {
return sw::Shader::PARAMETER_SAMPLER; return sw::Shader::PARAMETER_SAMPLER;
} }
switch(operand->getQualifier()) const TQualifier qualifier = operand->getQualifier();
if((EvqFragColor == qualifier) || (EvqFragData == qualifier))
{
if(((EvqFragData == qualifier) && (EvqFragColor == outputQualifier)) ||
((EvqFragColor == qualifier) && (EvqFragData == outputQualifier)))
{
mContext.error(operand->getLine(), "static assignment to both gl_FragData and gl_FragColor", "");
}
outputQualifier = qualifier;
}
switch(qualifier)
{ {
case EvqTemporary: return sw::Shader::PARAMETER_TEMP; case EvqTemporary: return sw::Shader::PARAMETER_TEMP;
case EvqGlobal: return sw::Shader::PARAMETER_TEMP; case EvqGlobal: return sw::Shader::PARAMETER_TEMP;
...@@ -1775,7 +1787,7 @@ namespace sh ...@@ -1775,7 +1787,7 @@ namespace sh
int OutputASM::registerIndex(TIntermTyped *operand) int OutputASM::registerIndex(TIntermTyped *operand)
{ {
if(registerType(operand) == sw::Shader::PARAMETER_SAMPLER) if(IsSampler(operand->getBasicType()))
{ {
return samplerRegister(operand); return samplerRegister(operand);
} }
...@@ -2375,7 +2387,7 @@ namespace sh ...@@ -2375,7 +2387,7 @@ namespace sh
default: UNREACHABLE(); default: UNREACHABLE();
} }
} }
else if (type.getBasicType() == EbtInt) else if(type.getBasicType() == EbtInt)
{ {
switch (type.getPrecision()) switch (type.getPrecision())
{ {
......
...@@ -161,6 +161,8 @@ namespace sh ...@@ -161,6 +161,8 @@ namespace sh
int currentFunction; int currentFunction;
std::vector<Function> functionArray; std::vector<Function> functionArray;
TQualifier outputQualifier;
TParseContext &mContext; TParseContext &mContext;
}; };
......
...@@ -114,6 +114,7 @@ namespace sh ...@@ -114,6 +114,7 @@ namespace sh
functionArray.push_back(Function(0, "main(", 0, 0)); functionArray.push_back(Function(0, "main(", 0, 0));
currentFunction = 0; currentFunction = 0;
outputQualifier = EvqOutput; // Set outputQualifier to any value other than EvqFragColor or EvqFragData
} }
OutputASM::~OutputASM() OutputASM::~OutputASM()
...@@ -1266,7 +1267,7 @@ namespace sh ...@@ -1266,7 +1267,7 @@ namespace sh
Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, int index) Instruction *OutputASM::emit(sw::Shader::Opcode op, TIntermTyped *dst, TIntermNode *src0, TIntermNode *src1, TIntermNode *src2, int index)
{ {
if(dst && registerType(dst) == sw::Shader::PARAMETER_SAMPLER) if(dst && IsSampler(dst))
{ {
op = sw::Shader::OPCODE_NULL; // Can't assign to a sampler, but this is hit when indexing sampler arrays op = sw::Shader::OPCODE_NULL; // Can't assign to a sampler, but this is hit when indexing sampler arrays
} }
...@@ -1463,7 +1464,7 @@ namespace sh ...@@ -1463,7 +1464,7 @@ namespace sh
{ {
parameter.index = registerIndex(arg) + index; parameter.index = registerIndex(arg) + index;
if(registerType(arg) == sw::Shader::PARAMETER_SAMPLER) if(IsSampler(arg))
{ {
TIntermBinary *binary = argument->getAsBinaryNode(); TIntermBinary *binary = argument->getAsBinaryNode();
...@@ -1740,12 +1741,23 @@ namespace sh ...@@ -1740,12 +1741,23 @@ namespace sh
sw::Shader::ParameterType OutputASM::registerType(TIntermTyped *operand) sw::Shader::ParameterType OutputASM::registerType(TIntermTyped *operand)
{ {
if(IsSampler(operand->getBasicType()) && (operand->getQualifier() == EvqUniform || operand->getQualifier() == EvqTemporary)) // Function parameters are temporaries if(IsSampler(operand))
{ {
return sw::Shader::PARAMETER_SAMPLER; return sw::Shader::PARAMETER_SAMPLER;
} }
switch(operand->getQualifier()) const TQualifier qualifier = operand->getQualifier();
if((EvqFragColor == qualifier) || (EvqFragData == qualifier))
{
if(((EvqFragData == qualifier) && (EvqFragColor == outputQualifier)) ||
((EvqFragColor == qualifier) && (EvqFragData == outputQualifier)))
{
mContext.error(operand->getLine(), "static assignment to both gl_FragData and gl_FragColor", "glFragColor");
}
outputQualifier = qualifier;
}
switch(qualifier)
{ {
case EvqTemporary: return sw::Shader::PARAMETER_TEMP; case EvqTemporary: return sw::Shader::PARAMETER_TEMP;
case EvqGlobal: return sw::Shader::PARAMETER_TEMP; case EvqGlobal: return sw::Shader::PARAMETER_TEMP;
...@@ -1775,7 +1787,7 @@ namespace sh ...@@ -1775,7 +1787,7 @@ namespace sh
int OutputASM::registerIndex(TIntermTyped *operand) int OutputASM::registerIndex(TIntermTyped *operand)
{ {
if(registerType(operand) == sw::Shader::PARAMETER_SAMPLER) if(IsSampler(operand))
{ {
return samplerRegister(operand); return samplerRegister(operand);
} }
...@@ -2375,7 +2387,7 @@ namespace sh ...@@ -2375,7 +2387,7 @@ namespace sh
default: UNREACHABLE(); default: UNREACHABLE();
} }
} }
else if (type.getBasicType() == EbtInt) else if(type.getBasicType() == EbtInt)
{ {
switch (type.getPrecision()) switch (type.getPrecision())
{ {
......
...@@ -161,6 +161,8 @@ namespace sh ...@@ -161,6 +161,8 @@ namespace sh
int currentFunction; int currentFunction;
std::vector<Function> functionArray; std::vector<Function> functionArray;
TQualifier outputQualifier;
TParseContext &mContext; TParseContext &mContext;
}; };
......
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