Verified using the NVIDIA proprietary driver for linux.
---
 tests/all.tests                                    |   9 +
 .../glsl-1.50/execution/geometry/CMakeLists.gl.txt |   1 +
 .../execution/geometry/primitive-id-restart.c      | 265 +++++++++++++++++++++
 3 files changed, 275 insertions(+)
 create mode 100644 
tests/spec/glsl-1.50/execution/geometry/primitive-id-restart.c

diff --git a/tests/all.tests b/tests/all.tests
index 7c1503a..a8c0f76 100644
--- a/tests/all.tests
+++ b/tests/all.tests
@@ -947,6 +947,15 @@ for i in [31, 32, 33, 34, 127, 128, 129, 130, 0]:
     add_concurrent_test(spec['glsl-1.50'],
                         'glsl-1.50-geometry-end-primitive {0}'.format(i))
 
+for prim_type in ['GL_POINTS', 'GL_LINE_LOOP', 'GL_LINE_STRIP', 'GL_LINES',
+                  'GL_TRIANGLES', 'GL_TRIANGLE_STRIP', 'GL_TRIANGLE_FAN',
+                  'GL_LINES_ADJACENCY', 'GL_LINE_STRIP_ADJACENCY',
+                  'GL_TRIANGLES_ADJACENCY', 'GL_TRIANGLE_STRIP_ADJACENCY']:
+    for restart_index in ['ffs', 'other']:
+        add_concurrent_test(spec['glsl-1.50'],
+                            'glsl-1.50-geometry-primitive-id-restart {0} 
{1}'.format(
+                                prim_type, restart_index))
+
 spec['glsl-3.30'] = Group()
 import_glsl_parser_tests(spec['glsl-3.30'],
                         os.path.join(testsDir, 'spec', 'glsl-3.30'),
diff --git a/tests/spec/glsl-1.50/execution/geometry/CMakeLists.gl.txt 
b/tests/spec/glsl-1.50/execution/geometry/CMakeLists.gl.txt
index d4becb7..aa61f6c 100644
--- a/tests/spec/glsl-1.50/execution/geometry/CMakeLists.gl.txt
+++ b/tests/spec/glsl-1.50/execution/geometry/CMakeLists.gl.txt
@@ -11,3 +11,4 @@ ${OPENGL_glu_LIBRARY}
 )
 
 piglit_add_executable (glsl-1.50-geometry-end-primitive end-primitive.c)
