"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/softpipe/sp_buffer.c" (16 Sep 2020, 10889 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sp_buffer.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20.1.5_vs_20.2.0-rc1.

    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_buffer.h"
   26 #include "sp_texture.h"
   27 
   28 #include "util/format/u_format.h"
   29 
   30 static bool
   31 get_dimensions(const struct pipe_shader_buffer *bview,
   32                const struct softpipe_resource *spr,
   33                unsigned *width)
   34 {
   35    *width = bview->buffer_size;
   36    /*
   37     * Bounds check the buffer size from the view
   38     * and the buffer size from the underlying buffer.
   39     */
   40    if (*width > spr->base.width0)
   41       return false;
   42    return true;
   43 }
   44 
   45 /*
   46  * Implement the image LOAD operation.
   47  */
   48 static void
   49 sp_tgsi_load(const struct tgsi_buffer *buffer,
   50              const struct tgsi_buffer_params *params,
   51              const int s[TGSI_QUAD_SIZE],
   52              float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
   53 {
   54    struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
   55    struct pipe_shader_buffer *bview;
   56    struct softpipe_resource *spr;
   57    unsigned width;
   58    int c, j;
   59    unsigned char *data_ptr;
   60    const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
   61 
   62    if (params->unit >= PIPE_MAX_SHADER_BUFFERS)
   63       goto fail_write_all_zero;
   64 
   65    bview = &sp_buf->sp_bview[params->unit];
   66    spr = softpipe_resource(bview->buffer);
   67    if (!spr)
   68       goto fail_write_all_zero;
   69 
   70    if (!get_dimensions(bview, spr, &width))
   71       return;
   72 
   73    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
   74       int s_coord;
   75       bool fill_zero = false;
   76       uint32_t sdata[4];
   77 
   78       if (!(params->execmask & (1 << j)))
   79          fill_zero = true;
   80 
   81       s_coord = s[j];
   82       if (s_coord >= width)
   83          fill_zero = true;
   84 
   85       if (fill_zero) {
   86          for (c = 0; c < 4; c++)
   87             rgba[c][j] = 0;
   88          continue;
   89       }
   90       data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
   91       for (c = 0; c < 4; c++) {
   92          format_desc->fetch_rgba_uint(sdata, data_ptr, 0, 0);
   93          ((uint32_t *)rgba[c])[j] = sdata[0];
   94          data_ptr += 4;
   95       }
   96    }
   97    return;
   98 fail_write_all_zero:
   99    memset(rgba, 0, TGSI_NUM_CHANNELS * TGSI_QUAD_SIZE * 4);
  100    return;
  101 }
  102 
  103 /*
  104  * Implement the buffer STORE operation.
  105  */
  106 static void
  107 sp_tgsi_store(const struct tgsi_buffer *buffer,
  108               const struct tgsi_buffer_params *params,
  109               const int s[TGSI_QUAD_SIZE],
  110               float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  111 {
  112    struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
  113    struct pipe_shader_buffer *bview;
  114    struct softpipe_resource *spr;
  115    unsigned width;
  116    unsigned char *data_ptr;
  117    int j, c;
  118    const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
  119 
  120    if (params->unit >= PIPE_MAX_SHADER_BUFFERS)
  121       return;
  122 
  123    bview = &sp_buf->sp_bview[params->unit];
  124    spr = softpipe_resource(bview->buffer);
  125    if (!spr)
  126       return;
  127 
  128    if (!get_dimensions(bview, spr, &width))
  129       return;
  130 
  131    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  132       int s_coord;
  133 
  134       if (!(params->execmask & (1 << j)))
  135          continue;
  136 
  137       s_coord = s[j];
  138       if (s_coord >= width)
  139          continue;
  140 
  141       data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
  142 
  143       for (c = 0; c < 4; c++) {
  144          if (params->writemask & (1 << c)) {
  145             unsigned temp[4];
  146             unsigned char *dptr = data_ptr + (c * 4);
  147             temp[0] = ((uint32_t *)rgba[c])[j];
  148             format_desc->pack_rgba_uint(dptr, 0, temp, 0, 1, 1);
  149          }
  150       }
  151    }
  152 }
  153 
  154 /*
  155  * Implement atomic operations on unsigned integers.
  156  */
  157 static void
  158 handle_op_atomic(const struct pipe_shader_buffer *bview,
  159                  bool just_read,
  160                  unsigned char *data_ptr,
  161                  uint qi,
  162                  enum tgsi_opcode opcode,
  163                  unsigned writemask,
  164                  float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
  165                  float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  166 {
  167    uint c;
  168    const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
  169    unsigned sdata[4];
  170 
  171    for (c = 0; c < 4; c++) {
  172       unsigned temp[4];
  173       unsigned char *dptr = data_ptr + (c * 4);
  174       format_desc->fetch_rgba_uint(temp, dptr, 0, 0);
  175       sdata[c] = temp[0];
  176    }
  177 
  178    if (just_read) {
  179       for (c = 0; c < 4; c++) {
  180          ((uint32_t *)rgba[c])[qi] = sdata[c];
  181       }
  182       return;
  183    }
  184 
  185    switch (opcode) {
  186    case TGSI_OPCODE_ATOMUADD:
  187       for (c = 0; c < 4; c++) {
  188          unsigned temp = sdata[c];
  189          sdata[c] += ((uint32_t *)rgba[c])[qi];
  190          ((uint32_t *)rgba[c])[qi] = temp;
  191       }
  192       break;
  193    case TGSI_OPCODE_ATOMXCHG:
  194       for (c = 0; c < 4; c++) {
  195          unsigned temp = sdata[c];
  196          sdata[c] = ((uint32_t *)rgba[c])[qi];
  197          ((uint32_t *)rgba[c])[qi] = temp;
  198       }
  199       break;
  200    case TGSI_OPCODE_ATOMCAS:
  201       for (c = 0; c < 4; c++) {
  202          unsigned dst_x = sdata[c];
  203          unsigned cmp_x = ((uint32_t *)rgba[c])[qi];
  204          unsigned src_x = ((uint32_t *)rgba2[c])[qi];
  205          unsigned temp = sdata[c];
  206          sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;
  207          ((uint32_t *)rgba[c])[qi] = temp;
  208       }
  209       break;
  210    case TGSI_OPCODE_ATOMAND:
  211       for (c = 0; c < 4; c++) {
  212          unsigned temp = sdata[c];
  213          sdata[c] &= ((uint32_t *)rgba[c])[qi];
  214          ((uint32_t *)rgba[c])[qi] = temp;
  215       }
  216       break;
  217    case TGSI_OPCODE_ATOMOR:
  218       for (c = 0; c < 4; c++) {
  219          unsigned temp = sdata[c];
  220          sdata[c] |= ((uint32_t *)rgba[c])[qi];
  221          ((uint32_t *)rgba[c])[qi] = temp;
  222       }
  223       break;
  224    case TGSI_OPCODE_ATOMXOR:
  225       for (c = 0; c < 4; c++) {
  226          unsigned temp = sdata[c];
  227          sdata[c] ^= ((uint32_t *)rgba[c])[qi];
  228          ((uint32_t *)rgba[c])[qi] = temp;
  229       }
  230       break;
  231    case TGSI_OPCODE_ATOMUMIN:
  232       for (c = 0; c < 4; c++) {
  233          unsigned dst_x = sdata[c];
  234          unsigned src_x = ((uint32_t *)rgba[c])[qi];
  235          sdata[c] = MIN2(dst_x, src_x);
  236          ((uint32_t *)rgba[c])[qi] = dst_x;
  237       }
  238       break;
  239    case TGSI_OPCODE_ATOMUMAX:
  240       for (c = 0; c < 4; c++) {
  241          unsigned dst_x = sdata[c];
  242          unsigned src_x = ((uint32_t *)rgba[c])[qi];
  243          sdata[c] = MAX2(dst_x, src_x);
  244          ((uint32_t *)rgba[c])[qi] = dst_x;
  245       }
  246       break;
  247    case TGSI_OPCODE_ATOMIMIN:
  248       for (c = 0; c < 4; c++) {
  249          int dst_x = sdata[c];
  250          int src_x = ((uint32_t *)rgba[c])[qi];
  251          sdata[c] = MIN2(dst_x, src_x);
  252          ((uint32_t *)rgba[c])[qi] = dst_x;
  253       }
  254       break;
  255    case TGSI_OPCODE_ATOMIMAX:
  256       for (c = 0; c < 4; c++) {
  257          int dst_x = sdata[c];
  258          int src_x = ((uint32_t *)rgba[c])[qi];
  259          sdata[c] = MAX2(dst_x, src_x);
  260          ((uint32_t *)rgba[c])[qi] = dst_x;
  261       }
  262       break;
  263    case TGSI_OPCODE_ATOMFADD:
  264       for (c = 0; c < 4; c++) {
  265          float temp = uif(sdata[c]);
  266          sdata[c] = fui(temp + rgba[c][qi]);
  267          rgba[c][qi] = temp;
  268       }
  269       break;
  270    default:
  271       assert(!"Unexpected TGSI opcode in sp_tgsi_op");
  272       break;
  273    }
  274 
  275    for (c = 0; c < 4; c++) {
  276       if (writemask & (1 << c)) {
  277          unsigned temp[4];
  278          unsigned char *dptr = data_ptr + (c * 4);
  279          temp[0] = sdata[c];
  280          format_desc->pack_rgba_uint(dptr, 0, temp, 0, 1, 1);
  281       }
  282    }
  283 }
  284 
  285 /*
  286  * Implement atomic buffer operations.
  287  */
  288 static void
  289 sp_tgsi_op(const struct tgsi_buffer *buffer,
  290            const struct tgsi_buffer_params *params,
  291            enum tgsi_opcode opcode,
  292            const int s[TGSI_QUAD_SIZE],
  293            float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
  294            float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
  295 {
  296    struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
  297    struct pipe_shader_buffer *bview;
  298    struct softpipe_resource *spr;
  299    unsigned width;
  300    int j, c;
  301    unsigned char *data_ptr;
  302 
  303    if (params->unit >= PIPE_MAX_SHADER_BUFFERS)
  304       return;
  305 
  306    bview = &sp_buf->sp_bview[params->unit];
  307    spr = softpipe_resource(bview->buffer);
  308    if (!spr)
  309       goto fail_write_all_zero;
  310 
  311    if (!get_dimensions(bview, spr, &width))
  312       goto fail_write_all_zero;
  313 
  314    for (j = 0; j < TGSI_QUAD_SIZE; j++) {
  315       int s_coord;
  316       bool just_read = false;
  317 
  318       s_coord = s[j];
  319       if (s_coord >= width) {
  320          for (c = 0; c < 4; c++) {
  321             rgba[c][j] = 0;
  322          }
  323          continue;
  324       }
  325 
  326       /* just readback the value for atomic if execmask isn't set */
  327       if (!(params->execmask & (1 << j))) {
  328          just_read = true;
  329       }
  330 
  331       data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
  332       /* we should see atomic operations on r32 formats */
  333 
  334       handle_op_atomic(bview, just_read, data_ptr, j,
  335                        opcode, params->writemask, rgba, rgba2);
  336    }
  337    return;
  338 fail_write_all_zero:
  339    memset(rgba, 0, TGSI_NUM_CHANNELS * TGSI_QUAD_SIZE * 4);
  340    return;
  341 }
  342 
  343 /*
  344  * return size of the attached buffer for RESQ opcode.
  345  */
  346 static void
  347 sp_tgsi_get_dims(const struct tgsi_buffer *buffer,
  348                  const struct tgsi_buffer_params *params,
  349                  int *dim)
  350 {
  351    struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
  352    struct pipe_shader_buffer *bview;
  353    struct softpipe_resource *spr;
  354 
  355    if (params->unit >= PIPE_MAX_SHADER_BUFFERS)
  356       return;
  357 
  358    bview = &sp_buf->sp_bview[params->unit];
  359    spr = softpipe_resource(bview->buffer);
  360    if (!spr)
  361       return;
  362 
  363    *dim = bview->buffer_size;
  364 }
  365 
  366 struct sp_tgsi_buffer *
  367 sp_create_tgsi_buffer(void)
  368 {
  369    struct sp_tgsi_buffer *buf = CALLOC_STRUCT(sp_tgsi_buffer);
  370    if (!buf)
  371       return NULL;
  372 
  373    buf->base.load = sp_tgsi_load;
  374    buf->base.store = sp_tgsi_store;
  375    buf->base.op = sp_tgsi_op;
  376    buf->base.get_dims = sp_tgsi_get_dims;
  377    return buf;
  378 };