[Piglit] [PATCH] gl 1.0: Stress test GL_LINE_LOOP.

Brian Paul brianp at vmware.com
Thu Jan 11 20:58:00 UTC 2018


Reviewed-by: Brian Paul <brianp at vmware.com>


On 01/11/2018 12:54 PM, Fabian Bieler wrote:
> Draw circles with long line loops and check the result.
> 
> In particular, check that the last line segment is drawn and that no
> additional segments in between arbitrary vertices are drawn.
> 
> V2: Increase vertex size and count to exhaust Mesa's vbo buffer and Gallium's
>      auxiliary draw buffer.
>      Add command line argument to set vertex count.
> ---
> 
>> I fixed some long line loop issues in Mesa/gallium a few years ago.  I _think_ 0x2000 (8192) is enough, but you might want to check more (Note that Mesa llvmpipe reports GL_MAX_ELEMENTS_VERTICES = 3000).
> 
>> Also, I see you're stepping the vertex count by <<=2 in the test loop below.  That _might_ skip some magic vertex counts which tickle bugs. Off-hand I don't have a good suggesting for how to be thorough about this without being really slow.
> I toyed and dismissed the idea of additional tests with random vertex counts as I don't think the occasional failure of this test would be investigated. I did add a command line option to manually set the vertex count for easier debugging, though.
> 
>> There's (at least) two places where the vertex buffer limits (the VBO module and draw/vbuf code) will trigger splitting/continuing long line loops.  This test should try to exceed both those buffer limits.  You might set some breakpoints in the Mesa/gallium code to see if they're getting hit.
> Mesa's VBO buffer is 1MB. Gallium's auxiliary draw code buffer size varies from driver to driver, but it's never bigger than 1MB.
> I increased the vertex size and count so that the vertex array is at least 3MB in size.
> 
>   tests/all.py                        |   1 +
>   tests/spec/gl-1.0/CMakeLists.gl.txt |   1 +
>   tests/spec/gl-1.0/long-line-loop.c  | 199 ++++++++++++++++++++++++++++++++++++
>   3 files changed, 201 insertions(+)
>   create mode 100644 tests/spec/gl-1.0/long-line-loop.c
> 
> diff --git a/tests/all.py b/tests/all.py
> index 32ab2b610..6abcb3aa8 100644
> --- a/tests/all.py
> +++ b/tests/all.py
> @@ -727,6 +727,7 @@ with profile.test_list.group_manager(
>       g(['gl-1.0-edgeflag-quads'])
>       g(['gl-1.0-empty-begin-end-clause'])
>       g(['gl-1.0-long-dlist'])
> +    g(['gl-1.0-long-line-loop'])
>       g(['gl-1.0-readpixels-oob'])
>       g(['gl-1.0-rendermode-feedback'])
>       g(['gl-1.0-front-invalidate-back'], run_concurrent=False)
> diff --git a/tests/spec/gl-1.0/CMakeLists.gl.txt b/tests/spec/gl-1.0/CMakeLists.gl.txt
> index 355df7472..2df3a8cf4 100644
> --- a/tests/spec/gl-1.0/CMakeLists.gl.txt
> +++ b/tests/spec/gl-1.0/CMakeLists.gl.txt
> @@ -26,6 +26,7 @@ piglit_add_executable (gl-1.0-fpexceptions fpexceptions.c)
>   piglit_add_executable (gl-1.0-front-invalidate-back front-invalidate-back.c)
>   piglit_add_executable (gl-1.0-logicop logicop.c)
>   piglit_add_executable (gl-1.0-long-dlist long-dlist.c)
> +piglit_add_executable (gl-1.0-long-line-loop long-line-loop.c)
>   piglit_add_executable (gl-1.0-ortho-pos orthpos.c)
>   piglit_add_executable (gl-1.0-no-op-paths no-op-paths.c)
>   piglit_add_executable (gl-1.0-polygon-line-aa polygon-line-aa.c)
> diff --git a/tests/spec/gl-1.0/long-line-loop.c b/tests/spec/gl-1.0/long-line-loop.c
> new file mode 100644
> index 000000000..02b756caa
> --- /dev/null
> +++ b/tests/spec/gl-1.0/long-line-loop.c
> @@ -0,0 +1,199 @@
> +/*
> + * Copyright © 2017 Fabian Bieler
> + *
> + * 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 long-line-loop.c
> + * Draw cricles with line loops and a line strips blended on top of each
> + * other and check that the renderings match.
> + */
> +
> +#include "piglit-util-gl.h"
> +
> +PIGLIT_GL_TEST_CONFIG_BEGIN
> +
> +	config.supports_gl_compat_version = 10;
> +	config.window_width = 1024;
> +	config.window_height = 1024;
> +	config.window_visual = PIGLIT_GL_VISUAL_RGB;
> +	config.khr_no_error_support = PIGLIT_NO_ERRORS;
> +
> +PIGLIT_GL_TEST_CONFIG_END
> +
> +static int max_vertices;
> +static int num_vertices;
> +static int probe_location[2];
> +static const float radius = 0.9;
> +
> +static void
> +print_usage_and_exit(const char *prog_name)
> +{
> +	printf("Usage: %s [<vertex_count>]\n"
> +	       "  where <vertex_count> is the number of vertices to test.\n"
> +	       "\n"
> +	       "  If omitted, sequentially test from 16 to max_vertices by "
> +	       "quadrupling,\n"
> +	       "  where max_vertices is GL_MAX_ELEMENTS_VERTICES clamped to "
> +	       "[0x10000, 0x40000].\n",
> +	       prog_name);
> +	piglit_report_result(PIGLIT_FAIL);
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +	glBlendFunc(GL_ONE, GL_ONE);
> +
> +	piglit_ortho_projection(piglit_width, piglit_height, false);
> +
> +	if (argc == 1) {
> +		/* This isn't a hard limit, but staying below should help
> +		 * performance.
> +		 *
> +		 * XXX: It could be interesting to go beyond this limit to
> +		 * test a different code path in the GL implementation.
> +		 */
> +		glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &max_vertices);
> +		max_vertices = CLAMP(max_vertices, 0x10000, 0x40000);
> +	} else if (argc == 2) {
> +		char *endptr;
> +		num_vertices = strtol(argv[1], &endptr, 0);
> +		if (endptr != argv[1] + strlen(argv[1]))
> +			print_usage_and_exit(argv[0]);
> +		if (num_vertices < 6)
> +			print_usage_and_exit(argv[0]);
> +	} else {
> +		print_usage_and_exit(argv[0]);
> +	}
> +}
> +
> +static void
> +draw_circle(int segments)
> +{
> +	/* The first (segments - 1) vertices describe the arc of a circle
> +	 * slice with central angle (360° - alpha).
> +	 * The last vertex is identical to the first vertex.
> +	 * alpha is chosen so that the last line segment covers two pixels.
> +	 */
> +	const float alpha = asinf(2.0 / (piglit_width / 2 * radius));
> +	struct {
> +		float pos[4];
> +		float green[4];
> +		float blue[4];
> +	} *vertex = malloc(sizeof(vertex[0]) * segments);
> +
> +	for (int i = 0; i < segments - 1; ++i) {
> +		const float phi = alpha -
> +				  (2 * M_PI - alpha) /
> +				  (float)(segments - 2) *
> +				  (float)i;
> +
> +		vertex[i].pos[0] = round(piglit_width / 2 *
> +					  (1 + radius * cosf(phi))) + 0.5;
> +		vertex[i].pos[1] = round(piglit_height / 2 *
> +					  (1 + radius * sinf(phi))) + 0.5;
> +		vertex[i].pos[2] = 0;
> +		vertex[i].pos[3] = 1;
> +		vertex[i].green[0] = 0;
> +		vertex[i].green[1] = 1;
> +		vertex[i].green[2] = 0;
> +		vertex[i].green[3] = 1;
> +		vertex[i].blue[0] = 0;
> +		vertex[i].blue[1] = 0;
> +		vertex[i].blue[2] = 1;
> +		vertex[i].blue[3] = 1;
> +	}
> +	memcpy(&vertex[segments - 1], &vertex[0], sizeof(vertex[0]));
> +
> +	/* Find a pixel in the last line segment: */
> +	for (int i = 0; i < 2; ++i)
> +		probe_location[i] = round((vertex[segments - 2].pos[i] +
> +					   vertex[segments - 1].pos[i] -
> +					   1.0) / 2.0);
> +
> +	/* Render twice: */
> +	glClear(GL_COLOR_BUFFER_BIT);
> +
> +	glVertexPointer(4, GL_FLOAT, sizeof(vertex[0]), vertex[0].pos);
> +	glColorPointer(4, GL_FLOAT, sizeof(vertex[0]), vertex[0].green);
> +
> +	glEnableClientState(GL_VERTEX_ARRAY);
> +	glEnableClientState(GL_COLOR_ARRAY);
> +
> +	glDrawArrays(GL_LINE_LOOP, 0, segments - 1);
> +
> +	glEnable(GL_BLEND);
> +	glColorPointer(4, GL_FLOAT, sizeof(vertex[0]), vertex[0].blue);
> +	glDrawArrays(GL_LINE_STRIP, 0, segments);
> +	glDisable(GL_BLEND);
> +
> +	free(vertex);
> +
> +	piglit_present_results();
> +}
> +
> +static bool
> +check_circle(void)
> +{
> +	bool pass = true;
> +	const float teal[] = {0, 1, 1};
> +	const float black[] = {0, 0, 0};
> +
> +	/* check that the two renderings are identical */
> +	pass = piglit_probe_rect_two_rgb(0, 0, piglit_width, piglit_height,
> +					 black, teal) && pass;
> +
> +	/* belt + suspenders: Additionally check that the last line segment
> +	 * was drawn...
> +	 */
> +	pass = piglit_probe_pixel_rgb(probe_location[0], probe_location[1],
> +				      teal) && pass;
> +
> +	/* ...and that the center of the circle is black */
> +	const int x = ceil(piglit_width / 2 * radius / M_SQRT2) + 1;
> +	const int y = ceil(piglit_height / 2 * radius / M_SQRT2) + 1;
> +	pass = piglit_probe_rect_rgb(x, y, piglit_width - 2 * x,
> +				     piglit_height - 2 * y, black) && pass;
> +
> +	return pass;
> +}
> +
> +enum piglit_result
> +piglit_display(void)
> +{
> +	bool pass = true;
> +
> +	if (max_vertices) {
> +		for (int vertices = 16;
> +		     vertices <= max_vertices;
> +		     vertices <<= 2) {
> +			draw_circle(vertices);
> +			pass = check_circle() && pass;
> +		}
> +	} else {
> +		draw_circle(num_vertices);
> +		pass = check_circle() && pass;
> +	}
> +
> +	return pass ? PIGLIT_PASS : PIGLIT_FAIL;
> +}
> +
> 



More information about the Piglit mailing list