[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