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 active-counters.c
26 * Compile a shader with a bunch of atomic counters and check that the
27 * active atomic counter and buffer query functions return sane
33 PIGLIT_GL_TEST_CONFIG_BEGIN
35 config
.supports_gl_core_version
= 31;
37 config
.window_width
= 1;
38 config
.window_height
= 1;
39 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
40 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
42 PIGLIT_GL_TEST_CONFIG_END
44 const char *fs_source
= "#version 140\n"
45 "#extension GL_ARB_shader_atomic_counters : enable\n"
49 "layout(binding=0) uniform atomic_uint x0[2];\n"
50 "layout(binding=0) uniform atomic_uint x1;\n"
51 "layout(binding=3, offset=8) uniform atomic_uint x2;\n"
52 "layout(binding=3, offset=12) uniform atomic_uint x3;\n"
54 "layout(binding=7, binding=2, offset=4) uniform;\n"
56 "layout(binding=2) uniform atomic_uint x4;\n"
57 "layout(binding=7, offset=8, offset=0) uniform atomic_uint x5;\n"
58 "layout(binding=3) uniform atomic_uint x6, x7;\n"
61 " fcolor.x = int(atomicCounter(x0[0]) + atomicCounter(x0[1])\n"
62 " + atomicCounter(x1) + atomicCounter(x2)\n"
63 " + atomicCounter(x3) + atomicCounter(x4)\n"
64 " + atomicCounter(x5) + atomicCounter(x6)\n"
65 " + atomicCounter(x7));\n"
69 unsigned num_counters
;
70 unsigned min_reasonable_size
;
73 static const struct buffer_info
*
74 expected_buffer_info(unsigned binding
)
77 static const struct buffer_info info
= { 2, 12 };
79 } else if (binding
== 2) {
80 static const struct buffer_info info
= { 1, 4 };
82 } else if (binding
== 3) {
83 static const struct buffer_info info
= { 4, 24 };
85 } else if (binding
== 7) {
86 static const struct buffer_info info
= { 1, 4 };
99 static const struct counter_info
*
100 expected_counter_info(const char *name
)
102 static const struct {
104 const struct counter_info info
;
106 { "x0[0]", { 0, 0, 2 } },
107 { "x1", { 0, 8, 1 }},
108 { "x2", { 3, 8, 1 }},
109 { "x3", { 3, 12, 1 }},
110 { "x4", { 2, 0, 1 }},
111 { "x5", { 7, 0, 1 }},
112 { "x6", { 3, 16, 1 }},
113 { "x7", { 3, 20, 1 }},
117 for (i
= 0; i
< ARRAY_SIZE(counters
); i
++) {
118 if (!strcmp(counters
[i
].name
, name
))
119 return &counters
[i
].info
;
126 piglit_init(int argc
, char **argv
)
128 struct atomic_counters_limits ls
= atomic_counters_get_limits();
129 bool visited_buffers
[8] = { false };
130 bool visited_counters
[8] = { false };
131 GLuint prog
= glCreateProgram();
134 piglit_require_gl_version(31);
135 piglit_require_extension("GL_ARB_shader_atomic_counters");
137 if (ls
.fragment_counters
< 9) {
138 fprintf(stderr
, "Insufficient number of supported atomic "
140 piglit_report_result(PIGLIT_SKIP
);
143 if (ls
.fragment_buffers
< 4) {
144 fprintf(stderr
, "Insufficient number of supported atomic "
145 "counter buffers.\n");
146 piglit_report_result(PIGLIT_SKIP
);
149 if (!atomic_counters_compile(prog
, GL_FRAGMENT_SHADER
, fs_source
)) {
150 fprintf(stderr
, "Program failed to compile.\n");
151 piglit_report_result(PIGLIT_FAIL
);
154 if (!atomic_counters_link(prog
)) {
155 fprintf(stderr
, "Program failed to link.\n");
156 piglit_report_result(PIGLIT_FAIL
);
159 glGetProgramiv(prog
, GL_ACTIVE_ATOMIC_COUNTER_BUFFERS
, &n
);
161 fprintf(stderr
, "Unexpected number of active counter "
163 piglit_report_result(PIGLIT_FAIL
);
166 if (!piglit_khr_no_error
) {
168 glGetActiveAtomicCounterBufferiv(
169 prog
, n
, GL_ATOMIC_COUNTER_BUFFER_BINDING
, &ret
);
171 if (!piglit_check_gl_error(GL_INVALID_VALUE
)) {
172 fprintf(stderr
, "glGetActiveAtomicCounterBufferiv "
173 "should have failed when trying to query a "
174 "non-existent buffer.\n");
175 piglit_report_result(PIGLIT_FAIL
);
178 if (ret
!= 0xdeadbeef) {
179 fprintf(stderr
, "Failed call to "
180 "glGetActiveAtomicCounterBufferiv didn't "
181 "preserve the output parameter contents.\n");
182 piglit_report_result(PIGLIT_FAIL
);
186 for (i
= 0; i
< n
; ++i
) {
187 const struct buffer_info
*binfo
;
188 int binding
, data_size
, num_counters
, ref
;
191 glGetActiveAtomicCounterBufferiv(
192 prog
, i
, GL_ATOMIC_COUNTER_BUFFER_BINDING
, &binding
);
193 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
194 fprintf(stderr
, "Couldn't obtain counter buffer binding"
196 piglit_report_result(PIGLIT_FAIL
);
199 binfo
= expected_buffer_info(binding
);
201 fprintf(stderr
, "Got unexpected buffer binding "
203 piglit_report_result(PIGLIT_FAIL
);
206 glGetActiveAtomicCounterBufferiv(
207 prog
, i
, GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE
,
209 if (!piglit_check_gl_error(GL_NO_ERROR
) ||
210 data_size
< binfo
->min_reasonable_size
) {
211 fprintf(stderr
, "Invalid buffer data size: %d,"
212 " expected at least: %d.\n", data_size
,
213 binfo
->min_reasonable_size
);
214 piglit_report_result(PIGLIT_FAIL
);
217 glGetActiveAtomicCounterBufferiv(
218 prog
, i
, GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS
,
220 if (!piglit_check_gl_error(GL_NO_ERROR
) ||
221 num_counters
!= binfo
->num_counters
) {
222 fprintf(stderr
, "Invalid number of atomic counters: %d,"
223 " expected: %d.\n", num_counters
,
224 binfo
->num_counters
);
225 piglit_report_result(PIGLIT_FAIL
);
228 if (visited_buffers
[i
]) {
229 fprintf(stderr
, "Buffer at binding point %d seen twice."
231 piglit_report_result(PIGLIT_FAIL
);
233 visited_buffers
[i
] = true;
235 glGetActiveAtomicCounterBufferiv(prog
, i
,
236 GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER
,
238 if (!piglit_check_gl_error(GL_NO_ERROR
) || ref
) {
239 fprintf(stderr
, "Buffer incorrectly reported to be "
240 "referenced by vertex shader.\n");
241 piglit_report_result(PIGLIT_FAIL
);
244 glGetActiveAtomicCounterBufferiv(prog
, i
,
245 GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER
,
247 if (!piglit_check_gl_error(GL_NO_ERROR
) || ref
) {
248 fprintf(stderr
, "Buffer incorrectly reported to be "
249 "referenced by tessellation control shader.\n");
250 piglit_report_result(PIGLIT_FAIL
);
253 glGetActiveAtomicCounterBufferiv(prog
, i
,
254 GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER
,
256 if (!piglit_check_gl_error(GL_NO_ERROR
) || ref
) {
257 fprintf(stderr
, "Buffer incorrectly reported to be "
258 "referenced by tessellation evaluation shader."
260 piglit_report_result(PIGLIT_FAIL
);
263 glGetActiveAtomicCounterBufferiv(prog
, i
,
264 GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER
,
266 if (!piglit_check_gl_error(GL_NO_ERROR
) || ref
) {
267 fprintf(stderr
, "Buffer incorrectly reported to be "
268 "referenced by geometry shader.\n");
269 piglit_report_result(PIGLIT_FAIL
);
272 glGetActiveAtomicCounterBufferiv(prog
, i
,
273 GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER
,
275 if (!piglit_check_gl_error(GL_NO_ERROR
) || !ref
) {
276 fprintf(stderr
, "Buffer incorrectly reported as "
277 "unreferenced from the fragment shader.\n");
278 piglit_report_result(PIGLIT_FAIL
);
281 glGetActiveAtomicCounterBufferiv(prog
, i
,
282 GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES
,
284 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
285 fprintf(stderr
, "Couldn't obtain list of active atomic "
286 "counters for buffer at binding point %d.\n",
288 piglit_report_result(PIGLIT_FAIL
);
291 for (j
= 0; j
< num_counters
; ++j
) {
292 const struct counter_info
*cinfo
;
293 int unif_type
, unif_size
, unif_name_len
,
294 unif_block_idx
, unif_offset
, unif_stride
,
298 glGetActiveUniformName(prog
, counters
[j
],
299 sizeof(unif_name
), NULL
,
302 cinfo
= expected_counter_info(unif_name
);
303 if (!piglit_check_gl_error(GL_NO_ERROR
) || !cinfo
) {
304 fprintf(stderr
, "Unknown atomic counter \"%s\"."
306 piglit_report_result(PIGLIT_FAIL
);
309 glGetActiveUniformsiv(prog
, 1, &counters
[j
],
310 GL_UNIFORM_TYPE
, &unif_type
);
311 if (!piglit_check_gl_error(GL_NO_ERROR
) ||
312 unif_type
!= GL_UNSIGNED_INT_ATOMIC_COUNTER
) {
313 fprintf(stderr
, "Atomic counter \"%s\" has "
314 "invalid type 0x%x, expected 0x%x.\n",
315 unif_name
, unif_type
,
316 GL_UNSIGNED_INT_ATOMIC_COUNTER
);
317 piglit_report_result(PIGLIT_FAIL
);
320 glGetActiveUniformsiv(prog
, 1, &counters
[j
],
321 GL_UNIFORM_SIZE
, &unif_size
);
322 if (!piglit_check_gl_error(GL_NO_ERROR
) ||
323 unif_size
!= cinfo
->size
) {
324 fprintf(stderr
, "Atomic counter \"%s\" has "
325 "invalid size %d, expected: %d.\n",
326 unif_name
, unif_size
, cinfo
->size
);
327 piglit_report_result(PIGLIT_FAIL
);
330 glGetActiveUniformsiv(prog
, 1, &counters
[j
],
331 GL_UNIFORM_NAME_LENGTH
, &unif_name_len
);
332 if (!piglit_check_gl_error(GL_NO_ERROR
) ||
333 unif_name_len
!= strlen(unif_name
) + 1) {
334 fprintf(stderr
, "Atomic counter \"%s\" has "
335 "invalid name length %d, expected: %d."
336 "\n", unif_name
, unif_name_len
,
337 (int)strlen(unif_name
) + 1);
338 piglit_report_result(PIGLIT_FAIL
);
341 glGetActiveUniformsiv(prog
, 1, &counters
[j
],
342 GL_UNIFORM_BLOCK_INDEX
, &unif_block_idx
);
343 if (!piglit_check_gl_error(GL_NO_ERROR
) ||
344 unif_block_idx
!= -1) {
345 fprintf(stderr
, "Atomic counter \"%s\" has "
346 "invalid block index %d, expected: -1."
347 "\n", unif_name
, unif_block_idx
);
348 piglit_report_result(PIGLIT_FAIL
);
351 glGetActiveUniformsiv(prog
, 1, &counters
[j
],
352 GL_UNIFORM_OFFSET
, &unif_offset
);
353 if (!piglit_check_gl_error(GL_NO_ERROR
) ||
354 unif_offset
!= cinfo
->offset
) {
355 fprintf(stderr
, "Atomic counter \"%s\" has "
356 "invalid offset %d, expected: %d.\n",
357 unif_name
, unif_offset
, cinfo
->offset
);
358 piglit_report_result(PIGLIT_FAIL
);
361 glGetActiveUniformsiv(prog
, 1, &counters
[j
],
362 GL_UNIFORM_ARRAY_STRIDE
, &unif_stride
);
363 if (!piglit_check_gl_error(GL_NO_ERROR
) ||
364 (cinfo
->size
> 1 && unif_stride
< 4) ||
365 (cinfo
->size
== 1 && unif_stride
!= 0)) {
366 fprintf(stderr
, "Atomic counter \"%s\" has "
367 "invalid array stride %d.\n",
368 unif_name
, unif_stride
);
369 piglit_report_result(PIGLIT_FAIL
);
372 glGetActiveUniformsiv(prog
, 1, &counters
[j
],
373 GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX
,
375 if (!piglit_check_gl_error(GL_NO_ERROR
) ||
376 unif_buffer_idx
!= i
) {
377 fprintf(stderr
, "Atomic counter \"%s\" has "
378 "invalid buffer index %d, expected %d."
379 "\n", unif_name
, unif_buffer_idx
, i
);
380 piglit_report_result(PIGLIT_FAIL
);
383 if (cinfo
->binding
!= binding
) {
384 fprintf(stderr
, "Atomic counter \"%s\" belongs "
385 "to the wrong binding point %d.\n",
387 piglit_report_result(PIGLIT_FAIL
);
390 if (visited_counters
[counters
[j
]]) {
391 fprintf(stderr
, "Atomic counter \"%s\" seen "
392 "twice.\n", unif_name
);
393 piglit_report_result(PIGLIT_FAIL
);
395 visited_counters
[counters
[j
]] = true;
399 glDeleteProgram(prog
);
401 piglit_report_result(PIGLIT_PASS
);