[Piglit] [PATCH v2] Test interaction of primitive restart and transform feedback.

Paul Berry stereotype441 at gmail.com
Tue Apr 9 11:02:10 PDT 2013


v2: Fix "written" subtest (which was testing the wrong query).
---
 tests/all.tests                           |   3 +
 tests/spec/gl-3.1/CMakeLists.gl.txt       |   1 +
 tests/spec/gl-3.1/primitive-restart-xfb.c | 259 ++++++++++++++++++++++++++++++
 3 files changed, 263 insertions(+)
 create mode 100644 tests/spec/gl-3.1/primitive-restart-xfb.c

diff --git a/tests/all.tests b/tests/all.tests
index 8d067be..daebbd3 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -703,6 +703,9 @@ gl31 = Group()
 spec['!OpenGL 3.1'] = gl31
 gl31['genned-names'] = concurrent_test('gl-3.1-genned-names')
 gl31['minmax'] = concurrent_test('gl-3.1-minmax')
+for subtest in ['generated', 'written', 'flush']:
+        cmdline = 'primitive-restart-xfb {0}'.format(subtest)
+        gl31[cmdline] = concurrent_test('gl-3.1-' + cmdline)
 
 # Group spec/glsl-es-1.00
 spec['glsl-es-1.00'] = Group()
