aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/all.tests3
-rw-r--r--tests/spec/gl-3.1/CMakeLists.gl.txt1
-rw-r--r--tests/spec/gl-3.1/primitive-restart-xfb.c259
3 files changed, 263 insertions, 0 deletions
diff --git a/tests/all.tests b/tests/all.tests
index 8d067be2..daebbd3c 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 b0885515..70eb135f 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 00000000..69f0fd70
--- /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;
+}