[Piglit] [PATCH] Add a test for primitive restart with an impossibly large index.

Kenneth Graunke kenneth at whitecape.org
Sat May 25 07:46:10 PDT 2013


When using glDrawElements with a data type of GL_UNSIGNED_BYTE, a
restart index greater than 0xff shouldn't match any index buffer value.

I could not find any explicit spec language which supports this claim,
but AMD and nVidia's closed source drivers as well as Mesa's software
restart handling all match this behavior.  The specification does say
that a restart occurs when the index "equals" the restart index, so
technically, they should never be equal.

Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
---
 tests/spec/gl-3.1/CMakeLists.gl.txt               |   1 +
 tests/spec/gl-3.1/primitive-restart-large-index.c | 197 ++++++++++++++++++++++
 2 files changed, 198 insertions(+)
 create mode 100644 tests/spec/gl-3.1/primitive-restart-large-index.c

diff --git a/tests/spec/gl-3.1/CMakeLists.gl.txt b/tests/spec/gl-3.1/CMakeLists.gl.txt
index 70eb135..4ef0e7e 100644
--- a/tests/spec/gl-3.1/CMakeLists.gl.txt
+++ b/tests/spec/gl-3.1/CMakeLists.gl.txt
@@ -11,6 +11,7 @@ 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-large-index primitive-restart-large-index.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-large-index.c b/tests/spec/gl-3.1/primitive-restart-large-index.c
new file mode 100644
index 0000000..982f349
--- /dev/null
+++ b/tests/spec/gl-3.1/primitive-restart-large-index.c
@@ -0,0 +1,197 @@
+/*
+ * 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-large-index.c
+ *
+ * Sets the primitive restart to 0x3303 and calls DrawElements with a type of
+ * GL_UNSIGNED_BYTE.  Since 0x3303 is larger than 0xff, it should not match
+ * any index buffer element, and no primitive restarts should occur.
+ *
+ * It also checks for two likely pitfalls:
+ * - Masking the restart index to the data type size (restart_index & 0xff)
+ * - Saturating the restart index to the maximum value (using 0xff)
+ */
+
+#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_RGBA;
+PIGLIT_GL_TEST_CONFIG_END
+
+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[]    = {0xff, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+static const GLint vertex_attrs[] = {
+ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 
+100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
+120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
+130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
+140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
+230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+250, 251, 252, 253, 254, 255
+};
+
+/* The expected result - the large index fails all comparisons, and no
+ * primitive restarts occur.
+ */
+static const GLint expected_xfb_result[] =
+	{ 255, 1, 2, 3, 4, 5, 6, 7, 8 };
+
+/* The result that would occur the index were masked off to byte size
+ * (causing a primitive restart when hitting an index of 3).
+ */
+static const GLint xfb_result_bad_restart_at_3[] =
+	{ 255, 1, 2, 4, 5, 6, 7, 8, 9 };
+
+/* The result that would occur the index were saturated at 0xff.  */
+static const GLint xfb_result_bad_restart_at_ff[] =
+	{   1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+static bool
+check_xfb_result()
+{
+	bool pass = false;
+	int i;
+	const int bytes = sizeof(expected_xfb_result);
+	const GLint *readback =
+		glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bytes,
+				 GL_MAP_READ_BIT);
+	if (memcmp(readback, expected_xfb_result, bytes) == 0) {
+		pass = true;
+	} else if (memcmp(readback, xfb_result_bad_restart_at_3, bytes) == 0) {
+		printf("Primitive restart incorrectly occured at index 3.\n"
+		       "The implementation wrongly used (index & 0xff).\n");
+	} else if (memcmp(readback, xfb_result_bad_restart_at_ff, bytes) == 0) {
+		printf("Primitive restart incorrectly occured at index 0xff.\n"
+		       "The implementation wrongly saturated the index.\n");
+	} else {
+		printf("Unexpected results:\n");
+		for (i = 0; i < ARRAY_SIZE(expected_xfb_result); i++)
+			printf("XFB[%i] == %i\n", i, readback[i]);
+	}
+	glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
+	return pass;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+	GLuint vs;
+	GLuint buf;
+	void *initial_data;
+	bool pass = true;
+	GLuint prog;
+	GLuint vao, vbo_attrs, vbo_indices;
+
+	/* Compile shader programs */
+	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));
+	glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
+	glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(expected_xfb_result),
+		     initial_data, GL_STREAM_READ);
+	free(initial_data);
+	glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+
+	/* Set up the VAO, vertex buffer, and index buffer. */
+	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);
+
+	/* Disable rendering */
+	glEnable(GL_RASTERIZER_DISCARD);
+
+	/* Enable primitive restart with an index that's larger than 0xff. */
+	glEnable(GL_PRIMITIVE_RESTART);
+	glPrimitiveRestartIndex(0x3303);
+
+	glBeginTransformFeedback(GL_TRIANGLES);
+	glDrawElements(GL_TRIANGLES, 10, GL_UNSIGNED_BYTE, NULL);
+	glEndTransformFeedback();
+	pass = piglit_check_gl_error(GL_NO_ERROR) && pass;
+	pass = check_xfb_result();
+
+	piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
+}
+
+
+enum piglit_result
+piglit_display(void)
+{
+	/* Should never be reached */
+	return PIGLIT_FAIL;
+}
-- 
1.8.2.2



More information about the Piglit mailing list