ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / arb_transform_feedback3 / ext_interleaved_two_bufs.c
blob3f724454fcaa5f59e291397e18efbdc9df06654f
1 /*
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
13 * Software.
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
21 * IN THE SOFTWARE.
24 #include "piglit-util-gl.h"
25 #include "xfb3_common.h"
27 /**
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
34 * per pipeline stage.
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[] =
56 "#version 150\n"
57 "out float x1_out;\n"
58 "out vec2 x2_out;\n"
59 "out vec3 x3_out;\n"
60 "out float y1_out;\n"
61 "out vec4 y2_out;\n"
62 "void main() {\n"
63 " gl_Position = vec4(0.0);\n"
64 " x1_out = 1.0;\n"
65 " x2_out = vec2(2.0, 3.0);\n"
66 " x3_out = vec3(4.0, 5.0, 6.0);\n"
67 " y1_out = 7.0;\n"
68 " y2_out = vec4(8.0, 9.0, 10.0, 11.0);\n"
69 "}";
71 static const char gs_text_two_sets_tmpl[] =
72 "#version 150\n"
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"
77 "out float x1_out;\n"
78 "out vec2 x2_out;\n"
79 "out vec3 x3_out;\n"
80 "out float y1_out;\n"
81 "out vec4 y2_out;\n"
82 "void main() {\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"
91 " EmitVertex();\n"
92 " EndPrimitive();\n"
93 "}";
95 #define BUF_1_FLOAT_N 6
96 #define BUF_2_FLOAT_N 5
98 /**
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",
107 "y1_out", "y2_out"
110 static void
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);
122 static void
123 build_and_use_program(unsigned gs_invocation_n)
125 GLuint prog;
127 if (gs_invocation_n == 0) {
128 prog = piglit_build_simple_program_multiple_shaders(
129 GL_VERTEX_SHADER, vs_two_sets_text, 0);
130 } else {
131 char *gs_text;
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);
137 free(gs_text);
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);
150 glLinkProgram(prog);
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);
156 glUseProgram(prog);
159 static bool
160 probe_buffers(const GLuint *xfb, const GLuint *queries, unsigned primitive_n)
162 bool pass;
163 unsigned i;
164 GLuint query_result;
165 float *first;
166 float *second;
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) &&
207 pass;
209 free(first);
210 free(second);
212 return pass;
215 static unsigned
216 parse_args(int argc, char **argv)
218 GLint gs_invocation_n;
220 if (argc != 2)
221 print_usage_and_exit(argv[0]);
223 if (strcmp(argv[1], "vs") == 0)
224 return 0;
226 piglit_require_extension("GL_ARB_gpu_shader5");
228 if (strcmp(argv[1], "gs") == 0)
229 return 1;
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;
244 void
245 piglit_init(int argc, char **argv)
247 bool pass;
248 unsigned primitive_n, gs_invocation_n;
249 GLuint queries[2];
250 GLuint xfb[2];
251 GLuint vao;
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,
268 GL_STREAM_READ);
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,
272 GL_STREAM_READ);
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);
307 enum piglit_result
308 piglit_display(void)
310 /* Should never be reached */
311 return PIGLIT_FAIL;