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/1254067
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
This commit is contained in:
Olli Etuaho 2018-10-01 15:59:59 +03:00 коммит произвёл Commit Bot
Родитель 624fbdcf55
Коммит 1dfd8ae2e0
2 изменённых файлов: 79 добавлений и 10 удалений

Просмотреть файл

@ -975,9 +975,10 @@ unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TInter
{
TIntermConstantUnion *constant = expr->getAsConstantUnion();
// TODO(oetuaho@nvidia.com): Get rid of the constant == nullptr check here once all constant
// expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
// fold as array size.
// ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
// safe against corner cases we still check for constant folding. Some interpretations of the
// 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())
{
error(line, "array size must be a constant integer expression", "");
@ -3945,10 +3946,10 @@ TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
// TODO(oetuaho@nvidia.com): Get rid of indexConstantUnion == nullptr below once ANGLE is able
// to constant fold all constant expressions. Right now we don't allow indexing interface blocks
// or fragment outputs with expressions that ANGLE is not able to constant fold, even if the
// index is a constant expression.
// ANGLE should be able to fold any constant expressions resulting in an integer - but to be
// safe we don't treat "EvqConst" that's evaluated according to the spec as being sufficient
// for constness. Some interpretations of the spec have allowed constant expressions with side
// effects - like array length() method on a non-constant array.
if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
{
if (baseExpression->isInterfaceBlock())
@ -4903,9 +4904,10 @@ TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &l
error(condition->getLine(), "case label must be a scalar integer", "case");
}
TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
// TODO(oetuaho@nvidia.com): Get rid of the conditionConst == nullptr check once all constant
// expressions can be folded. Right now we don't allow constant expressions that ANGLE can't
// fold in case labels.
// ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
// safe against corner cases we still check for conditionConst. Some interpretations of the
// spec have allowed constant expressions with side effects - like array length() method on a
// non-constant array.
if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
{
error(condition->getLine(), "case label must be constant", "case");

Просмотреть файл

@ -5967,3 +5967,70 @@ TEST_F(FragmentShaderValidationTest, CaseInsideBlock)
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;
}
}