2 * Copyright © 2013 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 * \file primitive-restart-xfb.c
27 * Test interactions between primitive restart and transform feedback
28 * primitive counting behaviour.
30 * This test makes a single glDrawElements(GL_TRIANGLE_STRIP, 9, ...)
31 * draw call, where the index buffer specifies 4 normal vertices, the
32 * primitive restart index, and then 4 more normal vertices. It
33 * verifies that the implementation correctly counts this as drawing 4
34 * triangles (rather than 7, which would be the behaviour of if
35 * primitive restart were not in use).
37 * The test can be run in three ways (selectable by a command line
40 * - "generated" verifies that the GL_PRIMITIVES_GENERATED query
41 * counts the primitives correctly.
43 * - "written" verifies that the
44 * GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query counts the
45 * primitives correctly.
47 * - "flush" verifies that if these 4 triangles are followed by a
48 * glFlush() and then more primitives further drawing, transform
49 * feedback for the latter primitives is placed at the correct
50 * location in the transform feedback buffer.
53 #include "piglit-util-gl.h"
55 PIGLIT_GL_TEST_CONFIG_BEGIN
56 config
.supports_gl_core_version
= 31;
57 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
58 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
59 PIGLIT_GL_TEST_CONFIG_END
69 static const char vs_text
[] =
72 "flat out int x_out;\n"
75 " gl_Position = vec4(0.0);\n"
80 static const GLchar
*varyings
[] = { "x_out" };
84 * Indices used for the test.
86 static const GLubyte indices
[] = {
87 /* For the main draw call */
88 0, 1, 2, 3, 0xff, 4, 5, 6, 7,
90 /* After the glFlush() call (when in TEST_MODE_FLUSH) */
95 static const GLint vertex_attrs
[] = { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 };
99 * Expected transform feedback result when in TEST_MODE_FLUSH:
100 * - 2 triangles with attribute 1 and 2 triangles with attribute value 2 (from
101 * the first draw call)
102 * - 2 triangles with attribute 3 (from the second draw call, after the flush)
104 static const GLint expected_xfb_result
[] =
105 { 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3 };
109 print_usage_and_exit(const char *prog_name
)
111 printf("Usage: %s <subtest>\n"
112 " where <subtest> is one of the following:\n"
115 " flush\n", prog_name
);
116 piglit_report_result(PIGLIT_FAIL
);
121 check_query_result(GLuint query
, GLuint expected
)
125 glGetQueryObjectuiv(query
, GL_QUERY_RESULT
, &result
);
126 if (result
!= expected
) {
127 printf("Query result: %u, expected: %u\n", result
, expected
);
139 const GLint
*readback
=
140 glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER
, 0,
141 sizeof(expected_xfb_result
), GL_MAP_READ_BIT
);
142 for (i
= 0; i
< ARRAY_SIZE(expected_xfb_result
); i
++) {
143 if (readback
[i
] != expected_xfb_result
[i
]) {
144 printf("XFB[%i] == %i, expected %i\n", i
, readback
[i
],
145 expected_xfb_result
[i
]);
149 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER
);
155 piglit_init(int argc
, char **argv
)
160 enum test_mode_enum test_mode
;
162 GLuint vao
, vbo_attrs
, vbo_indices
;
166 print_usage_and_exit(argv
[0]);
167 if (strcmp(argv
[1], "generated") == 0)
168 test_mode
= TEST_MODE_GENERATED
;
169 else if (strcmp(argv
[1], "written") == 0)
170 test_mode
= TEST_MODE_WRITTEN
;
171 else if (strcmp(argv
[1], "flush") == 0)
172 test_mode
= TEST_MODE_FLUSH
;
174 print_usage_and_exit(argv
[0]);
176 prog
= piglit_build_simple_program_unlinked(vs_text
, NULL
);
177 glTransformFeedbackVaryings(prog
, 1, varyings
, GL_INTERLEAVED_ATTRIBS
);
178 glBindAttribLocation(prog
, 0, "x_in");
180 if (!piglit_link_check_status(prog
) ||
181 !piglit_check_gl_error(GL_NO_ERROR
)) {
182 piglit_report_result(PIGLIT_FAIL
);
186 /* Create transform feedback buffer and pre-load it with
189 glGenBuffers(1, &buf
);
190 initial_data
= malloc(sizeof(expected_xfb_result
));
191 memset(initial_data
, 0xcc, sizeof(expected_xfb_result
));
192 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER
, 0, buf
);
193 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER
, sizeof(expected_xfb_result
),
194 initial_data
, GL_STREAM_READ
);
198 glGenVertexArrays(1, &vao
);
199 glBindVertexArray(vao
);
200 glGenBuffers(1, &vbo_attrs
);
201 glBindBuffer(GL_ARRAY_BUFFER
, vbo_attrs
);
202 glBufferData(GL_ARRAY_BUFFER
, sizeof(vertex_attrs
), vertex_attrs
,
204 glVertexAttribIPointer(0, 1, GL_INT
, 0, NULL
);
205 glEnableVertexAttribArray(0);
206 glGenBuffers(1, &vbo_indices
);
207 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER
, vbo_indices
);
208 glBufferData(GL_ELEMENT_ARRAY_BUFFER
, sizeof(indices
), indices
,
212 glEnable(GL_RASTERIZER_DISCARD
);
213 glEnable(GL_PRIMITIVE_RESTART
);
214 glPrimitiveRestartIndex(0xff);
215 glGenQueries(1, &query
);
218 case TEST_MODE_GENERATED
:
219 glBeginQuery(GL_PRIMITIVES_GENERATED
, query
);
220 glBeginTransformFeedback(GL_TRIANGLES
);
221 glDrawElements(GL_TRIANGLE_STRIP
, 9, GL_UNSIGNED_BYTE
, NULL
);
222 glEndTransformFeedback();
223 glEndQuery(GL_PRIMITIVES_GENERATED
);
224 pass
= check_query_result(query
, 4);
226 case TEST_MODE_WRITTEN
:
227 glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
, query
);
228 glBeginTransformFeedback(GL_TRIANGLES
);
229 glDrawElements(GL_TRIANGLE_STRIP
, 9, GL_UNSIGNED_BYTE
, NULL
);
230 glEndTransformFeedback();
231 glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
);
232 pass
= check_query_result(query
, 4);
234 case TEST_MODE_FLUSH
:
235 glBeginTransformFeedback(GL_TRIANGLES
);
236 glDrawElements(GL_TRIANGLE_STRIP
, 9, GL_UNSIGNED_BYTE
, NULL
);
238 glDrawElements(GL_TRIANGLE_STRIP
, 4, GL_UNSIGNED_BYTE
,
239 (void *) (9 * sizeof(GLubyte
)));
240 glEndTransformFeedback();
241 pass
= check_xfb_result();
245 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
246 piglit_report_result(pass
? PIGLIT_PASS
: PIGLIT_FAIL
);
253 /* Should never be reached */