Home | History | Annotate | Download | only in softpipe
      1 /*
      2  * Copyright 2016 Red Hat.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * the Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     21  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     22  */
     23 
     24 #include "sp_context.h"
     25 #include "sp_image.h"
     26 #include "sp_texture.h"
     27 
     28 #include "util/u_format.h"
     29 
     30 /*
     31  * Get the offset into the base image
     32  * first element for a buffer or layer/level for texture.
     33  */
     34 static uint32_t
     35 get_image_offset(const struct softpipe_resource *spr,
     36                  const struct pipe_image_view *iview,
     37                  enum pipe_format format, unsigned r_coord)
     38 {
     39    int base_layer = 0;
     40 
     41    if (spr->base.target == PIPE_BUFFER)
     42       return iview->u.buf.offset;
     43 
     44    if (spr->base.target == PIPE_TEXTURE_1D_ARRAY ||
     45        spr->base.target == PIPE_TEXTURE_2D_ARRAY ||
     46        spr->base.target == PIPE_TEXTURE_CUBE_ARRAY ||
     47        spr->base.target == PIPE_TEXTURE_CUBE ||
     48        spr->base.target == PIPE_TEXTURE_3D)
     49       base_layer = r_coord + iview->u.tex.first_layer;
     50    return softpipe_get_tex_image_offset(spr, iview->u.tex.level, base_layer);
     51 }
     52 
     53 /*
     54  * Does this texture instruction have a layer or depth parameter.
     55  */
     56 static inline bool
     57 has_layer_or_depth(unsigned tgsi_tex_instr)
     58 {
     59    return (tgsi_tex_instr == TGSI_TEXTURE_3D ||
     60            tgsi_tex_instr == TGSI_TEXTURE_CUBE ||
     61            tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY ||
     62            tgsi_tex_instr == TGSI_TEXTURE_2D_ARRAY ||
     63            tgsi_tex_instr == TGSI_TEXTURE_CUBE_ARRAY ||
     64            tgsi_tex_instr == TGSI_TEXTURE_2D_ARRAY_MSAA);
     65 }
     66 
     67 /*
     68  * Is this texture instruction a single non-array coordinate.
     69  */
     70 static inline bool
     71 has_1coord(unsigned tgsi_tex_instr)
     72 {
     73    return (tgsi_tex_instr == TGSI_TEXTURE_BUFFER ||
     74            tgsi_tex_instr == TGSI_TEXTURE_1D ||
     75            tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY);
     76 }
     77 
     78 /*
     79  * check the bounds vs w/h/d
     80  */
     81 static inline bool
     82 bounds_check(int width, int height, int depth,
     83              int s, int t, int r)
     84 {
     85    if (s < 0 || s >= width)
     86       return false;
     87    if (t < 0 || t >= height)
     88       return false;
     89    if (r < 0 || r >= depth)
     90       return false;
     91    return true;
     92 }
     93 
     94 /*
     95  * Checks if the texture target compatible with the image resource
     96  * pipe target.
     97  */
     98 static inline bool
     99 has_compat_target(unsigned pipe_target, unsigned tgsi_target)
    100 {
    101    switch (pipe_target) {
    102    case PIPE_TEXTURE_1D:
    103       if (tgsi_target == TGSI_TEXTURE_1D)
    104          return true;
    105       break;
    106    case PIPE_TEXTURE_2D:
    107       if (tgsi_target == TGSI_TEXTURE_2D)
    108          return true;
    109       break;
    110    case PIPE_TEXTURE_RECT:
    111       if (tgsi_target == TGSI_TEXTURE_RECT)
    112          return true;
    113       break;
    114    case PIPE_TEXTURE_3D:
    115       if (tgsi_target == TGSI_TEXTURE_3D ||
    116           tgsi_target == TGSI_TEXTURE_2D)
    117          return true;
    118       break;
    119    case PIPE_TEXTURE_CUBE:
    120       if (tgsi_target == TGSI_TEXTURE_CUBE ||
    121           tgsi_target == TGSI_TEXTURE_2D)
    122          return true;
    123       break;
    124    case PIPE_TEXTURE_1D_ARRAY:
    125       if (tgsi_target == TGSI_TEXTURE_1D ||
    126           tgsi_target == TGSI_TEXTURE_1D_ARRAY)
    127          return true;
    128       break;
    129    case PIPE_TEXTURE_2D_ARRAY:
    130       if (tgsi_target == TGSI_TEXTURE_2D ||
    131           tgsi_target == TGSI_TEXTURE_2D_ARRAY)
    132          return true;
    133       break;
    134    case PIPE_TEXTURE_CUBE_ARRAY:
    135       if (tgsi_target == TGSI_TEXTURE_CUBE ||
    136           tgsi_target == TGSI_TEXTURE_CUBE_ARRAY ||
    137           tgsi_target == TGSI_TEXTURE_2D)
    138          return true;
    139       break;
    140    case PIPE_BUFFER:
    141       return (tgsi_target == TGSI_TEXTURE_BUFFER);
    142    }
    143    return false;
    144 }
    145 
    146 static bool
    147 get_dimensions(const struct pipe_image_view *iview,
    148                const struct softpipe_resource *spr,
    149                unsigned tgsi_tex_instr,
    150                enum pipe_format pformat,
    151                unsigned *width,
    152                unsigned *height,
    153                unsigned *depth)
    154 {
    155    if (tgsi_tex_instr == TGSI_TEXTURE_BUFFER) {
    156       *width = iview->u.buf.size / util_format_get_blocksize(pformat);
    157       *height = 1;
    158       *depth = 1;
    159       /*
    160        * Bounds check the buffer size from the view
    161        * and the buffer size from the underlying buffer.
    162        */
    163       if (util_format_get_stride(pformat, *width) >
    164           util_format_get_stride(spr->base.format, spr->base.width0))
    165          return false;
    166    } else {
    167       unsigned level;
    168 
    169       level = spr->base.target == PIPE_BUFFER ? 0 : iview->u.tex.level;
    170       *width = u_minify(spr->base.width0, level);
    171       *height = u_minify(spr->base.height0, level);
    172 
    173       if (spr->base.target == PIPE_TEXTURE_3D)
    174          *depth = u_minify(spr->base.depth0, level);
    175       else
    176          *depth = spr->base.array_size;
    177 
    178       /* Make sure the resource and view have compatiable formats */
    179       if (util_format_get_blocksize(pformat) >
    180           util_format_get_blocksize(spr->base.format))
    181          return false;
    182    }
    183    return true;
    184 }
    185 
    186 static void
    187 fill_coords(const struct tgsi_image_params *params,
    188             unsigned index,
    189             const int s[TGSI_QUAD_SIZE],
    190             const int t[TGSI_QUAD_SIZE],
    191             const int r[TGSI_QUAD_SIZE],
    192             int *s_coord, int *t_coord, int *r_coord)
    193 {
    194    *s_coord = s[index];
    195    *t_coord = has_1coord(params->tgsi_tex_instr) ? 0 : t[index];
    196    *r_coord = has_layer_or_depth(params->tgsi_tex_instr) ?
    197       (params->tgsi_tex_instr == TGSI_TEXTURE_1D_ARRAY ? t[index] : r[index]) : 0;
    198 }
    199 /*
    200  * Implement the image LOAD operation.
    201  */
    202 static void
    203 sp_tgsi_load(const struct tgsi_image *image,
    204              const struct tgsi_image_params *params,
    205              const int s[TGSI_QUAD_SIZE],
    206              const int t[TGSI_QUAD_SIZE],
    207              const int r[TGSI_QUAD_SIZE],
    208              const int sample[TGSI_QUAD_SIZE],
    209              float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
    210 {
    211    struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
    212    struct pipe_image_view *iview;
    213    struct softpipe_resource *spr;
    214    unsigned width, height, depth;
    215    unsigned stride;
    216    int c, j;
    217    char *data_ptr;
    218    unsigned offset = 0;
    219 
    220    if (params->unit >= PIPE_MAX_SHADER_IMAGES)
    221       goto fail_write_all_zero;
    222    iview = &sp_img->sp_iview[params->unit];
    223    spr = (struct softpipe_resource *)iview->resource;
    224    if (!spr)
    225       goto fail_write_all_zero;
    226 
    227    if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))
    228       goto fail_write_all_zero;
    229 
    230    if (!get_dimensions(iview, spr, params->tgsi_tex_instr,
    231                        params->format, &width, &height, &depth))
    232       return;
    233 
    234    stride = util_format_get_stride(params->format, width);
    235 
    236    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
    237       int s_coord, t_coord, r_coord;
    238       bool fill_zero = false;
    239 
    240       if (!(params->execmask & (1 << j)))
    241          fill_zero = true;
    242 
    243       fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);
    244       if (!bounds_check(width, height, depth,
    245                         s_coord, t_coord, r_coord))
    246          fill_zero = true;
    247 
    248       if (fill_zero) {
    249          int nc = util_format_get_nr_components(params->format);
    250          int ival = util_format_is_pure_integer(params->format);
    251          for (c = 0; c < 4; c++) {
    252             rgba[c][j] = 0;
    253             if (c == 3 && nc < 4) {
    254                if (ival)
    255                   ((int32_t *)rgba[c])[j] = 1;
    256                else
    257                   rgba[c][j] = 1.0;
    258             }
    259          }
    260          continue;
    261       }
    262       offset = get_image_offset(spr, iview, params->format, r_coord);
    263       data_ptr = (char *)spr->data + offset;
    264 
    265       if (util_format_is_pure_sint(params->format)) {
    266          int32_t sdata[4];
    267 
    268          util_format_read_4i(params->format,
    269                              sdata, 0,
    270                              data_ptr, stride,
    271                              s_coord, t_coord, 1, 1);
    272          for (c = 0; c < 4; c++)
    273             ((int32_t *)rgba[c])[j] = sdata[c];
    274       } else if (util_format_is_pure_uint(params->format)) {
    275          uint32_t sdata[4];
    276          util_format_read_4ui(params->format,
    277                              sdata, 0,
    278                              data_ptr, stride,
    279                              s_coord, t_coord, 1, 1);
    280          for (c = 0; c < 4; c++)
    281             ((uint32_t *)rgba[c])[j] = sdata[c];
    282       } else {
    283          float sdata[4];
    284          util_format_read_4f(params->format,
    285                              sdata, 0,
    286                              data_ptr, stride,
    287                              s_coord, t_coord, 1, 1);
    288          for (c = 0; c < 4; c++)
    289             rgba[c][j] = sdata[c];
    290       }
    291    }
    292    return;
    293 fail_write_all_zero:
    294    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
    295       for (c = 0; c < 4; c++)
    296          rgba[c][j] = 0;
    297    }
    298    return;
    299 }
    300 
    301 /*
    302  * Implement the image STORE operation.
    303  */
    304 static void
    305 sp_tgsi_store(const struct tgsi_image *image,
    306               const struct tgsi_image_params *params,
    307               const int s[TGSI_QUAD_SIZE],
    308               const int t[TGSI_QUAD_SIZE],
    309               const int r[TGSI_QUAD_SIZE],
    310               const int sample[TGSI_QUAD_SIZE],
    311               float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
    312 {
    313    struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
    314    struct pipe_image_view *iview;
    315    struct softpipe_resource *spr;
    316    unsigned width, height, depth;
    317    unsigned stride;
    318    char *data_ptr;
    319    int j, c;
    320    unsigned offset = 0;
    321    unsigned pformat = params->format;
    322 
    323    if (params->unit >= PIPE_MAX_SHADER_IMAGES)
    324       return;
    325    iview = &sp_img->sp_iview[params->unit];
    326    spr = (struct softpipe_resource *)iview->resource;
    327    if (!spr)
    328       return;
    329    if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))
    330       return;
    331 
    332    if (params->format == PIPE_FORMAT_NONE)
    333       pformat = spr->base.format;
    334 
    335    if (!get_dimensions(iview, spr, params->tgsi_tex_instr,
    336                        pformat, &width, &height, &depth))
    337       return;
    338 
    339    stride = util_format_get_stride(pformat, width);
    340 
    341    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
    342       int s_coord, t_coord, r_coord;
    343 
    344       if (!(params->execmask & (1 << j)))
    345          continue;
    346 
    347       fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);
    348       if (!bounds_check(width, height, depth,
    349                         s_coord, t_coord, r_coord))
    350          continue;
    351 
    352       offset = get_image_offset(spr, iview, pformat, r_coord);
    353       data_ptr = (char *)spr->data + offset;
    354 
    355       if (util_format_is_pure_sint(pformat)) {
    356          int32_t sdata[4];
    357          for (c = 0; c < 4; c++)
    358             sdata[c] = ((int32_t *)rgba[c])[j];
    359          util_format_write_4i(pformat, sdata, 0, data_ptr, stride,
    360                               s_coord, t_coord, 1, 1);
    361       } else if (util_format_is_pure_uint(pformat)) {
    362          uint32_t sdata[4];
    363          for (c = 0; c < 4; c++)
    364             sdata[c] = ((uint32_t *)rgba[c])[j];
    365          util_format_write_4ui(pformat, sdata, 0, data_ptr, stride,
    366                                s_coord, t_coord, 1, 1);
    367       } else {
    368          float sdata[4];
    369          for (c = 0; c < 4; c++)
    370             sdata[c] = rgba[c][j];
    371          util_format_write_4f(pformat, sdata, 0, data_ptr, stride,
    372                               s_coord, t_coord, 1, 1);
    373       }
    374    }
    375 }
    376 
    377 /*
    378  * Implement atomic operations on unsigned integers.
    379  */
    380 static void
    381 handle_op_uint(const struct pipe_image_view *iview,
    382                const struct tgsi_image_params *params,
    383                bool just_read,
    384                char *data_ptr,
    385                uint qi,
    386                unsigned stride,
    387                unsigned opcode,
    388                int s,
    389                int t,
    390                float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
    391                float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
    392 {
    393    uint c;
    394    int nc = util_format_get_nr_components(params->format);
    395    unsigned sdata[4];
    396 
    397    util_format_read_4ui(params->format,
    398                         sdata, 0,
    399                         data_ptr, stride,
    400                         s, t, 1, 1);
    401 
    402    if (just_read) {
    403       for (c = 0; c < nc; c++) {
    404          ((uint32_t *)rgba[c])[qi] = sdata[c];
    405       }
    406       return;
    407    }
    408    switch (opcode) {
    409    case TGSI_OPCODE_ATOMUADD:
    410       for (c = 0; c < nc; c++) {
    411          unsigned temp = sdata[c];
    412          sdata[c] += ((uint32_t *)rgba[c])[qi];
    413          ((uint32_t *)rgba[c])[qi] = temp;
    414       }
    415       break;
    416    case TGSI_OPCODE_ATOMXCHG:
    417       for (c = 0; c < nc; c++) {
    418          unsigned temp = sdata[c];
    419          sdata[c] = ((uint32_t *)rgba[c])[qi];
    420          ((uint32_t *)rgba[c])[qi] = temp;
    421       }
    422       break;
    423    case TGSI_OPCODE_ATOMCAS:
    424       for (c = 0; c < nc; c++) {
    425          unsigned dst_x = sdata[c];
    426          unsigned cmp_x = ((uint32_t *)rgba[c])[qi];
    427          unsigned src_x = ((uint32_t *)rgba2[c])[qi];
    428          unsigned temp = sdata[c];
    429          sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;
    430          ((uint32_t *)rgba[c])[qi] = temp;
    431       }
    432       break;
    433    case TGSI_OPCODE_ATOMAND:
    434       for (c = 0; c < nc; c++) {
    435          unsigned temp = sdata[c];
    436          sdata[c] &= ((uint32_t *)rgba[c])[qi];
    437          ((uint32_t *)rgba[c])[qi] = temp;
    438       }
    439       break;
    440    case TGSI_OPCODE_ATOMOR:
    441       for (c = 0; c < nc; c++) {
    442          unsigned temp = sdata[c];
    443          sdata[c] |= ((uint32_t *)rgba[c])[qi];
    444          ((uint32_t *)rgba[c])[qi] = temp;
    445       }
    446       break;
    447    case TGSI_OPCODE_ATOMXOR:
    448       for (c = 0; c < nc; c++) {
    449          unsigned temp = sdata[c];
    450          sdata[c] ^= ((uint32_t *)rgba[c])[qi];
    451          ((uint32_t *)rgba[c])[qi] = temp;
    452       }
    453       break;
    454    case TGSI_OPCODE_ATOMUMIN:
    455       for (c = 0; c < nc; c++) {
    456          unsigned dst_x = sdata[c];
    457          unsigned src_x = ((uint32_t *)rgba[c])[qi];
    458          sdata[c] = MIN2(dst_x, src_x);
    459          ((uint32_t *)rgba[c])[qi] = dst_x;
    460       }
    461       break;
    462    case TGSI_OPCODE_ATOMUMAX:
    463       for (c = 0; c < nc; c++) {
    464          unsigned dst_x = sdata[c];
    465          unsigned src_x = ((uint32_t *)rgba[c])[qi];
    466          sdata[c] = MAX2(dst_x, src_x);
    467          ((uint32_t *)rgba[c])[qi] = dst_x;
    468       }
    469       break;
    470    case TGSI_OPCODE_ATOMIMIN:
    471       for (c = 0; c < nc; c++) {
    472          int dst_x = sdata[c];
    473          int src_x = ((uint32_t *)rgba[c])[qi];
    474          sdata[c] = MIN2(dst_x, src_x);
    475          ((uint32_t *)rgba[c])[qi] = dst_x;
    476       }
    477       break;
    478    case TGSI_OPCODE_ATOMIMAX:
    479       for (c = 0; c < nc; c++) {
    480          int dst_x = sdata[c];
    481          int src_x = ((uint32_t *)rgba[c])[qi];
    482          sdata[c] = MAX2(dst_x, src_x);
    483          ((uint32_t *)rgba[c])[qi] = dst_x;
    484       }
    485       break;
    486    default:
    487       assert(!"Unexpected TGSI opcode in sp_tgsi_op");
    488       break;
    489    }
    490    util_format_write_4ui(params->format, sdata, 0, data_ptr, stride,
    491                          s, t, 1, 1);
    492 }
    493 
    494 /*
    495  * Implement atomic operations on signed integers.
    496  */
    497 static void
    498 handle_op_int(const struct pipe_image_view *iview,
    499               const struct tgsi_image_params *params,
    500               bool just_read,
    501               char *data_ptr,
    502               uint qi,
    503               unsigned stride,
    504               unsigned opcode,
    505               int s,
    506               int t,
    507               float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
    508               float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
    509 {
    510    uint c;
    511    int nc = util_format_get_nr_components(params->format);
    512    int sdata[4];
    513    util_format_read_4i(params->format,
    514                        sdata, 0,
    515                        data_ptr, stride,
    516                        s, t, 1, 1);
    517 
    518    if (just_read) {
    519       for (c = 0; c < nc; c++) {
    520          ((int32_t *)rgba[c])[qi] = sdata[c];
    521       }
    522       return;
    523    }
    524    switch (opcode) {
    525    case TGSI_OPCODE_ATOMUADD:
    526       for (c = 0; c < nc; c++) {
    527          int temp = sdata[c];
    528          sdata[c] += ((int32_t *)rgba[c])[qi];
    529          ((int32_t *)rgba[c])[qi] = temp;
    530       }
    531       break;
    532    case TGSI_OPCODE_ATOMXCHG:
    533       for (c = 0; c < nc; c++) {
    534          int temp = sdata[c];
    535          sdata[c] = ((int32_t *)rgba[c])[qi];
    536          ((int32_t *)rgba[c])[qi] = temp;
    537       }
    538       break;
    539    case TGSI_OPCODE_ATOMCAS:
    540       for (c = 0; c < nc; c++) {
    541          int dst_x = sdata[c];
    542          int cmp_x = ((int32_t *)rgba[c])[qi];
    543          int src_x = ((int32_t *)rgba2[c])[qi];
    544          int temp = sdata[c];
    545          sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;
    546          ((int32_t *)rgba[c])[qi] = temp;
    547       }
    548       break;
    549    case TGSI_OPCODE_ATOMAND:
    550       for (c = 0; c < nc; c++) {
    551          int temp = sdata[c];
    552          sdata[c] &= ((int32_t *)rgba[c])[qi];
    553          ((int32_t *)rgba[c])[qi] = temp;
    554       }
    555       break;
    556    case TGSI_OPCODE_ATOMOR:
    557       for (c = 0; c < nc; c++) {
    558          int temp = sdata[c];
    559          sdata[c] |= ((int32_t *)rgba[c])[qi];
    560          ((int32_t *)rgba[c])[qi] = temp;
    561       }
    562       break;
    563    case TGSI_OPCODE_ATOMXOR:
    564       for (c = 0; c < nc; c++) {
    565          int temp = sdata[c];
    566          sdata[c] ^= ((int32_t *)rgba[c])[qi];
    567          ((int32_t *)rgba[c])[qi] = temp;
    568       }
    569       break;
    570    case TGSI_OPCODE_ATOMUMIN:
    571       for (c = 0; c < nc; c++) {
    572          int dst_x = sdata[c];
    573          int src_x = ((int32_t *)rgba[c])[qi];
    574          sdata[c] = MIN2(dst_x, src_x);
    575          ((int32_t *)rgba[c])[qi] = dst_x;
    576       }
    577       break;
    578    case TGSI_OPCODE_ATOMUMAX:
    579       for (c = 0; c < nc; c++) {
    580          int dst_x = sdata[c];
    581          int src_x = ((int32_t *)rgba[c])[qi];
    582          sdata[c] = MAX2(dst_x, src_x);
    583          ((int32_t *)rgba[c])[qi] = dst_x;
    584       }
    585       break;
    586    case TGSI_OPCODE_ATOMIMIN:
    587       for (c = 0; c < nc; c++) {
    588          int dst_x = sdata[c];
    589          int src_x = ((int32_t *)rgba[c])[qi];
    590          sdata[c] = MIN2(dst_x, src_x);
    591          ((int32_t *)rgba[c])[qi] = dst_x;
    592       }
    593       break;
    594    case TGSI_OPCODE_ATOMIMAX:
    595       for (c = 0; c < nc; c++) {
    596          int dst_x = sdata[c];
    597          int src_x = ((int32_t *)rgba[c])[qi];
    598          sdata[c] = MAX2(dst_x, src_x);
    599          ((int32_t *)rgba[c])[qi] = dst_x;
    600       }
    601       break;
    602    default:
    603       assert(!"Unexpected TGSI opcode in sp_tgsi_op");
    604       break;
    605    }
    606    util_format_write_4i(params->format, sdata, 0, data_ptr, stride,
    607                         s, t, 1, 1);
    608 }
    609 
    610 /* GLES OES_shader_image_atomic.txt allows XCHG on R32F */
    611 static void
    612 handle_op_r32f_xchg(const struct pipe_image_view *iview,
    613                     const struct tgsi_image_params *params,
    614                     bool just_read,
    615                     char *data_ptr,
    616                     uint qi,
    617                     unsigned stride,
    618                     unsigned opcode,
    619                     int s,
    620                     int t,
    621                     float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
    622 {
    623    float sdata[4];
    624    uint c;
    625    int nc = 1;
    626    util_format_read_4f(params->format,
    627                        sdata, 0,
    628                        data_ptr, stride,
    629                        s, t, 1, 1);
    630    if (just_read) {
    631       for (c = 0; c < nc; c++) {
    632          ((int32_t *)rgba[c])[qi] = sdata[c];
    633       }
    634       return;
    635    }
    636 
    637    for (c = 0; c < nc; c++) {
    638       int temp = sdata[c];
    639       sdata[c] = ((float *)rgba[c])[qi];
    640       ((float *)rgba[c])[qi] = temp;
    641    }
    642    util_format_write_4f(params->format, sdata, 0, data_ptr, stride,
    643                         s, t, 1, 1);
    644 }
    645 
    646 /*
    647  * Implement atomic image operations.
    648  */
    649 static void
    650 sp_tgsi_op(const struct tgsi_image *image,
    651            const struct tgsi_image_params *params,
    652            unsigned opcode,
    653            const int s[TGSI_QUAD_SIZE],
    654            const int t[TGSI_QUAD_SIZE],
    655            const int r[TGSI_QUAD_SIZE],
    656            const int sample[TGSI_QUAD_SIZE],
    657            float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
    658            float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
    659 {
    660    struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
    661    struct pipe_image_view *iview;
    662    struct softpipe_resource *spr;
    663    unsigned width, height, depth;
    664    unsigned stride;
    665    int j, c;
    666    unsigned offset;
    667    char *data_ptr;
    668 
    669    if (params->unit >= PIPE_MAX_SHADER_IMAGES)
    670       return;
    671    iview = &sp_img->sp_iview[params->unit];
    672    spr = (struct softpipe_resource *)iview->resource;
    673    if (!spr)
    674       goto fail_write_all_zero;
    675    if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))
    676       goto fail_write_all_zero;
    677 
    678    if (!get_dimensions(iview, spr, params->tgsi_tex_instr,
    679                        params->format, &width, &height, &depth))
    680       goto fail_write_all_zero;
    681 
    682    stride = util_format_get_stride(spr->base.format, width);
    683 
    684    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
    685       int s_coord, t_coord, r_coord;
    686       bool just_read = false;
    687 
    688       fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);
    689       if (!bounds_check(width, height, depth,
    690                         s_coord, t_coord, r_coord)) {
    691          int nc = util_format_get_nr_components(params->format);
    692          int ival = util_format_is_pure_integer(params->format);
    693          int c;
    694          for (c = 0; c < 4; c++) {
    695             rgba[c][j] = 0;
    696             if (c == 3 && nc < 4) {
    697                if (ival)
    698                   ((int32_t *)rgba[c])[j] = 1;
    699                else
    700                   rgba[c][j] = 1.0;
    701             }
    702          }
    703          continue;
    704       }
    705 
    706       /* just readback the value for atomic if execmask isn't set */
    707       if (!(params->execmask & (1 << j))) {
    708          just_read = true;
    709       }
    710 
    711       offset = get_image_offset(spr, iview, params->format, r_coord);
    712       data_ptr = (char *)spr->data + offset;
    713 
    714       /* we should see atomic operations on r32 formats */
    715       if (util_format_is_pure_uint(params->format))
    716          handle_op_uint(iview, params, just_read, data_ptr, j, stride,
    717                         opcode, s_coord, t_coord, rgba, rgba2);
    718       else if (util_format_is_pure_sint(params->format))
    719          handle_op_int(iview, params, just_read, data_ptr, j, stride,
    720                        opcode, s_coord, t_coord, rgba, rgba2);
    721       else if (params->format == PIPE_FORMAT_R32_FLOAT &&
    722                opcode == TGSI_OPCODE_ATOMXCHG)
    723          handle_op_r32f_xchg(iview, params, just_read, data_ptr, j, stride,
    724                              opcode, s_coord, t_coord, rgba);
    725       else
    726          assert(0);
    727    }
    728    return;
    729 fail_write_all_zero:
    730    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
    731       for (c = 0; c < 4; c++)
    732          rgba[c][j] = 0;
    733    }
    734    return;
    735 }
    736 
    737 static void
    738 sp_tgsi_get_dims(const struct tgsi_image *image,
    739                  const struct tgsi_image_params *params,
    740                  int dims[4])
    741 {
    742    struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
    743    struct pipe_image_view *iview;
    744    struct softpipe_resource *spr;
    745    int level;
    746 
    747    if (params->unit >= PIPE_MAX_SHADER_IMAGES)
    748       return;
    749    iview = &sp_img->sp_iview[params->unit];
    750    spr = (struct softpipe_resource *)iview->resource;
    751    if (!spr)
    752       return;
    753 
    754    if (params->tgsi_tex_instr == TGSI_TEXTURE_BUFFER) {
    755       dims[0] = iview->u.buf.size / util_format_get_blocksize(iview->format);
    756       dims[1] = dims[2] = dims[3] = 0;
    757       return;
    758    }
    759 
    760    level = iview->u.tex.level;
    761    dims[0] = u_minify(spr->base.width0, level);
    762    switch (params->tgsi_tex_instr) {
    763    case TGSI_TEXTURE_1D_ARRAY:
    764       dims[1] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1;
    765       /* fallthrough */
    766    case TGSI_TEXTURE_1D:
    767       return;
    768    case TGSI_TEXTURE_2D_ARRAY:
    769       dims[2] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1;
    770       /* fallthrough */
    771    case TGSI_TEXTURE_2D:
    772    case TGSI_TEXTURE_CUBE:
    773    case TGSI_TEXTURE_RECT:
    774       dims[1] = u_minify(spr->base.height0, level);
    775       return;
    776    case TGSI_TEXTURE_3D:
    777       dims[1] = u_minify(spr->base.height0, level);
    778       dims[2] = u_minify(spr->base.depth0, level);
    779       return;
    780    case TGSI_TEXTURE_CUBE_ARRAY:
    781       dims[1] = u_minify(spr->base.height0, level);
    782       dims[2] = (iview->u.tex.last_layer - iview->u.tex.first_layer + 1) / 6;
    783       break;
    784    default:
    785       assert(!"unexpected texture target in sp_get_dims()");
    786       return;
    787    }
    788 }
    789 
    790 struct sp_tgsi_image *
    791 sp_create_tgsi_image(void)
    792 {
    793    struct sp_tgsi_image *img = CALLOC_STRUCT(sp_tgsi_image);
    794    if (!img)
    795       return NULL;
    796 
    797    img->base.load = sp_tgsi_load;
    798    img->base.store = sp_tgsi_store;
    799    img->base.op = sp_tgsi_op;
    800    img->base.get_dims = sp_tgsi_get_dims;
    801    return img;
    802 };
    803