+piglit_add_executable (glsl-1.50-geometry-primitive-id-restart 
primitive-id-restart.c)
diff --git a/tests/spec/glsl-1.50/execution/geometry/primitive-id-restart.c 
b/tests/spec/glsl-1.50/execution/geometry/primitive-id-restart.c
new file mode 100644
index 0000000..72f024d
--- /dev/null
+++ b/tests/spec/glsl-1.50/execution/geometry/primitive-id-restart.c
@@ -0,0 +1,265 @@
+/*
+ * 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-id-restart.c
+ *
+ * Verify that the use of primitive restart does not reset the
+ * geometry shader's gl_PrimitiveID counter.
+ *
+ * From the GL 3.2 core spec, section 2.12.4 (Geometry Shader
+ * Execution Environment):
+ *
+ *     Restarting a primitive topology using the primitive restart
+ *     index has no effect on the primitive ID counter.
+ *
+ * This test uses a simple geometry shader that copies
+ * gl_PrimitiveIDIn to a single output, which is captured using
+ * transform feedback.
+ *
+ * The test operates by specifying a sequence of:
+ *
+ * - One vertex followed by primitive restart
+ * - Two vertices followed by primitive restart
+ * - Three vertices followed by primitive restart
+ *
+ * And so on up to twelve.  The resulting transform feedback output is
+ * checked to verify that the primitive ID's received by the geometry
+ * shaders count upwards from 0, without restarting anywhere.
+ *
+ * Note: some generations of Intel hardware require primitive restart
+ * to be emulated in software when either:
+ *
+ * - certain primitive types are used, or
+ *
+ * - the primitive restart index is not all 0xff's.
+ *
+ * To make sure that both the hardware and software primitive restart
+ * codepaths are tested, this test accepts command line options to
+ * control (a) which primitive type to use, and (b) whether the
+ * primitive restart index should be all 0xff's.
+ */
+
+#include "piglit-util-gl-common.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+       config.supports_gl_compat_version = 32;
+       config.supports_gl_core_version = 32;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+
+#define LONGEST_INPUT_SEQUENCE 12
+#define NUM_INPUT_ELEMENTS \
+       (LONGEST_INPUT_SEQUENCE * (LONGEST_INPUT_SEQUENCE + 3) / 2)
+#define MAX_TOTAL_PRIMS \
+       (LONGEST_INPUT_SEQUENCE * (LONGEST_INPUT_SEQUENCE + 1) / 2)
+
+
+static const char *vs_text =
+       "#version 150\n"
+       "\n"
+       "void main()\n"
+       "{\n"
+       "}\n";
+
+static const char *gs_template =
+       "#version 150\n"
+       "#define INPUT_LAYOUT %s\n"
+       "layout(INPUT_LAYOUT) in;\n"
+       "layout(points, max_vertices = 1) out;\n"
+       "\n"
+       "out int primitive_id;\n"
+       "\n"
+       "void main()\n"
+       "{\n"
+       "  primitive_id = gl_PrimitiveIDIn;\n"
+       "  EmitVertex();\n"
+       "}\n";
+
+static const char *varyings[] = { "primitive_id" };
+
+
+struct prim_type_info
+{
+       const char *name;
+       GLenum prim_type;
+       const char *input_layout;
+} prim_types[] = {
+#define PRIM_TYPE(prim_type, input_layout) \
+       { #prim_type, prim_type, input_layout }
+       PRIM_TYPE(GL_POINTS, "points"),
+       PRIM_TYPE(GL_LINE_LOOP, "lines"),
+       PRIM_TYPE(GL_LINE_STRIP, "lines"),
+       PRIM_TYPE(GL_LINES, "lines"),
+       PRIM_TYPE(GL_TRIANGLES, "triangles"),
+       PRIM_TYPE(GL_TRIANGLE_STRIP, "triangles"),
+       PRIM_TYPE(GL_TRIANGLE_FAN, "triangles"),
+       PRIM_TYPE(GL_LINES_ADJACENCY, "lines_adjacency"),
+       PRIM_TYPE(GL_LINE_STRIP_ADJACENCY, "lines_adjacency"),
+       PRIM_TYPE(GL_TRIANGLES_ADJACENCY, "triangles_adjacency"),
+       PRIM_TYPE(GL_TRIANGLE_STRIP_ADJACENCY, "triangles_adjacency"),
+#undef PRIM_TYPE
+};
+
+
+static void
+print_usage_and_exit(const char *prog_name)
+{
+       int i;
+       printf("Usage: %s <primitive> <restart-index>\n"
+              "  where <primitive> is one of the following:\n", prog_name);
+       for(i = 0; i < ARRAY_SIZE(prim_types); i++)
+               printf("    %s\n", prim_types[i].name);
+       printf("  and <restart-index> is one of the following:\n"
+              "    ffs - use a primitive restart index that is all 0xffs\n"
+              "    other - use a different primitive restart index\n");
+       piglit_report_result(PIGLIT_FAIL);
+}
+
+
+void
+piglit_init(int argc, char **argv)
+{
+       GLenum prim_type = 0;
+       const char *input_layout = NULL;
+       GLubyte prim_restart_index;
+       char *gs_text;
+       GLuint prog, vs, gs, vao, xfb_buf, element_buf, generated_query,
+               primitives_generated;
+       GLubyte *elements;
+       int i, j;
+       GLsizei num_elements;
+       bool pass = true;
+       GLuint *readback;
+
+       /* Parse params */
+       if (argc != 3)
+               print_usage_and_exit(argv[0]);
+       for (i = 0; i < ARRAY_SIZE(prim_types); i++) {
+               if (strcmp(argv[1], prim_types[i].name) == 0) {
+                       prim_type = prim_types[i].prim_type;
+                       input_layout = prim_types[i].input_layout;
+                       break;
+               }
+       }
+       if (input_layout == NULL)
+               print_usage_and_exit(argv[0]);
+       if (strcmp(argv[2], "ffs") == 0)
+               prim_restart_index = 0xff;
+       else if (strcmp(argv[2], "other") == 0)
+               prim_restart_index = 1;
+       else
+               print_usage_and_exit(argv[0]);
+
+       /* Compile shaders */
+       prog = glCreateProgram();
+       vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_text);
+       glAttachShader(prog, vs);
+       asprintf(&gs_text, gs_template, input_layout);
+       gs = piglit_compile_shader_text(GL_GEOMETRY_SHADER, gs_text);
+       free(gs_text);
+       glAttachShader(prog, gs);
+       glTransformFeedbackVaryings(prog, 1, varyings, GL_INTERLEAVED_ATTRIBS);
+       glLinkProgram(prog);
+       if (!piglit_link_check_status(prog))
+               piglit_report_result(PIGLIT_FAIL);
+       glUseProgram(prog);
+
+       /* Set up other GL state */
+       glGenVertexArrays(1, &vao);
+       glBindVertexArray(vao);
+       glGenBuffers(1, &xfb_buf);
+       glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buf);
+       glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
+                    MAX_TOTAL_PRIMS * sizeof(GLint), NULL,
+                    GL_STREAM_READ);
+       glGenQueries(1, &generated_query);
+       glEnable(GL_RASTERIZER_DISCARD);
+       glEnable(GL_PRIMITIVE_RESTART);
+       glPrimitiveRestartIndex(prim_restart_index);
+
+       /* Set up element buffer */
+       glGenBuffers(1, &element_buf);
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buf);
+       glBufferData(GL_ELEMENT_ARRAY_BUFFER,
+                    sizeof(GLubyte) * NUM_INPUT_ELEMENTS, NULL,
+                    GL_STATIC_DRAW);
+       elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_WRITE);
+       num_elements = 0;
+       for (i = 1; i <= LONGEST_INPUT_SEQUENCE; i++) {
+               for (j = 0; j < i; j++) {
+                       /* Every element that isn't the primitive
+                        * restart index can just be element 0, since
+                        * we don't care about the actual vertex data.
+                        */
+                       elements[num_elements++] = 0;
+               }
+               elements[num_elements++] = prim_restart_index;
+       }
+       glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+
+       /* Run vertices through the pipeline */
+       glBeginQuery(GL_PRIMITIVES_GENERATED, generated_query);
+       glBeginTransformFeedback(GL_POINTS);
+       glDrawElements(prim_type, num_elements, GL_UNSIGNED_BYTE, NULL);
+       glEndTransformFeedback();
+       glEndQuery(GL_PRIMITIVES_GENERATED);
+
+       /* Find out how many times the GS got invoked so we'll know
+        * how many transform feedback outputs to examine.
+        */
+       glGetQueryObjectuiv(generated_query, GL_QUERY_RESULT,
+                           &primitives_generated);
+       if (primitives_generated > MAX_TOTAL_PRIMS) {
+               printf("Expected no more than %d primitives, got %d\n",
+                      MAX_TOTAL_PRIMS, primitives_generated);
+               pass = false;
+
+               /* Set primitives_generated to MAX_TOTAL_PRIMS so that
+                * we don't overflow the buffer in the loop below.
+                */
+       }
+
+       /* Check transform feedback outputs. */
+       readback = glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
+       for (i = 0; i < primitives_generated; i++) {
+               if (readback[i] != i) {
+                       printf("Expected primitive %d to have gl_PrimitiveIDIn"
+                              " = %d, got %d instead\n", i, i, readback[i]);
+                       pass = false;
+               }
+       }
+       glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
+
+       piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
+}
+
+
+enum piglit_result
+piglit_display(void)
+{
+       /* Should never be reached */
+       return PIGLIT_FAIL;
+}
-- 
1.8.4

_______________________________________________
Piglit mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to