Commit 6c9503ec by Jamie Madill Committed by Commit Bot

D3D11: Improve integer pow workaround.

A slight bug in the problem case detection applied the workaround overly-broadly. Also included a much more thorough test. BUG=angleproject:851 Change-Id: I5c09d67eee3622c144401769af85958f23b60c57 Reviewed-on: https://chromium-review.googlesource.com/371380Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 1200c41b
...@@ -95,7 +95,8 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -95,7 +95,8 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
} }
// Test 3: value is integer or pretty close to an integer. // Test 3: value is integer or pretty close to an integer.
float frac = std::abs(value) - std::floor(std::abs(value)); float absval = std::abs(value);
float frac = absval - std::round(absval);
if (frac > 0.0001f) if (frac > 0.0001f)
{ {
return true; return true;
......
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
using namespace angle; using namespace angle;
namespace
{
class GLSLTest : public ANGLETest class GLSLTest : public ANGLETest
{ {
protected: protected:
...@@ -1607,43 +1610,65 @@ TEST_P(GLSLTest, DepthRangeUniforms) ...@@ -1607,43 +1610,65 @@ TEST_P(GLSLTest, DepthRangeUniforms)
glDeleteProgram(program); glDeleteProgram(program);
} }
std::string GenerateSmallPowShader(double base, double exponent)
{
std::stringstream stream;
stream.precision(8);
double result = pow(base, exponent);
stream << "precision highp float;\n"
<< "float fun(float arg)\n"
<< "{\n"
<< " return pow(arg, " << std::fixed << exponent << ");\n"
<< "}\n"
<< "\n"
<< "void main()\n"
<< "{\n"
<< " const float a = " << std::scientific << base << ";\n"
<< " float b = fun(a);\n"
<< " if (abs(" << result << " - b) < " << std::abs(result * 0.001) << ")\n"
<< " {\n"
<< " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
<< " }\n"
<< " else\n"
<< " {\n"
<< " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
<< " }\n"
<< "}\n";
return stream.str();
}
// Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function' // Covers the WebGL test 'glsl/bugs/pow-of-small-constant-in-user-defined-function'
// See http://anglebug.com/851 // See http://anglebug.com/851
TEST_P(GLSLTest, PowOfSmallConstant) TEST_P(GLSLTest, PowOfSmallConstant)
{ {
const std::string &fragmentShaderSource = SHADER_SOURCE std::vector<double> bads;
( for (int eps = -1; eps <= 1; ++eps)
precision highp float; {
for (int i = -4; i <= 5; ++i)
float fun(float arg)
{ {
// These values are still easily within the highp range. if (i >= -1 && i <= 1)
// The minimum range in terms of 10's exponent is around -19 to 19, and IEEE-754 single precision range is higher than that. continue;
return pow(arg, 2.0); const double epsilon = 1.0e-8;
double bad = static_cast<double>(i) + static_cast<double>(eps) * epsilon;
bads.push_back(bad);
} }
}
void main() for (double bad : bads)
{ {
// Note that the bug did not reproduce if an uniform was passed to the function instead of a constant, const std::string &fragmentShaderSource = GenerateSmallPowShader(1.0e-6, bad);
// or if the expression was moved outside the user-defined function.
const float a = 1.0e-6;
float b = 1.0e12 * fun(a);
if (abs(b - 1.0) < 0.01)
{
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); // green
}
else
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // red
}
}
);
ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource); ANGLE_GL_PROGRAM(program, mSimpleVSSource, fragmentShaderSource);
drawQuad(program.get(), "inputAttribute", 0.5f); drawQuad(program.get(), "inputAttribute", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
EXPECT_GL_NO_ERROR(); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
EXPECT_GL_NO_ERROR();
}
} }
// Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and // Test that fragment shaders which contain non-constant loop indexers and compiled for FL9_3 and
...@@ -2185,6 +2210,8 @@ TEST_P(GLSLTest, NestedPowStatements) ...@@ -2185,6 +2210,8 @@ TEST_P(GLSLTest, NestedPowStatements)
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
} }
} // anonymous namespace
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(GLSLTest, ANGLE_INSTANTIATE_TEST(GLSLTest,
ES2_D3D9(), ES2_D3D9(),
......
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