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 /** @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.
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
44 iterate_template(const char *template, unsigned n
)
52 for (i
= 0; i
< n
; ++i
) {
55 ret
= asprintf(&s
, template, i
);
58 ret
= asprintf(&ss
, "%s%s", tmp
, s
);
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.
74 generate_source(const char *src_template
,
75 const char *decl_template
, const char *insn_template
,
78 char *decls
= iterate_template(decl_template
, n
);
79 char *insns
= iterate_template(insn_template
, n
);
83 ret
= asprintf(&src
, src_template
, decls
, insns
);
93 run_test_vertex_max_counters(unsigned num_counters
)
95 /* Generate a shader with 'num_counters' counters. */
96 char *vs_source
= generate_source(
98 "#extension GL_ARB_shader_atomic_counters : enable\n"
102 "in vec4 position;\n"
103 "flat out ivec4 vcolor;\n"
108 " vcolor.x = int(y);\n"
109 " gl_Position = position;\n"
111 "layout(binding=0) uniform atomic_uint x%d;\n",
112 " y += atomicCounterDecrement(x%d);\n",
114 GLuint prog
= glCreateProgram();
115 bool ret
= atomic_counters_compile(prog
, GL_VERTEX_SHADER
, vs_source
) &&
116 atomic_counters_link(prog
);
118 glDeleteProgram(prog
);
124 run_test_fragment_max_counters(unsigned num_counters
)
126 /* Generate a shader with 'num_counters' counters. */
127 char *fs_source
= generate_source(
129 "#extension GL_ARB_shader_atomic_counters : enable\n"
133 "out ivec4 fcolor;\n"
138 " fcolor.x = int(y);\n"
140 "layout(binding=0) uniform atomic_uint x%d;\n",
141 " y += atomicCounterDecrement(x%d);\n",
143 GLuint prog
= glCreateProgram();
144 bool ret
= atomic_counters_compile(prog
, GL_FRAGMENT_SHADER
, fs_source
) &&
145 atomic_counters_link(prog
);
147 glDeleteProgram(prog
);
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(
159 "#extension GL_ARB_shader_atomic_counters : enable\n"
163 "flat in ivec4 vcolor;\n"
164 "out ivec4 fcolor;\n"
167 " uint y = uint(vcolor.x);\n"
169 " fcolor.x = int(y);\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(
177 "#extension GL_ARB_shader_atomic_counters : enable\n"
181 "in vec4 position;\n"
182 "flat out ivec4 vcolor;\n"
187 " vcolor.x = int(y);\n"
188 " gl_Position = position;\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
);
205 run_test_fragment_max_buffers(unsigned num_buffers
)
207 /* Generate a shader with 'num_buffers' buffers. */
208 char *src
= generate_source(
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"
214 "out ivec4 fcolor;\n"
221 " fcolor.x = int(x);\n"
224 "layout(binding=I, offset=0) uniform atomic_uint Y(I);\n"
226 " x += atomicCounterDecrement(y%d);\n",
228 GLuint prog
= glCreateProgram();
229 bool ret
= atomic_counters_compile(prog
, GL_FRAGMENT_SHADER
, src
) &&
230 atomic_counters_link(prog
);
232 glDeleteProgram(prog
);
238 run_test_vertex_max_buffers(unsigned num_buffers
)
240 /* Generate a shader with 'num_buffers' buffers. */
241 char *src
= generate_source(
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"
247 "in vec4 position;\n"
248 "flat out ivec4 vcolor;\n"
255 " vcolor.x = int(x);\n"
256 " gl_Position = position;\n"
259 "layout(binding=I, offset=0) uniform atomic_uint X(I);\n"
261 " x += atomicCounterDecrement(x%d);\n",
263 GLuint prog
= glCreateProgram();
264 bool ret
= atomic_counters_compile(prog
, GL_VERTEX_SHADER
, src
) &&
265 atomic_counters_link(prog
);
267 glDeleteProgram(prog
);
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(
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"
283 "out ivec4 fcolor;\n"
290 " fcolor.x = int(x);\n"
293 "layout(binding=I, offset=0) uniform atomic_uint Y(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(
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"
304 "in vec4 position;\n"
305 "flat out ivec4 vcolor;\n"
312 " vcolor.x = int(x);\n"
313 " gl_Position = position;\n"
316 "layout(binding=I, offset=4) uniform atomic_uint X(I);\n"
318 " x += atomicCounterDecrement(x%d);\n",
320 GLuint prog
= glCreateProgram();
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
);
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"
338 "layout(binding=%d) uniform atomic_uint x;"
343 GLuint prog
= glCreateProgram();
346 ret
= asprintf(&src
, src_template
, binding
);
349 ret
= atomic_counters_compile(prog
, GL_FRAGMENT_SHADER
, src
);
351 glDeleteProgram(prog
);
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"
362 "in vec4 position;\n"
363 "layout(binding=%d) uniform atomic_uint x;"
366 " gl_Position = position;\n"
369 GLuint prog
= glCreateProgram();
372 ret
= asprintf(&src
, src_template
, binding
);
375 ret
= atomic_counters_compile(prog
, GL_VERTEX_SHADER
, src
);
377 glDeleteProgram(prog
);
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
,
414 - ls
.fragment_counters
+ 1);
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
,
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
,
454 combined_test_max_vs_bufs
);
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
,
467 combined_test_max_vs_bufs
+ 1);
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
,
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
,
486 piglit_report_result(status
);