diff --git a/tests/spec/gl-3.1/CMakeLists.gl.txt b/tests/spec/gl-3.1/CMakeLists.gl.txt
index b088551..70eb135 100644
--- a/tests/spec/gl-3.1/CMakeLists.gl.txt
+++ b/tests/spec/gl-3.1/CMakeLists.gl.txt
@@ -11,5 +11,6 @@ link_libraries (
 
 piglit_add_executable (gl-3.1-genned-names genned-names.c)
 piglit_add_executable (gl-3.1-minmax minmax.c)
+piglit_add_executable (gl-3.1-primitive-restart-xfb primitive-restart-xfb.c)
 
 # vim: ft=cmake:
diff --git a/tests/spec/gl-3.1/primitive-restart-xfb.c b/tests/spec/gl-3.1/primitive-restart-xfb.c
new file mode 100644
index 0000000..69f0fd7
--- /dev/null
+++ b/tests/spec/gl-3.1/primitive-restart-xfb.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file primitive-restart-xfb.c
+ *
+ * Test interactions between primitive restart and transform feedback
+ * primitive counting behaviour.
+ *
+ * This test makes a single glDrawElements(GL_TRIANGLE_STRIP, 9, ...)
+ * draw call, where the index buffer specifies 4 normal vertices, the
+ * primitive restart index, and then 4 more normal vertices.  It
+ * verifies that the implementation correctly counts this as drawing 4
+ * triangles (rather than 7, which would be the behaviour of if
+ * primitive restart were not in use).
+ *
+ * The test can be run in three ways (selectable by a command line
+ * argument):
+ *
+ * - "generated" verifies that the GL_PRIMITIVES_GENERATED query
+ *   counts the primitives correctly.
+ *
+ * - "written" verifies that the
+ *   GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query counts the
+ *   primitives correctly.
+ *
+ * - "flush" verifies that if these 4 triangles are followed by a
+ *   glFlush() and then more primitives further drawing, transform
+ *   feedback for the latter primitives is placed at the correct
+ *   location in the transform feedback buffer.
+ */
+
+#include "piglit-util-gl-common.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+	config.supports_gl_core_version = 31;
+	config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB |
+		PIGLIT_GL_VISUAL_ALPHA;
+PIGLIT_GL_TEST_CONFIG_END
+
+
+enum test_mode_enum {
+	TEST_MODE_GENERATED,
+	TEST_MODE_WRITTEN,
+	TEST_MODE_FLUSH,
+};
+
+
+static const char vs_text[] =
+	"#version 130\n"
+	"in int x_in;\n"
+	"flat out int x_out;\n"
+	"void main()\n"
+	"{\n"
+	"  gl_Position = vec4(0.0);\n"
+	"  x_out = x_in;\n"
+	"}\n";
+
+
+static const GLchar *varyings[] = { "x_out" };
+
+
+/**
+ * Indices used for the test.
+ */
+static const GLubyte indices[] = {
+	/* For the main draw call */
+	0, 1, 2, 3, 0xff, 4, 5, 6, 7,
+
+	/* After the glFlush() call (when in TEST_MODE_FLUSH) */
+	8, 9, 10, 11
+};
+
+
+static const GLint vertex_attrs[] = { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 };
+
+
+/**
+ * Expected transform feedback result when in TEST_MODE_FLUSH:
+ * - 2 triangles with attribute 1 and 2 triangles with attribute value 2 (from
+ *   the first draw call)
+ * - 2 triangles with attribute 3 (from the second draw call, after the flush)
+ */
+static const GLint expected_xfb_result[] =
+	{ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3 };
+
+
+static void
+print_usage_and_exit(const char *prog_name)
+{
+	printf("Usage: %s <subtest>\n"
+	       "  where <subtest> is one of the following:\n"
+	       "    generated\n"
+	       "    written\n"
+	       "    flush\n", prog_name);
+	piglit_report_result(PIGLIT_FAIL);
+}
+
+
+static bool
+check_query_result(GLuint query, GLuint expected)
+{
+	GLuint result;
+
+	glGetQueryObjectuiv(query, GL_QUERY_RESULT, &result);
+	if (result != expected) {
+		printf("Query result: %u, expected: %u\n", result, expected);
+		return false;
+	}
+	return true;
+}
+
+
+static bool
+check_xfb_result()
+{
+	bool pass = true;
+	int i;
+	const GLint *readback =
+		glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0,
+				 sizeof(expected_xfb_result), GL_MAP_READ_BIT);
+	for (i = 0; i < ARRAY_SIZE(expected_xfb_result); i++) {
+		if (readback[i] != expected_xfb_result[i]) {
+			printf("XFB[%i] == %i, expected %i\n", i, readback[i],
+			       expected_xfb_result[i]);
+			pass = false;
+		}
+	}
+	glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
+	return pass;
+}
+
+
+void
+piglit_init(int argc, char **argv)
+{
+	GLuint vs;
+	GLuint buf;
+	void *initial_data;
+	bool pass = true;
+	enum test_mode_enum test_mode;
+	GLuint prog;
+	GLuint vao, vbo_attrs, vbo_indices;
+	GLuint query;
+
+	if (argc != 2)
+		print_usage_and_exit(argv[0]);
+	if (strcmp(argv[1], "generated") == 0)
+		test_mode = TEST_MODE_GENERATED;
+	else if (strcmp(argv[1], "written") == 0)
+		test_mode = TEST_MODE_WRITTEN;
+	else if (strcmp(argv[1], "flush") == 0)
+		test_mode = TEST_MODE_FLUSH;
+	else
+		print_usage_and_exit(argv[0]);
+
+	prog = glCreateProgram();
+	vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_text);
+	glAttachShader(prog, vs);
+	glDeleteShader(vs);
+	glTransformFeedbackVaryings(prog, 1, varyings, GL_INTERLEAVED_ATTRIBS);
+	glBindAttribLocation(prog, 0, "x_in");
+	glLinkProgram(prog);
+	if (!piglit_link_check_status(prog) ||
+	    !piglit_check_gl_error(GL_NO_ERROR)) {
+		piglit_report_result(PIGLIT_FAIL);
+	}
+	glUseProgram(prog);
+
+	/* Create transform feedback buffer and pre-load it with
+	 * garbage.
+	 */
+	glGenBuffers(1, &buf);
+	initial_data = malloc(sizeof(expected_xfb_result));
+	memset(initial_data, 0xcc, sizeof(expected_xfb_result));
+	glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+	glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(expected_xfb_result),
+		     initial_data, GL_STREAM_READ);
+	free(initial_data);
+
+	/* Set up VAO/VBO */
+	glGenVertexArrays(1, &vao);
+	glBindVertexArray(vao);
+	glGenBuffers(1, &vbo_attrs);
+	glBindBuffer(GL_ARRAY_BUFFER, vbo_attrs);
+	glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_attrs), vertex_attrs,
+		     GL_STREAM_DRAW);
+	glVertexAttribIPointer(0, 1, GL_INT, 0, NULL);
+	glEnableVertexAttribArray(0);
+	glGenBuffers(1, &vbo_indices);
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo_indices);
+	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,
+		     GL_STREAM_DRAW);
+
+	/* Misc setup */
+	glEnable(GL_RASTERIZER_DISCARD);
+	glEnable(GL_PRIMITIVE_RESTART);
+	glPrimitiveRestartIndex(0xff);
+	glGenQueries(1, &query);
+
+	switch (test_mode) {
+	case TEST_MODE_GENERATED:
+		glBeginQuery(GL_PRIMITIVES_GENERATED, query);
+		glBeginTransformFeedback(GL_TRIANGLES);
+		glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_BYTE, NULL);
+		glEndTransformFeedback();
+		glEndQuery(GL_PRIMITIVES_GENERATED);
+		pass = check_query_result(query, 4);
+		break;
+	case TEST_MODE_WRITTEN:
+		glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, query);
+		glBeginTransformFeedback(GL_TRIANGLES);
+		glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_BYTE, NULL);
+		glEndTransformFeedback();
+		glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
+		pass = check_query_result(query, 4);
+		break;
+	case TEST_MODE_FLUSH:
+		glBeginTransformFeedback(GL_TRIANGLES);
+		glDrawElements(GL_TRIANGLE_STRIP, 9, GL_UNSIGNED_BYTE, NULL);
+		glFlush();
+		glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE,
+			       (void *) (9 * sizeof(GLubyte)));
+		glEndTransformFeedback();
+		pass = check_xfb_result();
+		break;
+	}
+
+	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
+	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
+}
+
+
+enum piglit_result
+piglit_display(void)
+{
+	/* Should never be reached */
+	return PIGLIT_FAIL;
+}
-- 
1.8.2.1



More information about the Piglit mailing list