1afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/*
2afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Copyright 2016 Red Hat.
3afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie *
4afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Permission is hereby granted, free of charge, to any person obtaining a
5afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * copy of this software and associated documentation files (the "Software"),
6afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * to deal in the Software without restriction, including without limitation
7afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * on the rights to use, copy, modify, merge, publish, distribute, sub
8afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * license, and/or sell copies of the Software, and to permit persons to whom
9afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * the Software is furnished to do so, subject to the following conditions:
10afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie *
11afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * The above copyright notice and this permission notice (including the next
12afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * paragraph) shall be included in all copies or substantial portions of the
13afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Software.
14afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie *
15afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * USE OR OTHER DEALINGS IN THE SOFTWARE.
22afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */
23afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
24afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie#include "sp_context.h"
25afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie#include "sp_buffer.h"
26afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie#include "sp_texture.h"
27afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
28afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie#include "util/u_format.h"
29afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
30afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic bool
31afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlieget_dimensions(const struct pipe_shader_buffer *bview,
32afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie               const struct softpipe_resource *spr,
33afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie               unsigned *width)
34afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{
35afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   *width = bview->buffer_size;
36afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   /*
37afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie    * Bounds check the buffer size from the view
38afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie    * and the buffer size from the underlying buffer.
39afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie    */
40afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   if (*width > spr->base.width0)
41afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      return false;
42afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   return true;
43afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie}
44afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
45afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/*
46afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Implement the image LOAD operation.
47afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */
48afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic void
49afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliesp_tgsi_load(const struct tgsi_buffer *buffer,
50afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie             const struct tgsi_buffer_params *params,
51afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie             const int s[TGSI_QUAD_SIZE],
52afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie             float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
53afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{
54afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
55afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct pipe_shader_buffer *bview;
56afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct softpipe_resource *spr;
57afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   unsigned width;
58afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   int c, j;
59afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   unsigned char *data_ptr;
60afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
61afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
626d6525a377250865cc6baa2c9cd5c6c0b6cd3f9cThomas Hindoe Paaboel Andersen   if (params->unit >= PIPE_MAX_SHADER_BUFFERS)
63afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      goto fail_write_all_zero;
64afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
65afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   bview = &sp_buf->sp_bview[params->unit];
66afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   spr = softpipe_resource(bview->buffer);
67afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   if (!spr)
68afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      goto fail_write_all_zero;
69afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
70afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   if (!get_dimensions(bview, spr, &width))
71afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      return;
72afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
73afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
74afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      int s_coord;
75afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      bool fill_zero = false;
76afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      uint32_t sdata[4];
77afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
78afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      if (!(params->execmask & (1 << j)))
79afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         fill_zero = true;
80afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
81afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      s_coord = s[j];
82afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      if (s_coord >= width)
83afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         fill_zero = true;
84afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
85afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      if (fill_zero) {
86afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         for (c = 0; c < 4; c++)
87afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie            rgba[c][j] = 0;
88afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         continue;
89afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
90afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
91afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
92afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         format_desc->fetch_rgba_uint(sdata, data_ptr, 0, 0);
93afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[j] = sdata[0];
94afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         data_ptr += 4;
95afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
96afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   }
97afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   return;
98afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliefail_write_all_zero:
99afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   memset(rgba, 0, TGSI_NUM_CHANNELS * TGSI_QUAD_SIZE * 4);
100afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   return;
101afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie}
102afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
103afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/*
104afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Implement the buffer STORE operation.
105afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */
106afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic void
107afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliesp_tgsi_store(const struct tgsi_buffer *buffer,
108afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie              const struct tgsi_buffer_params *params,
109afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie              const int s[TGSI_QUAD_SIZE],
110afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie              float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
111afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{
112afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
113afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct pipe_shader_buffer *bview;
114afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct softpipe_resource *spr;
115afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   unsigned width;
116afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   unsigned char *data_ptr;
117afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   int j, c;
118afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
119afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
1206d6525a377250865cc6baa2c9cd5c6c0b6cd3f9cThomas Hindoe Paaboel Andersen   if (params->unit >= PIPE_MAX_SHADER_BUFFERS)
121afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      return;
122afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
123afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   bview = &sp_buf->sp_bview[params->unit];
124afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   spr = softpipe_resource(bview->buffer);
125afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   if (!spr)
126afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      return;
127afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
128afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   if (!get_dimensions(bview, spr, &width))
129afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      return;
130afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
131afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
132afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      int s_coord;
133afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
134afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      if (!(params->execmask & (1 << j)))
135afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         continue;
136afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
137afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      s_coord = s[j];
138afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      if (s_coord >= width)
139afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         continue;
140afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
141afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
142afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
143afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
144afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         if (params->writemask & (1 << c)) {
145afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie            unsigned temp[4];
146afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie            unsigned char *dptr = data_ptr + (c * 4);
147afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie            temp[0] = ((uint32_t *)rgba[c])[j];
148afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie            format_desc->pack_rgba_uint(dptr, 0, temp, 0, 1, 1);
149afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         }
150afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
151afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   }
152afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie}
153afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
154afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/*
155afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Implement atomic operations on unsigned integers.
156afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */
157afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic void
158afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliehandle_op_uint(const struct pipe_shader_buffer *bview,
159afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie               bool just_read,
160afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie               unsigned char *data_ptr,
161afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie               uint qi,
162afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie               unsigned opcode,
163afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie               unsigned writemask,
164afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie               float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
165afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie               float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
166afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{
167afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   uint c;
168afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   const struct util_format_description *format_desc = util_format_description(PIPE_FORMAT_R32_UINT);
169afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   unsigned sdata[4];
170afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
171afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   for (c = 0; c < 4; c++) {
172afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      unsigned temp[4];
173afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      unsigned char *dptr = data_ptr + (c * 4);
174afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      format_desc->fetch_rgba_uint(temp, dptr, 0, 0);
175afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      sdata[c] = temp[0];
176afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   }
177afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
178afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   if (just_read) {
179afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
180afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = sdata[c];
181afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
182afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      return;
183afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   }
184afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
185afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   switch (opcode) {
186afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   case TGSI_OPCODE_ATOMUADD:
187afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
188afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned temp = sdata[c];
189afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         sdata[c] += ((uint32_t *)rgba[c])[qi];
190afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = temp;
191afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
192afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
193afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   case TGSI_OPCODE_ATOMXCHG:
194afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
195afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned temp = sdata[c];
196afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         sdata[c] = ((uint32_t *)rgba[c])[qi];
197afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = temp;
198afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
199afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
200afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   case TGSI_OPCODE_ATOMCAS:
201afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
202afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned dst_x = sdata[c];
203afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned cmp_x = ((uint32_t *)rgba[c])[qi];
204afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned src_x = ((uint32_t *)rgba2[c])[qi];
205afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned temp = sdata[c];
206afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         sdata[c] = (dst_x == cmp_x) ? src_x : dst_x;
207afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = temp;
208afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
209afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
210afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   case TGSI_OPCODE_ATOMAND:
211afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
212afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned temp = sdata[c];
213afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         sdata[c] &= ((uint32_t *)rgba[c])[qi];
214afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = temp;
215afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
216afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
217afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   case TGSI_OPCODE_ATOMOR:
218afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
219afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned temp = sdata[c];
220afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         sdata[c] |= ((uint32_t *)rgba[c])[qi];
221afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = temp;
222afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
223afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
224afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   case TGSI_OPCODE_ATOMXOR:
225afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
226afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned temp = sdata[c];
227afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         sdata[c] ^= ((uint32_t *)rgba[c])[qi];
228afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = temp;
229afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
230afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
231afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   case TGSI_OPCODE_ATOMUMIN:
232afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
233afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned dst_x = sdata[c];
234afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned src_x = ((uint32_t *)rgba[c])[qi];
235afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         sdata[c] = MIN2(dst_x, src_x);
236afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = dst_x;
237afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
238afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
239afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   case TGSI_OPCODE_ATOMUMAX:
240afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
241afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned dst_x = sdata[c];
242afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned src_x = ((uint32_t *)rgba[c])[qi];
243afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         sdata[c] = MAX2(dst_x, src_x);
244afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = dst_x;
245afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
246afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
247afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   case TGSI_OPCODE_ATOMIMIN:
248afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
249afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         int dst_x = sdata[c];
250afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         int src_x = ((uint32_t *)rgba[c])[qi];
251afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         sdata[c] = MIN2(dst_x, src_x);
252afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = dst_x;
253afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
254afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
255afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   case TGSI_OPCODE_ATOMIMAX:
256afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      for (c = 0; c < 4; c++) {
257afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         int dst_x = sdata[c];
258afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         int src_x = ((uint32_t *)rgba[c])[qi];
259afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         sdata[c] = MAX2(dst_x, src_x);
260afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         ((uint32_t *)rgba[c])[qi] = dst_x;
261afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
262afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
263afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   default:
264afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      assert(!"Unexpected TGSI opcode in sp_tgsi_op");
265afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      break;
266afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   }
267afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
268afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   for (c = 0; c < 4; c++) {
269afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      if (writemask & (1 << c)) {
270afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned temp[4];
271afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         unsigned char *dptr = data_ptr + (c * 4);
272afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         temp[0] = sdata[c];
273afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         format_desc->pack_rgba_uint(dptr, 0, temp, 0, 1, 1);
274afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
275afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   }
276afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie}
277afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
278afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/*
279afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * Implement atomic buffer operations.
280afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */
281afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic void
282afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliesp_tgsi_op(const struct tgsi_buffer *buffer,
283afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie           const struct tgsi_buffer_params *params,
284afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie           unsigned opcode,
285afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie           const int s[TGSI_QUAD_SIZE],
286afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie           float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
287afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie           float rgba2[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
288afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{
289afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
290afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct pipe_shader_buffer *bview;
291afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct softpipe_resource *spr;
292afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   unsigned width;
293afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   int j, c;
294afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   unsigned char *data_ptr;
295afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
2966d6525a377250865cc6baa2c9cd5c6c0b6cd3f9cThomas Hindoe Paaboel Andersen   if (params->unit >= PIPE_MAX_SHADER_BUFFERS)
297afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      return;
298afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
299afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   bview = &sp_buf->sp_bview[params->unit];
300afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   spr = softpipe_resource(bview->buffer);
301afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   if (!spr)
302afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      goto fail_write_all_zero;
303afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
304afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   if (!get_dimensions(bview, spr, &width))
305afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      goto fail_write_all_zero;
306afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
307afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   for (j = 0; j < TGSI_QUAD_SIZE; j++) {
308afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      int s_coord;
309afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      bool just_read = false;
310afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
311afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      s_coord = s[j];
312afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      if (s_coord >= width) {
313afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         for (c = 0; c < 4; c++) {
314afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie            rgba[c][j] = 0;
315afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         }
316afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         continue;
317afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
318afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
319afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      /* just readback the value for atomic if execmask isn't set */
320afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      if (!(params->execmask & (1 << j))) {
321afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie         just_read = true;
322afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      }
323afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
324afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      data_ptr = (unsigned char *)spr->data + bview->buffer_offset + s_coord;
325afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      /* we should see atomic operations on r32 formats */
326afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
327afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      handle_op_uint(bview, just_read, data_ptr, j,
328afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie                     opcode, params->writemask, rgba, rgba2);
329afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   }
330afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   return;
331afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliefail_write_all_zero:
332afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   memset(rgba, 0, TGSI_NUM_CHANNELS * TGSI_QUAD_SIZE * 4);
333afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   return;
334afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie}
335afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
336afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie/*
337afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie * return size of the attached buffer for RESQ opcode.
338afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie */
339afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestatic void
340afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliesp_tgsi_get_dims(const struct tgsi_buffer *buffer,
341afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie                 const struct tgsi_buffer_params *params,
342afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie                 int *dim)
343afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{
344afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct sp_tgsi_buffer *sp_buf = (struct sp_tgsi_buffer *)buffer;
345afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct pipe_shader_buffer *bview;
346afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct softpipe_resource *spr;
347afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
3486d6525a377250865cc6baa2c9cd5c6c0b6cd3f9cThomas Hindoe Paaboel Andersen   if (params->unit >= PIPE_MAX_SHADER_BUFFERS)
349afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      return;
350afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
351afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   bview = &sp_buf->sp_bview[params->unit];
352afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   spr = softpipe_resource(bview->buffer);
353afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   if (!spr)
354afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      return;
355afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
356afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   *dim = bview->buffer_size;
357afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie}
358afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
359afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliestruct sp_tgsi_buffer *
360afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airliesp_create_tgsi_buffer(void)
361afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie{
362afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   struct sp_tgsi_buffer *buf = CALLOC_STRUCT(sp_tgsi_buffer);
363afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   if (!buf)
364afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie      return NULL;
365afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie
366afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   buf->base.load = sp_tgsi_load;
367afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   buf->base.store = sp_tgsi_store;
368afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   buf->base.op = sp_tgsi_op;
369afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   buf->base.get_dims = sp_tgsi_get_dims;
370afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie   return buf;
371afa8707ba93a7d226a76319acda2a8dd89524db7Dave Airlie};
372