[Piglit] [PATCH] glsl-1.50-geometry-end-primitive: ensure position data is reasonably aligned

sroland at vmware.com sroland at vmware.com
Fri Jan 8 17:12:22 PST 2016


From: Roland Scheidegger <sroland at vmware.com>

The rect halves comparison is in fact not valid in general. The reason is that
the same geometry does not have the same precision even if it it just shifted
by some fixed amount in one direction.
As an example, some calculated x value near 7 will be near 263 if drawn with
a viewport x value of 256. The value near 7 has 5 bits more precision -
when calculating the fixed-point values for rasterization (with subpixel
accuracy), the lower value thus may be rounded in a different direction
than the higher one, even with correct rounding (not even entirely sure what
"correct" rounding here means, nearest-floor or nearest-even or whatever, the
problem is independent from that). This can then cause different pixels to be
covered by the primitive.
This causes a failure with this test in llvmpipe when the rounding mode is
changed slightly (from "mostly" nearest-away-from-zero to nearest-even). I was
not able to reproduce this with this test on nvidia or amd hardware, but they
are definitely affected in theory by the same issue (proven by some quick and
dirty test).
So, simply add then subtract some fixed amount to the position values, which
ensures there should be no differences in the position later even after
viewport translate (we use window size + 1 here, so the values in range
-1.0 - +1.0 will all have the same exponent (just above the window size)).
(We must do that with uniforms otherwise mesa will optimize the add/sub away -
this is definitely unsafe math optimization but may well be allowed.)

This may be a problem with more tests, albeit most tend to use vertex data
which is already sufficiently aligned (e.g. drawing simple aligned rects).
---
 tests/general/quad-invariance.c                    | 55 +++++++++-------------
 .../glsl-1.50/execution/geometry/end-primitive.c   | 15 +++++-
 2 files changed, 36 insertions(+), 34 deletions(-)

diff --git a/tests/general/quad-invariance.c b/tests/general/quad-invariance.c
index b5741d0..fd51dec 100644
--- a/tests/general/quad-invariance.c
+++ b/tests/general/quad-invariance.c
@@ -38,9 +38,13 @@
 
 #include "piglit-util-gl.h"
 
+#define PATTERN_SIZE 256
+
 PIGLIT_GL_TEST_CONFIG_BEGIN
 
 	config.supports_gl_compat_version = 10;
+	config.window_width = 2*PATTERN_SIZE;
+	config.window_height = PATTERN_SIZE;
 
 	config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
 
