WIP not faster -> drop it --- tests/util/piglit-util-gl.c | 180 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+)
diff --git a/tests/util/piglit-util-gl.c b/tests/util/piglit-util-gl.c index e9c20385e..39125e3a4 100644 --- a/tests/util/piglit-util-gl.c +++ b/tests/util/piglit-util-gl.c @@ -1067,6 +1067,27 @@ can_probe_ubyte() return r <= 8 && g <= 8 && b <= 8 && a <= 8; } +static bool +can_and_should_probe_gpu(int x, int y, int w, int h) +{ + //TODO: check environment variable to enable feature + if (piglit_get_gl_version() < 32) + return false; + if (!piglit_is_extension_supported("GL_ARB_explicit_uniform_location")) + return false; + if (!piglit_use_fbo) + return false; + int query; + glGetQueryiv(GL_PRIMITIVES_GENERATED, GL_CURRENT_QUERY, &query); + if (query) + return false; + + if (w * h <= 0x100) //TODO: benchmark this + return false; + + return true; +} + static void print_components_ubyte(const GLubyte *pixel, unsigned components) { @@ -1261,6 +1282,156 @@ probe_rect_ubyte(int x, int y, int w, int h, int num_components, return true; } +static bool +probe_rect_gpu(int x, int y, int w, int h, int num_components, + const float *expected, bool silent) +{ + assert (num_components == 3 || num_components == 4); + + //TODO: check if moving logic to vs and passing bool is faster + static const char *vs_src = + "#version 150\n" + "#extension GL_ARB_explicit_uniform_location : enable\n" + "layout(location = 0) uniform sampler2D color_buffer;\n" + "layout(location = 1) uniform ivec4 rect;\n" + "out vec4 color;\n" + "out ivec2 xy;\n" + "void main()\n" + "{\n" + " xy = ivec2(rect.x, rect.y);\n" + " xy += ivec2(gl_VertexID % rect.z, gl_VertexID / rect.z);\n" + " color = texelFetch(color_buffer, xy, 0);\n" + "}\n"; +#define GS_SRC_HEADER \ + "#version 150\n" \ + "#extension GL_ARB_explicit_uniform_location : enable\n" \ + "layout(points) in;\n" \ + "layout(points, max_vertices=1) out;\n" \ + "layout(location = 11) uniform vec4 expected;\n" \ + "layout(location = 12) uniform vec4 tolerance;\n" \ + "in vec4 color[];\n" \ + "in ivec2 xy[];\n" \ + "out ivec2 xy_err;\n" \ + "out vec4 color_err;\n" \ + "void main()\n" \ + "{\n" +#define GS_SRC_FOOTER \ + " xy_err = xy[0];\n" \ + " color_err = color[0];\n" \ + " EmitVertex();\n" \ + " }\n" \ + "}\n" + static const char *gs_src3 = + GS_SRC_HEADER + " if (any(greaterThan(abs(expected.xyz - color[0].xyz), tolerance.xyz))) {\n" + GS_SRC_FOOTER; + static const char *gs_src4 = + GS_SRC_HEADER + " if (any(greaterThan(abs(expected - color[0]), tolerance))) {\n" + GS_SRC_FOOTER; +#undef GS_SRC_HEADER +#undef GS_SRC_FOOTER + + static int prog3, prog4; + int *prog = num_components == 3 ? &prog3 : &prog4; + const char *gs_src = num_components == 3 ? gs_src3 : gs_src4; + + if (!*prog) { + *prog = piglit_build_simple_program_unlinked_multiple_shaders( + GL_VERTEX_SHADER, vs_src, GL_GEOMETRY_SHADER, gs_src, 0); + const char *names[] = {"xy_err", "color_err"}; + glTransformFeedbackVaryings(*prog, 2, names, GL_INTERLEAVED_ATTRIBS); + glLinkProgram(*prog); + } + + /* Set up the transform feedback buffer. */ + unsigned buf; + int old_buf; + glGenBuffers(1, &buf); + glGetIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &old_buf); + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf); + glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, + (2*sizeof(int) + 4*sizeof(float)), NULL, GL_STREAM_READ); + + //FIXME: how to get previous buffer binding? + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf); + + /* bind program */ + int old_prog; + glGetIntegerv(GL_CURRENT_PROGRAM, &old_prog); + glUseProgram(*prog); + + /* set up uniforms */ + glUniform1i(0, 0); + glUniform4i(1, x, y, w, h); + if (num_components == 3) { + glUniform3fv(11, 1, expected); + } else { + glUniform4fv(11, 1, expected); + } + glUniform4fv(12, 1, piglit_tolerance); + + /* bind texture */ + int tex; + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &tex); + int old_texture_unit; + glGetIntegerv(GL_ACTIVE_TEXTURE, &old_texture_unit); + glActiveTexture(GL_TEXTURE0); + int old_tex; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_tex); + glBindTexture(GL_TEXTURE_2D, tex); + + bool old_raster_discard = glIsEnabled(GL_RASTERIZER_DISCARD); + glEnable(GL_RASTERIZER_DISCARD); + + //XXX: Disable arrays? + + unsigned query; + glGenQueries(1, &query); + glBeginQuery(GL_PRIMITIVES_GENERATED, query); + glBeginTransformFeedback(GL_POINTS); + + glDrawArrays(GL_POINTS, 0, w * h); + + glEndTransformFeedback(); + glEndQuery(GL_PRIMITIVES_GENERATED); + + /* restore state */ + if (!old_raster_discard) + glDisable(GL_RASTERIZER_DISCARD); + glBindTexture(GL_TEXTURE_2D, old_tex); + glActiveTexture(old_texture_unit); + glUseProgram(old_prog); + //glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, ???); + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, old_buf); + + int result; + glGetQueryObjectiv(query, GL_QUERY_RESULT, &result); + + if (result != 0) { + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf); + struct { + int xy[2]; + float color[4]; + } data; + glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, + sizeof(data), &data); + glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, old_buf); + + if (!silent) { + print_bad_pixel_float(data.xy[0], data.xy[1], + num_components, expected, + data.color); + } + } + + /* delete objects */ + glDeleteQueries(1, &query); + glDeleteBuffers(1, &buf); + + return result == 0; +} + int piglit_probe_rect_rgb_silent(int x, int y, int w, int h, const float *expected) { @@ -1268,6 +1439,9 @@ piglit_probe_rect_rgb_silent(int x, int y, int w, int h, const float *expected) GLfloat *probe; GLfloat *pixels; + if (can_and_should_probe_gpu(x, y, w, h)) + return probe_rect_gpu(x, y, w, h, 3, expected, true); + if (can_probe_ubyte()) return probe_rect_ubyte(x, y, w, h, 3, expected, true); @@ -1328,6 +1502,9 @@ piglit_probe_rect_rgb(int x, int y, int w, int h, const float *expected) GLfloat *probe; GLfloat *pixels; + if (can_and_should_probe_gpu(x, y, w, h)) + return probe_rect_gpu(x, y, w, h, 3, expected, false); + if (can_probe_ubyte()) return probe_rect_ubyte(x, y, w, h, 3, expected, false); @@ -1436,6 +1613,9 @@ piglit_probe_rect_rgba(int x, int y, int w, int h, const float *expected) GLfloat *probe; GLfloat *pixels; + if (can_and_should_probe_gpu(x, y, w, h)) + return probe_rect_gpu(x, y, w, h, 4, expected, false); + if (can_probe_ubyte()) return probe_rect_ubyte(x, y, w, h, 4, expected, false); -- 2.15.1 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/piglit