From: Roland Scheidegger <srol...@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 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/piglit