@@ -49,41 +53,24 @@ PIGLIT_GL_TEST_CONFIG_END
 enum piglit_result
 piglit_display(void)
 {
+	int i;
 	GLboolean pass = GL_TRUE;
-	float verts[12][2] = {
+	float verts[3][2] = {
 		/* prim 1: left half of screen. */
-		{-1.0, -1.0},
-		{ 0.0, -1.0},
-		{ 0.0,  1.0},
-		{-1.0,  1.0},
-		/* prim 2: right half of screen. */
-		{ 0.0, -1.0},
-		{ 1.0, -1.0},
-		{ 1.0,  1.0},
+		{-1.0 + 2.0f / PATTERN_SIZE, -1.0},
+		{-1.0 + 2.0f / PATTERN_SIZE,  1.0},
 		{ 0.0,  1.0},
-		/* prim 3: somewhere off the screen. */
-		{ 2.0, -1.0},
-		{ 3.0, -1.0},
-		{ 3.0,  1.0},
-		{ 2.0,  1.0},
 	};
-	float colors[12][4] = {
-		{1.0, 0.0, 0.0, 0.0},
-		{0.0, 1.0, 0.0, 0.0},
-		{0.0, 0.0, 1.0, 0.0},
-		{1.0, 1.0, 1.0, 0.0},
-
-		{1.0, 0.0, 0.0, 0.0},
-		{0.0, 1.0, 0.0, 0.0},
-		{0.0, 0.0, 1.0, 0.0},
-		{1.0, 1.0, 1.0, 0.0},
-
-		{1.0, 0.0, 0.0, 0.0},
-		{0.0, 1.0, 0.0, 0.0},
-		{0.0, 0.0, 1.0, 0.0},
-		{1.0, 1.0, 1.0, 0.0},
+	float colors[3][4] = {
+		{1.0, 0.0, 0.0, 1.0},
+		{1.0, 0.0, 0.0, 1.0},
+		{1.0, 0.0, 0.0, 1.0},
+
 	};
+
 	static GLboolean once = GL_TRUE;
+	for (i = 0; i < (1 << 24) && pass; i++) {
+		verts[1][0] += 5.96046447754E-08f * 2.0f;
 
 	glClearColor(0.0, 0.0, 0.0, 0.0);
 	glClear(GL_COLOR_BUFFER_BIT);
@@ -94,19 +81,21 @@ piglit_display(void)
 	glEnableClientState(GL_VERTEX_ARRAY);
 
 	/* left: 1 prim */
-	glDrawArrays(GL_QUADS, 0, 4);
+	glViewport(0, 0, piglit_width/2, piglit_height);
+	glDrawArrays(GL_TRIANGLES, 0, 3);
 
+	glViewport(piglit_width/2, 0, piglit_width/2, piglit_height);
 	/* right: 1 prim */
-	glDrawArrays(GL_QUADS, 4, 8);
+	glDrawArrays(GL_TRIANGLES, 0, 3);
 
 	if (once) {
 		printf("Left and right half should match.\n");
 		once = GL_FALSE;
 	}
 
-	pass = piglit_probe_rect_halves_equal_rgba(0, 0, piglit_width,
+	pass &= piglit_probe_rect_halves_equal_rgba(0, 0, piglit_width,
 	                                           piglit_height);
-
+	}
 	piglit_present_results();
 
 	return pass ? PIGLIT_PASS : PIGLIT_WARN;
diff --git a/tests/spec/glsl-1.50/execution/geometry/end-primitive.c b/tests/spec/glsl-1.50/execution/geometry/end-primitive.c
index 6df3a89..e251ad0 100644
--- a/tests/spec/glsl-1.50/execution/geometry/end-primitive.c
+++ b/tests/spec/glsl-1.50/execution/geometry/end-primitive.c
@@ -92,6 +92,8 @@ static const char *spiral_text =
 	"#version 150\n"
 	"\n"
 	"uniform int num_vertices;\n"
+	"uniform float hack1;\n"
+	"uniform float hack2;\n"
 	"\n"
 	"vec2 spiral(int vertex_id)\n"
 	"{\n"
@@ -105,7 +107,10 @@ static const char *spiral_text =
 	"  if (vertex_id % 2 == 1) r += 1.0;\n"
 	"  float max_r = b*sqrt(a*float(num_vertices)) + 1.0;\n"
 	"  r /= max_r;\n"
-	"  return r*vec2(cos(theta), sin(theta));\n"
+	"  vec2 tmp = r*vec2(cos(theta), sin(theta));\n"
+        "  // ensure reasonably aligned vertices \n"
+        "  // note cannot use literals as they'd get optimized away... \n"
+        "  return tmp + hack1 - hack2;\n"
 	"}\n";
 
 /**
@@ -303,6 +308,10 @@ draw_ref_pattern()
 	glUseProgram(prog_ref);
 	glUniform1i(glGetUniformLocation(prog_ref, "num_vertices"),
 		    num_vertices);
+	glUniform1f(glGetUniformLocation(prog_ref, "hack1"),
+		    (float)PATTERN_SIZE * 2.0f + 1.0f);
+	glUniform1f(glGetUniformLocation(prog_ref, "hack2"),
+		    (float)PATTERN_SIZE * 2.0f + 1.0f);
 	glEnable(GL_PRIMITIVE_RESTART);
 	glPrimitiveRestartIndex(0xffffffff);
 
@@ -342,6 +351,10 @@ draw_test_pattern()
 	glUseProgram(prog_test);
 	glUniform1i(glGetUniformLocation(prog_test, "num_vertices"),
 		    num_vertices);
+	glUniform1f(glGetUniformLocation(prog_ref, "hack1"),
+		    (float)PATTERN_SIZE * 2.0f + 1.0f);
+	glUniform1f(glGetUniformLocation(prog_ref, "hack2"),
+		    (float)PATTERN_SIZE * 2.0f + 1.0f);
 	glDrawArrays(GL_POINTS, 0, 3);
 }
 
-- 
2.1.4



More information about the Piglit mailing list