gallium/tests: silence warning in compute.c
[mesa.git] / src / gallium / tests / trivial / compute.c
1 /*
2 * Copyright (C) 2011 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <sys/stat.h>
30 #include <inttypes.h>
31 #include "pipe/p_state.h"
32 #include "pipe/p_context.h"
33 #include "pipe/p_screen.h"
34 #include "pipe/p_defines.h"
35 #include "pipe/p_shader_tokens.h"
36 #include "util/u_memory.h"
37 #include "util/u_inlines.h"
38 #include "util/u_sampler.h"
39 #include "util/u_format.h"
40 #include "tgsi/tgsi_text.h"
41 #include "pipe-loader/pipe_loader.h"
42
43 #define MAX_RESOURCES 4
44
45 struct context {
46 struct pipe_loader_device *dev;
47 struct pipe_screen *screen;
48 struct pipe_context *pipe;
49 void *hwcs;
50 void *hwsmp[MAX_RESOURCES];
51 struct pipe_resource *tex[MAX_RESOURCES];
52 bool tex_rw[MAX_RESOURCES];
53 struct pipe_sampler_view *view[MAX_RESOURCES];
54 struct pipe_surface *surf[MAX_RESOURCES];
55 };
56
57 #define DUMP_COMPUTE_PARAM(p, c) do { \
58 uint64_t __v[4]; \
59 int __i, __n; \
60 \
61 __n = ctx->screen->get_compute_param(ctx->screen, c, __v); \
62 printf("%s: {", #c); \
63 \
64 for (__i = 0; __i < __n / sizeof(*__v); ++__i) \
65 printf(" %"PRIu64, __v[__i]); \
66 \
67 printf(" }\n"); \
68 } while (0)
69
70 static void init_ctx(struct context *ctx)
71 {
72 int ret;
73
74 ret = pipe_loader_probe(&ctx->dev, 1);
75 assert(ret);
76
77 ctx->screen = pipe_loader_create_screen(ctx->dev);
78 assert(ctx->screen);
79
80 ctx->pipe = ctx->screen->context_create(ctx->screen, NULL, 0);
81 assert(ctx->pipe);
82
83 DUMP_COMPUTE_PARAM(p, PIPE_COMPUTE_CAP_GRID_DIMENSION);
84 DUMP_COMPUTE_PARAM(p, PIPE_COMPUTE_CAP_MAX_GRID_SIZE);
85 DUMP_COMPUTE_PARAM(p, PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE);
86 }
87
88 static void destroy_ctx(struct context *ctx)
89 {
90 ctx->pipe->destroy(ctx->pipe);
91 ctx->screen->destroy(ctx->screen);
92 pipe_loader_release(&ctx->dev, 1);
93 FREE(ctx);
94 }
95
96 static char *
97 preprocess_prog(struct context *ctx, const char *src, const char *defs)
98 {
99 const char header[] =
100 "#define RGLOBAL RES[32767]\n"
101 "#define RLOCAL RES[32766]\n"
102 "#define RPRIVATE RES[32765]\n"
103 "#define RINPUT RES[32764]\n";
104 char cmd[512];
105 char tmp[] = "/tmp/test-compute.tgsi-XXXXXX";
106 char *buf;
107 int fd, ret;
108 struct stat st;
109 FILE *p;
110
111 /* Open a temporary file */
112 fd = mkstemp(tmp);
113 assert(fd >= 0);
114 snprintf(cmd, sizeof(cmd), "cpp -P -nostdinc -undef %s > %s",
115 defs ? defs : "", tmp);
116
117 /* Preprocess */
118 p = popen(cmd, "w");
119 fwrite(header, strlen(header), 1, p);
120 fwrite(src, strlen(src), 1, p);
121 ret = pclose(p);
122 assert(!ret);
123
124 /* Read back */
125 ret = fstat(fd, &st);
126 assert(!ret);
127
128 buf = malloc(st.st_size + 1);
129 ret = read(fd, buf, st.st_size);
130 assert(ret == st.st_size);
131 buf[ret] = 0;
132
133 /* Clean up */
134 close(fd);
135 unlink(tmp);
136
137 return buf;
138 }
139
140 static void init_prog(struct context *ctx, unsigned local_sz,
141 unsigned private_sz, unsigned input_sz,
142 const char *src, const char *defs)
143 {
144 struct pipe_context *pipe = ctx->pipe;
145 struct tgsi_token prog[1024];
146 struct pipe_compute_state cs = {
147 .prog = prog,
148 .req_local_mem = local_sz,
149 .req_private_mem = private_sz,
150 .req_input_mem = input_sz
151 };
152 char *psrc = preprocess_prog(ctx, src, defs);
153 int ret;
154
155 ret = tgsi_text_translate(psrc, prog, Elements(prog));
156 assert(ret);
157 free(psrc);
158
159 ctx->hwcs = pipe->create_compute_state(pipe, &cs);
160 assert(ctx->hwcs);
161
162 pipe->bind_compute_state(pipe, ctx->hwcs);
163 }
164
165 static void destroy_prog(struct context *ctx)
166 {
167 struct pipe_context *pipe = ctx->pipe;
168
169 pipe->delete_compute_state(pipe, ctx->hwcs);
170 ctx->hwcs = NULL;
171 }
172
173 static void init_tex(struct context *ctx, int slot,
174 enum pipe_texture_target target, bool rw,
175 enum pipe_format format, int w, int h,
176 void (*init)(void *, int, int, int))
177 {
178 struct pipe_context *pipe = ctx->pipe;
179 struct pipe_resource **tex = &ctx->tex[slot];
180 struct pipe_resource ttex = {
181 .target = target,
182 .format = format,
183 .width0 = w,
184 .height0 = h,
185 .depth0 = 1,
186 .array_size = 1,
187 .bind = (PIPE_BIND_SAMPLER_VIEW |
188 PIPE_BIND_COMPUTE_RESOURCE |
189 PIPE_BIND_GLOBAL)
190 };
191 int dx = util_format_get_blocksize(format);
192 int dy = util_format_get_stride(format, w);
193 int nx = (target == PIPE_BUFFER ? (w / dx) :
194 util_format_get_nblocksx(format, w));
195 int ny = (target == PIPE_BUFFER ? 1 :
196 util_format_get_nblocksy(format, h));
197 struct pipe_transfer *xfer;
198 char *map;
199 int x, y;
200
201 *tex = ctx->screen->resource_create(ctx->screen, &ttex);
202 assert(*tex);
203
204 map = pipe->transfer_map(pipe, *tex, 0, PIPE_TRANSFER_WRITE,
205 &(struct pipe_box) { .width = w,
206 .height = h,
207 .depth = 1 }, &xfer);
208 assert(xfer);
209 assert(map);
210
211 for (y = 0; y < ny; ++y) {
212 for (x = 0; x < nx; ++x) {
213 init(map + y * dy + x * dx, slot, x, y);
214 }
215 }
216
217 pipe->transfer_unmap(pipe, xfer);
218
219 ctx->tex_rw[slot] = rw;
220 }
221
222 static bool default_check(void *x, void *y, int sz) {
223 return !memcmp(x, y, sz);
224 }
225
226 static void check_tex(struct context *ctx, int slot,
227 void (*expect)(void *, int, int, int),
228 bool (*check)(void *, void *, int))
229 {
230 struct pipe_context *pipe = ctx->pipe;
231 struct pipe_resource *tex = ctx->tex[slot];
232 int dx = util_format_get_blocksize(tex->format);
233 int dy = util_format_get_stride(tex->format, tex->width0);
234 int nx = (tex->target == PIPE_BUFFER ? (tex->width0 / dx) :
235 util_format_get_nblocksx(tex->format, tex->width0));
236 int ny = (tex->target == PIPE_BUFFER ? 1 :
237 util_format_get_nblocksy(tex->format, tex->height0));
238 struct pipe_transfer *xfer;
239 char *map;
240 int x, y, i;
241 int err = 0;
242
243 if (!check)
244 check = default_check;
245
246 map = pipe->transfer_map(pipe, tex, 0, PIPE_TRANSFER_READ,
247 &(struct pipe_box) { .width = tex->width0,
248 .height = tex->height0,
249 .depth = 1 }, &xfer);
250 assert(xfer);
251 assert(map);
252
253 for (y = 0; y < ny; ++y) {
254 for (x = 0; x < nx; ++x) {
255 uint32_t exp[4];
256 uint32_t *res = (uint32_t *)(map + y * dy + x * dx);
257
258 expect(exp, slot, x, y);
259 if (check(res, exp, dx) || (++err) > 20)
260 continue;
261
262 if (dx < 4) {
263 uint32_t u = 0, v = 0;
264
265 for (i = 0; i < dx; i++) {
266 u |= ((uint8_t *)exp)[i] << (8 * i);
267 v |= ((uint8_t *)res)[i] << (8 * i);
268 }
269 printf("(%d, %d): got 0x%x, expected 0x%x\n",
270 x, y, v, u);
271 } else {
272 for (i = 0; i < dx / 4; i++) {
273 printf("(%d, %d)[%d]: got 0x%x/%f,"
274 " expected 0x%x/%f\n", x, y, i,
275 res[i], ((float *)res)[i],
276 exp[i], ((float *)exp)[i]);
277 }
278 }
279 }
280 }
281
282 pipe->transfer_unmap(pipe, xfer);
283
284 if (err)
285 printf("(%d, %d): \x1b[31mFAIL\x1b[0m (%d)\n", x, y, err);
286 else
287 printf("(%d, %d): \x1b[32mOK\x1b[0m\n", x, y);
288 }
289
290 static void destroy_tex(struct context *ctx)
291 {
292 int i;
293
294 for (i = 0; i < MAX_RESOURCES; ++i) {
295 if (ctx->tex[i])
296 pipe_resource_reference(&ctx->tex[i], NULL);
297 }
298 }
299
300 static void init_sampler_views(struct context *ctx, const int *slots)
301 {
302 struct pipe_context *pipe = ctx->pipe;
303 struct pipe_sampler_view tview;
304 int i;
305
306 for (i = 0; *slots >= 0; ++i, ++slots) {
307 u_sampler_view_default_template(&tview, ctx->tex[*slots],
308 ctx->tex[*slots]->format);
309
310 ctx->view[i] = pipe->create_sampler_view(pipe, ctx->tex[*slots],
311 &tview);
312 assert(ctx->view[i]);
313 }
314
315 pipe->set_sampler_views(pipe, PIPE_SHADER_COMPUTE, 0, i, ctx->view);
316 }
317
318 static void destroy_sampler_views(struct context *ctx)
319 {
320 struct pipe_context *pipe = ctx->pipe;
321 int i;
322
323 pipe->set_sampler_views(pipe, PIPE_SHADER_COMPUTE, 0, MAX_RESOURCES, NULL);
324
325 for (i = 0; i < MAX_RESOURCES; ++i) {
326 if (ctx->view[i]) {
327 pipe->sampler_view_destroy(pipe, ctx->view[i]);
328 ctx->view[i] = NULL;
329 }
330 }
331 }
332
333 static void init_compute_resources(struct context *ctx, const int *slots)
334 {
335 struct pipe_context *pipe = ctx->pipe;
336 int i;
337
338 for (i = 0; *slots >= 0; ++i, ++slots) {
339 struct pipe_surface tsurf = {
340 .format = ctx->tex[*slots]->format,
341 .writable = ctx->tex_rw[*slots]
342 };
343
344 if (ctx->tex[*slots]->target == PIPE_BUFFER)
345 tsurf.u.buf.last_element = ctx->tex[*slots]->width0 - 1;
346
347 ctx->surf[i] = pipe->create_surface(pipe, ctx->tex[*slots],
348 &tsurf);
349 assert(ctx->surf[i]);
350 }
351
352 pipe->set_compute_resources(pipe, 0, i, ctx->surf);
353 }
354
355 static void destroy_compute_resources(struct context *ctx)
356 {
357 struct pipe_context *pipe = ctx->pipe;
358 int i;
359
360 pipe->set_compute_resources(pipe, 0, MAX_RESOURCES, NULL);
361
362 for (i = 0; i < MAX_RESOURCES; ++i) {
363 if (ctx->surf[i]) {
364 pipe->surface_destroy(pipe, ctx->surf[i]);
365 ctx->surf[i] = NULL;
366 }
367 }
368 }
369
370 static void init_sampler_states(struct context *ctx, int n)
371 {
372 struct pipe_context *pipe = ctx->pipe;
373 struct pipe_sampler_state smp = {
374 .normalized_coords = 1,
375 };
376 int i;
377
378 for (i = 0; i < n; ++i) {
379 ctx->hwsmp[i] = pipe->create_sampler_state(pipe, &smp);
380 assert(ctx->hwsmp[i]);
381 }
382
383 pipe->bind_sampler_states(pipe, PIPE_SHADER_COMPUTE, 0, i, ctx->hwsmp);
384 }
385
386 static void destroy_sampler_states(struct context *ctx)
387 {
388 struct pipe_context *pipe = ctx->pipe;
389 int i;
390
391 pipe->bind_sampler_states(pipe, PIPE_SHADER_COMPUTE,
392 0, MAX_RESOURCES, NULL);
393
394 for (i = 0; i < MAX_RESOURCES; ++i) {
395 if (ctx->hwsmp[i]) {
396 pipe->delete_sampler_state(pipe, ctx->hwsmp[i]);
397 ctx->hwsmp[i] = NULL;
398 }
399 }
400 }
401
402 static void init_globals(struct context *ctx, const int *slots,
403 uint32_t **handles)
404 {
405 struct pipe_context *pipe = ctx->pipe;
406 struct pipe_resource *res[MAX_RESOURCES];
407 int i;
408
409 for (i = 0; *slots >= 0; ++i, ++slots)
410 res[i] = ctx->tex[*slots];
411
412 pipe->set_global_binding(pipe, 0, i, res, handles);
413 }
414
415 static void destroy_globals(struct context *ctx)
416 {
417 struct pipe_context *pipe = ctx->pipe;
418
419 pipe->set_global_binding(pipe, 0, MAX_RESOURCES, NULL, NULL);
420 }
421
422 static void launch_grid(struct context *ctx, const uint *block_layout,
423 const uint *grid_layout, uint32_t pc,
424 void *input)
425 {
426 struct pipe_context *pipe = ctx->pipe;
427 struct pipe_grid_info info;
428 int i;
429
430 for (i = 0; i < 3; i++) {
431 info.block[i] = block_layout[i];
432 info.grid[i] = grid_layout[i];
433 }
434 info.pc = pc;
435 info.input = input;
436
437 pipe->launch_grid(pipe, &info);
438 }
439
440 static void test_default_init(void *p, int s, int x, int y)
441 {
442 *(uint32_t *)p = 0xdeadbeef;
443 }
444
445 /* test_system_values */
446 static void test_system_values_expect(void *p, int s, int x, int y)
447 {
448 int id = x / 16, sv = (x % 16) / 4, c = x % 4;
449 int tid[] = { id % 20, (id % 240) / 20, id / 240, 0 };
450 int bsz[] = { 4, 3, 5, 1};
451 int gsz[] = { 5, 4, 1, 1};
452
453 switch (sv) {
454 case 0:
455 *(uint32_t *)p = tid[c] / bsz[c];
456 break;
457 case 1:
458 *(uint32_t *)p = bsz[c];
459 break;
460 case 2:
461 *(uint32_t *)p = gsz[c];
462 break;
463 case 3:
464 *(uint32_t *)p = tid[c] % bsz[c];
465 break;
466 }
467 }
468
469 static void test_system_values(struct context *ctx)
470 {
471 const char *src = "COMP\n"
472 "DCL RES[0], BUFFER, RAW, WR\n"
473 "DCL SV[0], BLOCK_ID[0]\n"
474 "DCL SV[1], BLOCK_SIZE[0]\n"
475 "DCL SV[2], GRID_SIZE[0]\n"
476 "DCL SV[3], THREAD_ID[0]\n"
477 "DCL TEMP[0], LOCAL\n"
478 "DCL TEMP[1], LOCAL\n"
479 "IMM UINT32 { 64, 0, 0, 0 }\n"
480 "IMM UINT32 { 16, 0, 0, 0 }\n"
481 "IMM UINT32 { 0, 0, 0, 0 }\n"
482 "\n"
483 "BGNSUB"
484 " UMUL TEMP[0], SV[0], SV[1]\n"
485 " UADD TEMP[0], TEMP[0], SV[3]\n"
486 " UMUL TEMP[1], SV[1], SV[2]\n"
487 " UMUL TEMP[0].w, TEMP[0], TEMP[1].zzzz\n"
488 " UMUL TEMP[0].zw, TEMP[0], TEMP[1].yyyy\n"
489 " UMUL TEMP[0].yzw, TEMP[0], TEMP[1].xxxx\n"
490 " UADD TEMP[0].xy, TEMP[0].xyxy, TEMP[0].zwzw\n"
491 " UADD TEMP[0].x, TEMP[0].xxxx, TEMP[0].yyyy\n"
492 " UMUL TEMP[0].x, TEMP[0], IMM[0]\n"
493 " STORE RES[0].xyzw, TEMP[0], SV[0]\n"
494 " UADD TEMP[0].x, TEMP[0], IMM[1]\n"
495 " STORE RES[0].xyzw, TEMP[0], SV[1]\n"
496 " UADD TEMP[0].x, TEMP[0], IMM[1]\n"
497 " STORE RES[0].xyzw, TEMP[0], SV[2]\n"
498 " UADD TEMP[0].x, TEMP[0], IMM[1]\n"
499 " STORE RES[0].xyzw, TEMP[0], SV[3]\n"
500 " RET\n"
501 "ENDSUB\n";
502
503 printf("- %s\n", __func__);
504
505 init_prog(ctx, 0, 0, 0, src, NULL);
506 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
507 76800, 0, test_default_init);
508 init_compute_resources(ctx, (int []) { 0, -1 });
509 launch_grid(ctx, (uint []){4, 3, 5}, (uint []){5, 4, 1}, 0, NULL);
510 check_tex(ctx, 0, test_system_values_expect, NULL);
511 destroy_compute_resources(ctx);
512 destroy_tex(ctx);
513 destroy_prog(ctx);
514 }
515
516 /* test_resource_access */
517 static void test_resource_access_init0(void *p, int s, int x, int y)
518 {
519 *(float *)p = 8.0 - (float)x;
520 }
521
522 static void test_resource_access_expect(void *p, int s, int x, int y)
523 {
524 *(float *)p = 8.0 - (float)((x + 4 * y) & 0x3f);
525 }
526
527 static void test_resource_access(struct context *ctx)
528 {
529 const char *src = "COMP\n"
530 "DCL RES[0], BUFFER, RAW, WR\n"
531 "DCL RES[1], 2D, RAW, WR\n"
532 "DCL SV[0], BLOCK_ID[0]\n"
533 "DCL TEMP[0], LOCAL\n"
534 "DCL TEMP[1], LOCAL\n"
535 "IMM UINT32 { 15, 0, 0, 0 }\n"
536 "IMM UINT32 { 16, 1, 0, 0 }\n"
537 "\n"
538 " BGNSUB\n"
539 " UADD TEMP[0].x, SV[0].xxxx, SV[0].yyyy\n"
540 " AND TEMP[0].x, TEMP[0], IMM[0]\n"
541 " UMUL TEMP[0].x, TEMP[0], IMM[1]\n"
542 " LOAD TEMP[0].xyzw, RES[0], TEMP[0]\n"
543 " UMUL TEMP[1], SV[0], IMM[1]\n"
544 " STORE RES[1].xyzw, TEMP[1], TEMP[0]\n"
545 " RET\n"
546 " ENDSUB\n";
547
548 printf("- %s\n", __func__);
549
550 init_prog(ctx, 0, 0, 0, src, NULL);
551 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
552 256, 0, test_resource_access_init0);
553 init_tex(ctx, 1, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
554 60, 12, test_default_init);
555 init_compute_resources(ctx, (int []) { 0, 1, -1 });
556 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){15, 12, 1}, 0, NULL);
557 check_tex(ctx, 1, test_resource_access_expect, NULL);
558 destroy_compute_resources(ctx);
559 destroy_tex(ctx);
560 destroy_prog(ctx);
561 }
562
563 /* test_function_calls */
564 static void test_function_calls_init(void *p, int s, int x, int y)
565 {
566 *(uint32_t *)p = 15 * y + x;
567 }
568
569 static void test_function_calls_expect(void *p, int s, int x, int y)
570 {
571 *(uint32_t *)p = (15 * y + x) < 4 ? 2 : 1 ;
572 }
573
574 static void test_function_calls(struct context *ctx)
575 {
576 const char *src = "COMP\n"
577 "DCL RES[0], 2D, RAW, WR\n"
578 "DCL SV[0], BLOCK_ID[0]\n"
579 "DCL SV[1], BLOCK_SIZE[0]\n"
580 "DCL SV[2], GRID_SIZE[0]\n"
581 "DCL SV[3], THREAD_ID[0]\n"
582 "DCL TEMP[0]\n"
583 "DCL TEMP[1]\n"
584 "DCL TEMP[2], LOCAL\n"
585 "IMM UINT32 { 0, 11, 22, 33 }\n"
586 "IMM FLT32 { 11, 33, 55, 99 }\n"
587 "IMM UINT32 { 4, 1, 0, 0 }\n"
588 "IMM UINT32 { 12, 0, 0, 0 }\n"
589 "\n"
590 "00: BGNSUB\n"
591 "01: UMUL TEMP[0].x, TEMP[0], TEMP[0]\n"
592 "02: UADD TEMP[1].x, TEMP[1], IMM[2].yyyy\n"
593 "03: USLT TEMP[0].x, TEMP[0], IMM[0]\n"
594 "04: RET\n"
595 "05: ENDSUB\n"
596 "06: BGNSUB\n"
597 "07: UMUL TEMP[0].x, TEMP[0], TEMP[0]\n"
598 "08: UADD TEMP[1].x, TEMP[1], IMM[2].yyyy\n"
599 "09: USLT TEMP[0].x, TEMP[0], IMM[0].yyyy\n"
600 "10: IF TEMP[0].xxxx\n"
601 "11: CAL :0\n"
602 "12: ENDIF\n"
603 "13: RET\n"
604 "14: ENDSUB\n"
605 "15: BGNSUB\n"
606 "16: UMUL TEMP[2], SV[0], SV[1]\n"
607 "17: UADD TEMP[2], TEMP[2], SV[3]\n"
608 "18: UMUL TEMP[2], TEMP[2], IMM[2]\n"
609 "00: MOV TEMP[1].x, IMM[2].wwww\n"
610 "19: LOAD TEMP[0].x, RES[0].xxxx, TEMP[2]\n"
611 "20: CAL :6\n"
612 "21: STORE RES[0].x, TEMP[2], TEMP[1].xxxx\n"
613 "22: RET\n"
614 "23: ENDSUB\n";
615
616 printf("- %s\n", __func__);
617
618 init_prog(ctx, 0, 0, 0, src, NULL);
619 init_tex(ctx, 0, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
620 15, 12, test_function_calls_init);
621 init_compute_resources(ctx, (int []) { 0, -1 });
622 launch_grid(ctx, (uint []){3, 3, 3}, (uint []){5, 4, 1}, 15, NULL);
623 check_tex(ctx, 0, test_function_calls_expect, NULL);
624 destroy_compute_resources(ctx);
625 destroy_tex(ctx);
626 destroy_prog(ctx);
627 }
628
629 /* test_input_global */
630 static void test_input_global_expect(void *p, int s, int x, int y)
631 {
632 *(uint32_t *)p = 0xdeadbeef - (x == 0 ? 0x10001 + 2 * s : 0);
633 }
634
635 static void test_input_global(struct context *ctx)
636 {
637 const char *src = "COMP\n"
638 "DCL SV[0], THREAD_ID[0]\n"
639 "DCL TEMP[0], LOCAL\n"
640 "DCL TEMP[1], LOCAL\n"
641 "IMM UINT32 { 8, 0, 0, 0 }\n"
642 "\n"
643 " BGNSUB\n"
644 " UMUL TEMP[0], SV[0], IMM[0]\n"
645 " LOAD TEMP[1].xy, RINPUT, TEMP[0]\n"
646 " LOAD TEMP[0].x, RGLOBAL, TEMP[1].yyyy\n"
647 " UADD TEMP[1].x, TEMP[0], -TEMP[1]\n"
648 " STORE RGLOBAL.x, TEMP[1].yyyy, TEMP[1]\n"
649 " RET\n"
650 " ENDSUB\n";
651 uint32_t input[8] = { 0x10001, 0x10002, 0x10003, 0x10004,
652 0x10005, 0x10006, 0x10007, 0x10008 };
653
654 printf("- %s\n", __func__);
655
656 init_prog(ctx, 0, 0, 32, src, NULL);
657 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT, 32, 0,
658 test_default_init);
659 init_tex(ctx, 1, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT, 32, 0,
660 test_default_init);
661 init_tex(ctx, 2, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT, 32, 0,
662 test_default_init);
663 init_tex(ctx, 3, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT, 32, 0,
664 test_default_init);
665 init_globals(ctx, (int []){ 0, 1, 2, 3, -1 },
666 (uint32_t *[]){ &input[1], &input[3],
667 &input[5], &input[7] });
668 launch_grid(ctx, (uint []){4, 1, 1}, (uint []){1, 1, 1}, 0, input);
669 check_tex(ctx, 0, test_input_global_expect, NULL);
670 check_tex(ctx, 1, test_input_global_expect, NULL);
671 check_tex(ctx, 2, test_input_global_expect, NULL);
672 check_tex(ctx, 3, test_input_global_expect, NULL);
673 destroy_globals(ctx);
674 destroy_tex(ctx);
675 destroy_prog(ctx);
676 }
677
678 /* test_private */
679 static void test_private_expect(void *p, int s, int x, int y)
680 {
681 *(uint32_t *)p = (x / 32) + x % 32;
682 }
683
684 static void test_private(struct context *ctx)
685 {
686 const char *src = "COMP\n"
687 "DCL RES[0], BUFFER, RAW, WR\n"
688 "DCL SV[0], BLOCK_ID[0]\n"
689 "DCL SV[1], BLOCK_SIZE[0]\n"
690 "DCL SV[2], THREAD_ID[0]\n"
691 "DCL TEMP[0], LOCAL\n"
692 "DCL TEMP[1], LOCAL\n"
693 "DCL TEMP[2], LOCAL\n"
694 "IMM UINT32 { 128, 0, 0, 0 }\n"
695 "IMM UINT32 { 4, 0, 0, 0 }\n"
696 "\n"
697 " BGNSUB\n"
698 " UMUL TEMP[0].x, SV[0], SV[1]\n"
699 " UADD TEMP[0].x, TEMP[0], SV[2]\n"
700 " MOV TEMP[1].x, IMM[0].wwww\n"
701 " BGNLOOP\n"
702 " USEQ TEMP[2].x, TEMP[1], IMM[0]\n"
703 " IF TEMP[2]\n"
704 " BRK\n"
705 " ENDIF\n"
706 " UDIV TEMP[2].x, TEMP[1], IMM[1]\n"
707 " UADD TEMP[2].x, TEMP[2], TEMP[0]\n"
708 " STORE RPRIVATE.x, TEMP[1], TEMP[2]\n"
709 " UADD TEMP[1].x, TEMP[1], IMM[1]\n"
710 " ENDLOOP\n"
711 " MOV TEMP[1].x, IMM[0].wwww\n"
712 " UMUL TEMP[0].x, TEMP[0], IMM[0]\n"
713 " BGNLOOP\n"
714 " USEQ TEMP[2].x, TEMP[1], IMM[0]\n"
715 " IF TEMP[2]\n"
716 " BRK\n"
717 " ENDIF\n"
718 " LOAD TEMP[2].x, RPRIVATE, TEMP[1]\n"
719 " STORE RES[0].x, TEMP[0], TEMP[2]\n"
720 " UADD TEMP[0].x, TEMP[0], IMM[1]\n"
721 " UADD TEMP[1].x, TEMP[1], IMM[1]\n"
722 " ENDLOOP\n"
723 " RET\n"
724 " ENDSUB\n";
725
726 printf("- %s\n", __func__);
727
728 init_prog(ctx, 0, 128, 0, src, NULL);
729 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
730 32768, 0, test_default_init);
731 init_compute_resources(ctx, (int []) { 0, -1 });
732 launch_grid(ctx, (uint []){16, 1, 1}, (uint []){16, 1, 1}, 0, NULL);
733 check_tex(ctx, 0, test_private_expect, NULL);
734 destroy_compute_resources(ctx);
735 destroy_tex(ctx);
736 destroy_prog(ctx);
737 }
738
739 /* test_local */
740 static void test_local_expect(void *p, int s, int x, int y)
741 {
742 *(uint32_t *)p = x & 0x20 ? 2 : 1;
743 }
744
745 static void test_local(struct context *ctx)
746 {
747 const char *src = "COMP\n"
748 "DCL RES[0], BUFFER, RAW, WR\n"
749 "DCL SV[0], BLOCK_ID[0]\n"
750 "DCL SV[1], BLOCK_SIZE[0]\n"
751 "DCL SV[2], THREAD_ID[0]\n"
752 "DCL TEMP[0], LOCAL\n"
753 "DCL TEMP[1], LOCAL\n"
754 "DCL TEMP[2], LOCAL\n"
755 "IMM UINT32 { 1, 0, 0, 0 }\n"
756 "IMM UINT32 { 2, 0, 0, 0 }\n"
757 "IMM UINT32 { 4, 0, 0, 0 }\n"
758 "IMM UINT32 { 32, 0, 0, 0 }\n"
759 "IMM UINT32 { 128, 0, 0, 0 }\n"
760 "\n"
761 " BGNSUB\n"
762 " UMUL TEMP[0].x, SV[2], IMM[2]\n"
763 " STORE RLOCAL.x, TEMP[0], IMM[0].wwww\n"
764 " MFENCE RLOCAL\n"
765 " USLT TEMP[1].x, SV[2], IMM[3]\n"
766 " IF TEMP[1]\n"
767 " UADD TEMP[1].x, TEMP[0], IMM[4]\n"
768 " BGNLOOP\n"
769 " LOAD TEMP[2].x, RLOCAL, TEMP[1]\n"
770 " USEQ TEMP[2].x, TEMP[2], IMM[0]\n"
771 " IF TEMP[2]\n"
772 " BRK\n"
773 " ENDIF\n"
774 " ENDLOOP\n"
775 " STORE RLOCAL.x, TEMP[0], IMM[0]\n"
776 " MFENCE RLOCAL\n"
777 " BGNLOOP\n"
778 " LOAD TEMP[2].x, RLOCAL, TEMP[1]\n"
779 " USEQ TEMP[2].x, TEMP[2], IMM[1]\n"
780 " IF TEMP[2]\n"
781 " BRK\n"
782 " ENDIF\n"
783 " ENDLOOP\n"
784 " ELSE\n"
785 " UADD TEMP[1].x, TEMP[0], -IMM[4]\n"
786 " BGNLOOP\n"
787 " LOAD TEMP[2].x, RLOCAL, TEMP[1]\n"
788 " USEQ TEMP[2].x, TEMP[2], IMM[0].wwww\n"
789 " IF TEMP[2]\n"
790 " BRK\n"
791 " ENDIF\n"
792 " ENDLOOP\n"
793 " STORE RLOCAL.x, TEMP[0], IMM[0]\n"
794 " MFENCE RLOCAL\n"
795 " BGNLOOP\n"
796 " LOAD TEMP[2].x, RLOCAL, TEMP[1]\n"
797 " USEQ TEMP[2].x, TEMP[2], IMM[0]\n"
798 " IF TEMP[2]\n"
799 " BRK\n"
800 " ENDIF\n"
801 " ENDLOOP\n"
802 " STORE RLOCAL.x, TEMP[0], IMM[1]\n"
803 " MFENCE RLOCAL\n"
804 " ENDIF\n"
805 " UMUL TEMP[1].x, SV[0], SV[1]\n"
806 " UMUL TEMP[1].x, TEMP[1], IMM[2]\n"
807 " UADD TEMP[1].x, TEMP[1], TEMP[0]\n"
808 " LOAD TEMP[0].x, RLOCAL, TEMP[0]\n"
809 " STORE RES[0].x, TEMP[1], TEMP[0]\n"
810 " RET\n"
811 " ENDSUB\n";
812
813 printf("- %s\n", __func__);
814
815 init_prog(ctx, 256, 0, 0, src, NULL);
816 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
817 4096, 0, test_default_init);
818 init_compute_resources(ctx, (int []) { 0, -1 });
819 launch_grid(ctx, (uint []){64, 1, 1}, (uint []){16, 1, 1}, 0, NULL);
820 check_tex(ctx, 0, test_local_expect, NULL);
821 destroy_compute_resources(ctx);
822 destroy_tex(ctx);
823 destroy_prog(ctx);
824 }
825
826 /* test_sample */
827 static void test_sample_init(void *p, int s, int x, int y)
828 {
829 *(float *)p = s ? 1 : x * y;
830 }
831
832 static void test_sample_expect(void *p, int s, int x, int y)
833 {
834 switch (x % 4) {
835 case 0:
836 *(float *)p = x / 4 * y;
837 break;
838 case 1:
839 case 2:
840 *(float *)p = 0;
841 break;
842 case 3:
843 *(float *)p = 1;
844 break;
845 }
846 }
847
848 static void test_sample(struct context *ctx)
849 {
850 const char *src = "COMP\n"
851 "DCL SVIEW[0], 2D, FLOAT\n"
852 "DCL RES[0], 2D, RAW, WR\n"
853 "DCL SAMP[0]\n"
854 "DCL SV[0], BLOCK_ID[0]\n"
855 "DCL TEMP[0], LOCAL\n"
856 "DCL TEMP[1], LOCAL\n"
857 "IMM UINT32 { 16, 1, 0, 0 }\n"
858 "IMM FLT32 { 128, 32, 0, 0 }\n"
859 "\n"
860 " BGNSUB\n"
861 " I2F TEMP[1], SV[0]\n"
862 " DIV TEMP[1], TEMP[1], IMM[1]\n"
863 " SAMPLE TEMP[1], TEMP[1], SVIEW[0], SAMP[0]\n"
864 " UMUL TEMP[0], SV[0], IMM[0]\n"
865 " STORE RES[0].xyzw, TEMP[0], TEMP[1]\n"
866 " RET\n"
867 " ENDSUB\n";
868
869 printf("- %s\n", __func__);
870
871 init_prog(ctx, 0, 0, 0, src, NULL);
872 init_tex(ctx, 0, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
873 128, 32, test_sample_init);
874 init_tex(ctx, 1, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
875 512, 32, test_sample_init);
876 init_compute_resources(ctx, (int []) { 1, -1 });
877 init_sampler_views(ctx, (int []) { 0, -1 });
878 init_sampler_states(ctx, 2);
879 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){128, 32, 1}, 0, NULL);
880 check_tex(ctx, 1, test_sample_expect, NULL);
881 destroy_sampler_states(ctx);
882 destroy_sampler_views(ctx);
883 destroy_compute_resources(ctx);
884 destroy_tex(ctx);
885 destroy_prog(ctx);
886 }
887
888 /* test_many_kern */
889 static void test_many_kern_expect(void *p, int s, int x, int y)
890 {
891 *(uint32_t *)p = x;
892 }
893
894 static void test_many_kern(struct context *ctx)
895 {
896 const char *src = "COMP\n"
897 "DCL RES[0], BUFFER, RAW, WR\n"
898 "DCL TEMP[0], LOCAL\n"
899 "IMM UINT32 { 0, 1, 2, 3 }\n"
900 "IMM UINT32 { 4, 0, 0, 0 }\n"
901 "\n"
902 " BGNSUB\n"
903 " UMUL TEMP[0].x, IMM[0].xxxx, IMM[1].xxxx\n"
904 " STORE RES[0].x, TEMP[0], IMM[0].xxxx\n"
905 " RET\n"
906 " ENDSUB\n"
907 " BGNSUB\n"
908 " UMUL TEMP[0].x, IMM[0].yyyy, IMM[1].xxxx\n"
909 " STORE RES[0].x, TEMP[0], IMM[0].yyyy\n"
910 " RET\n"
911 " ENDSUB\n"
912 " BGNSUB\n"
913 " UMUL TEMP[0].x, IMM[0].zzzz, IMM[1].xxxx\n"
914 " STORE RES[0].x, TEMP[0], IMM[0].zzzz\n"
915 " RET\n"
916 " ENDSUB\n"
917 " BGNSUB\n"
918 " UMUL TEMP[0].x, IMM[0].wwww, IMM[1].xxxx\n"
919 " STORE RES[0].x, TEMP[0], IMM[0].wwww\n"
920 " RET\n"
921 " ENDSUB\n";
922
923 printf("- %s\n", __func__);
924
925 init_prog(ctx, 0, 0, 0, src, NULL);
926 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
927 16, 0, test_default_init);
928 init_compute_resources(ctx, (int []) { 0, -1 });
929 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){1, 1, 1}, 0, NULL);
930 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){1, 1, 1}, 5, NULL);
931 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){1, 1, 1}, 10, NULL);
932 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){1, 1, 1}, 15, NULL);
933 check_tex(ctx, 0, test_many_kern_expect, NULL);
934 destroy_compute_resources(ctx);
935 destroy_tex(ctx);
936 destroy_prog(ctx);
937 }
938
939 /* test_constant */
940 static void test_constant_init(void *p, int s, int x, int y)
941 {
942 *(float *)p = s ? 0xdeadbeef : 8.0 - (float)x;
943 }
944
945 static void test_constant_expect(void *p, int s, int x, int y)
946 {
947 *(float *)p = 8.0 - (float)x;
948 }
949
950 static void test_constant(struct context *ctx)
951 {
952 const char *src = "COMP\n"
953 "DCL RES[0], BUFFER, RAW\n"
954 "DCL RES[1], BUFFER, RAW, WR\n"
955 "DCL SV[0], BLOCK_ID[0]\n"
956 "DCL TEMP[0], LOCAL\n"
957 "DCL TEMP[1], LOCAL\n"
958 "IMM UINT32 { 4, 0, 0, 0 }\n"
959 "\n"
960 " BGNSUB\n"
961 " UMUL TEMP[0].x, SV[0], IMM[0]\n"
962 " LOAD TEMP[1].x, RES[0], TEMP[0]\n"
963 " STORE RES[1].x, TEMP[0], TEMP[1]\n"
964 " RET\n"
965 " ENDSUB\n";
966
967 printf("- %s\n", __func__);
968
969 init_prog(ctx, 0, 0, 0, src, NULL);
970 init_tex(ctx, 0, PIPE_BUFFER, false, PIPE_FORMAT_R32_FLOAT,
971 256, 0, test_constant_init);
972 init_tex(ctx, 1, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
973 256, 0, test_constant_init);
974 init_compute_resources(ctx, (int []) { 0, 1, -1 });
975 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){64, 1, 1}, 0, NULL);
976 check_tex(ctx, 1, test_constant_expect, NULL);
977 destroy_compute_resources(ctx);
978 destroy_tex(ctx);
979 destroy_prog(ctx);
980 }
981
982 /* test_resource_indirect */
983 static void test_resource_indirect_init(void *p, int s, int x, int y)
984 {
985 *(uint32_t *)p = s == 0 ? 0xdeadbeef :
986 s == 1 ? x % 2 :
987 s == 2 ? 2 * x :
988 2 * x + 1;
989 }
990
991 static void test_resource_indirect_expect(void *p, int s, int x, int y)
992 {
993 *(uint32_t *)p = 2 * x + (x % 2 ? 1 : 0);
994 }
995
996 static void test_resource_indirect(struct context *ctx)
997 {
998 const char *src = "COMP\n"
999 "DCL RES[0], BUFFER, RAW, WR\n"
1000 "DCL RES[1..3], BUFFER, RAW\n"
1001 "DCL SV[0], BLOCK_ID[0]\n"
1002 "DCL TEMP[0], LOCAL\n"
1003 "DCL TEMP[1], LOCAL\n"
1004 "IMM UINT32 { 4, 0, 0, 0 }\n"
1005 "\n"
1006 " BGNSUB\n"
1007 " UMUL TEMP[0].x, SV[0], IMM[0]\n"
1008 " LOAD TEMP[1].x, RES[1], TEMP[0]\n"
1009 " LOAD TEMP[1].x, RES[TEMP[1].x+2], TEMP[0]\n"
1010 " STORE RES[0].x, TEMP[0], TEMP[1]\n"
1011 " RET\n"
1012 " ENDSUB\n";
1013
1014 printf("- %s\n", __func__);
1015
1016 init_prog(ctx, 0, 0, 0, src, NULL);
1017 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
1018 256, 0, test_resource_indirect_init);
1019 init_tex(ctx, 1, PIPE_BUFFER, false, PIPE_FORMAT_R32_FLOAT,
1020 256, 0, test_resource_indirect_init);
1021 init_tex(ctx, 2, PIPE_BUFFER, false, PIPE_FORMAT_R32_FLOAT,
1022 256, 0, test_resource_indirect_init);
1023 init_tex(ctx, 3, PIPE_BUFFER, false, PIPE_FORMAT_R32_FLOAT,
1024 256, 0, test_resource_indirect_init);
1025 init_compute_resources(ctx, (int []) { 0, 1, 2, 3, -1 });
1026 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){64, 1, 1}, 0, NULL);
1027 check_tex(ctx, 0, test_resource_indirect_expect, NULL);
1028 destroy_compute_resources(ctx);
1029 destroy_tex(ctx);
1030 destroy_prog(ctx);
1031 }
1032
1033 /* test_surface_ld */
1034 enum pipe_format surface_fmts[] = {
1035 PIPE_FORMAT_B8G8R8A8_UNORM,
1036 PIPE_FORMAT_B8G8R8X8_UNORM,
1037 PIPE_FORMAT_A8R8G8B8_UNORM,
1038 PIPE_FORMAT_X8R8G8B8_UNORM,
1039 PIPE_FORMAT_X8R8G8B8_UNORM,
1040 PIPE_FORMAT_L8_UNORM,
1041 PIPE_FORMAT_A8_UNORM,
1042 PIPE_FORMAT_I8_UNORM,
1043 PIPE_FORMAT_L8A8_UNORM,
1044 PIPE_FORMAT_R32_FLOAT,
1045 PIPE_FORMAT_R32G32_FLOAT,
1046 PIPE_FORMAT_R32G32B32A32_FLOAT,
1047 PIPE_FORMAT_R32_UNORM,
1048 PIPE_FORMAT_R32G32_UNORM,
1049 PIPE_FORMAT_R32G32B32A32_UNORM,
1050 PIPE_FORMAT_R32_SNORM,
1051 PIPE_FORMAT_R32G32_SNORM,
1052 PIPE_FORMAT_R32G32B32A32_SNORM,
1053 PIPE_FORMAT_R8_UINT,
1054 PIPE_FORMAT_R8G8_UINT,
1055 PIPE_FORMAT_R8G8B8A8_UINT,
1056 PIPE_FORMAT_R8_SINT,
1057 PIPE_FORMAT_R8G8_SINT,
1058 PIPE_FORMAT_R8G8B8A8_SINT,
1059 PIPE_FORMAT_R32_UINT,
1060 PIPE_FORMAT_R32G32_UINT,
1061 PIPE_FORMAT_R32G32B32A32_UINT,
1062 PIPE_FORMAT_R32_SINT,
1063 PIPE_FORMAT_R32G32_SINT,
1064 PIPE_FORMAT_R32G32B32A32_SINT
1065 };
1066
1067 static void test_surface_ld_init0f(void *p, int s, int x, int y)
1068 {
1069 float v[] = { 1.0, -.75, .50, -.25 };
1070 int i = 0;
1071
1072 util_format_write_4f(surface_fmts[i], v, 0, p, 0, 0, 0, 1, 1);
1073 }
1074
1075 static void test_surface_ld_init0i(void *p, int s, int x, int y)
1076 {
1077 int v[] = { 0xffffffff, 0xffff, 0xff, 0xf };
1078 int i = 0;
1079
1080 util_format_write_4i(surface_fmts[i], v, 0, p, 0, 0, 0, 1, 1);
1081 }
1082
1083 static void test_surface_ld_expectf(void *p, int s, int x, int y)
1084 {
1085 float v[4], w[4];
1086 int i = 0;
1087
1088 test_surface_ld_init0f(v, s, x / 4, y);
1089 util_format_read_4f(surface_fmts[i], w, 0, v, 0, 0, 0, 1, 1);
1090 *(float *)p = w[x % 4];
1091 }
1092
1093 static void test_surface_ld_expecti(void *p, int s, int x, int y)
1094 {
1095 int32_t v[4], w[4];
1096 int i = 0;
1097
1098 test_surface_ld_init0i(v, s, x / 4, y);
1099 util_format_read_4i(surface_fmts[i], w, 0, v, 0, 0, 0, 1, 1);
1100 *(uint32_t *)p = w[x % 4];
1101 }
1102
1103 static void test_surface_ld(struct context *ctx)
1104 {
1105 const char *src = "COMP\n"
1106 "DCL RES[0], 2D\n"
1107 "DCL RES[1], 2D, RAW, WR\n"
1108 "DCL SV[0], BLOCK_ID[0]\n"
1109 "DCL TEMP[0], LOCAL\n"
1110 "DCL TEMP[1], LOCAL\n"
1111 "IMM UINT32 { 16, 1, 0, 0 }\n"
1112 "\n"
1113 " BGNSUB\n"
1114 " LOAD TEMP[1], RES[0], SV[0]\n"
1115 " UMUL TEMP[0], SV[0], IMM[0]\n"
1116 " STORE RES[1].xyzw, TEMP[0], TEMP[1]\n"
1117 " RET\n"
1118 " ENDSUB\n";
1119 int i = 0;
1120
1121 printf("- %s\n", __func__);
1122
1123 init_prog(ctx, 0, 0, 0, src, NULL);
1124
1125 for (i = 0; i < Elements(surface_fmts); i++) {
1126 bool is_int = util_format_is_pure_integer(surface_fmts[i]);
1127
1128 printf(" - %s\n", util_format_name(surface_fmts[i]));
1129
1130 if (!ctx->screen->is_format_supported(ctx->screen,
1131 surface_fmts[i], PIPE_TEXTURE_2D, 1,
1132 PIPE_BIND_COMPUTE_RESOURCE)) {
1133 printf("(unsupported)\n");
1134 continue;
1135 }
1136
1137 init_tex(ctx, 0, PIPE_TEXTURE_2D, true, surface_fmts[i],
1138 128, 32, (is_int ? test_surface_ld_init0i : test_surface_ld_init0f));
1139 init_tex(ctx, 1, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
1140 512, 32, test_default_init);
1141 init_compute_resources(ctx, (int []) { 0, 1, -1 });
1142 init_sampler_states(ctx, 2);
1143 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){128, 32, 1}, 0,
1144 NULL);
1145 check_tex(ctx, 1, (is_int ? test_surface_ld_expecti : test_surface_ld_expectf), NULL);
1146 destroy_sampler_states(ctx);
1147 destroy_compute_resources(ctx);
1148 destroy_tex(ctx);
1149 }
1150
1151 destroy_prog(ctx);
1152 }
1153
1154 /* test_surface_st */
1155 static void test_surface_st_init0f(void *p, int s, int x, int y)
1156 {
1157 float v[] = { 1.0, -.75, 0.5, -.25 };
1158 *(float *)p = v[x % 4];
1159 }
1160
1161 static void test_surface_st_init0i(void *p, int s, int x, int y)
1162 {
1163 int v[] = { 0xffffffff, 0xffff, 0xff, 0xf };
1164 *(int32_t *)p = v[x % 4];
1165 }
1166
1167 static void test_surface_st_init1(void *p, int s, int x, int y)
1168 {
1169 int i = 0;
1170 memset(p, 1, util_format_get_blocksize(surface_fmts[i]));
1171 }
1172
1173 static void test_surface_st_expectf(void *p, int s, int x, int y)
1174 {
1175 float vf[4];
1176 int i = 0, j;
1177
1178 for (j = 0; j < 4; j++)
1179 test_surface_st_init0f(&vf[j], s, 4 * x + j, y);
1180 util_format_write_4f(surface_fmts[i], vf, 0, p, 0, 0, 0, 1, 1);
1181 }
1182
1183 static void test_surface_st_expects(void *p, int s, int x, int y)
1184 {
1185 int32_t v[4];
1186 int i = 0, j;
1187
1188 for (j = 0; j < 4; j++)
1189 test_surface_st_init0i(&v[j], s, 4 * x + j, y);
1190 util_format_write_4i(surface_fmts[i], v, 0, p, 0, 0, 0, 1, 1);
1191 }
1192
1193 static void test_surface_st_expectu(void *p, int s, int x, int y)
1194 {
1195 uint32_t v[4];
1196 int i = 0, j;
1197
1198 for (j = 0; j < 4; j++)
1199 test_surface_st_init0i(&v[j], s, 4 * x + j, y);
1200 util_format_write_4ui(surface_fmts[i], v, 0, p, 0, 0, 0, 1, 1);
1201 }
1202
1203 static bool test_surface_st_check(void *x, void *y, int sz)
1204 {
1205 int i = 0, j;
1206
1207 if (util_format_is_float(surface_fmts[i])) {
1208 return fabs(*(float *)x - *(float *)y) < 3.92156863e-3;
1209
1210 } else if ((sz % 4) == 0) {
1211 for (j = 0; j < sz / 4; j++)
1212 if (abs(((uint32_t *)x)[j] -
1213 ((uint32_t *)y)[j]) > 1)
1214 return false;
1215 return true;
1216 } else {
1217 return !memcmp(x, y, sz);
1218 }
1219 }
1220
1221 static void test_surface_st(struct context *ctx)
1222 {
1223 const char *src = "COMP\n"
1224 "DCL RES[0], 2D, RAW\n"
1225 "DCL RES[1], 2D, WR\n"
1226 "DCL SV[0], BLOCK_ID[0]\n"
1227 "DCL TEMP[0], LOCAL\n"
1228 "DCL TEMP[1], LOCAL\n"
1229 "IMM UINT32 { 16, 1, 0, 0 }\n"
1230 "\n"
1231 " BGNSUB\n"
1232 " UMUL TEMP[0], SV[0], IMM[0]\n"
1233 " LOAD TEMP[1], RES[0], TEMP[0]\n"
1234 " STORE RES[1], SV[0], TEMP[1]\n"
1235 " RET\n"
1236 " ENDSUB\n";
1237 int i = 0;
1238
1239 printf("- %s\n", __func__);
1240
1241 init_prog(ctx, 0, 0, 0, src, NULL);
1242
1243 for (i = 0; i < Elements(surface_fmts); i++) {
1244 bool is_signed = (util_format_description(surface_fmts[i])
1245 ->channel[0].type == UTIL_FORMAT_TYPE_SIGNED);
1246 bool is_int = util_format_is_pure_integer(surface_fmts[i]);
1247
1248 printf(" - %s\n", util_format_name(surface_fmts[i]));
1249
1250 if (!ctx->screen->is_format_supported(ctx->screen,
1251 surface_fmts[i], PIPE_TEXTURE_2D, 1,
1252 PIPE_BIND_COMPUTE_RESOURCE)) {
1253 printf("(unsupported)\n");
1254 continue;
1255 }
1256
1257 init_tex(ctx, 0, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
1258 512, 32, (is_int ? test_surface_st_init0i : test_surface_st_init0f));
1259 init_tex(ctx, 1, PIPE_TEXTURE_2D, true, surface_fmts[i],
1260 128, 32, test_surface_st_init1);
1261 init_compute_resources(ctx, (int []) { 0, 1, -1 });
1262 init_sampler_states(ctx, 2);
1263 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){128, 32, 1}, 0,
1264 NULL);
1265 check_tex(ctx, 1, (is_int && is_signed ? test_surface_st_expects :
1266 is_int && !is_signed ? test_surface_st_expectu :
1267 test_surface_st_expectf), test_surface_st_check);
1268 destroy_sampler_states(ctx);
1269 destroy_compute_resources(ctx);
1270 destroy_tex(ctx);
1271 }
1272
1273 destroy_prog(ctx);
1274 }
1275
1276 /* test_barrier */
1277 static void test_barrier_expect(void *p, int s, int x, int y)
1278 {
1279 *(uint32_t *)p = 31;
1280 }
1281
1282 static void test_barrier(struct context *ctx)
1283 {
1284 const char *src = "COMP\n"
1285 "DCL RES[0], BUFFER, RAW, WR\n"
1286 "DCL SV[0], BLOCK_ID[0]\n"
1287 "DCL SV[1], BLOCK_SIZE[0]\n"
1288 "DCL SV[2], THREAD_ID[0]\n"
1289 "DCL TEMP[0], LOCAL\n"
1290 "DCL TEMP[1], LOCAL\n"
1291 "DCL TEMP[2], LOCAL\n"
1292 "DCL TEMP[3], LOCAL\n"
1293 "IMM UINT32 { 1, 0, 0, 0 }\n"
1294 "IMM UINT32 { 4, 0, 0, 0 }\n"
1295 "IMM UINT32 { 32, 0, 0, 0 }\n"
1296 "\n"
1297 " BGNSUB\n"
1298 " UMUL TEMP[0].x, SV[2], IMM[1]\n"
1299 " MOV TEMP[1].x, IMM[0].wwww\n"
1300 " BGNLOOP\n"
1301 " BARRIER\n"
1302 " STORE RLOCAL.x, TEMP[0], TEMP[1]\n"
1303 " BARRIER\n"
1304 " MOV TEMP[2].x, IMM[0].wwww\n"
1305 " BGNLOOP\n"
1306 " UMUL TEMP[3].x, TEMP[2], IMM[1]\n"
1307 " LOAD TEMP[3].x, RLOCAL, TEMP[3]\n"
1308 " USNE TEMP[3].x, TEMP[3], TEMP[1]\n"
1309 " IF TEMP[3]\n"
1310 " END\n"
1311 " ENDIF\n"
1312 " UADD TEMP[2].x, TEMP[2], IMM[0]\n"
1313 " USEQ TEMP[3].x, TEMP[2], SV[1]\n"
1314 " IF TEMP[3]\n"
1315 " BRK\n"
1316 " ENDIF\n"
1317 " ENDLOOP\n"
1318 " UADD TEMP[1].x, TEMP[1], IMM[0]\n"
1319 " USEQ TEMP[2].x, TEMP[1], IMM[2]\n"
1320 " IF TEMP[2]\n"
1321 " BRK\n"
1322 " ENDIF\n"
1323 " ENDLOOP\n"
1324 " UMUL TEMP[1].x, SV[0], SV[1]\n"
1325 " UMUL TEMP[1].x, TEMP[1], IMM[1]\n"
1326 " UADD TEMP[1].x, TEMP[1], TEMP[0]\n"
1327 " LOAD TEMP[0].x, RLOCAL, TEMP[0]\n"
1328 " STORE RES[0].x, TEMP[1], TEMP[0]\n"
1329 " RET\n"
1330 " ENDSUB\n";
1331
1332 printf("- %s\n", __func__);
1333
1334 init_prog(ctx, 256, 0, 0, src, NULL);
1335 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
1336 4096, 0, test_default_init);
1337 init_compute_resources(ctx, (int []) { 0, -1 });
1338 launch_grid(ctx, (uint []){64, 1, 1}, (uint []){16, 1, 1}, 0, NULL);
1339 check_tex(ctx, 0, test_barrier_expect, NULL);
1340 destroy_compute_resources(ctx);
1341 destroy_tex(ctx);
1342 destroy_prog(ctx);
1343 }
1344
1345 /* test_atom_ops */
1346 static void test_atom_ops_init(void *p, int s, int x, int y)
1347 {
1348 *(uint32_t *)p = 0xbad;
1349 }
1350
1351 static void test_atom_ops_expect(void *p, int s, int x, int y)
1352 {
1353 switch (x) {
1354 case 0:
1355 *(uint32_t *)p = 0xce6c8eef;
1356 break;
1357 case 1:
1358 *(uint32_t *)p = 0xdeadbeef;
1359 break;
1360 case 2:
1361 *(uint32_t *)p = 0x11111111;
1362 break;
1363 case 3:
1364 *(uint32_t *)p = 0x10011001;
1365 break;
1366 case 4:
1367 *(uint32_t *)p = 0xdfbdbfff;
1368 break;
1369 case 5:
1370 *(uint32_t *)p = 0x11111111;
1371 break;
1372 case 6:
1373 *(uint32_t *)p = 0x11111111;
1374 break;
1375 case 7:
1376 *(uint32_t *)p = 0xdeadbeef;
1377 break;
1378 case 8:
1379 *(uint32_t *)p = 0xdeadbeef;
1380 break;
1381 case 9:
1382 *(uint32_t *)p = 0x11111111;
1383 break;
1384 }
1385 }
1386
1387 static void test_atom_ops(struct context *ctx, bool global)
1388 {
1389 const char *src = "COMP\n"
1390 "#ifdef TARGET_GLOBAL\n"
1391 "#define target RES[0]\n"
1392 "#else\n"
1393 "#define target RLOCAL\n"
1394 "#endif\n"
1395 ""
1396 "DCL RES[0], BUFFER, RAW, WR\n"
1397 "#define threadid SV[0]\n"
1398 "DCL threadid, THREAD_ID[0]\n"
1399 ""
1400 "#define offset TEMP[0]\n"
1401 "DCL offset, LOCAL\n"
1402 "#define tmp TEMP[1]\n"
1403 "DCL tmp, LOCAL\n"
1404 ""
1405 "#define k0 IMM[0]\n"
1406 "IMM UINT32 { 0, 0, 0, 0 }\n"
1407 "#define k1 IMM[1]\n"
1408 "IMM UINT32 { 1, 0, 0, 0 }\n"
1409 "#define k2 IMM[2]\n"
1410 "IMM UINT32 { 2, 0, 0, 0 }\n"
1411 "#define k3 IMM[3]\n"
1412 "IMM UINT32 { 3, 0, 0, 0 }\n"
1413 "#define k4 IMM[4]\n"
1414 "IMM UINT32 { 4, 0, 0, 0 }\n"
1415 "#define k5 IMM[5]\n"
1416 "IMM UINT32 { 5, 0, 0, 0 }\n"
1417 "#define k6 IMM[6]\n"
1418 "IMM UINT32 { 6, 0, 0, 0 }\n"
1419 "#define k7 IMM[7]\n"
1420 "IMM UINT32 { 7, 0, 0, 0 }\n"
1421 "#define k8 IMM[8]\n"
1422 "IMM UINT32 { 8, 0, 0, 0 }\n"
1423 "#define k9 IMM[9]\n"
1424 "IMM UINT32 { 9, 0, 0, 0 }\n"
1425 "#define korig IMM[10].xxxx\n"
1426 "#define karg IMM[10].yyyy\n"
1427 "IMM UINT32 { 3735928559, 286331153, 0, 0 }\n"
1428 "\n"
1429 " BGNSUB\n"
1430 " UMUL offset.x, threadid, k4\n"
1431 " STORE target.x, offset, korig\n"
1432 " USEQ tmp.x, threadid, k0\n"
1433 " IF tmp\n"
1434 " ATOMUADD tmp.x, target, offset, karg\n"
1435 " ATOMUADD tmp.x, target, offset, tmp\n"
1436 " ENDIF\n"
1437 " USEQ tmp.x, threadid, k1\n"
1438 " IF tmp\n"
1439 " ATOMXCHG tmp.x, target, offset, karg\n"
1440 " ATOMXCHG tmp.x, target, offset, tmp\n"
1441 " ENDIF\n"
1442 " USEQ tmp.x, threadid, k2\n"
1443 " IF tmp\n"
1444 " ATOMCAS tmp.x, target, offset, korig, karg\n"
1445 " ATOMCAS tmp.x, target, offset, tmp, k0\n"
1446 " ENDIF\n"
1447 " USEQ tmp.x, threadid, k3\n"
1448 " IF tmp\n"
1449 " ATOMAND tmp.x, target, offset, karg\n"
1450 " ATOMAND tmp.x, target, offset, tmp\n"
1451 " ENDIF\n"
1452 " USEQ tmp.x, threadid, k4\n"
1453 " IF tmp\n"
1454 " ATOMOR tmp.x, target, offset, karg\n"
1455 " ATOMOR tmp.x, target, offset, tmp\n"
1456 " ENDIF\n"
1457 " USEQ tmp.x, threadid, k5\n"
1458 " IF tmp\n"
1459 " ATOMXOR tmp.x, target, offset, karg\n"
1460 " ATOMXOR tmp.x, target, offset, tmp\n"
1461 " ENDIF\n"
1462 " USEQ tmp.x, threadid, k6\n"
1463 " IF tmp\n"
1464 " ATOMUMIN tmp.x, target, offset, karg\n"
1465 " ATOMUMIN tmp.x, target, offset, tmp\n"
1466 " ENDIF\n"
1467 " USEQ tmp.x, threadid, k7\n"
1468 " IF tmp\n"
1469 " ATOMUMAX tmp.x, target, offset, karg\n"
1470 " ATOMUMAX tmp.x, target, offset, tmp\n"
1471 " ENDIF\n"
1472 " USEQ tmp.x, threadid, k8\n"
1473 " IF tmp\n"
1474 " ATOMIMIN tmp.x, target, offset, karg\n"
1475 " ATOMIMIN tmp.x, target, offset, tmp\n"
1476 " ENDIF\n"
1477 " USEQ tmp.x, threadid, k9\n"
1478 " IF tmp\n"
1479 " ATOMIMAX tmp.x, target, offset, karg\n"
1480 " ATOMIMAX tmp.x, target, offset, tmp\n"
1481 " ENDIF\n"
1482 "#ifdef TARGET_LOCAL\n"
1483 " LOAD tmp.x, RLOCAL, offset\n"
1484 " STORE RES[0].x, offset, tmp\n"
1485 "#endif\n"
1486 " RET\n"
1487 " ENDSUB\n";
1488
1489 printf("- %s (%s)\n", __func__, global ? "global" : "local");
1490
1491 init_prog(ctx, 40, 0, 0, src,
1492 (global ? "-DTARGET_GLOBAL" : "-DTARGET_LOCAL"));
1493 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
1494 40, 0, test_atom_ops_init);
1495 init_compute_resources(ctx, (int []) { 0, -1 });
1496 launch_grid(ctx, (uint []){10, 1, 1}, (uint []){1, 1, 1}, 0, NULL);
1497 check_tex(ctx, 0, test_atom_ops_expect, NULL);
1498 destroy_compute_resources(ctx);
1499 destroy_tex(ctx);
1500 destroy_prog(ctx);
1501 }
1502
1503 /* test_atom_race */
1504 static void test_atom_race_expect(void *p, int s, int x, int y)
1505 {
1506 *(uint32_t *)p = x & 0x20 ? 0x11111111 : 0xffffffff;
1507 }
1508
1509 static void test_atom_race(struct context *ctx, bool global)
1510 {
1511 const char *src = "COMP\n"
1512 "#ifdef TARGET_GLOBAL\n"
1513 "#define target RES[0]\n"
1514 "#else\n"
1515 "#define target RLOCAL\n"
1516 "#endif\n"
1517 ""
1518 "DCL RES[0], BUFFER, RAW, WR\n"
1519 ""
1520 "#define blockid SV[0]\n"
1521 "DCL blockid, BLOCK_ID[0]\n"
1522 "#define blocksz SV[1]\n"
1523 "DCL blocksz, BLOCK_SIZE[0]\n"
1524 "#define threadid SV[2]\n"
1525 "DCL threadid, THREAD_ID[0]\n"
1526 ""
1527 "#define offset TEMP[0]\n"
1528 "DCL offset, LOCAL\n"
1529 "#define arg TEMP[1]\n"
1530 "DCL arg, LOCAL\n"
1531 "#define count TEMP[2]\n"
1532 "DCL count, LOCAL\n"
1533 "#define vlocal TEMP[3]\n"
1534 "DCL vlocal, LOCAL\n"
1535 "#define vshared TEMP[4]\n"
1536 "DCL vshared, LOCAL\n"
1537 "#define last TEMP[5]\n"
1538 "DCL last, LOCAL\n"
1539 "#define tmp0 TEMP[6]\n"
1540 "DCL tmp0, LOCAL\n"
1541 "#define tmp1 TEMP[7]\n"
1542 "DCL tmp1, LOCAL\n"
1543 ""
1544 "#define k0 IMM[0]\n"
1545 "IMM UINT32 { 0, 0, 0, 0 }\n"
1546 "#define k1 IMM[1]\n"
1547 "IMM UINT32 { 1, 0, 0, 0 }\n"
1548 "#define k4 IMM[2]\n"
1549 "IMM UINT32 { 4, 0, 0, 0 }\n"
1550 "#define k32 IMM[3]\n"
1551 "IMM UINT32 { 32, 0, 0, 0 }\n"
1552 "#define k128 IMM[4]\n"
1553 "IMM UINT32 { 128, 0, 0, 0 }\n"
1554 "#define kdeadcafe IMM[5]\n"
1555 "IMM UINT32 { 3735931646, 0, 0, 0 }\n"
1556 "#define kallowed_set IMM[6]\n"
1557 "IMM UINT32 { 559035650, 0, 0, 0 }\n"
1558 "#define k11111111 IMM[7]\n"
1559 "IMM UINT32 { 286331153, 0, 0, 0 }\n"
1560 "\n"
1561 " BGNSUB\n"
1562 " MOV offset.x, threadid\n"
1563 "#ifdef TARGET_GLOBAL\n"
1564 " UMUL tmp0.x, blockid, blocksz\n"
1565 " UADD offset.x, offset, tmp0\n"
1566 "#endif\n"
1567 " UMUL offset.x, offset, k4\n"
1568 " USLT tmp0.x, threadid, k32\n"
1569 " STORE target.x, offset, k0\n"
1570 " BARRIER\n"
1571 " IF tmp0\n"
1572 " MOV vlocal.x, k0\n"
1573 " MOV arg.x, kdeadcafe\n"
1574 " BGNLOOP\n"
1575 " INEG arg.x, arg\n"
1576 " ATOMUADD vshared.x, target, offset, arg\n"
1577 " SFENCE target\n"
1578 " USNE tmp0.x, vshared, vlocal\n"
1579 " IF tmp0\n"
1580 " BRK\n"
1581 " ENDIF\n"
1582 " UADD vlocal.x, vlocal, arg\n"
1583 " ENDLOOP\n"
1584 " UADD vlocal.x, vshared, arg\n"
1585 " LOAD vshared.x, target, offset\n"
1586 " USEQ tmp0.x, vshared, vlocal\n"
1587 " STORE target.x, offset, tmp0\n"
1588 " ELSE\n"
1589 " UADD offset.x, offset, -k128\n"
1590 " MOV count.x, k0\n"
1591 " MOV last.x, k0\n"
1592 " BGNLOOP\n"
1593 " LOAD vshared.x, target, offset\n"
1594 " USEQ tmp0.x, vshared, kallowed_set.xxxx\n"
1595 " USEQ tmp1.x, vshared, kallowed_set.yyyy\n"
1596 " OR tmp0.x, tmp0, tmp1\n"
1597 " IF tmp0\n"
1598 " USEQ tmp0.x, vshared, last\n"
1599 " IF tmp0\n"
1600 " CONT\n"
1601 " ENDIF\n"
1602 " MOV last.x, vshared\n"
1603 " ELSE\n"
1604 " END\n"
1605 " ENDIF\n"
1606 " UADD count.x, count, k1\n"
1607 " USEQ tmp0.x, count, k128\n"
1608 " IF tmp0\n"
1609 " BRK\n"
1610 " ENDIF\n"
1611 " ENDLOOP\n"
1612 " ATOMXCHG tmp0.x, target, offset, k11111111\n"
1613 " UADD offset.x, offset, k128\n"
1614 " ATOMXCHG tmp0.x, target, offset, k11111111\n"
1615 " SFENCE target\n"
1616 " ENDIF\n"
1617 "#ifdef TARGET_LOCAL\n"
1618 " LOAD tmp0.x, RLOCAL, offset\n"
1619 " UMUL tmp1.x, blockid, blocksz\n"
1620 " UMUL tmp1.x, tmp1, k4\n"
1621 " UADD offset.x, offset, tmp1\n"
1622 " STORE RES[0].x, offset, tmp0\n"
1623 "#endif\n"
1624 " RET\n"
1625 " ENDSUB\n";
1626
1627 printf("- %s (%s)\n", __func__, global ? "global" : "local");
1628
1629 init_prog(ctx, 256, 0, 0, src,
1630 (global ? "-DTARGET_GLOBAL" : "-DTARGET_LOCAL"));
1631 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
1632 4096, 0, test_default_init);
1633 init_compute_resources(ctx, (int []) { 0, -1 });
1634 launch_grid(ctx, (uint []){64, 1, 1}, (uint []){16, 1, 1}, 0, NULL);
1635 check_tex(ctx, 0, test_atom_race_expect, NULL);
1636 destroy_compute_resources(ctx);
1637 destroy_tex(ctx);
1638 destroy_prog(ctx);
1639 }
1640
1641 int main(int argc, char *argv[])
1642 {
1643 struct context *ctx = CALLOC_STRUCT(context);
1644
1645 unsigned tests = (argc > 1) ? strtoul(argv[1], NULL, 0) : ~0;
1646
1647 init_ctx(ctx);
1648
1649 if (tests & (1 << 0))
1650 test_system_values(ctx);
1651 if (tests & (1 << 1))
1652 test_resource_access(ctx);
1653 if (tests & (1 << 2))
1654 test_function_calls(ctx);
1655 if (tests & (1 << 3))
1656 test_input_global(ctx);
1657 if (tests & (1 << 4))
1658 test_private(ctx);
1659 if (tests & (1 << 5))
1660 test_local(ctx);
1661 if (tests & (1 << 6))
1662 test_sample(ctx);
1663 if (tests & (1 << 7))
1664 test_many_kern(ctx);
1665 if (tests & (1 << 8))
1666 test_constant(ctx);
1667 if (tests & (1 << 9))
1668 test_resource_indirect(ctx);
1669 if (tests & (1 << 10))
1670 test_surface_ld(ctx);
1671 if (tests & (1 << 11))
1672 test_surface_st(ctx);
1673 if (tests & (1 << 12))
1674 test_barrier(ctx);
1675 if (tests & (1 << 13))
1676 test_atom_ops(ctx, true);
1677 if (tests & (1 << 14))
1678 test_atom_race(ctx, true);
1679 if (tests & (1 << 15))
1680 test_atom_ops(ctx, false);
1681 if (tests & (1 << 16))
1682 test_atom_race(ctx, false);
1683
1684 destroy_ctx(ctx);
1685
1686 return 0;
1687 }