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

Ian Romanick idr at freedesktop.org
Fri May 24 13:07:14 PDT 2013


On 05/25/2013 07:46 AM, Kenneth Graunke wrote:
> When using glDrawElements with a data type of GL_UNSIGNED_BYTE, a
> restart index greater than 0xff shouldn't match any index buffer value.

Should we also test GL_UNSIGNED_SHORT?

> 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;
> +}
>



More information about the Piglit mailing list