2 * Copyright (c) 2014 - 2015 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
21 * DEALINGS IN THE SOFTWARE.
24 #include "piglit-util-gl.h"
25 #include "piglit-shader.h"
28 #define NUM_ATOMIC_COUNTERS 8
30 static GLuint atomics_bo
= 0;
31 static GLuint indirect_bo
= 0;
32 static bool verbose
= false;
33 static bool indirect_dispatch
= false;
34 static bool global_id
= false;
35 static GLint prog
= 0;
37 static uint32_t global_x
= 0, global_y
= 0, global_z
= 0;
38 static uint32_t local_x
= 0, local_y
= 0, local_z
= 0;
40 static uint32_t sizes
[] = {
41 1, 2, 3, 4, 5, 7, 8, 9, 15, 16, 17, 31, 32, 33, 63, 64, 65,
42 127, 128, 129, 255, 256, 257, 511, 512, 513, 1023, 1024
45 static const char *extensions
=
46 "#extension GL_ARB_shader_atomic_counters: require\n";
48 static const char *compute_shader_source
=
49 "layout(binding = 0) uniform atomic_uint a0;\n"
50 "layout(binding = 0) uniform atomic_uint a1;\n"
51 "layout(binding = 0) uniform atomic_uint a2;\n"
52 "layout(binding = 0) uniform atomic_uint a3;\n"
53 "layout(binding = 0) uniform atomic_uint a4;\n"
54 "layout(binding = 0) uniform atomic_uint a5;\n"
55 "layout(binding = 0) uniform atomic_uint a6;\n"
56 "layout(binding = 0) uniform atomic_uint a7;\n"
58 "#ifdef GLOBAL_ID_TEST\n"
59 "#define ID_VAR gl_GlobalInvocationID\n"
60 "#define ID_DIM(a) (gl_NumWorkGroups.a * gl_WorkGroupSize.a)\n"
62 "#define ID_VAR gl_LocalInvocationID\n"
63 "#define ID_DIM(a) (gl_WorkGroupSize.a)\n"
68 " uint x = ID_VAR.x;\n"
69 " uint y = ID_VAR.y;\n"
70 " uint z = ID_VAR.z;\n"
71 " uint hx = ID_DIM(x) / 2u;\n"
72 " uint hy = ID_DIM(y) / 2u;\n"
73 " uint hz = ID_DIM(z) / 2u;\n"
75 " if (((x & y) & z) == 0u)\n"
76 " atomicCounterIncrement(a0);\n"
77 " if (((x | y) | z) == 7u)\n"
78 " atomicCounterIncrement(a1);\n"
79 " if (x == y && y == z)\n"
80 " atomicCounterIncrement(a2);\n"
81 " if (x != y && y != z && x != z)\n"
82 " atomicCounterIncrement(a3);\n"
83 " if (((x & y) & z) == 2u)\n"
84 " atomicCounterIncrement(a4);\n"
85 " if (((x | y) | z) == 5u)\n"
86 " atomicCounterIncrement(a5);\n"
87 " if (x < hx && y < hy && z < hz)\n"
88 " atomicCounterIncrement(a6);\n"
89 " if (x >= hx || y >= hy || z >= hz)\n"
90 " atomicCounterIncrement(a7);\n"
101 glDeleteProgram(prog
);
106 static enum piglit_result
107 compare_atomic_counters(uint32_t *values
, uint32_t xs
, uint32_t ys
,
113 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER
, 0, atomics_bo
);
114 p
= glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER
,
116 NUM_ATOMIC_COUNTERS
* sizeof(uint32_t),
120 printf("Couldn't map atomic counter to verify expected value.\n");
124 for (unsigned i
= 0; i
< NUM_ATOMIC_COUNTERS
; i
++) {
125 uint32_t found
= p
[i
];
127 printf("Atomic counter %d\n"
132 values
[i
] == found
? "pass" : "fail");
133 if (values
[i
] != found
) {
134 printf("Atomic counter test %d failed for (%d, %d, %d)\n",
136 printf(" Reference: %u\n", values
[i
]);
137 printf(" Observed: %u\n", found
);
143 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER
);
145 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
149 cs_ids_confirm_initial_atomic_counters()
151 uint32_t atomics_init
[NUM_ATOMIC_COUNTERS
] = { 0 };
152 return compare_atomic_counters(atomics_init
, 0, 0, 0);
156 cs_ids_confirm_size()
158 uint32_t values
[NUM_ATOMIC_COUNTERS
];
177 memset(&values
, 0, sizeof values
);
179 const bool no_work
= global_x
== 0 || global_y
== 0 || global_z
== 0;
180 for (z
= 0; z
< zs
&& !no_work
; z
++) {
181 for (y
= 0; y
< ys
; y
++) {
182 for (x
= 0; x
< xs
; x
++) {
183 if (((x
& y
) & z
) == 0u)
185 if (((x
| y
) | z
) == 7u)
187 if (x
== y
&& y
== z
)
189 if (x
!= y
&& y
!= z
&& x
!= z
)
191 if (((x
& y
) & z
) == 2u)
193 if (((x
| y
) | z
) == 5u)
195 if (x
< hx
&& y
< hy
&& z
< hz
)
197 if (x
>= hx
|| y
>= hy
|| z
>= hz
)
204 for (i
= 0; i
< NUM_ATOMIC_COUNTERS
; i
++)
205 values
[i
] *= global_x
* global_y
* global_z
;
208 return compare_atomic_counters(values
, xs
, ys
, zs
);
212 static enum piglit_result
213 build_program_for_size(uint32_t x
, uint32_t y
, uint32_t z
)
217 if (local_x
== x
&& local_y
== y
&&
218 local_z
== z
&& prog
!= 0) {
225 src
= concat(hunk("#define GLOBAL_ID_TEST\n"),
226 hunk(compute_shader_source
),
229 src
= hunk(compute_shader_source
);
232 prog
= generate_cs_prog(x
, y
, z
, hunk(extensions
), src
);
246 cs_ids_set_local_size(uint32_t x
, uint32_t y
, uint32_t z
)
248 enum piglit_result result
= PIGLIT_PASS
;
250 if (x
== 0 || y
== 0 || z
== 0) {
255 result
= build_program_for_size(x
, y
, z
);
256 if (result
!= PIGLIT_PASS
)
257 piglit_report_result(result
);
264 cs_ids_set_global_size(uint32_t x
, uint32_t y
, uint32_t z
)
266 GLuint indirect_buf
[3] = { x
, y
, z
};
272 glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER
, indirect_bo
);
273 glBufferData(GL_DISPATCH_INDIRECT_BUFFER
,
274 sizeof(indirect_buf
),
275 indirect_buf
, GL_STREAM_READ
);
282 cs_ids_setup_atomics_for_test()
284 uint32_t atomics_init
[NUM_ATOMIC_COUNTERS
] = { 0 };
286 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER
, 0, atomics_bo
);
287 glBufferData(GL_ATOMIC_COUNTER_BUFFER
,
288 sizeof(atomics_init
),
289 atomics_init
, GL_STATIC_DRAW
);
293 /* Running the test without checking the result is useful for creating display
297 cs_ids_run_test_without_check()
300 printf("Testing local dim = %dx%dx%d; "
301 "global dim = %dx%dx%d\n",
302 local_x
, local_y
, local_z
,
303 global_x
, global_y
, global_z
);
305 if (local_x
== 0 || local_y
== 0 || local_z
== 0) {
306 fprintf(stderr
, "Internal error: local size not set\n");
312 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
313 if (indirect_dispatch
) {
314 glBindBuffer(GL_DISPATCH_INDIRECT_BUFFER
, indirect_bo
);
315 glDispatchComputeIndirect(0);
317 glDispatchCompute(global_x
, global_y
, global_z
);
319 glMemoryBarrier(GL_ALL_BARRIER_BITS
);
326 enum piglit_result result
;
328 cs_ids_setup_atomics_for_test();
329 cs_ids_run_test_without_check();
331 result
= cs_ids_confirm_size();
332 if (result
!= PIGLIT_PASS
)
333 piglit_report_result(result
);
339 static enum piglit_result
340 test_size(uint32_t x
, uint32_t y
, uint32_t z
)
342 enum piglit_result result
;
344 result
= cs_ids_set_local_size(x
, y
, z
);
345 if (result
!= PIGLIT_PASS
)
346 piglit_report_result(result
);
348 result
= cs_ids_run_test();
349 if (result
!= PIGLIT_PASS
)
350 piglit_report_result(result
);
357 cs_ids_test_all_sizes()
359 enum piglit_result result
= PIGLIT_PASS
;
364 for (zi
= 0; zi
< ARRAY_SIZE(sizes
); zi
++) {
368 for (yi
= 0; yi
< ARRAY_SIZE(sizes
); yi
++) {
372 for (xi
= 0; xi
< ARRAY_SIZE(sizes
); xi
++) {
374 if ((x
* y
* z
) > 1024)
376 result
= test_size(x
, y
, z
);
377 if (result
!= PIGLIT_PASS
)
387 cs_ids_common_init(void)
389 piglit_require_extension("GL_ARB_compute_shader");
390 piglit_require_extension("GL_ARB_shader_atomic_counters");
392 glGenBuffers(1, &atomics_bo
);
393 if (!piglit_check_gl_error(GL_NO_ERROR
))
394 piglit_report_result(PIGLIT_FAIL
);
396 glGenBuffers(1, &indirect_bo
);
397 if (!piglit_check_gl_error(GL_NO_ERROR
))
398 piglit_report_result(PIGLIT_FAIL
);
399 cs_ids_set_global_size(1, 1, 1);
405 cs_ids_common_destroy(void)
408 glDeleteBuffers(1, &atomics_bo
);
409 if (indirect_bo
!= 0)
410 glDeleteBuffers(1, &indirect_bo
);
415 cs_ids_set_local_id_test(void)
418 uint32_t x
= local_x
, y
= local_y
, z
= local_z
;
421 cs_ids_set_local_size(x
, y
, z
);
427 cs_ids_set_global_id_test(void)
430 uint32_t x
= local_x
, y
= local_y
, z
= local_z
;
433 cs_ids_set_local_size(x
, y
, z
);
439 cs_ids_use_indirect_dispatch(void)
441 indirect_dispatch
= true;
446 cs_ids_use_direct_dispatch(void)
448 indirect_dispatch
= false;