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

Reply via email to