Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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. }
  1621.