gallium/tests: check format in compute tests, make selectable
[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, PIPE_SEARCH_DIR);
78 assert(ctx->screen);
79
80 ctx->pipe = ctx->screen->context_create(ctx->screen, NULL);
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_compute_sampler_views(pipe, 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_compute_sampler_views(pipe, 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_compute_sampler_states(pipe, 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_compute_sampler_states(pipe, 0, MAX_RESOURCES, NULL);
392
393 for (i = 0; i < MAX_RESOURCES; ++i) {
394 if (ctx->hwsmp[i]) {
395 pipe->delete_sampler_state(pipe, ctx->hwsmp[i]);
396 ctx->hwsmp[i] = NULL;
397 }
398 }
399 }
400
401 static void init_globals(struct context *ctx, const int *slots,
402 uint32_t **handles)
403 {
404 struct pipe_context *pipe = ctx->pipe;
405 struct pipe_resource *res[MAX_RESOURCES];
406 int i;
407
408 for (i = 0; *slots >= 0; ++i, ++slots)
409 res[i] = ctx->tex[*slots];
410
411 pipe->set_global_binding(pipe, 0, i, res, handles);
412 }
413
414 static void destroy_globals(struct context *ctx)
415 {
416 struct pipe_context *pipe = ctx->pipe;
417
418 pipe->set_global_binding(pipe, 0, MAX_RESOURCES, NULL, NULL);
419 }
420
421 static void launch_grid(struct context *ctx, const uint *block_layout,
422 const uint *grid_layout, uint32_t pc,
423 const void *input)
424 {
425 struct pipe_context *pipe = ctx->pipe;
426
427 pipe->launch_grid(pipe, block_layout, grid_layout, pc, input);
428 }
429
430 static void test_system_values(struct context *ctx)
431 {
432 const char *src = "COMP\n"
433 "DCL RES[0], BUFFER, RAW, WR\n"
434 "DCL SV[0], BLOCK_ID[0]\n"
435 "DCL SV[1], BLOCK_SIZE[0]\n"
436 "DCL SV[2], GRID_SIZE[0]\n"
437 "DCL SV[3], THREAD_ID[0]\n"
438 "DCL TEMP[0], LOCAL\n"
439 "DCL TEMP[1], LOCAL\n"
440 "IMM UINT32 { 64, 0, 0, 0 }\n"
441 "IMM UINT32 { 16, 0, 0, 0 }\n"
442 "IMM UINT32 { 0, 0, 0, 0 }\n"
443 "\n"
444 "BGNSUB"
445 " UMUL TEMP[0], SV[0], SV[1]\n"
446 " UADD TEMP[0], TEMP[0], SV[3]\n"
447 " UMUL TEMP[1], SV[1], SV[2]\n"
448 " UMUL TEMP[0].w, TEMP[0], TEMP[1].zzzz\n"
449 " UMUL TEMP[0].zw, TEMP[0], TEMP[1].yyyy\n"
450 " UMUL TEMP[0].yzw, TEMP[0], TEMP[1].xxxx\n"
451 " UADD TEMP[0].xy, TEMP[0].xyxy, TEMP[0].zwzw\n"
452 " UADD TEMP[0].x, TEMP[0].xxxx, TEMP[0].yyyy\n"
453 " UMUL TEMP[0].x, TEMP[0], IMM[0]\n"
454 " STORE RES[0].xyzw, TEMP[0], SV[0]\n"
455 " UADD TEMP[0].x, TEMP[0], IMM[1]\n"
456 " STORE RES[0].xyzw, TEMP[0], SV[1]\n"
457 " UADD TEMP[0].x, TEMP[0], IMM[1]\n"
458 " STORE RES[0].xyzw, TEMP[0], SV[2]\n"
459 " UADD TEMP[0].x, TEMP[0], IMM[1]\n"
460 " STORE RES[0].xyzw, TEMP[0], SV[3]\n"
461 " RET\n"
462 "ENDSUB\n";
463 void init(void *p, int s, int x, int y) {
464 *(uint32_t *)p = 0xdeadbeef;
465 }
466 void expect(void *p, int s, int x, int y) {
467 int id = x / 16, sv = (x % 16) / 4, c = x % 4;
468 int tid[] = { id % 20, (id % 240) / 20, id / 240, 0 };
469 int bsz[] = { 4, 3, 5, 1};
470 int gsz[] = { 5, 4, 1, 1};
471
472 switch (sv) {
473 case 0:
474 *(uint32_t *)p = tid[c] / bsz[c];
475 break;
476 case 1:
477 *(uint32_t *)p = bsz[c];
478 break;
479 case 2:
480 *(uint32_t *)p = gsz[c];
481 break;
482 case 3:
483 *(uint32_t *)p = tid[c] % bsz[c];
484 break;
485 }
486 }
487
488 printf("- %s\n", __func__);
489
490 init_prog(ctx, 0, 0, 0, src, NULL);
491 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
492 76800, 0, init);
493 init_compute_resources(ctx, (int []) { 0, -1 });
494 launch_grid(ctx, (uint []){4, 3, 5}, (uint []){5, 4, 1}, 0, NULL);
495 check_tex(ctx, 0, expect, NULL);
496 destroy_compute_resources(ctx);
497 destroy_tex(ctx);
498 destroy_prog(ctx);
499 }
500
501 static void test_resource_access(struct context *ctx)
502 {
503 const char *src = "COMP\n"
504 "DCL RES[0], BUFFER, RAW, WR\n"
505 "DCL RES[1], 2D, RAW, WR\n"
506 "DCL SV[0], BLOCK_ID[0]\n"
507 "DCL TEMP[0], LOCAL\n"
508 "DCL TEMP[1], LOCAL\n"
509 "IMM UINT32 { 15, 0, 0, 0 }\n"
510 "IMM UINT32 { 16, 1, 0, 0 }\n"
511 "\n"
512 " BGNSUB\n"
513 " UADD TEMP[0].x, SV[0].xxxx, SV[0].yyyy\n"
514 " AND TEMP[0].x, TEMP[0], IMM[0]\n"
515 " UMUL TEMP[0].x, TEMP[0], IMM[1]\n"
516 " LOAD TEMP[0].xyzw, RES[0], TEMP[0]\n"
517 " UMUL TEMP[1], SV[0], IMM[1]\n"
518 " STORE RES[1].xyzw, TEMP[1], TEMP[0]\n"
519 " RET\n"
520 " ENDSUB\n";
521 void init0(void *p, int s, int x, int y) {
522 *(float *)p = 8.0 - (float)x;
523 }
524 void init1(void *p, int s, int x, int y) {
525 *(uint32_t *)p = 0xdeadbeef;
526 }
527 void expect(void *p, int s, int x, int y) {
528 *(float *)p = 8.0 - (float)((x + 4*y) & 0x3f);
529 }
530
531 printf("- %s\n", __func__);
532
533 init_prog(ctx, 0, 0, 0, src, NULL);
534 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
535 256, 0, init0);
536 init_tex(ctx, 1, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
537 60, 12, init1);
538 init_compute_resources(ctx, (int []) { 0, 1, -1 });
539 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){15, 12, 1}, 0, NULL);
540 check_tex(ctx, 1, expect, NULL);
541 destroy_compute_resources(ctx);
542 destroy_tex(ctx);
543 destroy_prog(ctx);
544 }
545
546 static void test_function_calls(struct context *ctx)
547 {
548 const char *src = "COMP\n"
549 "DCL RES[0], 2D, RAW, WR\n"
550 "DCL SV[0], BLOCK_ID[0]\n"
551 "DCL SV[1], BLOCK_SIZE[0]\n"
552 "DCL SV[2], GRID_SIZE[0]\n"
553 "DCL SV[3], THREAD_ID[0]\n"
554 "DCL TEMP[0]\n"
555 "DCL TEMP[1]\n"
556 "DCL TEMP[2], LOCAL\n"
557 "IMM UINT32 { 0, 11, 22, 33 }\n"
558 "IMM FLT32 { 11, 33, 55, 99 }\n"
559 "IMM UINT32 { 4, 1, 0, 0 }\n"
560 "IMM UINT32 { 12, 0, 0, 0 }\n"
561 "\n"
562 "00: BGNSUB\n"
563 "01: UMUL TEMP[0].x, TEMP[0], TEMP[0]\n"
564 "02: UADD TEMP[1].x, TEMP[1], IMM[2].yyyy\n"
565 "03: USLT TEMP[0].x, TEMP[0], IMM[0]\n"
566 "04: RET\n"
567 "05: ENDSUB\n"
568 "06: BGNSUB\n"
569 "07: UMUL TEMP[0].x, TEMP[0], TEMP[0]\n"
570 "08: UADD TEMP[1].x, TEMP[1], IMM[2].yyyy\n"
571 "09: USLT TEMP[0].x, TEMP[0], IMM[0].yyyy\n"
572 "10: IF TEMP[0].xxxx\n"
573 "11: CAL :0\n"
574 "12: ENDIF\n"
575 "13: RET\n"
576 "14: ENDSUB\n"
577 "15: BGNSUB\n"
578 "16: UMUL TEMP[2], SV[0], SV[1]\n"
579 "17: UADD TEMP[2], TEMP[2], SV[3]\n"
580 "18: UMUL TEMP[2], TEMP[2], IMM[2]\n"
581 "00: MOV TEMP[1].x, IMM[2].wwww\n"
582 "19: LOAD TEMP[0].x, RES[0].xxxx, TEMP[2]\n"
583 "20: CAL :6\n"
584 "21: STORE RES[0].x, TEMP[2], TEMP[1].xxxx\n"
585 "22: RET\n"
586 "23: ENDSUB\n";
587 void init(void *p, int s, int x, int y) {
588 *(uint32_t *)p = 15 * y + x;
589 }
590 void expect(void *p, int s, int x, int y) {
591 *(uint32_t *)p = (15 * y + x) < 4 ? 2 : 1 ;
592 }
593
594 printf("- %s\n", __func__);
595
596 init_prog(ctx, 0, 0, 0, src, NULL);
597 init_tex(ctx, 0, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
598 15, 12, init);
599 init_compute_resources(ctx, (int []) { 0, -1 });
600 launch_grid(ctx, (uint []){3, 3, 3}, (uint []){5, 4, 1}, 15, NULL);
601 check_tex(ctx, 0, expect, NULL);
602 destroy_compute_resources(ctx);
603 destroy_tex(ctx);
604 destroy_prog(ctx);
605 }
606
607 static void test_input_global(struct context *ctx)
608 {
609 const char *src = "COMP\n"
610 "DCL SV[0], THREAD_ID[0]\n"
611 "DCL TEMP[0], LOCAL\n"
612 "DCL TEMP[1], LOCAL\n"
613 "IMM UINT32 { 8, 0, 0, 0 }\n"
614 "\n"
615 " BGNSUB\n"
616 " UMUL TEMP[0], SV[0], IMM[0]\n"
617 " LOAD TEMP[1].xy, RINPUT, TEMP[0]\n"
618 " LOAD TEMP[0].x, RGLOBAL, TEMP[1].yyyy\n"
619 " UADD TEMP[1].x, TEMP[0], -TEMP[1]\n"
620 " STORE RGLOBAL.x, TEMP[1].yyyy, TEMP[1]\n"
621 " RET\n"
622 " ENDSUB\n";
623 void init(void *p, int s, int x, int y) {
624 *(uint32_t *)p = 0xdeadbeef;
625 }
626 void expect(void *p, int s, int x, int y) {
627 *(uint32_t *)p = 0xdeadbeef - (x == 0 ? 0x10001 + 2 * s : 0);
628 }
629 uint32_t input[8] = { 0x10001, 0x10002, 0x10003, 0x10004,
630 0x10005, 0x10006, 0x10007, 0x10008 };
631
632 printf("- %s\n", __func__);
633
634 init_prog(ctx, 0, 0, 32, src, NULL);
635 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT, 32, 0, init);
636 init_tex(ctx, 1, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT, 32, 0, init);
637 init_tex(ctx, 2, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT, 32, 0, init);
638 init_tex(ctx, 3, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT, 32, 0, init);
639 init_globals(ctx, (int []){ 0, 1, 2, 3, -1 },
640 (uint32_t *[]){ &input[1], &input[3],
641 &input[5], &input[7] });
642 launch_grid(ctx, (uint []){4, 1, 1}, (uint []){1, 1, 1}, 0, input);
643 check_tex(ctx, 0, expect, NULL);
644 check_tex(ctx, 1, expect, NULL);
645 check_tex(ctx, 2, expect, NULL);
646 check_tex(ctx, 3, expect, NULL);
647 destroy_globals(ctx);
648 destroy_tex(ctx);
649 destroy_prog(ctx);
650 }
651
652 static void test_private(struct context *ctx)
653 {
654 const char *src = "COMP\n"
655 "DCL RES[0], BUFFER, RAW, WR\n"
656 "DCL SV[0], BLOCK_ID[0]\n"
657 "DCL SV[1], BLOCK_SIZE[0]\n"
658 "DCL SV[2], THREAD_ID[0]\n"
659 "DCL TEMP[0], LOCAL\n"
660 "DCL TEMP[1], LOCAL\n"
661 "DCL TEMP[2], LOCAL\n"
662 "IMM UINT32 { 128, 0, 0, 0 }\n"
663 "IMM UINT32 { 4, 0, 0, 0 }\n"
664 "\n"
665 " BGNSUB\n"
666 " UMUL TEMP[0].x, SV[0], SV[1]\n"
667 " UADD TEMP[0].x, TEMP[0], SV[2]\n"
668 " MOV TEMP[1].x, IMM[0].wwww\n"
669 " BGNLOOP\n"
670 " USEQ TEMP[2].x, TEMP[1], IMM[0]\n"
671 " IF TEMP[2]\n"
672 " BRK\n"
673 " ENDIF\n"
674 " UDIV TEMP[2].x, TEMP[1], IMM[1]\n"
675 " UADD TEMP[2].x, TEMP[2], TEMP[0]\n"
676 " STORE RPRIVATE.x, TEMP[1], TEMP[2]\n"
677 " UADD TEMP[1].x, TEMP[1], IMM[1]\n"
678 " ENDLOOP\n"
679 " MOV TEMP[1].x, IMM[0].wwww\n"
680 " UMUL TEMP[0].x, TEMP[0], IMM[0]\n"
681 " BGNLOOP\n"
682 " USEQ TEMP[2].x, TEMP[1], IMM[0]\n"
683 " IF TEMP[2]\n"
684 " BRK\n"
685 " ENDIF\n"
686 " LOAD TEMP[2].x, RPRIVATE, TEMP[1]\n"
687 " STORE RES[0].x, TEMP[0], TEMP[2]\n"
688 " UADD TEMP[0].x, TEMP[0], IMM[1]\n"
689 " UADD TEMP[1].x, TEMP[1], IMM[1]\n"
690 " ENDLOOP\n"
691 " RET\n"
692 " ENDSUB\n";
693 void init(void *p, int s, int x, int y) {
694 *(uint32_t *)p = 0xdeadbeef;
695 }
696 void expect(void *p, int s, int x, int y) {
697 *(uint32_t *)p = (x / 32) + x % 32;
698 }
699
700 printf("- %s\n", __func__);
701
702 init_prog(ctx, 0, 128, 0, src, NULL);
703 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
704 32768, 0, init);
705 init_compute_resources(ctx, (int []) { 0, -1 });
706 launch_grid(ctx, (uint []){16, 1, 1}, (uint []){16, 1, 1}, 0, NULL);
707 check_tex(ctx, 0, expect, NULL);
708 destroy_compute_resources(ctx);
709 destroy_tex(ctx);
710 destroy_prog(ctx);
711 }
712
713 static void test_local(struct context *ctx)
714 {
715 const char *src = "COMP\n"
716 "DCL RES[0], BUFFER, RAW, WR\n"
717 "DCL SV[0], BLOCK_ID[0]\n"
718 "DCL SV[1], BLOCK_SIZE[0]\n"
719 "DCL SV[2], THREAD_ID[0]\n"
720 "DCL TEMP[0], LOCAL\n"
721 "DCL TEMP[1], LOCAL\n"
722 "DCL TEMP[2], LOCAL\n"
723 "IMM UINT32 { 1, 0, 0, 0 }\n"
724 "IMM UINT32 { 2, 0, 0, 0 }\n"
725 "IMM UINT32 { 4, 0, 0, 0 }\n"
726 "IMM UINT32 { 32, 0, 0, 0 }\n"
727 "IMM UINT32 { 128, 0, 0, 0 }\n"
728 "\n"
729 " BGNSUB\n"
730 " UMUL TEMP[0].x, SV[2], IMM[2]\n"
731 " STORE RLOCAL.x, TEMP[0], IMM[0].wwww\n"
732 " MFENCE RLOCAL\n"
733 " USLT TEMP[1].x, SV[2], IMM[3]\n"
734 " IF TEMP[1]\n"
735 " UADD TEMP[1].x, TEMP[0], IMM[4]\n"
736 " BGNLOOP\n"
737 " LOAD TEMP[2].x, RLOCAL, TEMP[1]\n"
738 " USEQ TEMP[2].x, TEMP[2], IMM[0]\n"
739 " IF TEMP[2]\n"
740 " BRK\n"
741 " ENDIF\n"
742 " ENDLOOP\n"
743 " STORE RLOCAL.x, TEMP[0], IMM[0]\n"
744 " MFENCE RLOCAL\n"
745 " BGNLOOP\n"
746 " LOAD TEMP[2].x, RLOCAL, TEMP[1]\n"
747 " USEQ TEMP[2].x, TEMP[2], IMM[1]\n"
748 " IF TEMP[2]\n"
749 " BRK\n"
750 " ENDIF\n"
751 " ENDLOOP\n"
752 " ELSE\n"
753 " UADD TEMP[1].x, TEMP[0], -IMM[4]\n"
754 " BGNLOOP\n"
755 " LOAD TEMP[2].x, RLOCAL, TEMP[1]\n"
756 " USEQ TEMP[2].x, TEMP[2], IMM[0].wwww\n"
757 " IF TEMP[2]\n"
758 " BRK\n"
759 " ENDIF\n"
760 " ENDLOOP\n"
761 " STORE RLOCAL.x, TEMP[0], IMM[0]\n"
762 " MFENCE RLOCAL\n"
763 " BGNLOOP\n"
764 " LOAD TEMP[2].x, RLOCAL, TEMP[1]\n"
765 " USEQ TEMP[2].x, TEMP[2], IMM[0]\n"
766 " IF TEMP[2]\n"
767 " BRK\n"
768 " ENDIF\n"
769 " ENDLOOP\n"
770 " STORE RLOCAL.x, TEMP[0], IMM[1]\n"
771 " MFENCE RLOCAL\n"
772 " ENDIF\n"
773 " UMUL TEMP[1].x, SV[0], SV[1]\n"
774 " UMUL TEMP[1].x, TEMP[1], IMM[2]\n"
775 " UADD TEMP[1].x, TEMP[1], TEMP[0]\n"
776 " LOAD TEMP[0].x, RLOCAL, TEMP[0]\n"
777 " STORE RES[0].x, TEMP[1], TEMP[0]\n"
778 " RET\n"
779 " ENDSUB\n";
780 void init(void *p, int s, int x, int y) {
781 *(uint32_t *)p = 0xdeadbeef;
782 }
783 void expect(void *p, int s, int x, int y) {
784 *(uint32_t *)p = x & 0x20 ? 2 : 1;
785 }
786
787 printf("- %s\n", __func__);
788
789 init_prog(ctx, 256, 0, 0, src, NULL);
790 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
791 4096, 0, init);
792 init_compute_resources(ctx, (int []) { 0, -1 });
793 launch_grid(ctx, (uint []){64, 1, 1}, (uint []){16, 1, 1}, 0, NULL);
794 check_tex(ctx, 0, expect, NULL);
795 destroy_compute_resources(ctx);
796 destroy_tex(ctx);
797 destroy_prog(ctx);
798 }
799
800 static void test_sample(struct context *ctx)
801 {
802 const char *src = "COMP\n"
803 "DCL SVIEW[0], 2D, FLOAT\n"
804 "DCL RES[0], 2D, RAW, WR\n"
805 "DCL SAMP[0]\n"
806 "DCL SV[0], BLOCK_ID[0]\n"
807 "DCL TEMP[0], LOCAL\n"
808 "DCL TEMP[1], LOCAL\n"
809 "IMM UINT32 { 16, 1, 0, 0 }\n"
810 "IMM FLT32 { 128, 32, 0, 0 }\n"
811 "\n"
812 " BGNSUB\n"
813 " I2F TEMP[1], SV[0]\n"
814 " DIV TEMP[1], TEMP[1], IMM[1]\n"
815 " SAMPLE TEMP[1], TEMP[1], SVIEW[0], SAMP[0]\n"
816 " UMUL TEMP[0], SV[0], IMM[0]\n"
817 " STORE RES[0].xyzw, TEMP[0], TEMP[1]\n"
818 " RET\n"
819 " ENDSUB\n";
820 void init(void *p, int s, int x, int y) {
821 *(float *)p = s ? 1 : x * y;
822 }
823 void expect(void *p, int s, int x, int y) {
824 switch (x % 4) {
825 case 0:
826 *(float *)p = x / 4 * y;
827 break;
828 case 1:
829 case 2:
830 *(float *)p = 0;
831 break;
832 case 3:
833 *(float *)p = 1;
834 break;
835 }
836 }
837
838 printf("- %s\n", __func__);
839
840 init_prog(ctx, 0, 0, 0, src, NULL);
841 init_tex(ctx, 0, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
842 128, 32, init);
843 init_tex(ctx, 1, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
844 512, 32, init);
845 init_compute_resources(ctx, (int []) { 1, -1 });
846 init_sampler_views(ctx, (int []) { 0, -1 });
847 init_sampler_states(ctx, 2);
848 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){128, 32, 1}, 0, NULL);
849 check_tex(ctx, 1, expect, NULL);
850 destroy_sampler_states(ctx);
851 destroy_sampler_views(ctx);
852 destroy_compute_resources(ctx);
853 destroy_tex(ctx);
854 destroy_prog(ctx);
855 }
856
857 static void test_many_kern(struct context *ctx)
858 {
859 const char *src = "COMP\n"
860 "DCL RES[0], BUFFER, RAW, WR\n"
861 "DCL TEMP[0], LOCAL\n"
862 "IMM UINT32 { 0, 1, 2, 3 }\n"
863 "IMM UINT32 { 4, 0, 0, 0 }\n"
864 "\n"
865 " BGNSUB\n"
866 " UMUL TEMP[0].x, IMM[0].xxxx, IMM[1].xxxx\n"
867 " STORE RES[0].x, TEMP[0], IMM[0].xxxx\n"
868 " RET\n"
869 " ENDSUB\n"
870 " BGNSUB\n"
871 " UMUL TEMP[0].x, IMM[0].yyyy, IMM[1].xxxx\n"
872 " STORE RES[0].x, TEMP[0], IMM[0].yyyy\n"
873 " RET\n"
874 " ENDSUB\n"
875 " BGNSUB\n"
876 " UMUL TEMP[0].x, IMM[0].zzzz, IMM[1].xxxx\n"
877 " STORE RES[0].x, TEMP[0], IMM[0].zzzz\n"
878 " RET\n"
879 " ENDSUB\n"
880 " BGNSUB\n"
881 " UMUL TEMP[0].x, IMM[0].wwww, IMM[1].xxxx\n"
882 " STORE RES[0].x, TEMP[0], IMM[0].wwww\n"
883 " RET\n"
884 " ENDSUB\n";
885 void init(void *p, int s, int x, int y) {
886 *(uint32_t *)p = 0xdeadbeef;
887 }
888 void expect(void *p, int s, int x, int y) {
889 *(uint32_t *)p = x;
890 }
891
892 printf("- %s\n", __func__);
893
894 init_prog(ctx, 0, 0, 0, src, NULL);
895 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
896 16, 0, init);
897 init_compute_resources(ctx, (int []) { 0, -1 });
898 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){1, 1, 1}, 0, NULL);
899 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){1, 1, 1}, 5, NULL);
900 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){1, 1, 1}, 10, NULL);
901 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){1, 1, 1}, 15, NULL);
902 check_tex(ctx, 0, expect, NULL);
903 destroy_compute_resources(ctx);
904 destroy_tex(ctx);
905 destroy_prog(ctx);
906 }
907
908 static void test_constant(struct context *ctx)
909 {
910 const char *src = "COMP\n"
911 "DCL RES[0], BUFFER, RAW\n"
912 "DCL RES[1], BUFFER, RAW, WR\n"
913 "DCL SV[0], BLOCK_ID[0]\n"
914 "DCL TEMP[0], LOCAL\n"
915 "DCL TEMP[1], LOCAL\n"
916 "IMM UINT32 { 4, 0, 0, 0 }\n"
917 "\n"
918 " BGNSUB\n"
919 " UMUL TEMP[0].x, SV[0], IMM[0]\n"
920 " LOAD TEMP[1].x, RES[0], TEMP[0]\n"
921 " STORE RES[1].x, TEMP[0], TEMP[1]\n"
922 " RET\n"
923 " ENDSUB\n";
924 void init(void *p, int s, int x, int y) {
925 *(float *)p = s ? 0xdeadbeef : 8.0 - (float)x;
926 }
927 void expect(void *p, int s, int x, int y) {
928 *(float *)p = 8.0 - (float)x;
929 }
930
931 printf("- %s\n", __func__);
932
933 init_prog(ctx, 0, 0, 0, src, NULL);
934 init_tex(ctx, 0, PIPE_BUFFER, false, PIPE_FORMAT_R32_FLOAT,
935 256, 0, init);
936 init_tex(ctx, 1, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
937 256, 0, init);
938 init_compute_resources(ctx, (int []) { 0, 1, -1 });
939 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){64, 1, 1}, 0, NULL);
940 check_tex(ctx, 1, expect, NULL);
941 destroy_compute_resources(ctx);
942 destroy_tex(ctx);
943 destroy_prog(ctx);
944 }
945
946 static void test_resource_indirect(struct context *ctx)
947 {
948 const char *src = "COMP\n"
949 "DCL RES[0], BUFFER, RAW, WR\n"
950 "DCL RES[1..3], BUFFER, RAW\n"
951 "DCL SV[0], BLOCK_ID[0]\n"
952 "DCL TEMP[0], LOCAL\n"
953 "DCL TEMP[1], LOCAL\n"
954 "IMM UINT32 { 4, 0, 0, 0 }\n"
955 "\n"
956 " BGNSUB\n"
957 " UMUL TEMP[0].x, SV[0], IMM[0]\n"
958 " LOAD TEMP[1].x, RES[1], TEMP[0]\n"
959 " LOAD TEMP[1].x, RES[TEMP[1].x+2], TEMP[0]\n"
960 " STORE RES[0].x, TEMP[0], TEMP[1]\n"
961 " RET\n"
962 " ENDSUB\n";
963 void init(void *p, int s, int x, int y) {
964 *(uint32_t *)p = s == 0 ? 0xdeadbeef :
965 s == 1 ? x % 2 :
966 s == 2 ? 2 * x :
967 2 * x + 1;
968 }
969 void expect(void *p, int s, int x, int y) {
970 *(uint32_t *)p = 2 * x + (x % 2 ? 1 : 0);
971 }
972
973 printf("- %s\n", __func__);
974
975 init_prog(ctx, 0, 0, 0, src, NULL);
976 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
977 256, 0, init);
978 init_tex(ctx, 1, PIPE_BUFFER, false, PIPE_FORMAT_R32_FLOAT,
979 256, 0, init);
980 init_tex(ctx, 2, PIPE_BUFFER, false, PIPE_FORMAT_R32_FLOAT,
981 256, 0, init);
982 init_tex(ctx, 3, PIPE_BUFFER, false, PIPE_FORMAT_R32_FLOAT,
983 256, 0, init);
984 init_compute_resources(ctx, (int []) { 0, 1, 2, 3, -1 });
985 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){64, 1, 1}, 0, NULL);
986 check_tex(ctx, 0, expect, NULL);
987 destroy_compute_resources(ctx);
988 destroy_tex(ctx);
989 destroy_prog(ctx);
990 }
991
992 enum pipe_format surface_fmts[] = {
993 PIPE_FORMAT_B8G8R8A8_UNORM,
994 PIPE_FORMAT_B8G8R8X8_UNORM,
995 PIPE_FORMAT_A8R8G8B8_UNORM,
996 PIPE_FORMAT_X8R8G8B8_UNORM,
997 PIPE_FORMAT_X8R8G8B8_UNORM,
998 PIPE_FORMAT_L8_UNORM,
999 PIPE_FORMAT_A8_UNORM,
1000 PIPE_FORMAT_I8_UNORM,
1001 PIPE_FORMAT_L8A8_UNORM,
1002 PIPE_FORMAT_R32_FLOAT,
1003 PIPE_FORMAT_R32G32_FLOAT,
1004 PIPE_FORMAT_R32G32B32A32_FLOAT,
1005 PIPE_FORMAT_R32_UNORM,
1006 PIPE_FORMAT_R32G32_UNORM,
1007 PIPE_FORMAT_R32G32B32A32_UNORM,
1008 PIPE_FORMAT_R32_SNORM,
1009 PIPE_FORMAT_R32G32_SNORM,
1010 PIPE_FORMAT_R32G32B32A32_SNORM,
1011 PIPE_FORMAT_R8_UINT,
1012 PIPE_FORMAT_R8G8_UINT,
1013 PIPE_FORMAT_R8G8B8A8_UINT,
1014 PIPE_FORMAT_R8_SINT,
1015 PIPE_FORMAT_R8G8_SINT,
1016 PIPE_FORMAT_R8G8B8A8_SINT,
1017 PIPE_FORMAT_R32_UINT,
1018 PIPE_FORMAT_R32G32_UINT,
1019 PIPE_FORMAT_R32G32B32A32_UINT,
1020 PIPE_FORMAT_R32_SINT,
1021 PIPE_FORMAT_R32G32_SINT,
1022 PIPE_FORMAT_R32G32B32A32_SINT
1023 };
1024
1025 static void test_surface_ld(struct context *ctx)
1026 {
1027 const char *src = "COMP\n"
1028 "DCL RES[0], 2D\n"
1029 "DCL RES[1], 2D, RAW, WR\n"
1030 "DCL SV[0], BLOCK_ID[0]\n"
1031 "DCL TEMP[0], LOCAL\n"
1032 "DCL TEMP[1], LOCAL\n"
1033 "IMM UINT32 { 16, 1, 0, 0 }\n"
1034 "\n"
1035 " BGNSUB\n"
1036 " LOAD TEMP[1], RES[0], SV[0]\n"
1037 " UMUL TEMP[0], SV[0], IMM[0]\n"
1038 " STORE RES[1].xyzw, TEMP[0], TEMP[1]\n"
1039 " RET\n"
1040 " ENDSUB\n";
1041 int i = 0;
1042 void init0f(void *p, int s, int x, int y) {
1043 float v[] = { 1.0, -.75, .50, -.25 };
1044 util_format_write_4f(surface_fmts[i], v, 0,
1045 p, 0, 0, 0, 1, 1);
1046 }
1047 void init0i(void *p, int s, int x, int y) {
1048 int v[] = { 0xffffffff, 0xffff, 0xff, 0xf };
1049 util_format_write_4i(surface_fmts[i], v, 0,
1050 p, 0, 0, 0, 1, 1);
1051 }
1052 void init1(void *p, int s, int x, int y) {
1053 *(uint32_t *)p = 0xdeadbeef;
1054 }
1055 void expectf(void *p, int s, int x, int y) {
1056 float v[4], w[4];
1057 init0f(v, s, x / 4, y);
1058 util_format_read_4f(surface_fmts[i], w, 0,
1059 v, 0, 0, 0, 1, 1);
1060 *(float *)p = w[x % 4];
1061 }
1062 void expecti(void *p, int s, int x, int y) {
1063 int32_t v[4], w[4];
1064 init0i(v, s, x / 4, y);
1065 util_format_read_4i(surface_fmts[i], w, 0,
1066 v, 0, 0, 0, 1, 1);
1067 *(uint32_t *)p = w[x % 4];
1068 }
1069
1070 printf("- %s\n", __func__);
1071
1072 init_prog(ctx, 0, 0, 0, src, NULL);
1073
1074 for (i = 0; i < Elements(surface_fmts); i++) {
1075 bool is_int = util_format_is_pure_integer(surface_fmts[i]);
1076
1077 printf(" - %s\n", util_format_name(surface_fmts[i]));
1078
1079 if (!ctx->screen->is_format_supported(ctx->screen,
1080 surface_fmts[i], PIPE_TEXTURE_2D, 1,
1081 PIPE_BIND_COMPUTE_RESOURCE)) {
1082 printf("(unsupported)\n");
1083 continue;
1084 }
1085
1086 init_tex(ctx, 0, PIPE_TEXTURE_2D, true, surface_fmts[i],
1087 128, 32, (is_int ? init0i : init0f));
1088 init_tex(ctx, 1, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
1089 512, 32, init1);
1090 init_compute_resources(ctx, (int []) { 0, 1, -1 });
1091 init_sampler_states(ctx, 2);
1092 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){128, 32, 1}, 0,
1093 NULL);
1094 check_tex(ctx, 1, (is_int ? expecti : expectf), NULL);
1095 destroy_sampler_states(ctx);
1096 destroy_compute_resources(ctx);
1097 destroy_tex(ctx);
1098 }
1099
1100 destroy_prog(ctx);
1101 }
1102
1103 static void test_surface_st(struct context *ctx)
1104 {
1105 const char *src = "COMP\n"
1106 "DCL RES[0], 2D, RAW\n"
1107 "DCL RES[1], 2D, 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 " UMUL TEMP[0], SV[0], IMM[0]\n"
1115 " LOAD TEMP[1], RES[0], TEMP[0]\n"
1116 " STORE RES[1], SV[0], TEMP[1]\n"
1117 " RET\n"
1118 " ENDSUB\n";
1119 int i = 0;
1120 void init0f(void *p, int s, int x, int y) {
1121 float v[] = { 1.0, -.75, 0.5, -.25 };
1122 *(float *)p = v[x % 4];
1123 }
1124 void init0i(void *p, int s, int x, int y) {
1125 int v[] = { 0xffffffff, 0xffff, 0xff, 0xf };
1126 *(int32_t *)p = v[x % 4];
1127 }
1128 void init1(void *p, int s, int x, int y) {
1129 memset(p, 1, util_format_get_blocksize(surface_fmts[i]));
1130 }
1131 void expectf(void *p, int s, int x, int y) {
1132 float vf[4];
1133 int j;
1134
1135 for (j = 0; j < 4; j++)
1136 init0f(&vf[j], s, 4 * x + j, y);
1137 util_format_write_4f(surface_fmts[i], vf, 0,
1138 p, 0, 0, 0, 1, 1);
1139 }
1140 void expects(void *p, int s, int x, int y) {
1141 int32_t v[4];
1142 int j;
1143
1144 for (j = 0; j < 4; j++)
1145 init0i(&v[j], s, 4 * x + j, y);
1146 util_format_write_4i(surface_fmts[i], v, 0,
1147 p, 0, 0, 0, 1, 1);
1148 }
1149 void expectu(void *p, int s, int x, int y) {
1150 uint32_t v[4];
1151 int j;
1152
1153 for (j = 0; j < 4; j++)
1154 init0i(&v[j], s, 4 * x + j, y);
1155 util_format_write_4ui(surface_fmts[i], v, 0,
1156 p, 0, 0, 0, 1, 1);
1157 }
1158 bool check(void *x, void *y, int sz) {
1159 int j;
1160
1161 if (util_format_is_float(surface_fmts[i])) {
1162 return fabs(*(float *)x - *(float *)y) < 3.92156863e-3;
1163
1164 } else if ((sz % 4) == 0) {
1165 for (j = 0; j < sz / 4; j++)
1166 if (abs(((uint32_t *)x)[j] -
1167 ((uint32_t *)y)[j]) > 1)
1168 return false;
1169 return true;
1170 } else {
1171 return !memcmp(x, y, sz);
1172 }
1173 }
1174
1175 printf("- %s\n", __func__);
1176
1177 init_prog(ctx, 0, 0, 0, src, NULL);
1178
1179 for (i = 0; i < Elements(surface_fmts); i++) {
1180 bool is_signed = (util_format_description(surface_fmts[i])
1181 ->channel[0].type == UTIL_FORMAT_TYPE_SIGNED);
1182 bool is_int = util_format_is_pure_integer(surface_fmts[i]);
1183
1184 printf(" - %s\n", util_format_name(surface_fmts[i]));
1185
1186 if (!ctx->screen->is_format_supported(ctx->screen,
1187 surface_fmts[i], PIPE_TEXTURE_2D, 1,
1188 PIPE_BIND_COMPUTE_RESOURCE)) {
1189 printf("(unsupported)\n");
1190 continue;
1191 }
1192
1193 init_tex(ctx, 0, PIPE_TEXTURE_2D, true, PIPE_FORMAT_R32_FLOAT,
1194 512, 32, (is_int ? init0i : init0f));
1195 init_tex(ctx, 1, PIPE_TEXTURE_2D, true, surface_fmts[i],
1196 128, 32, init1);
1197 init_compute_resources(ctx, (int []) { 0, 1, -1 });
1198 init_sampler_states(ctx, 2);
1199 launch_grid(ctx, (uint []){1, 1, 1}, (uint []){128, 32, 1}, 0,
1200 NULL);
1201 check_tex(ctx, 1, (is_int && is_signed ? expects :
1202 is_int && !is_signed ? expectu :
1203 expectf), check);
1204 destroy_sampler_states(ctx);
1205 destroy_compute_resources(ctx);
1206 destroy_tex(ctx);
1207 }
1208
1209 destroy_prog(ctx);
1210 }
1211
1212 static void test_barrier(struct context *ctx)
1213 {
1214 const char *src = "COMP\n"
1215 "DCL RES[0], BUFFER, RAW, WR\n"
1216 "DCL SV[0], BLOCK_ID[0]\n"
1217 "DCL SV[1], BLOCK_SIZE[0]\n"
1218 "DCL SV[2], THREAD_ID[0]\n"
1219 "DCL TEMP[0], LOCAL\n"
1220 "DCL TEMP[1], LOCAL\n"
1221 "DCL TEMP[2], LOCAL\n"
1222 "DCL TEMP[3], LOCAL\n"
1223 "IMM UINT32 { 1, 0, 0, 0 }\n"
1224 "IMM UINT32 { 4, 0, 0, 0 }\n"
1225 "IMM UINT32 { 32, 0, 0, 0 }\n"
1226 "\n"
1227 " BGNSUB\n"
1228 " UMUL TEMP[0].x, SV[2], IMM[1]\n"
1229 " MOV TEMP[1].x, IMM[0].wwww\n"
1230 " BGNLOOP\n"
1231 " BARRIER\n"
1232 " STORE RLOCAL.x, TEMP[0], TEMP[1]\n"
1233 " BARRIER\n"
1234 " MOV TEMP[2].x, IMM[0].wwww\n"
1235 " BGNLOOP\n"
1236 " UMUL TEMP[3].x, TEMP[2], IMM[1]\n"
1237 " LOAD TEMP[3].x, RLOCAL, TEMP[3]\n"
1238 " USNE TEMP[3].x, TEMP[3], TEMP[1]\n"
1239 " IF TEMP[3]\n"
1240 " END\n"
1241 " ENDIF\n"
1242 " UADD TEMP[2].x, TEMP[2], IMM[0]\n"
1243 " USEQ TEMP[3].x, TEMP[2], SV[1]\n"
1244 " IF TEMP[3]\n"
1245 " BRK\n"
1246 " ENDIF\n"
1247 " ENDLOOP\n"
1248 " UADD TEMP[1].x, TEMP[1], IMM[0]\n"
1249 " USEQ TEMP[2].x, TEMP[1], IMM[2]\n"
1250 " IF TEMP[2]\n"
1251 " BRK\n"
1252 " ENDIF\n"
1253 " ENDLOOP\n"
1254 " UMUL TEMP[1].x, SV[0], SV[1]\n"
1255 " UMUL TEMP[1].x, TEMP[1], IMM[1]\n"
1256 " UADD TEMP[1].x, TEMP[1], TEMP[0]\n"
1257 " LOAD TEMP[0].x, RLOCAL, TEMP[0]\n"
1258 " STORE RES[0].x, TEMP[1], TEMP[0]\n"
1259 " RET\n"
1260 " ENDSUB\n";
1261 void init(void *p, int s, int x, int y) {
1262 *(uint32_t *)p = 0xdeadbeef;
1263 }
1264 void expect(void *p, int s, int x, int y) {
1265 *(uint32_t *)p = 31;
1266 }
1267
1268 printf("- %s\n", __func__);
1269
1270 init_prog(ctx, 256, 0, 0, src, NULL);
1271 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
1272 4096, 0, init);
1273 init_compute_resources(ctx, (int []) { 0, -1 });
1274 launch_grid(ctx, (uint []){64, 1, 1}, (uint []){16, 1, 1}, 0, NULL);
1275 check_tex(ctx, 0, expect, NULL);
1276 destroy_compute_resources(ctx);
1277 destroy_tex(ctx);
1278 destroy_prog(ctx);
1279 }
1280
1281 static void test_atom_ops(struct context *ctx, bool global)
1282 {
1283 const char *src = "COMP\n"
1284 "#ifdef TARGET_GLOBAL\n"
1285 "#define target RES[0]\n"
1286 "#else\n"
1287 "#define target RLOCAL\n"
1288 "#endif\n"
1289 ""
1290 "DCL RES[0], BUFFER, RAW, WR\n"
1291 "#define threadid SV[0]\n"
1292 "DCL threadid, THREAD_ID[0]\n"
1293 ""
1294 "#define offset TEMP[0]\n"
1295 "DCL offset, LOCAL\n"
1296 "#define tmp TEMP[1]\n"
1297 "DCL tmp, LOCAL\n"
1298 ""
1299 "#define k0 IMM[0]\n"
1300 "IMM UINT32 { 0, 0, 0, 0 }\n"
1301 "#define k1 IMM[1]\n"
1302 "IMM UINT32 { 1, 0, 0, 0 }\n"
1303 "#define k2 IMM[2]\n"
1304 "IMM UINT32 { 2, 0, 0, 0 }\n"
1305 "#define k3 IMM[3]\n"
1306 "IMM UINT32 { 3, 0, 0, 0 }\n"
1307 "#define k4 IMM[4]\n"
1308 "IMM UINT32 { 4, 0, 0, 0 }\n"
1309 "#define k5 IMM[5]\n"
1310 "IMM UINT32 { 5, 0, 0, 0 }\n"
1311 "#define k6 IMM[6]\n"
1312 "IMM UINT32 { 6, 0, 0, 0 }\n"
1313 "#define k7 IMM[7]\n"
1314 "IMM UINT32 { 7, 0, 0, 0 }\n"
1315 "#define k8 IMM[8]\n"
1316 "IMM UINT32 { 8, 0, 0, 0 }\n"
1317 "#define k9 IMM[9]\n"
1318 "IMM UINT32 { 9, 0, 0, 0 }\n"
1319 "#define korig IMM[10].xxxx\n"
1320 "#define karg IMM[10].yyyy\n"
1321 "IMM UINT32 { 3735928559, 286331153, 0, 0 }\n"
1322 "\n"
1323 " BGNSUB\n"
1324 " UMUL offset.x, threadid, k4\n"
1325 " STORE target.x, offset, korig\n"
1326 " USEQ tmp.x, threadid, k0\n"
1327 " IF tmp\n"
1328 " ATOMUADD tmp.x, target, offset, karg\n"
1329 " ATOMUADD tmp.x, target, offset, tmp\n"
1330 " ENDIF\n"
1331 " USEQ tmp.x, threadid, k1\n"
1332 " IF tmp\n"
1333 " ATOMXCHG tmp.x, target, offset, karg\n"
1334 " ATOMXCHG tmp.x, target, offset, tmp\n"
1335 " ENDIF\n"
1336 " USEQ tmp.x, threadid, k2\n"
1337 " IF tmp\n"
1338 " ATOMCAS tmp.x, target, offset, korig, karg\n"
1339 " ATOMCAS tmp.x, target, offset, tmp, k0\n"
1340 " ENDIF\n"
1341 " USEQ tmp.x, threadid, k3\n"
1342 " IF tmp\n"
1343 " ATOMAND tmp.x, target, offset, karg\n"
1344 " ATOMAND tmp.x, target, offset, tmp\n"
1345 " ENDIF\n"
1346 " USEQ tmp.x, threadid, k4\n"
1347 " IF tmp\n"
1348 " ATOMOR tmp.x, target, offset, karg\n"
1349 " ATOMOR tmp.x, target, offset, tmp\n"
1350 " ENDIF\n"
1351 " USEQ tmp.x, threadid, k5\n"
1352 " IF tmp\n"
1353 " ATOMXOR tmp.x, target, offset, karg\n"
1354 " ATOMXOR tmp.x, target, offset, tmp\n"
1355 " ENDIF\n"
1356 " USEQ tmp.x, threadid, k6\n"
1357 " IF tmp\n"
1358 " ATOMUMIN tmp.x, target, offset, karg\n"
1359 " ATOMUMIN tmp.x, target, offset, tmp\n"
1360 " ENDIF\n"
1361 " USEQ tmp.x, threadid, k7\n"
1362 " IF tmp\n"
1363 " ATOMUMAX tmp.x, target, offset, karg\n"
1364 " ATOMUMAX tmp.x, target, offset, tmp\n"
1365 " ENDIF\n"
1366 " USEQ tmp.x, threadid, k8\n"
1367 " IF tmp\n"
1368 " ATOMIMIN tmp.x, target, offset, karg\n"
1369 " ATOMIMIN tmp.x, target, offset, tmp\n"
1370 " ENDIF\n"
1371 " USEQ tmp.x, threadid, k9\n"
1372 " IF tmp\n"
1373 " ATOMIMAX tmp.x, target, offset, karg\n"
1374 " ATOMIMAX tmp.x, target, offset, tmp\n"
1375 " ENDIF\n"
1376 "#ifdef TARGET_LOCAL\n"
1377 " LOAD tmp.x, RLOCAL, offset\n"
1378 " STORE RES[0].x, offset, tmp\n"
1379 "#endif\n"
1380 " RET\n"
1381 " ENDSUB\n";
1382
1383 void init(void *p, int s, int x, int y) {
1384 *(uint32_t *)p = 0xbad;
1385 }
1386 void expect(void *p, int s, int x, int y) {
1387 switch (x) {
1388 case 0:
1389 *(uint32_t *)p = 0xce6c8eef;
1390 break;
1391 case 1:
1392 *(uint32_t *)p = 0xdeadbeef;
1393 break;
1394 case 2:
1395 *(uint32_t *)p = 0x11111111;
1396 break;
1397 case 3:
1398 *(uint32_t *)p = 0x10011001;
1399 break;
1400 case 4:
1401 *(uint32_t *)p = 0xdfbdbfff;
1402 break;
1403 case 5:
1404 *(uint32_t *)p = 0x11111111;
1405 break;
1406 case 6:
1407 *(uint32_t *)p = 0x11111111;
1408 break;
1409 case 7:
1410 *(uint32_t *)p = 0xdeadbeef;
1411 break;
1412 case 8:
1413 *(uint32_t *)p = 0xdeadbeef;
1414 break;
1415 case 9:
1416 *(uint32_t *)p = 0x11111111;
1417 break;
1418 }
1419 }
1420
1421 printf("- %s (%s)\n", __func__, global ? "global" : "local");
1422
1423 init_prog(ctx, 40, 0, 0, src,
1424 (global ? "-DTARGET_GLOBAL" : "-DTARGET_LOCAL"));
1425 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
1426 40, 0, init);
1427 init_compute_resources(ctx, (int []) { 0, -1 });
1428 launch_grid(ctx, (uint []){10, 1, 1}, (uint []){1, 1, 1}, 0, NULL);
1429 check_tex(ctx, 0, expect, NULL);
1430 destroy_compute_resources(ctx);
1431 destroy_tex(ctx);
1432 destroy_prog(ctx);
1433 }
1434
1435 static void test_atom_race(struct context *ctx, bool global)
1436 {
1437 const char *src = "COMP\n"
1438 "#ifdef TARGET_GLOBAL\n"
1439 "#define target RES[0]\n"
1440 "#else\n"
1441 "#define target RLOCAL\n"
1442 "#endif\n"
1443 ""
1444 "DCL RES[0], BUFFER, RAW, WR\n"
1445 ""
1446 "#define blockid SV[0]\n"
1447 "DCL blockid, BLOCK_ID[0]\n"
1448 "#define blocksz SV[1]\n"
1449 "DCL blocksz, BLOCK_SIZE[0]\n"
1450 "#define threadid SV[2]\n"
1451 "DCL threadid, THREAD_ID[0]\n"
1452 ""
1453 "#define offset TEMP[0]\n"
1454 "DCL offset, LOCAL\n"
1455 "#define arg TEMP[1]\n"
1456 "DCL arg, LOCAL\n"
1457 "#define count TEMP[2]\n"
1458 "DCL count, LOCAL\n"
1459 "#define vlocal TEMP[3]\n"
1460 "DCL vlocal, LOCAL\n"
1461 "#define vshared TEMP[4]\n"
1462 "DCL vshared, LOCAL\n"
1463 "#define last TEMP[5]\n"
1464 "DCL last, LOCAL\n"
1465 "#define tmp0 TEMP[6]\n"
1466 "DCL tmp0, LOCAL\n"
1467 "#define tmp1 TEMP[7]\n"
1468 "DCL tmp1, LOCAL\n"
1469 ""
1470 "#define k0 IMM[0]\n"
1471 "IMM UINT32 { 0, 0, 0, 0 }\n"
1472 "#define k1 IMM[1]\n"
1473 "IMM UINT32 { 1, 0, 0, 0 }\n"
1474 "#define k4 IMM[2]\n"
1475 "IMM UINT32 { 4, 0, 0, 0 }\n"
1476 "#define k32 IMM[3]\n"
1477 "IMM UINT32 { 32, 0, 0, 0 }\n"
1478 "#define k128 IMM[4]\n"
1479 "IMM UINT32 { 128, 0, 0, 0 }\n"
1480 "#define kdeadcafe IMM[5]\n"
1481 "IMM UINT32 { 3735931646, 0, 0, 0 }\n"
1482 "#define kallowed_set IMM[6]\n"
1483 "IMM UINT32 { 559035650, 0, 0, 0 }\n"
1484 "#define k11111111 IMM[7]\n"
1485 "IMM UINT32 { 286331153, 0, 0, 0 }\n"
1486 "\n"
1487 " BGNSUB\n"
1488 " MOV offset.x, threadid\n"
1489 "#ifdef TARGET_GLOBAL\n"
1490 " UMUL tmp0.x, blockid, blocksz\n"
1491 " UADD offset.x, offset, tmp0\n"
1492 "#endif\n"
1493 " UMUL offset.x, offset, k4\n"
1494 " USLT tmp0.x, threadid, k32\n"
1495 " STORE target.x, offset, k0\n"
1496 " BARRIER\n"
1497 " IF tmp0\n"
1498 " MOV vlocal.x, k0\n"
1499 " MOV arg.x, kdeadcafe\n"
1500 " BGNLOOP\n"
1501 " INEG arg.x, arg\n"
1502 " ATOMUADD vshared.x, target, offset, arg\n"
1503 " SFENCE target\n"
1504 " USNE tmp0.x, vshared, vlocal\n"
1505 " IF tmp0\n"
1506 " BRK\n"
1507 " ENDIF\n"
1508 " UADD vlocal.x, vlocal, arg\n"
1509 " ENDLOOP\n"
1510 " UADD vlocal.x, vshared, arg\n"
1511 " LOAD vshared.x, target, offset\n"
1512 " USEQ tmp0.x, vshared, vlocal\n"
1513 " STORE target.x, offset, tmp0\n"
1514 " ELSE\n"
1515 " UADD offset.x, offset, -k128\n"
1516 " MOV count.x, k0\n"
1517 " MOV last.x, k0\n"
1518 " BGNLOOP\n"
1519 " LOAD vshared.x, target, offset\n"
1520 " USEQ tmp0.x, vshared, kallowed_set.xxxx\n"
1521 " USEQ tmp1.x, vshared, kallowed_set.yyyy\n"
1522 " OR tmp0.x, tmp0, tmp1\n"
1523 " IF tmp0\n"
1524 " USEQ tmp0.x, vshared, last\n"
1525 " IF tmp0\n"
1526 " CONT\n"
1527 " ENDIF\n"
1528 " MOV last.x, vshared\n"
1529 " ELSE\n"
1530 " END\n"
1531 " ENDIF\n"
1532 " UADD count.x, count, k1\n"
1533 " USEQ tmp0.x, count, k128\n"
1534 " IF tmp0\n"
1535 " BRK\n"
1536 " ENDIF\n"
1537 " ENDLOOP\n"
1538 " ATOMXCHG tmp0.x, target, offset, k11111111\n"
1539 " UADD offset.x, offset, k128\n"
1540 " ATOMXCHG tmp0.x, target, offset, k11111111\n"
1541 " SFENCE target\n"
1542 " ENDIF\n"
1543 "#ifdef TARGET_LOCAL\n"
1544 " LOAD tmp0.x, RLOCAL, offset\n"
1545 " UMUL tmp1.x, blockid, blocksz\n"
1546 " UMUL tmp1.x, tmp1, k4\n"
1547 " UADD offset.x, offset, tmp1\n"
1548 " STORE RES[0].x, offset, tmp0\n"
1549 "#endif\n"
1550 " RET\n"
1551 " ENDSUB\n";
1552
1553 void init(void *p, int s, int x, int y) {
1554 *(uint32_t *)p = 0xdeadbeef;
1555 }
1556 void expect(void *p, int s, int x, int y) {
1557 *(uint32_t *)p = x & 0x20 ? 0x11111111 : 0xffffffff;
1558 }
1559
1560 printf("- %s (%s)\n", __func__, global ? "global" : "local");
1561
1562 init_prog(ctx, 256, 0, 0, src,
1563 (global ? "-DTARGET_GLOBAL" : "-DTARGET_LOCAL"));
1564 init_tex(ctx, 0, PIPE_BUFFER, true, PIPE_FORMAT_R32_FLOAT,
1565 4096, 0, init);
1566 init_compute_resources(ctx, (int []) { 0, -1 });
1567 launch_grid(ctx, (uint []){64, 1, 1}, (uint []){16, 1, 1}, 0, NULL);
1568 check_tex(ctx, 0, expect, NULL);
1569 destroy_compute_resources(ctx);
1570 destroy_tex(ctx);
1571 destroy_prog(ctx);
1572 }
1573
1574 int main(int argc, char *argv[])
1575 {
1576 struct context *ctx = CALLOC_STRUCT(context);
1577
1578 unsigned tests = (argc > 1) ? strtoul(argv[1], NULL, 0) : ~0;
1579
1580 init_ctx(ctx);
1581
1582 if (tests & (1 << 0))
1583 test_system_values(ctx);
1584 if (tests & (1 << 1))
1585 test_resource_access(ctx);
1586 if (tests & (1 << 2))
1587 test_function_calls(ctx);
1588 if (tests & (1 << 3))
1589 test_input_global(ctx);
1590 if (tests & (1 << 4))
1591 test_private(ctx);
1592 if (tests & (1 << 5))
1593 test_local(ctx);
1594 if (tests & (1 << 6))
1595 test_sample(ctx);
1596 if (tests & (1 << 7))
1597 test_many_kern(ctx);
1598 if (tests & (1 << 8))
1599 test_constant(ctx);
1600 if (tests & (1 << 9))
1601 test_resource_indirect(ctx);
1602 if (tests & (1 << 10))
1603 test_surface_ld(ctx);
1604 if (tests & (1 << 11))
1605 test_surface_st(ctx);
1606 if (tests & (1 << 12))
1607 test_barrier(ctx);
1608 if (tests & (1 << 13))
1609 test_atom_ops(ctx, true);
1610 if (tests & (1 << 14))
1611 test_atom_race(ctx, true);
1612 if (tests & (1 << 15))
1613 test_atom_ops(ctx, false);
1614 if (tests & (1 << 16))
1615 test_atom_race(ctx, false);
1616
1617 destroy_ctx(ctx);
1618
1619 return 0;
1620 }