fbo-mrt-alphatest: Actually require MRTs to be available.
[piglit.git] / tests / spec / arb_shader_atomic_counters / max-counters.c
blob19b0444d5e07554913ebc3ba571dffc5f0ce6c72
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 /** @file max-counters.c
26 * Test that using more than the maximum number of supported atomic
27 * counters, buffers or bindings fails with a linking error.
30 #include "common.h"
32 PIGLIT_GL_TEST_CONFIG_BEGIN
34 config.supports_gl_core_version = 31;
36 config.window_width = 1;
37 config.window_height = 1;
38 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGBA;
39 config.khr_no_error_support = PIGLIT_NO_ERRORS;
41 PIGLIT_GL_TEST_CONFIG_END
43 static char *
44 iterate_template(const char *template, unsigned n)
46 char *ss;
47 int i, ret;
49 ss = strdup("");
50 assert(ss);
52 for (i = 0; i < n; ++i) {
53 char *s, *tmp = ss;
55 ret = asprintf(&s, template, i);
56 assert(ret >= 0);
58 ret = asprintf(&ss, "%s%s", tmp, s);
59 assert(ret >= 0);
61 free(tmp);
62 free(s);
65 return ss;
68 /**
69 * Generate source code by substituting the first occurrence of "%s"
70 * in \a src_template with \a n copies of \a decl_template and the
71 * second occurrence of "%s" with \a n copies of \a insn_template.
73 static char *
74 generate_source(const char *src_template,
75 const char *decl_template, const char *insn_template,
76 unsigned n)
78 char *decls = iterate_template(decl_template, n);
79 char *insns = iterate_template(insn_template, n);
80 char *src;
81 int ret;
83 ret = asprintf(&src, src_template, decls, insns);
84 assert(ret);
86 free(decls);
87 free(insns);
89 return src;
92 static bool
93 run_test_vertex_max_counters(unsigned num_counters)
95 /* Generate a shader with 'num_counters' counters. */
96 char *vs_source = generate_source(
97 "#version 140\n"
98 "#extension GL_ARB_shader_atomic_counters : enable\n"
99 "\n"
100 "%s\n"
101 "\n"
102 "in vec4 position;\n"
103 "flat out ivec4 vcolor;\n"
104 "\n"
105 "void main() {\n"
106 " uint y = 0u;\n"
107 " %s\n"
108 " vcolor.x = int(y);\n"
109 " gl_Position = position;\n"
110 "}\n",
111 "layout(binding=0) uniform atomic_uint x%d;\n",
112 " y += atomicCounterDecrement(x%d);\n",
113 num_counters);
114 GLuint prog = glCreateProgram();
115 bool ret = atomic_counters_compile(prog, GL_VERTEX_SHADER, vs_source) &&
116 atomic_counters_link(prog);
118 glDeleteProgram(prog);
119 free(vs_source);
120 return ret;
123 static bool
124 run_test_fragment_max_counters(unsigned num_counters)
126 /* Generate a shader with 'num_counters' counters. */
127 char *fs_source = generate_source(
128 "#version 140\n"
129 "#extension GL_ARB_shader_atomic_counters : enable\n"
130 "\n"
131 "%s\n"
132 "\n"
133 "out ivec4 fcolor;\n"
134 "\n"
135 "void main() {\n"
136 " uint y = 0u;\n"
137 " %s\n"
138 " fcolor.x = int(y);\n"
139 "}\n",
140 "layout(binding=0) uniform atomic_uint x%d;\n",
141 " y += atomicCounterDecrement(x%d);\n",
142 num_counters);
143 GLuint prog = glCreateProgram();
144 bool ret = atomic_counters_compile(prog, GL_FRAGMENT_SHADER, fs_source) &&
145 atomic_counters_link(prog);
147 glDeleteProgram(prog);
148 free(fs_source);
149 return ret;
152 static bool
153 run_test_combined_max_counters(unsigned num_fragment_counters,
154 unsigned num_vertex_counters)
156 /* Generate a shader with 'num_fragment_counters' counters. */
157 char *fs_source = generate_source(
158 "#version 140\n"
159 "#extension GL_ARB_shader_atomic_counters : enable\n"
160 "\n"
161 "%s\n"
162 "\n"
163 "flat in ivec4 vcolor;\n"
164 "out ivec4 fcolor;\n"
165 "\n"
166 "void main() {\n"
167 " uint y = uint(vcolor.x);\n"
168 " %s\n"
169 " fcolor.x = int(y);\n"
170 "}\n",
171 "layout(binding=0) uniform atomic_uint fx%d;\n",
172 " y += atomicCounterDecrement(fx%d);\n",
173 num_fragment_counters);
174 /* Generate a shader with 'num_vertex_counters' counters. */
175 char *vs_source = generate_source(
176 "#version 140\n"
177 "#extension GL_ARB_shader_atomic_counters : enable\n"
178 "\n"
179 "%s\n"
180 "\n"
181 "in vec4 position;\n"
182 "flat out ivec4 vcolor;\n"
183 "\n"
184 "void main() {\n"
185 " uint y = 0u;\n"
186 " %s\n"
187 " vcolor.x = int(y);\n"
188 " gl_Position = position;\n"
189 "}\n",
190 "layout(binding=1) uniform atomic_uint vx%d;\n",
191 " y += atomicCounterDecrement(vx%d);\n",
192 num_vertex_counters);
193 GLuint prog = glCreateProgram();
194 bool ret = atomic_counters_compile(prog, GL_FRAGMENT_SHADER, fs_source) &&
195 atomic_counters_compile(prog, GL_VERTEX_SHADER, vs_source) &&
196 atomic_counters_link(prog);
198 glDeleteProgram(prog);
199 free(fs_source);
200 free(vs_source);
201 return ret;
204 static bool
205 run_test_fragment_max_buffers(unsigned num_buffers)
207 /* Generate a shader with 'num_buffers' buffers. */
208 char *src = generate_source(
209 "#version 140\n"
210 "#extension GL_ARB_shader_atomic_counters : enable\n"
211 "#define PASTE(A,B) A ## B\n"
212 "#define Y(I) PASTE(y, I)\n"
213 "\n"
214 "out ivec4 fcolor;\n"
215 "\n"
216 "%s"
217 "\n"
218 "void main() {\n"
219 " uint x = 0u;\n"
220 " %s\n"
221 " fcolor.x = int(x);\n"
222 "}\n",
223 "#define I %d\n"
224 "layout(binding=I, offset=0) uniform atomic_uint Y(I);\n"
225 "#undef I\n",
226 " x += atomicCounterDecrement(y%d);\n",
227 num_buffers);
228 GLuint prog = glCreateProgram();
229 bool ret = atomic_counters_compile(prog, GL_FRAGMENT_SHADER, src) &&
230 atomic_counters_link(prog);
232 glDeleteProgram(prog);
233 free(src);
234 return ret;
237 static bool
238 run_test_vertex_max_buffers(unsigned num_buffers)
240 /* Generate a shader with 'num_buffers' buffers. */
241 char *src = generate_source(
242 "#version 140\n"
243 "#extension GL_ARB_shader_atomic_counters : enable\n"
244 "#define PASTE(A,B) A ## B\n"
245 "#define X(I) PASTE(x, I)\n"
246 "\n"
247 "in vec4 position;\n"
248 "flat out ivec4 vcolor;\n"
249 "\n"
250 "%s"
251 "\n"
252 "void main() {\n"
253 " uint x = 0u;\n"
254 " %s\n"
255 " vcolor.x = int(x);\n"
256 " gl_Position = position;\n"
257 "}\n",
258 "#define I %d\n"
259 "layout(binding=I, offset=0) uniform atomic_uint X(I);\n"
260 "#undef I\n",
261 " x += atomicCounterDecrement(x%d);\n",
262 num_buffers);
263 GLuint prog = glCreateProgram();
264 bool ret = atomic_counters_compile(prog, GL_VERTEX_SHADER, src) &&
265 atomic_counters_link(prog);
267 glDeleteProgram(prog);
268 free(src);
269 return ret;
272 static bool
273 run_test_combined_max_buffers(unsigned num_fragment_buffers,
274 unsigned num_vertex_buffers)
276 /* Generate a shader with 'num_fragment_buffers' buffers. */
277 char *fs_source = generate_source(
278 "#version 140\n"
279 "#extension GL_ARB_shader_atomic_counters : enable\n"
280 "#define PASTE(A,B) A ## B\n"
281 "#define Y(I) PASTE(y, I)\n"
282 "\n"
283 "out ivec4 fcolor;\n"
284 "\n"
285 "%s"
286 "\n"
287 "void main() {\n"
288 " uint x = 0u;\n"
289 " %s\n"
290 " fcolor.x = int(x);\n"
291 "}\n",
292 "#define I %d\n"
293 "layout(binding=I, offset=0) uniform atomic_uint Y(I);\n"
294 "#undef I\n",
295 " x += atomicCounterDecrement(y%d);\n",
296 num_fragment_buffers);
297 /* Generate a shader with 'num_vertex_buffers' buffers. */
298 char *vs_source = generate_source(
299 "#version 140\n"
300 "#extension GL_ARB_shader_atomic_counters : enable\n"
301 "#define PASTE(A,B) A ## B\n"
302 "#define X(I) PASTE(x, I)\n"
303 "\n"
304 "in vec4 position;\n"
305 "flat out ivec4 vcolor;\n"
306 "\n"
307 "%s"
308 "\n"
309 "void main() {\n"
310 " uint x = 0u;\n"
311 " %s\n"
312 " vcolor.x = int(x);\n"
313 " gl_Position = position;\n"
314 "}\n",
315 "#define I %d\n"
316 "layout(binding=I, offset=4) uniform atomic_uint X(I);\n"
317 "#undef I\n",
318 " x += atomicCounterDecrement(x%d);\n",
319 num_vertex_buffers);
320 GLuint prog = glCreateProgram();
321 bool ret =
322 atomic_counters_compile(prog, GL_FRAGMENT_SHADER, fs_source) &&
323 atomic_counters_compile(prog, GL_VERTEX_SHADER, vs_source) &&
324 atomic_counters_link(prog);
326 glDeleteProgram(prog);
327 free(fs_source);
328 free(vs_source);
329 return ret;
332 static bool
333 run_test_fragment_max_bindings(unsigned binding)
335 const char *src_template = "#version 140\n"
336 "#extension GL_ARB_shader_atomic_counters : enable\n"
337 "\n"
338 "layout(binding=%d) uniform atomic_uint x;"
339 "\n"
340 "void main() {\n"
341 "}\n";
342 char *src;
343 GLuint prog = glCreateProgram();
344 int ret;
346 ret = asprintf(&src, src_template, binding);
347 assert(ret);
349 ret = atomic_counters_compile(prog, GL_FRAGMENT_SHADER, src);
351 glDeleteProgram(prog);
352 free(src);
353 return ret;
356 static bool
357 run_test_vertex_max_bindings(unsigned binding)
359 const char *src_template = "#version 140\n"
360 "#extension GL_ARB_shader_atomic_counters : enable\n"
361 "\n"
362 "in vec4 position;\n"
363 "layout(binding=%d) uniform atomic_uint x;"
364 "\n"
365 "void main() {\n"
366 " gl_Position = position;\n"
367 "}\n";
368 char *src;
369 GLuint prog = glCreateProgram();
370 int ret;
372 ret = asprintf(&src, src_template, binding);
373 assert(ret);
375 ret = atomic_counters_compile(prog, GL_VERTEX_SHADER, src);
377 glDeleteProgram(prog);
378 free(src);
379 return ret;
382 void
383 piglit_init(int argc, char **argv)
385 enum piglit_result status = PIGLIT_PASS;
386 struct atomic_counters_limits ls = atomic_counters_get_limits();
388 piglit_require_gl_version(31);
389 piglit_require_extension("GL_ARB_shader_atomic_counters");
391 printf("Max combined: %d\n", ls.combined_counters);
392 printf("Max VS: %d\n", ls.vertex_counters);
393 printf("Max FS: %d\n", ls.fragment_counters);
395 atomic_counters_subtest(&status, GL_VERTEX_SHADER,
396 "Vertex shader test above maximum "
397 "number of atomic counters",
398 !run_test_vertex_max_counters,
399 ls.vertex_counters + 1);
401 atomic_counters_subtest(&status, GL_FRAGMENT_SHADER,
402 "Fragment shader test above maximum "
403 "number of atomic counters",
404 !run_test_fragment_max_counters,
405 ls.fragment_counters + 1);
407 if (ls.vertex_counters + ls.fragment_counters > ls.combined_counters) {
408 atomic_counters_subtest(&status, GL_NONE,
409 "Combined test above maximum number "
410 "of atomic counters",
411 !run_test_combined_max_counters,
412 ls.fragment_counters,
413 ls.combined_counters
414 - ls.fragment_counters + 1);
415 } else {
416 piglit_report_subtest_result(
417 PIGLIT_SKIP, "Combined test above maximum number "
418 "of atomic counters");
421 atomic_counters_subtest(&status, GL_FRAGMENT_SHADER,
422 "Fragment shader test under maximum "
423 "number of atomic counter buffers",
424 run_test_fragment_max_buffers,
425 ls.fragment_buffers);
427 atomic_counters_subtest(&status, GL_FRAGMENT_SHADER,
428 "Fragment shader test above maximum "
429 "number of atomic counter buffers",
430 !run_test_fragment_max_buffers,
431 ls.fragment_buffers + 1);
433 atomic_counters_subtest(&status, GL_VERTEX_SHADER,
434 "Vertex shader test under maximum "
435 "number of atomic counter buffers",
436 run_test_vertex_max_buffers,
437 ls.vertex_buffers);
439 atomic_counters_subtest(&status, GL_VERTEX_SHADER,
440 "Vertex shader test above maximum "
441 "number of atomic counter buffers",
442 !run_test_vertex_max_buffers,
443 ls.vertex_buffers + 1);
445 const int combined_test_max_vs_bufs =
446 MIN2(ls.vertex_buffers, ls.combined_buffers - ls.fragment_buffers);
448 if (combined_test_max_vs_bufs > 0) {
449 atomic_counters_subtest(&status, GL_NONE,
450 "Combined test under maximum "
451 "number of atomic counter buffers",
452 run_test_combined_max_buffers,
453 ls.fragment_buffers,
454 combined_test_max_vs_bufs);
455 } else {
456 piglit_report_subtest_result(
457 PIGLIT_SKIP, "Combined test under maximum "
458 "number of atomic counter buffers");
461 if (combined_test_max_vs_bufs < ls.vertex_buffers) {
462 atomic_counters_subtest(&status, GL_NONE,
463 "Combined test above maximum "
464 "number of atomic counter buffers",
465 !run_test_combined_max_buffers,
466 ls.fragment_buffers,
467 combined_test_max_vs_bufs + 1);
468 } else {
469 piglit_report_subtest_result(
470 PIGLIT_SKIP, "Combined test above maximum "
471 "number of atomic counter buffers");
474 atomic_counters_subtest(&status, GL_FRAGMENT_SHADER,
475 "Fragment shader test above maximum "
476 "number of atomic counter bindings",
477 !run_test_fragment_max_bindings,
478 ls.bindings + 1);
480 atomic_counters_subtest(&status, GL_VERTEX_SHADER,
481 "Vertex shader test above maximum "
482 "number of atomic counter bindings",
483 !run_test_vertex_max_bindings,
484 ls.bindings + 1);
486 piglit_report_result(status);
489 enum piglit_result
490 piglit_display(void)
492 return PIGLIT_PASS;