Commit 1dfd8ae2 by Olli Etuaho Committed by Commit Bot

Improve test coverage of constant folding

Clean up some TODOs in the code as well as add tests to make sure that ANGLE treats expressions indexing into constant arrays as constant expressions in different contexts. This complements the existing tests in ConstantFoldingTest. BUG=angleproject:2298 TEST=angle_unittests Change-Id: I779bf03891f7d06f14d293e69101c05d7dbf57b6 Reviewed-on: https://chromium-review.googlesource.com/1254067Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 624fbdcf
...@@ -975,9 +975,10 @@ unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TInter ...@@ -975,9 +975,10 @@ unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TInter
{ {
TIntermConstantUnion *constant = expr->getAsConstantUnion(); TIntermConstantUnion *constant = expr->getAsConstantUnion();
// TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
// expressions can be folded. Right now we don't allow constant expressions that ANGLE can't // safe against corner cases we still check for constant folding. Some interpretations of the
// fold as array size. // spec have allowed constant expressions with side effects - like array length() method on a
// non-constant array.
if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt()) if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
{ {
error(line, "array size must be a constant integer expression", ""); error(line, "array size must be a constant integer expression", "");
...@@ -3945,10 +3946,10 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, ...@@ -3945,10 +3946,10 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion(); TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
// TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able // ANGLE should be able to fold any constant expressions resulting in an integer - but to be
// to constant fold all constant expressions. Right now we don't allow indexing interface blocks // safe we don't treat "EvqConst" that's evaluated according to the spec as being sufficient
// or fragment outputs with expressions that ANGLE is not able to constant fold, even if the // for constness. Some interpretations of the spec have allowed constant expressions with side
// index is a constant expression. // effects - like array length() method on a non-constant array.
if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr) if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
{ {
if (baseExpression->isInterfaceBlock()) if (baseExpression->isInterfaceBlock())
...@@ -4903,9 +4904,10 @@ TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &l ...@@ -4903,9 +4904,10 @@ TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &l
error(condition->getLine(), "case label must be a scalar integer", "case"); error(condition->getLine(), "case label must be a scalar integer", "case");
} }
TIntermConstantUnion *conditionConst = condition->getAsConstantUnion(); TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
// TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
// expressions can be folded. Right now we don't allow constant expressions that ANGLE can't // safe against corner cases we still check for conditionConst. Some interpretations of the
// fold in case labels. // spec have allowed constant expressions with side effects - like array length() method on a
// non-constant array.
if (condition->getQualifier() != EvqConst || conditionConst == nullptr) if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
{ {
error(condition->getLine(), "case label must be constant", "case"); error(condition->getLine(), "case label must be constant", "case");
......
...@@ -5967,3 +5967,70 @@ TEST_F(FragmentShaderValidationTest, CaseInsideBlock) ...@@ -5967,3 +5967,70 @@ TEST_F(FragmentShaderValidationTest, CaseInsideBlock)
FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog; FAIL() << "Shader compilation succeeded, expecting failure:\n" << mInfoLog;
} }
} }
// Test using a value from a constant array as a case label.
TEST_F(FragmentShaderValidationTest, ValueFromConstantArrayAsCaseLabel)
{
const std::string &shaderString =
R"(#version 300 es
precision mediump float;
uniform int u;
const int[3] arr = int[3](2, 1, 0);
out vec4 my_FragColor;
void main()
{
switch (u)
{
case arr[1]:
my_FragColor = vec4(0.0);
case 2:
case 0:
default:
my_FragColor = vec4(1.0);
}
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
// Test using a value from a constant array as a fragment output index.
TEST_F(FragmentShaderValidationTest, ValueFromConstantArrayAsFragmentOutputIndex)
{
const std::string &shaderString =
R"(#version 300 es
precision mediump float;
uniform int u;
const int[3] arr = int[3](4, 1, 0);
out vec4 my_FragData[2];
void main()
{
my_FragData[arr[1]] = vec4(0.0);
my_FragData[arr[2]] = vec4(0.0);
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
// Test using a value from a constant array as an array size.
TEST_F(FragmentShaderValidationTest, ValueFromConstantArrayAsArraySize)
{
const std::string &shaderString =
R"(#version 300 es
precision mediump float;
uniform int u;
const int[3] arr = int[3](0, 2, 0);
const int[arr[1]] arr2 = int[2](2, 1);
out vec4 my_FragColor;
void main()
{
my_FragColor = vec4(arr2[1]);
})";
if (!compile(shaderString))
{
FAIL() << "Shader compilation failed, expecting success:\n" << mInfoLog;
}
}
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