summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2019-08-08 15:40:29 -0700
committerIan Romanick <ian.d.romanick@intel.com>2020-02-19 17:43:16 -0800
commitae9a8633f08b6f49fd151f9d18909f2ac980fb03 (patch)
treebae22c3c95f4bf2daabf1e1ce8465f7069113863
parentfde152ac76cde4688fa5b967770cce458905f044 (diff)
glsl: Verify floating point underflow compared with zero
Recent optimizations added to Mesa's GLSL compiler detected that (x*y) must be greater than zero if both x and y are greater than zero. It would then use this information to eliminate comparisons with zero like (x*y) > 0 because the result "must" be true. If x and y are sufficiently small, the multiplication can underflow and flush to zero. These tests exercise this for multiplication, pow, exp2, and fma. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=111308 Part-of: <https://gitlab.freedesktop.org/mesa/piglit/merge_requests/110>
-rw-r--r--tests/spec/arb_gpu_shader5/execution/fs-underflow-fma-compare-zero.shader_test64
-rw-r--r--tests/spec/glsl-1.20/execution/fs-underflow-exp2-compare-zero.shader_test45
-rw-r--r--tests/spec/glsl-1.20/execution/fs-underflow-mul-compare-zero.shader_test59
-rw-r--r--tests/spec/glsl-1.20/execution/fs-underflow-pow-compare-zero.shader_test62
4 files changed, 230 insertions, 0 deletions
diff --git a/tests/spec/arb_gpu_shader5/execution/fs-underflow-fma-compare-zero.shader_test b/tests/spec/arb_gpu_shader5/execution/fs-underflow-fma-compare-zero.shader_test
new file mode 100644
index 000000000..1f81a4f6d
--- /dev/null
+++ b/tests/spec/arb_gpu_shader5/execution/fs-underflow-fma-compare-zero.shader_test
@@ -0,0 +1,64 @@
+# Some compilers may try to optimize comparisons based on the expected
+# range of the sources. Check that pessimal cases are handled correctly.
+#
+# See also https://bugs.freedesktop.org/show_bug.cgi?id=111308
+
+[require]
+GLSL >= 1.50
+GL_ARB_gpu_shader5
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 150
+#extension GL_ARB_gpu_shader5: require
+
+uniform float a;
+uniform float b;
+uniform float c;
+uniform float zero = 0.0;
+uniform bool expect_non_zero;
+
+const float epsilon = 0.000000000000000000433681;
+
+out vec4 piglit_fragcolor;
+
+void main(void)
+{
+ /* The worrysome optimization only occurs if the compiler believes that
+ * the mathematical result of the multiply is > 0.
+ */
+ float ab = (abs(a) + epsilon) * (abs(b) + epsilon);
+ float result = fma(ab, epsilon, abs(zero));
+
+ piglit_fragcolor = expect_non_zero == (0 < result)
+ ? vec4(0.0, 1.0, 0.0, 1.0)
+ : vec4(1.0, 0.0, 0.0, 1.0);
+}
+
+[test]
+# 2**(-61) * 2**(61) * 2**(-61) = 2**(-61)
+uniform float a 0.000000000000000000433681
+uniform float b 2305843009213693952
+uniform int expect_non_zero 1
+draw rect -1 -1 1 1
+
+# 2**(-61) * 2**(-28) * 2**(-61) = 2**(-150)
+uniform float a 0.000000000000000000433681
+uniform float b 0.0000000037252902984619140625
+uniform int expect_non_zero 0
+draw rect 0 -1 1 1
+
+# 2**(-45) * 2**(-44) * 2**(-61) = 2**(-150)
+uniform float a 0.000000000000028421709430404007434844970703125
+uniform float b 0.00000000000005684341886080801486968994140625
+uniform int expect_non_zero 0
+draw rect -1 0 1 1
+
+# 2**(-61) * 2**(-61) * 2**(-61) = 2**(-183)
+uniform float a 0.000000000000000000433681
+uniform float b 0.000000000000000000433681
+uniform int expect_non_zero 0
+draw rect 0 0 1 1
+
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/glsl-1.20/execution/fs-underflow-exp2-compare-zero.shader_test b/tests/spec/glsl-1.20/execution/fs-underflow-exp2-compare-zero.shader_test
new file mode 100644
index 000000000..433b4bd05
--- /dev/null
+++ b/tests/spec/glsl-1.20/execution/fs-underflow-exp2-compare-zero.shader_test
@@ -0,0 +1,45 @@
+# Some compilers may try to optimize comparisons based on the expected
+# range of the sources. Check that pessimal cases are handled correctly.
+#
+# See also https://bugs.freedesktop.org/show_bug.cgi?id=111308
+
+[require]
+GLSL >= 1.20
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 120
+
+uniform float power;
+uniform bool expect_non_zero;
+
+void main(void)
+{
+ float result = exp2(power);
+
+ gl_FragColor = expect_non_zero == (0 < result)
+ ? vec4(0.0, 1.0, 0.0, 1.0)
+ : vec4(1.0, 0.0, 0.0, 1.0);
+}
+
+[test]
+uniform float power 0
+uniform int expect_non_zero 1
+draw rect -1 -1 1 1
+
+uniform float power -6
+uniform int expect_non_zero 1
+draw rect 0 -1 1 1
+
+# Smallest possible subnormal number is 2**-149. If someone has a
+# representation that has more exponent, this case may incorrectly fail.
+uniform float power -150
+uniform int expect_non_zero 0
+draw rect -1 0 1 1
+
+uniform float power -1000000
+uniform int expect_non_zero 0
+draw rect 0 0 1 1
+
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/glsl-1.20/execution/fs-underflow-mul-compare-zero.shader_test b/tests/spec/glsl-1.20/execution/fs-underflow-mul-compare-zero.shader_test
new file mode 100644
index 000000000..7591b01a1
--- /dev/null
+++ b/tests/spec/glsl-1.20/execution/fs-underflow-mul-compare-zero.shader_test
@@ -0,0 +1,59 @@
+# Some compilers may try to optimize comparisons based on the expected
+# range of the sources. Check that pessimal cases are handled correctly.
+#
+# See also https://bugs.freedesktop.org/show_bug.cgi?id=111308
+
+[require]
+GLSL >= 1.20
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 120
+
+uniform float a;
+uniform float b;
+uniform float c;
+uniform bool expect_non_zero;
+
+const float epsilon = 0.000000000000000000433681;
+
+void main(void)
+{
+ /* The worrysome optimization only occurs if the compiler believes that
+ * the mathematical result of the multiply is > 0.
+ */
+ float result = (abs(a) + epsilon) *
+ (abs(b) + epsilon) *
+ epsilon;
+ gl_FragColor = expect_non_zero == (0 < result)
+ ? vec4(0.0, 1.0, 0.0, 1.0)
+ : vec4(1.0, 0.0, 0.0, 1.0);
+}
+
+[test]
+# 2**(-61) * 2**(61) * 2**(-61) = 2**(-61)
+uniform float a 0.000000000000000000433681
+uniform float b 2305843009213693952
+uniform int expect_non_zero 1
+draw rect -1 -1 1 1
+
+# 2**(-61) * 2**(-28) * 2**(-61) = 2**(-150)
+uniform float a 0.000000000000000000433681
+uniform float b 0.0000000037252902984619140625
+uniform int expect_non_zero 0
+draw rect 0 -1 1 1
+
+# 2**(-45) * 2**(-44) * 2**(-61) = 2**(-150)
+uniform float a 0.000000000000028421709430404007434844970703125
+uniform float b 0.00000000000005684341886080801486968994140625
+uniform int expect_non_zero 0
+draw rect -1 0 1 1
+
+# 2**(-61) * 2**(-61) * 2**(-61) = 2**(-183)
+uniform float a 0.000000000000000000433681
+uniform float b 0.000000000000000000433681
+uniform int expect_non_zero 0
+draw rect 0 0 1 1
+
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/glsl-1.20/execution/fs-underflow-pow-compare-zero.shader_test b/tests/spec/glsl-1.20/execution/fs-underflow-pow-compare-zero.shader_test
new file mode 100644
index 000000000..01222affa
--- /dev/null
+++ b/tests/spec/glsl-1.20/execution/fs-underflow-pow-compare-zero.shader_test
@@ -0,0 +1,62 @@
+# Some compilers may try to optimize comparisons based on the expected
+# range of the sources. Check that pessimal cases are handled correctly.
+#
+# See also https://bugs.freedesktop.org/show_bug.cgi?id=111308
+
+[require]
+GLSL >= 1.20
+
+[vertex shader passthrough]
+
+[fragment shader]
+#version 120
+
+uniform float base;
+uniform float power;
+uniform bool expect_non_zero;
+
+void main(void)
+{
+ float result = pow(base, power);
+
+ gl_FragColor = expect_non_zero == (0 < result)
+ ? vec4(0.0, 1.0, 0.0, 1.0)
+ : vec4(1.0, 0.0, 0.0, 1.0);
+}
+
+[test]
+uniform float base 2
+uniform float power 0
+uniform int expect_non_zero 1
+draw rect -1 -1 1 1
+
+# Smallest possible subnormal number is 2**-149. If someone has a
+# representation that has more exponent, this case may incorrectly fail.
+uniform float base 2
+uniform float power -150
+uniform int expect_non_zero 0
+draw rect 0 -1 1 1
+
+# Be very careful here... GLSL 1.20 has very low requirements for
+# precision of calculations. GLSL ES 1.00, for example, only requires
+# 2**-61. Specify a number slightly larger than that to ensure the
+# hardware doesn't flush to zero. Smallest possible subnormal number
+# is 2**-149. If someone has a representation that has more exponent,
+# this case may incorrectly fail.
+#
+# Note: 2**(-150) = (2**(-61))**2.459
+uniform float base 0.000000000000000000433681
+uniform float power 2.459
+uniform int expect_non_zero 0
+draw rect -1 0 1 1
+
+# Like the previous case, but use 2**61 and a much larger negative
+# exponent.
+#
+# Note: 2**(-150) = (2**(-61))**2.459
+uniform float base 2305843009213693952
+uniform float power -2.459
+uniform int expect_non_zero 0
+draw rect 0 0 1 1
+
+probe all rgba 0.0 1.0 0.0 1.0