[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