OSDN Git Service

Fixed atan corner case
authorAlexis Hetu <sugoi@google.com>
Tue, 15 May 2018 18:07:19 +0000 (14:07 -0400)
committerAlexis Hétu <sugoi@google.com>
Wed, 16 May 2018 17:44:32 +0000 (17:44 +0000)
atan(0, <negative>) was returning 0 instead of PI. Did a simple
fix in the arctan() function and added an associated unit test.

Change-Id: Idbbdaf099b5104e3aaa2868ca8fd806c6c735981
Reviewed-on: https://swiftshader-review.googlesource.com/18868
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
src/Shader/ShaderCore.cpp
tests/unittests/unittests.cpp

index 883131c..338605c 100644 (file)
@@ -402,14 +402,13 @@ namespace sw
                Float4 y0 = Abs(y);
 
                // Rotate to right quadrant when in left quadrant
-               Int4 non_zero_y = CmpNEQ(y0, Float4(0.0f));
-               Int4 Q = CmpLT(x0, Float4(0.0f)) & non_zero_y;
+               Int4 Q = CmpLT(x0, Float4(0.0f));
                theta += As<Float4>(Q & As<Int4>(half_pi));
                Float4 x1 = As<Float4>((Q & As<Int4>(y0)) | (~Q & As<Int4>(x0)));  // FIXME: Vector select
                Float4 y1 = As<Float4>((Q & As<Int4>(-x0)) | (~Q & As<Int4>(y0))); // FIXME: Vector select
 
                // Mirror to first octant when in second octant
-               Int4 O = CmpNLT(y1, x1) & non_zero_y;
+               Int4 O = CmpNLT(y1, x1);
                Float4 x2 = As<Float4>((O & As<Int4>(y1)) | (~O & As<Int4>(x1))); // FIXME: Vector select
                Float4 y2 = As<Float4>((O & As<Int4>(x1)) | (~O & As<Int4>(y1))); // FIXME: Vector select
 
@@ -417,7 +416,7 @@ namespace sw
                Int4 zero_x = CmpEQ(x2, Float4(0.0f));
                Int4 inf_y = IsInf(y2); // Since x2 >= y2, this means x2 == y2 == inf, so we use 45 degrees or pi/4
                Float4 atan2_theta = arctan_01(y2 / x2, pp);
-               theta += As<Float4>((~zero_x & ~inf_y & non_zero_y & ((O & As<Int4>(half_pi - atan2_theta)) | (~O & (As<Int4>(atan2_theta))))) | // FIXME: Vector select
+               theta += As<Float4>((~zero_x & ~inf_y & ((O & As<Int4>(half_pi - atan2_theta)) | (~O & (As<Int4>(atan2_theta))))) | // FIXME: Vector select
                                    (inf_y & As<Int4>(quarter_pi)));
 
                // Recover loss of precision for tiny theta angles
index 1418e43..3132258 100644 (file)
@@ -258,9 +258,12 @@ protected:
                GLint posLoc = glGetAttribLocation(program, "position");
                EXPECT_GLENUM_EQ(GL_NONE, glGetError());
 
-               GLint location = glGetUniformLocation(program, textureName);
-               ASSERT_NE(-1, location);
-               glUniform1i(location, 0);
+               if(textureName)
+               {
+                       GLint location = glGetUniformLocation(program, textureName);
+                       ASSERT_NE(-1, location);
+                       glUniform1i(location, 0);
+               }
 
                float vertices[18] = { -1.0f,  1.0f, 0.5f,
                                       -1.0f, -1.0f, 0.5f,
@@ -368,6 +371,60 @@ TEST_F(SwiftShaderTest, SamplerArrayInStructArrayAsFunctionArg)
        Uninitialize();
 }
 
+// Test sampling from a sampler in a struct as a function argument
+TEST_F(SwiftShaderTest, AtanCornerCases)
+{
+       Initialize(3, false);
+
+       const std::string vs =
+               "#version 300 es\n"
+               "in vec4 position;\n"
+               "void main()\n"
+               "{\n"
+               "       gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+               "}\n";
+
+       const std::string fs =
+               "#version 300 es\n"
+               "precision mediump float;\n"
+               "const float kPI = 3.14159265358979323846;"
+               "uniform float positive_value;\n"
+               "uniform float negative_value;\n"
+               "out vec4 fragColor;\n"
+               "void main()\n"
+               "{\n"
+               "       // Should yield vec4(0, pi, pi/2, -pi/2)\n"
+               "       vec4 result = atan(vec4(0.0, 0.0, positive_value, negative_value),\n"
+               "                          vec4(positive_value, negative_value, 0.0, 0.0));\n"
+               "       fragColor = (result / vec4(kPI)) + vec4(0.5, -0.5, 0.0, 1.0) + vec4(0.5 / 255.0);\n"
+               "}\n";
+
+       const ProgramHandles ph = createProgram(vs, fs);
+
+       glUseProgram(ph.program);
+       GLint positive_value = glGetUniformLocation(ph.program, "positive_value");
+       ASSERT_NE(-1, positive_value);
+       GLint negative_value = glGetUniformLocation(ph.program, "negative_value");
+       ASSERT_NE(-1, negative_value);
+       glUniform1f(positive_value,  1.0);
+       glUniform1f(negative_value, -1.0);
+
+       glClearColor(0.0, 0.0, 0.0, 0.0);
+       glClear(GL_COLOR_BUFFER_BIT);
+       EXPECT_GLENUM_EQ(GL_NONE, glGetError());
+
+       drawQuad(ph.program, nullptr);
+
+       deleteProgram(ph);
+
+       unsigned char grey[4] = { 128, 128, 128, 128 };
+       compareColor(grey);
+
+       EXPECT_GLENUM_EQ(GL_NONE, glGetError());
+
+       Uninitialize();
+}
+
 // Note: GL_ARB_texture_rectangle is part of gl2extchromium.h in the Chromium repo
 // GL_ARB_texture_rectangle
 #ifndef GL_ARB_texture_rectangle