[Piglit] [PATCH v2] arb_query_buffer_object: Update and add more test scenarios
Jordan Justen
jordan.l.justen at intel.com
Fri Apr 22 23:17:49 UTC 2016
Bump requirement to OpenGL 3.2 and add OpenGL Core profile support.
Test several other query types. (Previously only GL_SAMPLES_PASSED was
tested.)
Also test retrieving the result to CPU memory before and after the
buffer based result.
Don't warn if the async test always has the results available.
v2:
* Only check GL_ARB_pipeline_statistics_query queries if the
extension is supported (Ilia)
Signed-off-by: Jordan Justen <jordan.l.justen at intel.com>
---
tests/spec/arb_query_buffer_object/qbo.c | 351 ++++++++++++++++++++-----------
1 file changed, 232 insertions(+), 119 deletions(-)
diff --git a/tests/spec/arb_query_buffer_object/qbo.c b/tests/spec/arb_query_buffer_object/qbo.c
index 0cee6c8..bd47dd2 100644
--- a/tests/spec/arb_query_buffer_object/qbo.c
+++ b/tests/spec/arb_query_buffer_object/qbo.c
@@ -28,13 +28,14 @@
* Tests ARB_query_buffer_object
* - synchronous wait for result
* - asynchrounous result, default value is left intact if result unavailable
+ * - asynchrounous result, retrieve result to client memory before & after
*/
#include "piglit-util-gl.h"
PIGLIT_GL_TEST_CONFIG_BEGIN
- config.supports_gl_compat_version = 30;
-// config.supports_gl_core_version = 32;
+ config.supports_gl_compat_version = 32;
+ config.supports_gl_core_version = 32;
config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE |
PIGLIT_GL_VISUAL_DEPTH;
@@ -43,200 +44,312 @@ PIGLIT_GL_TEST_CONFIG_END
#define BUFFER_OFFSET(i) ((GLint *)((unsigned char*)NULL + (i)))
static const float green[] = {0, 1, 0, 1};
-static const float red[] = {1, 0, 0, 1};
static unsigned query;
static unsigned qbo;
static int prog;
static int qbo_prog;
+static int sync_mode_loc;
+static int original_count_loc;
+static int expect_exact_loc;
static int expected_count_loc;
-static int qbo_async_prog;
-
-enum piglit_result
-synchronous_query(void)
+static bool has_pipeline_stats;
+
+enum sync_mode {
+ QBO_SYNC,
+ QBO_ASYNC,
+ QBO_ASYNC_CPU_READ_BEFORE,
+ QBO_ASYNC_CPU_READ_AFTER,
+ NUM_QBO_SYNC_MODES,
+};
+
+static char* sync_mode_names[] = {
+ "SYNC",
+ "ASYNC",
+ "ASYNC_CPU_READ_BEFORE",
+ "ASYNC_CPU_READ_AFTER",
+};
+
+static enum sync_mode sync_mode;
+
+static bool
+is_pipeline_stats_query(GLenum q)
{
- GLboolean pass;
-
- glClearColor(0.5, 0.5, 0.5, 1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- // enable query, draw something that should pass
- glEnable(GL_DEPTH_TEST);
- glUseProgram(prog);
- glBeginQuery(GL_SAMPLES_PASSED, query);
- piglit_draw_rect_z(0.5, -1, -1, 2, 2);
- glEndQuery(GL_SAMPLES_PASSED);
-
- // Stuff query result into qbo
- glBindBuffer(GL_QUERY_BUFFER, qbo);
- glGetQueryObjectivARB(query, GL_QUERY_RESULT, BUFFER_OFFSET(0));
- // Make it available to shader as uniform buffer 0
- glBindBufferBase(GL_UNIFORM_BUFFER, 0, qbo);
+ switch (q) {
+ case GL_VERTICES_SUBMITTED_ARB:
+ case GL_PRIMITIVES_SUBMITTED_ARB:
+ case GL_VERTEX_SHADER_INVOCATIONS_ARB:
+ case GL_TESS_CONTROL_SHADER_PATCHES_ARB:
+ case GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB:
+ case GL_GEOMETRY_SHADER_INVOCATIONS:
+ case GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB:
+ case GL_FRAGMENT_SHADER_INVOCATIONS_ARB:
+ case GL_COMPUTE_SHADER_INVOCATIONS_ARB:
+ case GL_CLIPPING_INPUT_PRIMITIVES_ARB:
+ case GL_CLIPPING_OUTPUT_PRIMITIVES_ARB:
+ return true;
+ default:
+ return false;
+ }
+}
- glUseProgram(qbo_prog);
+static GLenum query_types[] = {
+ GL_ANY_SAMPLES_PASSED,
+ GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
+ GL_CLIPPING_INPUT_PRIMITIVES_ARB,
+ GL_CLIPPING_OUTPUT_PRIMITIVES_ARB,
+ /* GL_COMPUTE_SHADER_INVOCATIONS_ARB, */
+ GL_FRAGMENT_SHADER_INVOCATIONS_ARB,
+ /* GL_GEOMETRY_SHADER_INVOCATIONS, */
+ /* GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB, */
+ GL_PRIMITIVES_GENERATED,
+ GL_PRIMITIVES_SUBMITTED_ARB,
+ GL_SAMPLES_PASSED_ARB,
+ /* GL_TESS_CONTROL_SHADER_PATCHES_ARB, */
+ /* GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB, */
+ GL_TIMESTAMP,
+ GL_TIME_ELAPSED,
+ GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN,
+ GL_VERTEX_SHADER_INVOCATIONS_ARB,
+ GL_VERTICES_SUBMITTED_ARB,
+};
+
+static GLenum query_type;
+
+static void
+get_query_values(GLenum query_type, uint32_t *original,
+ bool *exact, uint32_t *expected)
+{
+ *original = 0xffffffff;
+ *exact = true;
+
+ switch (query_type) {
+ case GL_ANY_SAMPLES_PASSED:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
+ *expected = 1;
+ break;
+ case GL_CLIPPING_INPUT_PRIMITIVES_ARB:
+ case GL_CLIPPING_OUTPUT_PRIMITIVES_ARB:
+ *exact = false;
+ *expected = 1;
+ break;
+ case GL_FRAGMENT_SHADER_INVOCATIONS_ARB:
+ *exact = false;
+ *expected = 1;
+ break;
+ case GL_PRIMITIVES_GENERATED:
+ case GL_PRIMITIVES_SUBMITTED_ARB:
+ *exact = false;
+ *expected = 1;
+ break;
+ case GL_SAMPLES_PASSED_ARB:
+ *expected = piglit_width * piglit_height;
+ break;
+ case GL_TIMESTAMP:
+ case GL_TIME_ELAPSED:
+ *exact = false;
+ *expected = 1;
+ break;
+ case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
+ *expected = 0;
+ break;
+ case GL_VERTEX_SHADER_INVOCATIONS_ARB:
+ case GL_VERTICES_SUBMITTED_ARB:
+ *exact = false;
+ *expected = 1;
+ break;
+ case GL_COMPUTE_SHADER_INVOCATIONS_ARB:
+ case GL_GEOMETRY_SHADER_INVOCATIONS:
+ case GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB:
+ case GL_TESS_CONTROL_SHADER_PATCHES_ARB:
+ case GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB:
+ default:
+ abort();
+ }
+}
- // expected count of samples passed
- glUniform1ui(expected_count_loc, piglit_width * piglit_height);
+static enum piglit_result
+cpu_gather_query(bool exact, uint32_t expected)
+{
+ GLint qresult;
- glDisable(GL_DEPTH_TEST);
- // draw green if query successful
- piglit_draw_rect(-1, -1, 2, 2);
+ glBindBuffer(GL_QUERY_BUFFER, 0);
- pass = piglit_probe_rect_rgba(0, 0, piglit_width, piglit_height, green);
+ glGetQueryObjectiv(query, GL_QUERY_RESULT, &qresult);
- piglit_present_results();
+ glBindBuffer(GL_QUERY_BUFFER, qbo);
- return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+ return (exact ? qresult == expected : qresult >= expected)
+ ? PIGLIT_PASS : PIGLIT_FAIL;
}
enum piglit_result
-asynchronous_query_with_default(void)
+run_subtest(void)
{
- enum piglit_result result;
- unsigned default_value[2] = { 42u, 0u };
- unsigned char *buffer;
- unsigned redcount, greencount, bluecount;
- size_t n;
+ uint32_t original;
+ bool exact;
+ uint32_t expected;
+ uint32_t default_value[2] = { 0u, 0u };
+ bool is_sync = sync_mode == QBO_SYNC;
+
+ get_query_values(query_type, &original, &exact, &expected);
+ default_value[0] = original;
glClearColor(0.5, 0.5, 0.5, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // Load default value into buffer
+ /* Load default value into buffer */
glBindBuffer(GL_QUERY_BUFFER, qbo);
glBufferData(GL_QUERY_BUFFER, 8, default_value, GL_DYNAMIC_COPY);
- // enable query, draw something that should pass
+ /* Enable query, draw something that should pass */
glEnable(GL_DEPTH_TEST);
glUseProgram(prog);
- glBeginQuery(GL_SAMPLES_PASSED, query);
+ glGenQueries(1, &query);
+ if (query_type != GL_TIMESTAMP)
+ glBeginQuery(query_type, query);
piglit_draw_rect_z(0.5, -1, -1, 2, 2);
- glEndQuery(GL_SAMPLES_PASSED);
+ if (query_type != GL_TIMESTAMP)
+ glEndQuery(query_type);
+ else
+ glQueryCounter(query, query_type);
+
+ if (sync_mode == QBO_ASYNC_CPU_READ_BEFORE &&
+ cpu_gather_query(exact, expected))
+ return PIGLIT_FAIL;
glBindBuffer(GL_QUERY_BUFFER, qbo);
- // Stuff query result into qbo
- glGetQueryObjectivARB(query, GL_QUERY_RESULT_NO_WAIT, BUFFER_OFFSET(0));
- // Stuff query availability into qbo
- glGetQueryObjectivARB(query, GL_QUERY_RESULT_AVAILABLE, BUFFER_OFFSET(4));
- // Make it available to shader as uniform buffer 0
+ if (is_sync) {
+ /* Stuff query result into qbo */
+ glGetQueryObjectivARB(query, GL_QUERY_RESULT,
+ BUFFER_OFFSET(0));
+ } else {
+ /* Stuff query result into qbo */
+ glGetQueryObjectivARB(query, GL_QUERY_RESULT_NO_WAIT, BUFFER_OFFSET(0));
+ /* Stuff query availability into qbo */
+ glGetQueryObjectivARB(query, GL_QUERY_RESULT_AVAILABLE, BUFFER_OFFSET(4));
+ }
+
+ if (sync_mode == QBO_ASYNC_CPU_READ_AFTER &&
+ cpu_gather_query(exact, expected))
+ return PIGLIT_FAIL;
+
+ /* Make it available to shader as uniform buffer 0 */
glBindBufferBase(GL_UNIFORM_BUFFER, 0, qbo);
- glUseProgram(qbo_async_prog);
+ glUseProgram(qbo_prog);
+
+ /* Setup program uniforms */
+ glUniform1ui(sync_mode_loc, is_sync ? GL_TRUE : GL_FALSE);
+ glUniform1ui(original_count_loc, original);
+ glUniform1ui(expect_exact_loc, exact ? GL_TRUE : GL_FALSE);
+ glUniform1ui(expected_count_loc, expected);
glDisable(GL_DEPTH_TEST);
- // draw green if query successful
+ /* Draw green if query successful */
piglit_draw_rect(-1, -1, 2, 2);
- // Any red values -> fail
- // No blue, we don't know if async result not available works -> warn
- buffer = malloc(piglit_width * piglit_height * 4);
- glReadPixels(0, 0, piglit_width, piglit_height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
- redcount = 0;
- bluecount = 0;
- greencount = 0;
- for (n = 0; n < piglit_width * piglit_height; n++) {
- unsigned char r = buffer[n*4 + 0];
- unsigned char g = buffer[n*4 + 1];
- unsigned char b = buffer[n*4 + 2];
- if (r)
- redcount++;
- if (b)
- bluecount++;
- if (g)
- greencount++;
- }
- free(buffer);
+ glDeleteQueries(1, &query);
- if (redcount || greencount != piglit_width * piglit_height) {
- result = PIGLIT_FAIL;
- }
- else if (bluecount == 0) {
- result = PIGLIT_WARN;
- printf("no pixels where async query result unavailable, uncertain test result\n");
- }
- else {
- result = PIGLIT_PASS;
- }
+ return piglit_probe_rect_rgba(0, 0, piglit_width,
+ piglit_height, green)
+ ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+enum piglit_result
+run_subtest_and_present(void)
+{
+ char *subtest_name;
+ enum piglit_result r = run_subtest();
piglit_present_results();
-
- return result;
+ asprintf(&subtest_name, "query-%s-%s",
+ piglit_get_gl_enum_name(query_type),
+ sync_mode_names[sync_mode]);
+ piglit_report_subtest_result(r, subtest_name);
+ free(subtest_name);
+ return r;
}
enum piglit_result
piglit_display(void)
{
- enum piglit_result r, r2;
-
- r = synchronous_query();
- piglit_report_subtest_result(r, "synchronous_query");
-
- r2 = asynchronous_query_with_default();
- piglit_report_subtest_result(r2, "asynchronous_query_with_default");
+ enum piglit_result r = PIGLIT_PASS;
+ enum piglit_result subtest_result;
+ int qnum;
+
+ for (qnum = 0; qnum < ARRAY_SIZE(query_types); qnum++) {
+ query_type = query_types[qnum];
+ for (sync_mode = QBO_SYNC;
+ sync_mode < NUM_QBO_SYNC_MODES;
+ sync_mode++) {
+ if (!has_pipeline_stats &&
+ is_pipeline_stats_query(query_type))
+ continue;
+ subtest_result = run_subtest_and_present();
+ r = MAX2(r, subtest_result);
+ }
+ }
- return MAX2(r, r2);
+ return r;
}
void
piglit_init(int argc, char **argv)
{
char *vsCode;
- char *fsCode, *qboFsCode, *qboAsyncFsCode;
+ char *fsCode, *qboFsCode;
piglit_require_extension("GL_ARB_query_buffer_object");
piglit_require_extension("GL_ARB_uniform_buffer_object");
-
- glGenQueries(1, &query);
+ has_pipeline_stats =
+ piglit_is_extension_supported("GL_ARB_pipeline_statistics_query");
glGenBuffers(1, &qbo);
glBindBuffer(GL_QUERY_BUFFER, qbo);
glBufferData(GL_QUERY_BUFFER, 4, NULL, GL_DYNAMIC_COPY);
vsCode =
- "#version 130\n"
+ "#version 150\n"
+ "in vec4 pos_in;\n"
"void main() {\n"
- " gl_Position = gl_Vertex;\n"
+ " gl_Position = pos_in;\n"
"}\n";
fsCode =
- "#version 130\n"
+ "#version 150\n"
+ "out vec4 color;\n"
"void main() {\n"
- " gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
+ " color = vec4(0.0, 0.0, 1.0, 1.0);\n"
"}\n";
qboFsCode =
- "#version 130\n"
- "#extension GL_ARB_uniform_buffer_object : require\n"
- "uniform query {\n"
- " uint result;\n"
- "};\n"
- "uniform uint expected_count;\n"
- "void main() {\n"
- " if (result == expected_count) {\n"
- " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
- " } else {\n"
- " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
- " }\n"
- "}\n";
- qboAsyncFsCode =
- "#version 130\n"
+ "#version 150\n"
"#extension GL_ARB_uniform_buffer_object : require\n"
"uniform query {\n"
" uint result;\n"
" uint available;\n"
"};\n"
+ "uniform bool sync_mode;\n"
+ "uniform uint original_count;\n"
+ "uniform bool expect_exact;\n"
+ "uniform uint expected_count;\n"
+ "out vec4 color;\n"
"void main() {\n"
- " if (available == 0u && result == 42u) {\n"
- " gl_FragColor = vec4(0.0, 1.0, 1.0, 1.0);\n"
- " } else if (available == 0u && result != 42u) {\n"
- " gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\n"
- " } else if (available != 0u && result > 0u) {\n"
- " gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+ " bool ready = sync_mode || available != 0u;\n"
+ " if (!ready && result == original_count) {\n"
+ " color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+ " } else if (ready &&\n"
+ " (expect_exact ? result == expected_count :\n"
+ " result >= expected_count)) {\n"
+ " color = vec4(0.0, 1.0, 0.0, 1.0);\n"
" } else {\n"
- " gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
+ " color = vec4(1.0, 0.0, 0.0, 1.0);\n"
" }\n"
"}\n";
prog = piglit_build_simple_program(vsCode, fsCode);
qbo_prog = piglit_build_simple_program(vsCode, qboFsCode);
+ sync_mode_loc = glGetUniformLocation(qbo_prog, "sync_mode");
+ original_count_loc = glGetUniformLocation(qbo_prog, "original_count");
+ expect_exact_loc = glGetUniformLocation(qbo_prog, "expect_exact");
expected_count_loc = glGetUniformLocation(qbo_prog, "expected_count");
- qbo_async_prog = piglit_build_simple_program(vsCode, qboAsyncFsCode);
}
--
2.8.1
More information about the Piglit
mailing list