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 DEALINGS
24 #include "piglit-util-gl.h"
25 #include "xfb3_common.h"
28 * @file ext_interleaved_two_bufs.c
30 * Record two interleaved sets of attributes, one holding two attributes and the
31 * other holding three, into two separate buffers. The test can be executed in
32 * three different ways: recording vertex shader, recording single geometry
33 * shader invocation or recording maximum amount of geometry shader invocations
36 * Recording both vertex shader and geometry shader outputs in parallel is not
37 * supported by the extension, the spec:
39 * "When a geometry shader is active (see section 2.12), transform feedback
40 * records the values of the selected geometry shader output variables from the
41 * emitted vertices. Otherwise, the values of the selected vertex shader output
42 * variables are recorded."
44 * This test uses the "EXT"-style GLSL transform feedback.
47 PIGLIT_GL_TEST_CONFIG_BEGIN
49 config
.supports_gl_compat_version
= 32;
50 config
.supports_gl_core_version
= 32;
51 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
53 PIGLIT_GL_TEST_CONFIG_END
55 static const char vs_two_sets_text
[] =
63 " gl_Position = vec4(0.0);\n"
65 " x2_out = vec2(2.0, 3.0);\n"
66 " x3_out = vec3(4.0, 5.0, 6.0);\n"
68 " y2_out = vec4(8.0, 9.0, 10.0, 11.0);\n"
71 static const char gs_text_two_sets_tmpl
[] =
73 "#extension GL_ARB_gpu_shader5 : enable\n"
74 "#define INVOCATION_MAX_N %u\n"
75 "layout(points, invocations = INVOCATION_MAX_N) in;\n"
76 "layout(points, max_vertices = 1) out;\n"
83 " gl_Position = gl_in[0].gl_Position;\n"
84 " x1_out = 1.0 + gl_InvocationID;\n"
85 " x2_out = vec2(2.0 + gl_InvocationID, 3.0 + gl_InvocationID);\n"
86 " x3_out = vec3(4.0 + gl_InvocationID, 5.0 + gl_InvocationID,\n"
87 " 6.0 + gl_InvocationID);\n"
88 " y1_out = 7.0 + gl_InvocationID;\n"
89 " y2_out = vec4(8.0 + gl_InvocationID, 9.0 + gl_InvocationID,\n"
90 " 10.0 + gl_InvocationID, 11.0 + gl_InvocationID);\n"
95 #define BUF_1_FLOAT_N 6
96 #define BUF_2_FLOAT_N 5
99 * The spec for ARB_transform_feedback3 says:
101 * If a string in <varyings> is "gl_NextBuffer", it does not identify a
102 * varying variable, but instead serves as a buffer separator value to
103 * direct subsequent varyings at the next transform feedback binding point.
105 static const char *varyings
[] = {
106 "x1_out", "x2_out", "x3_out", "gl_NextBuffer",
111 print_usage_and_exit(const char *prog_name
)
113 printf("Usage: %s <subtest>\n"
114 " where <subtest> is one of the following:\n"
115 " vs (vertex shader only)\n"
116 " gs (with geometry shader invoked once per stage)\n"
117 " gs_max (with geometry shader invoked max times per "
118 "stage)\n", prog_name
);
119 piglit_report_result(PIGLIT_FAIL
);
123 build_and_use_program(unsigned gs_invocation_n
)
127 if (gs_invocation_n
== 0) {
128 prog
= piglit_build_simple_program_multiple_shaders(
129 GL_VERTEX_SHADER
, vs_two_sets_text
, 0);
133 (void)!asprintf(&gs_text
, gs_text_two_sets_tmpl
, gs_invocation_n
);
134 prog
= piglit_build_simple_program_multiple_shaders(
135 GL_VERTEX_SHADER
, vs_pass_thru_text
,
136 GL_GEOMETRY_SHADER
, gs_text
, 0);
141 * In the EXT-style the recorded varyings need to be set before linking.
143 * Also it should be noticed that when mixed mode is used, i.e., where
144 * one records multiple attributes per buffer but also uses separate
145 * buffers, the mode must be set to interleaved.
147 glTransformFeedbackVaryings(prog
, ARRAY_SIZE(varyings
), varyings
,
148 GL_INTERLEAVED_ATTRIBS
);
151 if (!piglit_link_check_status(prog
))
152 piglit_report_result(PIGLIT_FAIL
);
153 if (!piglit_check_gl_error(GL_NO_ERROR
))
154 piglit_report_result(PIGLIT_FAIL
);
160 probe_buffers(const GLuint
*xfb
, const GLuint
*queries
, unsigned primitive_n
)
168 const unsigned first_n
= primitive_n
* BUF_1_FLOAT_N
;
169 const unsigned second_n
= primitive_n
* BUF_2_FLOAT_N
;
171 glGetQueryObjectuiv(queries
[0], GL_QUERY_RESULT
, &query_result
);
172 if (query_result
!= primitive_n
) {
173 printf("Expected %u primitives written, got %u\n",
174 primitive_n
, query_result
);
175 piglit_report_result(PIGLIT_FAIL
);
178 glGetQueryObjectuiv(queries
[1], GL_QUERY_RESULT
, &query_result
);
179 if (query_result
!= primitive_n
) {
180 printf("Expected %u primitives generated, got %u\n",
181 primitive_n
, query_result
);
182 piglit_report_result(PIGLIT_FAIL
);
185 first
= malloc(first_n
* sizeof(float));
186 second
= malloc(second_n
* sizeof(float));
188 for (i
= 0; i
< primitive_n
; ++i
) {
189 first
[i
* BUF_1_FLOAT_N
+ 0] = i
+ 1.0; /* x1 */
190 first
[i
* BUF_1_FLOAT_N
+ 1] = i
+ 2.0; /* x2[0] */
191 first
[i
* BUF_1_FLOAT_N
+ 2] = i
+ 3.0; /* x2[1] */
192 first
[i
* BUF_1_FLOAT_N
+ 3] = i
+ 4.0; /* x3[0] */
193 first
[i
* BUF_1_FLOAT_N
+ 4] = i
+ 5.0; /* x3[1] */
194 first
[i
* BUF_1_FLOAT_N
+ 5] = i
+ 6.0; /* x3[2] */
196 second
[i
* BUF_2_FLOAT_N
+ 0] = i
+ 7.0; /* y1 */
197 second
[i
* BUF_2_FLOAT_N
+ 1] = i
+ 8.0; /* y2[0] */
198 second
[i
* BUF_2_FLOAT_N
+ 2] = i
+ 9.0; /* y2[1] */
199 second
[i
* BUF_2_FLOAT_N
+ 3] = i
+ 10.0; /* y2[2] */
200 second
[i
* BUF_2_FLOAT_N
+ 4] = i
+ 11.0; /* y2u3] */
203 pass
= piglit_probe_buffer(xfb
[0], GL_TRANSFORM_FEEDBACK_BUFFER
,
204 "first", 1, first_n
, first
);
205 pass
= piglit_probe_buffer(xfb
[1], GL_TRANSFORM_FEEDBACK_BUFFER
,
206 "second", 1, second_n
, second
) &&
216 parse_args(int argc
, char **argv
)
218 GLint gs_invocation_n
;
221 print_usage_and_exit(argv
[0]);
223 if (strcmp(argv
[1], "vs") == 0)
226 piglit_require_extension("GL_ARB_gpu_shader5");
228 if (strcmp(argv
[1], "gs") == 0)
231 if (strcmp(argv
[1], "gs_max") != 0)
232 print_usage_and_exit(argv
[0]);
234 glGetIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS
, &gs_invocation_n
);
235 if (gs_invocation_n
<= 0) {
236 printf("Maximum amount of geometry shader invocations "
237 "needs to be positive (%u).\n", gs_invocation_n
);
238 piglit_report_result(PIGLIT_FAIL
);
241 return gs_invocation_n
;
245 piglit_init(int argc
, char **argv
)
248 unsigned primitive_n
, gs_invocation_n
;
253 piglit_require_GLSL_version(150);
254 piglit_require_extension("GL_ARB_transform_feedback3");
256 gs_invocation_n
= parse_args(argc
, argv
);
258 /* Zero invocations means the feedback is produced by vertex shader */
259 primitive_n
= gs_invocation_n
? gs_invocation_n
: 1;
261 build_and_use_program(gs_invocation_n
);
263 /* Set up the transform feedback buffers. */
264 glGenBuffers(ARRAY_SIZE(xfb
), xfb
);
265 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER
, 0, xfb
[0]);
266 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER
,
267 primitive_n
* BUF_1_FLOAT_N
* sizeof(float), NULL
,
269 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER
, 1, xfb
[1]);
270 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER
,
271 primitive_n
* BUF_2_FLOAT_N
* sizeof(float), NULL
,
274 /* Test only records using transform feedback. */
275 glEnable(GL_RASTERIZER_DISCARD
);
277 if (!piglit_check_gl_error(GL_NO_ERROR
))
278 piglit_report_result(PIGLIT_FAIL
);
280 glGenQueries(2, queries
);
281 glBeginQuery(GL_PRIMITIVES_GENERATED
, queries
[0]);
282 glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
, queries
[1]);
284 /* Test is run under desktop OpenGL 3.2 -> use of VAOs is required */
285 glGenVertexArrays(1, &vao
);
286 glBindVertexArray(vao
);
288 /* Draw and record */
289 glBeginTransformFeedback(GL_POINTS
);
290 glDrawArrays(GL_POINTS
, 0, 1);
291 glEndQuery(GL_PRIMITIVES_GENERATED
);
292 glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
);
293 glEndTransformFeedback();
294 glDeleteVertexArrays(1, &vao
);
296 if (!piglit_check_gl_error(GL_NO_ERROR
))
297 piglit_report_result(PIGLIT_FAIL
);
299 pass
= probe_buffers(xfb
, queries
, primitive_n
);
301 glDeleteBuffers(2, xfb
);
302 glDeleteQueries(2, queries
);
304 piglit_report_result(pass
? PIGLIT_PASS
: PIGLIT_FAIL
);
310 /* Should never be reached */