Test shader built-in corner cases in constant folding tests
IEEE rules for generating zero or infinity are now checked for the
constant folding of several built-in functions except for the cases
where ESSL 3.00.6 explicitly states that the results are undefined.
BUG=chromium:661857
TEST=angle_unittests
Change-Id: I2ce427229a5583039694d060ea6db29c5bdace97
Reviewed-on: https://chromium-review.googlesource.com/414370
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/tests/compiler_tests/ConstantFolding_test.cpp b/src/tests/compiler_tests/ConstantFolding_test.cpp
index fd316d5..d953314 100644
--- a/src/tests/compiler_tests/ConstantFolding_test.cpp
+++ b/src/tests/compiler_tests/ConstantFolding_test.cpp
@@ -12,6 +12,7 @@
#include "angle_gl.h"
#include "gtest/gtest.h"
#include "GLSLANG/ShaderLang.h"
+#include "common/mathutil.h"
#include "compiler/translator/PoolAlloc.h"
#include "compiler/translator/TranslatorESSL.h"
@@ -68,11 +69,27 @@
private:
bool isEqual(const TConstantUnion &node, const float &value) const
{
+ if (node.getType() != EbtFloat)
+ {
+ return false;
+ }
+ if (value == std::numeric_limits<float>::infinity())
+ {
+ return gl::isInf(node.getFConst()) && node.getFConst() > 0;
+ }
+ else if (value == -std::numeric_limits<float>::infinity())
+ {
+ return gl::isInf(node.getFConst()) && node.getFConst() < 0;
+ }
return mFaultTolerance >= fabsf(node.getFConst() - value);
}
bool isEqual(const TConstantUnion &node, const int &value) const
{
+ if (node.getType() != EbtInt)
+ {
+ return false;
+ }
ASSERT(mFaultTolerance < std::numeric_limits<int>::max());
// abs() returns 0 at least on some platforms when the minimum int value is passed in (it
// doesn't have a positive counterpart).
@@ -82,6 +99,10 @@
bool isEqual(const TConstantUnion &node, const unsigned int &value) const
{
+ if (node.getType() != EbtUInt)
+ {
+ return false;
+ }
ASSERT(mFaultTolerance < static_cast<unsigned int>(std::numeric_limits<int>::max()));
return static_cast<int>(mFaultTolerance) >=
abs(static_cast<int>(node.getUConst() - value)) &&
@@ -90,6 +111,10 @@
bool isEqual(const TConstantUnion &node, const bool &value) const
{
+ if (node.getType() != EbtBool)
+ {
+ return false;
+ }
return node.getBConst() == value;
}
@@ -171,6 +196,36 @@
TPoolAllocator allocator;
};
+class ConstantFoldingExpressionTest : public ConstantFoldingTest
+{
+ public:
+ ConstantFoldingExpressionTest() {}
+
+ void evaluateFloat(const std::string &floatExpression)
+ {
+ std::stringstream shaderStream;
+ shaderStream << "#version 300 es\n"
+ "precision mediump float;\n"
+ "out float my_FragColor;\n"
+ "void main()\n"
+ "{\n"
+ << " my_FragColor = " << floatExpression << ";\n"
+ << "}\n";
+ compile(shaderStream.str());
+ }
+};
+
+// Test that zero, true or false are not found in AST when they are not expected. This is to make
+// sure that the subsequent tests run correctly.
+TEST_F(ConstantFoldingExpressionTest, FoldFloatTestSanityCheck)
+{
+ const std::string &floatString = "1.0";
+ evaluateFloat(floatString);
+ ASSERT_FALSE(constantFoundInAST(0.0f));
+ ASSERT_FALSE(constantFoundInAST(true));
+ ASSERT_FALSE(constantFoundInAST(false));
+}
+
TEST_F(ConstantFoldingTest, FoldIntegerAdd)
{
const std::string &shaderString =
@@ -1088,17 +1143,222 @@
// ESSL 3.00.6 section 4.1.4 Floats:
// "A value with a magnitude too small to be represented as a mantissa and exponent is converted to
// zero."
-TEST_F(ConstantFoldingTest, FoldTooSmallFloat)
+TEST_F(ConstantFoldingExpressionTest, FoldTooSmallFloat)
{
- const std::string &shaderString =
- "#version 300 es\n"
- "precision mediump float;\n"
- "out vec4 my_FragColor;\n"
- "void main()\n"
- "{\n"
- " bool b = (0.0 == 1.0e-2048);\n"
- " my_FragColor = vec4(b);\n"
- "}\n";
- compile(shaderString);
- ASSERT_TRUE(constantFoundInAST(true));
+ const std::string &floatString = "1.0e-2048";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim radians(x) x -> inf = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldRadiansInfinity)
+{
+ const std::string &floatString = "radians(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim degrees(x) x -> inf = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldDegreesInfinity)
+{
+ const std::string &floatString = "degrees(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that sinh(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldSinhInfinity)
+{
+ const std::string &floatString = "sinh(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that sinh(-inf) = -inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldSinhNegativeInfinity)
+{
+ const std::string &floatString = "sinh(-1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that cosh(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldCoshInfinity)
+{
+ const std::string &floatString = "cosh(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that cosh(-inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldCoshNegativeInfinity)
+{
+ const std::string &floatString = "cosh(-1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that asinh(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldAsinhInfinity)
+{
+ const std::string &floatString = "asinh(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that asinh(-inf) = -inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldAsinhNegativeInfinity)
+{
+ const std::string &floatString = "asinh(-1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(-std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that acosh(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldAcoshInfinity)
+{
+ const std::string &floatString = "acosh(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that pow or powr(0, inf) = 0.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldPowInfinity)
+{
+ const std::string &floatString = "pow(0.0, 1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// IEEE 754 dictates that exp(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldExpInfinity)
+{
+ const std::string &floatString = "exp(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that exp(-inf) = 0.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldExpNegativeInfinity)
+{
+ const std::string &floatString = "exp(-1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// IEEE 754 dictates that log(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldLogInfinity)
+{
+ const std::string &floatString = "log(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that exp2(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldExp2Infinity)
+{
+ const std::string &floatString = "exp2(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that exp2(-inf) = 0.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldExp2NegativeInfinity)
+{
+ const std::string &floatString = "exp2(-1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// IEEE 754 dictates that log2(inf) = inf.
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldLog2Infinity)
+{
+ const std::string &floatString = "log2(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim sqrt(x) x -> inf = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldSqrtInfinity)
+{
+ const std::string &floatString = "sqrt(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that rSqrt(inf) = 0
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldInversesqrtInfinity)
+{
+ const std::string &floatString = "inversesqrt(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(0.0f));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim length(x) x -> inf = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldLengthInfinity)
+{
+ const std::string &floatString = "length(1.0e2048)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim dot(x, y) x -> inf, y > 0 = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldDotInfinity)
+{
+ const std::string &floatString = "dot(1.0e2048, 1.0)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// IEEE 754 dictates that behavior of infinity is derived from limiting cases of real arithmetic.
+// lim dot(vec2(x, y), vec2(z)) x -> inf, finite y, z > 0 = inf
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldDotInfinity2)
+{
+ const std::string &floatString = "dot(vec2(1.0e2048, -1.0), vec2(1.0))";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(std::numeric_limits<float>::infinity()));
+}
+
+// Faceforward behavior with infinity as a parameter can be derived from dot().
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldFaceForwardInfinity)
+{
+ const std::string &floatString = "faceforward(4.0, 1.0e2048, 1.0)";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(-4.0f));
+}
+
+// Faceforward behavior with infinity as a parameter can be derived from dot().
+// ESSL 3.00.6 section 4.5.1: "Infinities and zeroes are generated as dictated by IEEE".
+TEST_F(ConstantFoldingExpressionTest, FoldFaceForwardInfinity2)
+{
+ const std::string &floatString = "faceforward(vec2(4.0), vec2(1.0e2048, -1.0), vec2(1.0)).x";
+ evaluateFloat(floatString);
+ ASSERT_TRUE(constantFoundInAST(-4.0f));
}