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/format/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 compatible 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      uint32_t sdata[4];
266      util_format_read_4(params->format,
267                         sdata, 0,
268                         data_ptr, stride,
269                         s_coord, t_coord, 1, 1);
270      for (c = 0; c < 4; c++)
271         ((uint32_t *)rgba[c])[j] = sdata[c];
272   }
273   return;
274fail_write_all_zero:
275   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
276      for (c = 0; c < 4; c++)
277         rgba[c][j] = 0;
278   }
279   return;
280}
281
282/*
283 * Implement the image STORE operation.
284 */
285static void
286sp_tgsi_store(const struct tgsi_image *image,
287              const struct tgsi_image_params *params,
288              const int s[TGSI_QUAD_SIZE],
289              const int t[TGSI_QUAD_SIZE],
290              const int r[TGSI_QUAD_SIZE],
291              const int sample[TGSI_QUAD_SIZE],
292              float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
293{
294   struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
295   struct pipe_image_view *iview;
296   struct softpipe_resource *spr;
297   unsigned width, height, depth;
298   unsigned stride;
299   char *data_ptr;
300   int j, c;
301   unsigned offset = 0;
302   unsigned pformat = params->format;
303
304   if (params->unit >= PIPE_MAX_SHADER_IMAGES)
305      return;
306   iview = &sp_img->sp_iview[params->unit];
307   spr = (struct softpipe_resource *)iview->resource;
308   if (!spr)
309      return;
310   if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))
311      return;
312
313   if (params->format == PIPE_FORMAT_NONE)
314      pformat = spr->base.format;
315
316   if (!get_dimensions(iview, spr, params->tgsi_tex_instr,
317                       pformat, &width, &height, &depth))
318      return;
319
320   stride = util_format_get_stride(pformat, width);
321
322   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
323      int s_coord, t_coord, r_coord;
324
325      if (!(params->execmask & (1 << j)))
326         continue;
327
328      fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);
329      if (!bounds_check(width, height, depth,
330                        s_coord, t_coord, r_coord))
331         continue;
332
333      offset = get_image_offset(spr, iview, pformat, r_coord);
334      data_ptr = (char *)spr->data + offset;
335
336      uint32_t sdata[4];
337      for (c = 0; c < 4; c++)
338         sdata[c] = ((uint32_t *)rgba[c])[j];
339      util_format_write_4(pformat, sdata, 0, data_ptr, stride,
340                          s_coord, t_coord, 1, 1);
341   }
342}
343
344/*
345 * Implement atomic operations on unsigned integers.
346 */
347static void
348handle_op_uint(const struct pipe_image_view *iview,
349               const struct tgsi_image_params *params,
350               bool just_read,
351               char *data_ptr,
352               uint qi,
353               unsigned stride,
354               enum tgsi_opcode opcode,
355               int s,
356               int t,
357               float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
358               float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
359{
360   uint c;
361   int nc = util_format_get_nr_components(params->format);
362   unsigned sdata[4];
363
364   util_format_read_4(params->format,
365                      sdata, 0,
366                      data_ptr, stride,
367                      s, t, 1, 1);
368
369   if (just_read) {
370      for (c = 0; c < nc; c++) {
371         ((uint32_t *)rgba[c])[qi] = sdata[c];
372      }
373      return;
374   }
375   switch (opcode) {
376   case TGSI_OPCODE_ATOMUADD:
377      for (c = 0; c < nc; c++) {
378         unsigned temp = sdata[c];
379         sdata[c] += ((uint32_t *)rgba[c])[qi];
380         ((uint32_t *)rgba[c])[qi] = temp;
381      }
382      break;
383   case TGSI_OPCODE_ATOMXCHG:
384      for (c = 0; c < nc; c++) {
385         unsigned temp = sdata[c];
386         sdata[c] = ((uint32_t *)rgba[c])[qi];
387         ((uint32_t *)rgba[c])[qi] = temp;
388      }
389      break;
390   case TGSI_OPCODE_ATOMCAS:
391      for (c = 0; c < nc; c++) {
392         unsigned dst_x = sdata[c];
393         unsigned cmp_x = ((uint32_t *)rgba[c])[qi];
394         unsigned src_x = ((uint32_t *)rgba2[c])[qi];
395         unsigned temp = sdata[c];
396         sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;
397         ((uint32_t *)rgba[c])[qi] = temp;
398      }
399      break;
400   case TGSI_OPCODE_ATOMAND:
401      for (c = 0; c < nc; c++) {
402         unsigned temp = sdata[c];
403         sdata[c] &= ((uint32_t *)rgba[c])[qi];
404         ((uint32_t *)rgba[c])[qi] = temp;
405      }
406      break;
407   case TGSI_OPCODE_ATOMOR:
408      for (c = 0; c < nc; c++) {
409         unsigned temp = sdata[c];
410         sdata[c] |= ((uint32_t *)rgba[c])[qi];
411         ((uint32_t *)rgba[c])[qi] = temp;
412      }
413      break;
414   case TGSI_OPCODE_ATOMXOR:
415      for (c = 0; c < nc; c++) {
416         unsigned temp = sdata[c];
417         sdata[c] ^= ((uint32_t *)rgba[c])[qi];
418         ((uint32_t *)rgba[c])[qi] = temp;
419      }
420      break;
421   case TGSI_OPCODE_ATOMUMIN:
422      for (c = 0; c < nc; c++) {
423         unsigned dst_x = sdata[c];
424         unsigned src_x = ((uint32_t *)rgba[c])[qi];
425         sdata[c] = MIN2(dst_x, src_x);
426         ((uint32_t *)rgba[c])[qi] = dst_x;
427      }
428      break;
429   case TGSI_OPCODE_ATOMUMAX:
430      for (c = 0; c < nc; c++) {
431         unsigned dst_x = sdata[c];
432         unsigned src_x = ((uint32_t *)rgba[c])[qi];
433         sdata[c] = MAX2(dst_x, src_x);
434         ((uint32_t *)rgba[c])[qi] = dst_x;
435      }
436      break;
437   case TGSI_OPCODE_ATOMIMIN:
438      for (c = 0; c < nc; c++) {
439         int dst_x = sdata[c];
440         int src_x = ((uint32_t *)rgba[c])[qi];
441         sdata[c] = MIN2(dst_x, src_x);
442         ((uint32_t *)rgba[c])[qi] = dst_x;
443      }
444      break;
445   case TGSI_OPCODE_ATOMIMAX:
446      for (c = 0; c < nc; c++) {
447         int dst_x = sdata[c];
448         int src_x = ((uint32_t *)rgba[c])[qi];
449         sdata[c] = MAX2(dst_x, src_x);
450         ((uint32_t *)rgba[c])[qi] = dst_x;
451      }
452      break;
453   default:
454      assert(!"Unexpected TGSI opcode in sp_tgsi_op");
455      break;
456   }
457   util_format_write_4(params->format, sdata, 0, data_ptr, stride,
458                       s, t, 1, 1);
459}
460
461/*
462 * Implement atomic operations on signed integers.
463 */
464static void
465handle_op_int(const struct pipe_image_view *iview,
466              const struct tgsi_image_params *params,
467              bool just_read,
468              char *data_ptr,
469              uint qi,
470              unsigned stride,
471              enum tgsi_opcode opcode,
472              int s,
473              int t,
474              float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
475              float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
476{
477   uint c;
478   int nc = util_format_get_nr_components(params->format);
479   int sdata[4];
480   util_format_read_4(params->format,
481                      sdata, 0,
482                      data_ptr, stride,
483                      s, t, 1, 1);
484
485   if (just_read) {
486      for (c = 0; c < nc; c++) {
487         ((int32_t *)rgba[c])[qi] = sdata[c];
488      }
489      return;
490   }
491   switch (opcode) {
492   case TGSI_OPCODE_ATOMUADD:
493      for (c = 0; c < nc; c++) {
494         int temp = sdata[c];
495         sdata[c] += ((int32_t *)rgba[c])[qi];
496         ((int32_t *)rgba[c])[qi] = temp;
497      }
498      break;
499   case TGSI_OPCODE_ATOMXCHG:
500      for (c = 0; c < nc; c++) {
501         int temp = sdata[c];
502         sdata[c] = ((int32_t *)rgba[c])[qi];
503         ((int32_t *)rgba[c])[qi] = temp;
504      }
505      break;
506   case TGSI_OPCODE_ATOMCAS:
507      for (c = 0; c < nc; c++) {
508         int dst_x = sdata[c];
509         int cmp_x = ((int32_t *)rgba[c])[qi];
510         int src_x = ((int32_t *)rgba2[c])[qi];
511         int temp = sdata[c];
512         sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;
513         ((int32_t *)rgba[c])[qi] = temp;
514      }
515      break;
516   case TGSI_OPCODE_ATOMAND:
517      for (c = 0; c < nc; c++) {
518         int temp = sdata[c];
519         sdata[c] &= ((int32_t *)rgba[c])[qi];
520         ((int32_t *)rgba[c])[qi] = temp;
521      }
522      break;
523   case TGSI_OPCODE_ATOMOR:
524      for (c = 0; c < nc; c++) {
525         int temp = sdata[c];
526         sdata[c] |= ((int32_t *)rgba[c])[qi];
527         ((int32_t *)rgba[c])[qi] = temp;
528      }
529      break;
530   case TGSI_OPCODE_ATOMXOR:
531      for (c = 0; c < nc; c++) {
532         int temp = sdata[c];
533         sdata[c] ^= ((int32_t *)rgba[c])[qi];
534         ((int32_t *)rgba[c])[qi] = temp;
535      }
536      break;
537   case TGSI_OPCODE_ATOMUMIN:
538      for (c = 0; c < nc; c++) {
539         int dst_x = sdata[c];
540         int src_x = ((int32_t *)rgba[c])[qi];
541         sdata[c] = MIN2(dst_x, src_x);
542         ((int32_t *)rgba[c])[qi] = dst_x;
543      }
544      break;
545   case TGSI_OPCODE_ATOMUMAX:
546      for (c = 0; c < nc; c++) {
547         int dst_x = sdata[c];
548         int src_x = ((int32_t *)rgba[c])[qi];
549         sdata[c] = MAX2(dst_x, src_x);
550         ((int32_t *)rgba[c])[qi] = dst_x;
551      }
552      break;
553   case TGSI_OPCODE_ATOMIMIN:
554      for (c = 0; c < nc; c++) {
555         int dst_x = sdata[c];
556         int src_x = ((int32_t *)rgba[c])[qi];
557         sdata[c] = MIN2(dst_x, src_x);
558         ((int32_t *)rgba[c])[qi] = dst_x;
559      }
560      break;
561   case TGSI_OPCODE_ATOMIMAX:
562      for (c = 0; c < nc; c++) {
563         int dst_x = sdata[c];
564         int src_x = ((int32_t *)rgba[c])[qi];
565         sdata[c] = MAX2(dst_x, src_x);
566         ((int32_t *)rgba[c])[qi] = dst_x;
567      }
568      break;
569   default:
570      assert(!"Unexpected TGSI opcode in sp_tgsi_op");
571      break;
572   }
573   util_format_write_4(params->format, sdata, 0, data_ptr, stride,
574                       s, t, 1, 1);
575}
576
577/* GLES OES_shader_image_atomic.txt allows XCHG on R32F */
578static void
579handle_op_r32f_xchg(const struct pipe_image_view *iview,
580                    const struct tgsi_image_params *params,
581                    bool just_read,
582                    char *data_ptr,
583                    uint qi,
584                    unsigned stride,
585                    enum tgsi_opcode opcode,
586                    int s,
587                    int t,
588                    float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
589{
590   float sdata[4];
591   uint c;
592   int nc = 1;
593   util_format_read_4(params->format,
594                      sdata, 0,
595                      data_ptr, stride,
596                      s, t, 1, 1);
597   if (just_read) {
598      for (c = 0; c < nc; c++) {
599         ((int32_t *)rgba[c])[qi] = sdata[c];
600      }
601      return;
602   }
603
604   for (c = 0; c < nc; c++) {
605      int temp = sdata[c];
606      sdata[c] = ((float *)rgba[c])[qi];
607      ((float *)rgba[c])[qi] = temp;
608   }
609   util_format_write_4(params->format, sdata, 0, data_ptr, stride,
610                       s, t, 1, 1);
611}
612
613/*
614 * Implement atomic image operations.
615 */
616static void
617sp_tgsi_op(const struct tgsi_image *image,
618           const struct tgsi_image_params *params,
619           enum tgsi_opcode opcode,
620           const int s[TGSI_QUAD_SIZE],
621           const int t[TGSI_QUAD_SIZE],
622           const int r[TGSI_QUAD_SIZE],
623           const int sample[TGSI_QUAD_SIZE],
624           float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
625           float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
626{
627   struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
628   struct pipe_image_view *iview;
629   struct softpipe_resource *spr;
630   unsigned width, height, depth;
631   unsigned stride;
632   int j, c;
633   unsigned offset;
634   char *data_ptr;
635
636   if (params->unit >= PIPE_MAX_SHADER_IMAGES)
637      return;
638   iview = &sp_img->sp_iview[params->unit];
639   spr = (struct softpipe_resource *)iview->resource;
640   if (!spr)
641      goto fail_write_all_zero;
642   if (!has_compat_target(spr->base.target, params->tgsi_tex_instr))
643      goto fail_write_all_zero;
644
645   if (!get_dimensions(iview, spr, params->tgsi_tex_instr,
646                       params->format, &width, &height, &depth))
647      goto fail_write_all_zero;
648
649   stride = util_format_get_stride(spr->base.format, width);
650
651   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
652      int s_coord, t_coord, r_coord;
653      bool just_read = false;
654
655      fill_coords(params, j, s, t, r, &s_coord, &t_coord, &r_coord);
656      if (!bounds_check(width, height, depth,
657                        s_coord, t_coord, r_coord)) {
658         int nc = util_format_get_nr_components(params->format);
659         int ival = util_format_is_pure_integer(params->format);
660         int c;
661         for (c = 0; c < 4; c++) {
662            rgba[c][j] = 0;
663            if (c == 3 && nc < 4) {
664               if (ival)
665                  ((int32_t *)rgba[c])[j] = 1;
666               else
667                  rgba[c][j] = 1.0;
668            }
669         }
670         continue;
671      }
672
673      /* just readback the value for atomic if execmask isn't set */
674      if (!(params->execmask & (1 << j))) {
675         just_read = true;
676      }
677
678      offset = get_image_offset(spr, iview, params->format, r_coord);
679      data_ptr = (char *)spr->data + offset;
680
681      /* we should see atomic operations on r32 formats */
682      if (util_format_is_pure_uint(params->format))
683         handle_op_uint(iview, params, just_read, data_ptr, j, stride,
684                        opcode, s_coord, t_coord, rgba, rgba2);
685      else if (util_format_is_pure_sint(params->format))
686         handle_op_int(iview, params, just_read, data_ptr, j, stride,
687                       opcode, s_coord, t_coord, rgba, rgba2);
688      else if (params->format == PIPE_FORMAT_R32_FLOAT &&
689               opcode == TGSI_OPCODE_ATOMXCHG)
690         handle_op_r32f_xchg(iview, params, just_read, data_ptr, j, stride,
691                             opcode, s_coord, t_coord, rgba);
692      else
693         assert(0);
694   }
695   return;
696fail_write_all_zero:
697   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
698      for (c = 0; c < 4; c++)
699         rgba[c][j] = 0;
700   }
701   return;
702}
703
704static void
705sp_tgsi_get_dims(const struct tgsi_image *image,
706                 const struct tgsi_image_params *params,
707                 int dims[4])
708{
709   struct sp_tgsi_image *sp_img = (struct sp_tgsi_image *)image;
710   struct pipe_image_view *iview;
711   struct softpipe_resource *spr;
712   int level;
713
714   if (params->unit >= PIPE_MAX_SHADER_IMAGES)
715      return;
716   iview = &sp_img->sp_iview[params->unit];
717   spr = (struct softpipe_resource *)iview->resource;
718   if (!spr)
719      return;
720
721   if (params->tgsi_tex_instr == TGSI_TEXTURE_BUFFER) {
722      dims[0] = iview->u.buf.size / util_format_get_blocksize(iview->format);
723      dims[1] = dims[2] = dims[3] = 0;
724      return;
725   }
726
727   level = iview->u.tex.level;
728   dims[0] = u_minify(spr->base.width0, level);
729   switch (params->tgsi_tex_instr) {
730   case TGSI_TEXTURE_1D_ARRAY:
731      dims[1] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1;
732      FALLTHROUGH;
733   case TGSI_TEXTURE_1D:
734      return;
735   case TGSI_TEXTURE_2D_ARRAY:
736      dims[2] = iview->u.tex.last_layer - iview->u.tex.first_layer + 1;
737      FALLTHROUGH;
738   case TGSI_TEXTURE_2D:
739   case TGSI_TEXTURE_CUBE:
740   case TGSI_TEXTURE_RECT:
741      dims[1] = u_minify(spr->base.height0, level);
742      return;
743   case TGSI_TEXTURE_3D:
744      dims[1] = u_minify(spr->base.height0, level);
745      dims[2] = u_minify(spr->base.depth0, level);
746      return;
747   case TGSI_TEXTURE_CUBE_ARRAY:
748      dims[1] = u_minify(spr->base.height0, level);
749      dims[2] = (iview->u.tex.last_layer - iview->u.tex.first_layer + 1) / 6;
750      break;
751   default:
752      assert(!"unexpected texture target in sp_get_dims()");
753      return;
754   }
755}
756
757struct sp_tgsi_image *
758sp_create_tgsi_image(void)
759{
760   struct sp_tgsi_image *img = CALLOC_STRUCT(sp_tgsi_image);
761   if (!img)
762      return NULL;
763
764   img->base.load = sp_tgsi_load;
765   img->base.store = sp_tgsi_store;
766   img->base.op = sp_tgsi_op;
767   img->base.get_dims = sp_tgsi_get_dims;
768   return img;
769};
770