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.jus...@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 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/piglit