summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2015-10-27 15:52:32 -0700
committerEric Anholt <eric@anholt.net>2019-04-10 16:01:45 -0700
commit968d55720fe686ad68424bbcac60e2593fd35154 (patch)
tree2d23fbae323c2bef091da47e1da4ec2455c8954f
parentdce99851706c8de211ade26aef4324ce8aaa017f (diff)
gl-1.1: Add a new test for large vertex counts.
There's a limitation on VC4 where it can only handle 65536 verts at a time in a glDrawArrays(), so the driver needs to split up the calls. This tests that path for all the primitive types. v2: handle error from glMapBuffer(). Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
-rw-r--r--tests/opengl.py7
-rw-r--r--tests/spec/gl-1.1/CMakeLists.gl.txt1
-rw-r--r--tests/spec/gl-1.1/drawarrays-vertex-count.c457
3 files changed, 465 insertions, 0 deletions
diff --git a/tests/opengl.py b/tests/opengl.py
index fb950d85d..3c71dde81 100644
--- a/tests/opengl.py
+++ b/tests/opengl.py
@@ -712,6 +712,13 @@ with profile.test_list.group_manager(
g(['getteximage-targets', '2D'])
g(['teximage-scale-bias'])
g(['tex-upside-down-miptree'])
+
+ for prim in ['GL_POINTS', 'GL_LINE_LOOP', 'GL_LINE_STRIP', 'GL_LINES',
+ 'GL_TRIANGLES', 'GL_TRIANGLE_STRIP', 'GL_TRIANGLE_FAN',
+ 'GL_QUADS', 'GL_QUAD_STRIP', 'GL_POLYGON']:
+ for mode in ['varray', 'vbo']:
+ g(['gl-1.1-drawarrays-vertex-count', '100000', mode, prim])
+
add_msaa_visual_plain_tests(g, ['draw-pixels'])
add_msaa_visual_plain_tests(g, ['read-front'], run_concurrent=False)
add_msaa_visual_plain_tests(g, ['read-front', 'clear-front-first'],
diff --git a/tests/spec/gl-1.1/CMakeLists.gl.txt b/tests/spec/gl-1.1/CMakeLists.gl.txt
index 9ed7ec9f3..6b9107633 100644
--- a/tests/spec/gl-1.1/CMakeLists.gl.txt
+++ b/tests/spec/gl-1.1/CMakeLists.gl.txt
@@ -10,6 +10,7 @@ link_libraries (
piglit_add_executable (gl-1.1-color-material-array color-material-array.c)
piglit_add_executable (gl-1.1-draw-arrays-start draw-arrays-start.c)
+piglit_add_executable (gl-1.1-drawarrays-vertex-count drawarrays-vertex-count.c)
piglit_add_executable (gl-1.1-read-pixels-after-display-list read-pixels-after-display-list.c)
piglit_add_executable (gl-1.1-set-vertex-color-after-draw set-vertex-color-after-draw.c)
piglit_add_executable (gl-1.1-xor xor.c)
diff --git a/tests/spec/gl-1.1/drawarrays-vertex-count.c b/tests/spec/gl-1.1/drawarrays-vertex-count.c
new file mode 100644
index 000000000..bec70bfe3
--- /dev/null
+++ b/tests/spec/gl-1.1/drawarrays-vertex-count.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright © 2016 Broadcom Limited
+ *
+ * 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 drawarrays-vertex-count.c
+ *
+ * Tests glDrawArrays with large vertex counts and a start vertex
+ * offset. Catches a limitation of the vc4 hardware where
+ * glDrawArrays() with a large count ends up truncating the high 16
+ * bits of vertex indices.
+ */
+
+#include "piglit-util-gl.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+ config.supports_gl_compat_version = 10;
+ config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
+PIGLIT_GL_TEST_CONFIG_END
+
+static GLenum primtype;
+static unsigned int count;
+static bool use_vbo;
+
+static const float green[4] = {0.0, 1.0, 0.0, 0.0};
+static const float black[4] = {0.0, 0.0, 0.0, 0.0};
+static const float red[4] = {1.0, 0.0, 0.0, 0.0};
+
+static int v_from_end(int count, int prims, int primsize)
+{
+ int v = count - prims * primsize;
+ return v - v % primsize;
+}
+
+/* Probes for a green filled rectangle in the screen, surrounded by black. */
+static bool
+probe_rect(int x, int y, int w, int h)
+{
+ return (piglit_probe_rect_rgba(x, y, w, h, green) &&
+ piglit_probe_rect_rgba(0, 0, piglit_width, y, black) &&
+ piglit_probe_rect_rgba(0, y, x, h, black) &&
+ piglit_probe_rect_rgba(x + w, y,
+ piglit_width - (x + w), h, black) &&
+ piglit_probe_rect_rgba(0, y + h,
+ piglit_width, piglit_height - (y + h),
+ black));
+}
+
+/* Probes for a green outlined rectangle in the screen, surrounded by black. */
+static bool
+probe_line_rect(int x1, int y1, int x2, int y2)
+{
+ int probe_w = x2 - x1 - 2;
+ int probe_h = y2 - y1 - 2;
+
+ /* Note that GL line rasterization may not include the endpoints. */
+ return (/* rect */
+ piglit_probe_rect_rgba(x1 + 1, y1, probe_w, 1, green) &&
+ piglit_probe_rect_rgba(x1 + 1, y2, probe_w, 1, green) &&
+ piglit_probe_rect_rgba(x1, y1 + 1, 1, probe_h, green) &&
+ piglit_probe_rect_rgba(x2, y1 + 1, 1, probe_h, green) &&
+ /* inside the rect */
+ piglit_probe_rect_rgba(x1 + 1, y1 + 1,
+ probe_w, probe_h, black) &&
+ /* outside the rect */
+ piglit_probe_rect_rgba(0, 0, piglit_width, y1, black) &&
+ piglit_probe_rect_rgba(0, y1,
+ x1, y2 - y1, black) &&
+ piglit_probe_rect_rgba(x2 + 1, y1,
+ piglit_width - x2, y2 - y1, black) &&
+ piglit_probe_rect_rgba(0, y2 + 1,
+ piglit_width, piglit_height - (y2 + 1),
+ black));
+}
+
+/* Sets a range of the color array to a spefific color. */
+static void
+set_colors(float *colors, unsigned int start, unsigned int count,
+ const float *color)
+{
+ unsigned int i;
+
+ for (i = start; i < start + count; i++)
+ memcpy(&colors[i * 4], color, 4 * sizeof(float));
+}
+
+void set_point(float *verts, int p, float x, float y)
+{
+ verts[p * 2 + 0] = x;
+ verts[p * 2 + 1] = y;
+}
+
+enum piglit_result
+piglit_display(void)
+{
+ /* Start vertex offset for DrawArrays. */
+ unsigned int sv = count / 3;
+ /* Vertex index for the primitive we care about */
+ unsigned int v;
+ bool pass = true;
+ char *data;
+ float *vert;
+ float *color;
+ unsigned int i;
+ GLsizei vert_size = 2 * sizeof(float);
+ GLsizei color_size = 4 * sizeof(float);
+ GLsizei vert_buffer_size = vert_size * (sv + count);
+ GLsizei color_buffer_size = color_size * (sv + count);
+ GLsizei buffer_size = vert_buffer_size + color_buffer_size;
+ int quad_x1 = piglit_width / 2 - 5;
+ int quad_y1 = piglit_height / 2 - 5;
+ int quad_x2 = quad_x1 + 10;
+ int quad_y2 = quad_y1 + 10;
+ int smallquad_x1 = piglit_width / 2;
+ int smallquad_y1 = piglit_height / 2;
+ int smallquad_x2 = smallquad_x1 + 1;
+ int smallquad_y2 = smallquad_y1 + 1;
+ piglit_ortho_projection(piglit_width, piglit_height, false);
+
+ if (use_vbo) {
+ GLuint vbo;
+
+ glGenBuffers(1, &vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, buffer_size, NULL, GL_STREAM_DRAW);
+ glVertexPointer(2, GL_FLOAT, 0, 0);
+
+ data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
+ } else {
+ data = malloc(buffer_size);
+ }
+ if (!data)
+ return PIGLIT_FAIL;
+
+ vert = (float *)data;
+ color = (float *)(data + vert_buffer_size);
+
+ if (use_vbo) {
+ glVertexPointer(2, GL_FLOAT, 0, 0);
+ glColorPointer(4, GL_FLOAT, 0,
+ (void *)(uintptr_t)vert_buffer_size);
+ } else {
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+ glColorPointer(4, GL_FLOAT, 0, color);
+ }
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* Initialize all colors to red. */
+ set_colors(color, 0, sv + count, red);
+
+ /* Initialize all the vertices to offscreen. */
+ for (i = 0; i < sv + count; i++)
+ set_point(vert, i, -1, -1);
+
+ switch (primtype) {
+ case GL_POINTS:
+ /* Four points in the middle of the screen. */
+ v = sv + v_from_end(count, 4, 1);
+ set_colors(color, v, 4, green);
+ /* Adjust point and line coordinates to pixel centers,
+ * to prevent rounding-based test failures.
+ */
+ set_point(vert, v++, smallquad_x1 + 0.5, smallquad_y1 + 0.5);
+ set_point(vert, v++, smallquad_x2 + 0.5, smallquad_y1 + 0.5);
+ set_point(vert, v++, smallquad_x1 + 0.5, smallquad_y2 + 0.5);
+ set_point(vert, v++, smallquad_x2 + 0.5, smallquad_y2 + 0.5);
+ break;
+
+ case GL_LINES:
+ /* Draw the outline of a quad. */
+ v = sv + v_from_end(count, 4, 2);
+ set_colors(color, v, 4 * 2, green);
+ set_point(vert, v++, quad_x1, quad_y1 + 0.5);
+ set_point(vert, v++, quad_x2, quad_y1 + 0.5);
+
+ set_point(vert, v++, quad_x1, quad_y2 + 0.5);
+ set_point(vert, v++, quad_x2, quad_y2 + 0.5);
+
+ set_point(vert, v++, quad_x1 + 0.5, quad_y1);
+ set_point(vert, v++, quad_x1 + 0.5, quad_y2);
+
+ set_point(vert, v++, quad_x2 + 0.5, quad_y1);
+ set_point(vert, v++, quad_x2 + 0.5, quad_y2);
+ break;
+
+ case GL_LINE_STRIP:
+ v = sv + v_from_end(count, 4, 1);
+ /* Strip start point plus a bunch of degenerate lines. */
+ for (i = sv; i < v; i++)
+ set_point(vert, i, quad_x1 + 0.5, quad_y1 + 0.5);
+
+ /* Last 4 points producing the real lines. */
+ set_colors(color, v - 1, 5, green);
+ set_point(vert, v++, quad_x2 + 0.5, quad_y1 + 0.5);
+ set_point(vert, v++, quad_x2 + 0.5, quad_y2 + 0.5);
+ set_point(vert, v++, quad_x1 + 0.5, quad_y2 + 0.5);
+ set_point(vert, v++, quad_x1 + 0.5, quad_y1 + 0.5);
+ break;
+
+ case GL_LINE_LOOP:
+ v = sv + v_from_end(count, 3, 1);
+ /* Loop start point plus a bunch of degenerate lines. */
+ set_colors(color, sv, 1, green);
+ for (i = sv; i < v; i++)
+ set_point(vert, i, quad_x1 + 0.5, quad_y1 + 0.5);
+
+ /* Last 3 points producing the real lines. */
+ set_colors(color, v - 1, 4, green);
+ set_point(vert, v++, quad_x2 + 0.5, quad_y1 + 0.5);
+ set_point(vert, v++, quad_x2 + 0.5, quad_y2 + 0.5);
+ set_point(vert, v++, quad_x1 + 0.5, quad_y2 + 0.5);
+ break;
+
+ case GL_TRIANGLES:
+ /* Set up a pair of triangles to make a quad. */
+ v = sv + v_from_end(count, 2, 3);
+ set_colors(color, v, 2 * 3, green);
+ set_point(vert, v++, quad_x1, quad_y1);
+ set_point(vert, v++, quad_x2, quad_y1);
+ set_point(vert, v++, quad_x1, quad_y2);
+
+ set_point(vert, v++, quad_x2, quad_y1);
+ set_point(vert, v++, quad_x2, quad_y2);
+ set_point(vert, v++, quad_x1, quad_y2);
+ break;
+
+ case GL_TRIANGLE_STRIP:
+ v = sv + v_from_end(count, 3, 1);
+ /* A bunch of degenerate tri strip triangles. */
+ for (i = sv; i < v; i++)
+ set_point(vert, i, quad_x1, quad_y1);
+
+ /* Last 3 strip points producing one more degenerate
+ * plus two real tris.
+ */
+ set_colors(color, v - 1, 4, green);
+ set_point(vert, v++, quad_x2, quad_y1);
+ set_point(vert, v++, quad_x1, quad_y2);
+ set_point(vert, v++, quad_x2, quad_y2);
+ break;
+
+ case GL_TRIANGLE_FAN:
+ case GL_POLYGON:
+ v = sv + v_from_end(count, 3, 1);
+ /* Fan start point plus a bunch of degenerate tris. */
+ set_colors(color, sv, 1, green);
+ for (i = sv; i < v; i++)
+ set_point(vert, i, quad_x1, quad_y1);
+
+ /* Last 3 fan points producing the real tris. */
+ set_colors(color, v, 3, green);
+ set_point(vert, v++, quad_x2, quad_y1);
+ set_point(vert, v++, quad_x2, quad_y2);
+ set_point(vert, v++, quad_x1, quad_y2);
+ break;
+
+ case GL_QUADS:
+ v = sv + v_from_end(count, 1, 4);
+ set_colors(color, v, 4, green);
+ set_point(vert, v++, quad_x1, quad_y1);
+ set_point(vert, v++, quad_x2, quad_y1);
+ set_point(vert, v++, quad_x2, quad_y2);
+ set_point(vert, v++, quad_x1, quad_y2);
+ break;
+
+ case GL_QUAD_STRIP:
+ v = sv + v_from_end(count, 1, 2);
+ for (i = sv; i < v; i++) {
+ if ((i - sv) % 2 == 0)
+ set_point(vert, i, quad_x1, quad_y1);
+ else
+ set_point(vert, i, quad_x2, quad_y1);
+ }
+ set_colors(color, v - 2, 4, green);
+ set_point(vert, v++, quad_x1, quad_y2);
+ set_point(vert, v++, quad_x2, quad_y2);
+ break;
+
+ default:
+ fprintf(stderr, "bad primitive\n");
+ piglit_report_result(PIGLIT_FAIL);
+ break;
+ }
+
+ /* Initialize the 0 - sv primitives to something that would
+ * draw some red garbage if we were to accidentally draw using
+ * them.
+ */
+ v = 0;
+ switch (primtype) {
+ case GL_POINTS:
+ for (i = 0; i < sv; i++) {
+ set_point(vert, v++,
+ i % piglit_width,
+ (i / piglit_width) % piglit_height);
+ }
+ break;
+
+ case GL_LINES:
+ case GL_LINE_STRIP:
+ case GL_LINE_LOOP:
+ for (i = 0; i < sv / 2; i++) {
+ int y = i % piglit_height;
+ set_point(vert, v++, 0, y);
+ set_point(vert, v++, piglit_width, y);
+ }
+ break;
+
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_FAN:
+ case GL_TRIANGLE_STRIP:
+ for (i = 0; i < sv / 3; i++) {
+ set_point(vert, v++, 0, 0);
+ set_point(vert, v++, piglit_width, 0);
+ set_point(vert, v++, 0, piglit_height);
+ }
+ break;
+
+ case GL_QUADS:
+ case GL_QUAD_STRIP:
+ case GL_POLYGON:
+ for (i = 0; i < sv / 4; i++) {
+ set_point(vert, v++, 0, 0);
+ set_point(vert, v++, piglit_width, 0);
+ set_point(vert, v++, piglit_width, piglit_height);
+ set_point(vert, v++, 0, piglit_height);
+ }
+ break;
+
+ default:
+ fprintf(stderr, "bad primitive\n");
+ piglit_report_result(PIGLIT_FAIL);
+ break;
+ }
+
+ if (use_vbo)
+ glUnmapBuffer(GL_ARRAY_BUFFER);
+
+ glDrawArrays(primtype, sv, count);
+
+ switch (primtype) {
+ case GL_POINTS:
+ pass = probe_rect(smallquad_x1, smallquad_y1,
+ smallquad_x2 - smallquad_x1 + 1,
+ smallquad_y2 - smallquad_y1 + 1);
+ break;
+
+ case GL_LINES:
+ case GL_LINE_LOOP:
+ case GL_LINE_STRIP:
+ pass = probe_line_rect(quad_x1, quad_y1,
+ quad_x2, quad_y2);
+ break;
+
+ case GL_TRIANGLES:
+ case GL_TRIANGLE_FAN:
+ case GL_TRIANGLE_STRIP:
+ case GL_QUADS:
+ case GL_QUAD_STRIP:
+ case GL_POLYGON:
+ pass = probe_rect(quad_x1, quad_y1,
+ quad_x2 - quad_x1,
+ quad_y2 - quad_y1);
+ break;
+
+ default:
+ fprintf(stderr, "bad primitive\n");
+ piglit_report_result(PIGLIT_FAIL);
+ break;
+ }
+
+ piglit_present_results();
+
+ if (!use_vbo)
+ free(data);
+
+ return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+static const struct {
+ const char *name;
+ GLenum e;
+} prims[] = {
+ { "GL_POINTS", GL_POINTS },
+ { "GL_LINES", GL_LINES },
+ { "GL_LINE_STRIP", GL_LINE_STRIP },
+ { "GL_LINE_LOOP", GL_LINE_LOOP },
+ { "GL_TRIANGLES", GL_TRIANGLES },
+ { "GL_TRIANGLE_STRIP", GL_TRIANGLE_STRIP },
+ { "GL_TRIANGLE_FAN", GL_TRIANGLE_FAN },
+ { "GL_QUADS", GL_QUADS },
+ { "GL_QUAD_STRIP", GL_QUAD_STRIP },
+ { "GL_POLYGON", GL_POLYGON },
+};
+
+static void usage(const char *progname)
+{
+ int i;
+
+ fprintf(stderr, "Usage: %s <vertcount> <vbo|varray> <primtype>\n",
+ progname);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "primtype may be:\n");
+ for (i = 0; i < ARRAY_SIZE(prims); i++)
+ fprintf(stderr, " %s\n", prims[i].name);
+ exit(1);
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+ int i;
+
+ if (argc != 4)
+ usage(argv[0]);
+
+ count = atoi(argv[1]);
+
+ if (strcmp(argv[2], "vbo") == 0) {
+ piglit_require_extension("GL_ARB_vertex_buffer_object");
+ use_vbo = true;
+ } else if (strcmp(argv[2], "varray") != 0) {
+ usage(argv[0]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(prims); i++) {
+ if (strcmp(prims[i].name, argv[3]) == 0) {
+ primtype = prims[i].e;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(prims))
+ usage(argv[0]);
+}