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 */
34static uint32_t
35get_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 */
56static inline bool
57has_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 */
70static inline bool
71has_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 */
81static inline bool
82bounds_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 */
98static inline bool
99has_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
146static bool
147get_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
186static void
187fill_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 */
202static void
203sp_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;
293fail_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 */
304static void
305sp_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 */
380static void
381handle_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               enum tgsi_opcode 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 */
497static void
498handle_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              enum tgsi_opcode 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 */
611static void
612handle_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                    enum tgsi_opcode 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 */
649static void
650sp_tgsi_op(const struct tgsi_image *image,
651           const struct tgsi_image_params *params,
652           enum tgsi_opcode 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;
729fail_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
737static void
738sp_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
790struct sp_tgsi_image *
791sp_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