2 * Copyright 2016 Red Hat.
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:
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
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.
24 #include "sp_context.h"
25 #include "sp_buffer.h"
26 #include "sp_texture.h"
28 #include "util/u_format.h"
31 get_dimensions(const struct pipe_shader_buffer
*bview
,
32 const struct softpipe_resource
*spr
,
35 *width
= bview
->buffer_size
;
37 * Bounds check the buffer size from the view
38 * and the buffer size from the underlying buffer.
40 if (*width
> spr
->base
.width0
)
46 * Implement the image LOAD operation.
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
])
54 struct sp_tgsi_buffer
*sp_buf
= (struct sp_tgsi_buffer
*)buffer
;
55 struct pipe_shader_buffer
*bview
;
56 struct softpipe_resource
*spr
;
59 unsigned char *data_ptr
;
60 const struct util_format_description
*format_desc
= util_format_description(PIPE_FORMAT_R32_UINT
);
62 if (params
->unit
>= PIPE_MAX_SHADER_BUFFERS
)
63 goto fail_write_all_zero
;
65 bview
= &sp_buf
->sp_bview
[params
->unit
];
66 spr
= softpipe_resource(bview
->buffer
);
68 goto fail_write_all_zero
;
70 if (!get_dimensions(bview
, spr
, &width
))
73 for (j
= 0; j
< TGSI_QUAD_SIZE
; j
++) {
75 bool fill_zero
= false;
78 if (!(params
->execmask
& (1 << j
)))
86 for (c
= 0; c
< 4; c
++)
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];
99 memset(rgba
, 0, TGSI_NUM_CHANNELS
* TGSI_QUAD_SIZE
* 4);
104 * Implement the buffer STORE operation.
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
])
112 struct sp_tgsi_buffer
*sp_buf
= (struct sp_tgsi_buffer
*)buffer
;
113 struct pipe_shader_buffer
*bview
;
114 struct softpipe_resource
*spr
;
116 unsigned char *data_ptr
;
118 const struct util_format_description
*format_desc
= util_format_description(PIPE_FORMAT_R32_UINT
);
120 if (params
->unit
>= PIPE_MAX_SHADER_BUFFERS
)
123 bview
= &sp_buf
->sp_bview
[params
->unit
];
124 spr
= softpipe_resource(bview
->buffer
);
128 if (!get_dimensions(bview
, spr
, &width
))
131 for (j
= 0; j
< TGSI_QUAD_SIZE
; j
++) {
134 if (!(params
->execmask
& (1 << j
)))
138 if (s_coord
>= width
)
141 data_ptr
= (unsigned char *)spr
->data
+ bview
->buffer_offset
+ s_coord
;
143 for (c
= 0; c
< 4; c
++) {
144 if (params
->writemask
& (1 << c
)) {
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);
155 * Implement atomic operations on unsigned integers.
158 handle_op_uint(const struct pipe_shader_buffer
*bview
,
160 unsigned char *data_ptr
,
162 enum tgsi_opcode opcode
,
164 float rgba
[TGSI_NUM_CHANNELS
][TGSI_QUAD_SIZE
],
165 float rgba2
[TGSI_NUM_CHANNELS
][TGSI_QUAD_SIZE
])
168 const struct util_format_description
*format_desc
= util_format_description(PIPE_FORMAT_R32_UINT
);
171 for (c
= 0; c
< 4; c
++) {
173 unsigned char *dptr
= data_ptr
+ (c
* 4);
174 format_desc
->fetch_rgba_uint(temp
, dptr
, 0, 0);
179 for (c
= 0; c
< 4; c
++) {
180 ((uint32_t *)rgba
[c
])[qi
] = sdata
[c
];
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
264 assert(!"Unexpected TGSI opcode in sp_tgsi_op");
268 for (c
= 0; c
< 4; c
++) {
269 if (writemask
& (1 << c
)) {
271 unsigned char *dptr
= data_ptr
+ (c
* 4);
273 format_desc
->pack_rgba_uint(dptr
, 0, temp
, 0, 1, 1);
279 * Implement atomic buffer operations.
282 sp_tgsi_op(const struct tgsi_buffer
*buffer
,
283 const struct tgsi_buffer_params
*params
,
284 enum tgsi_opcode opcode
,
285 const int s
[TGSI_QUAD_SIZE
],
286 float rgba
[TGSI_NUM_CHANNELS
][TGSI_QUAD_SIZE
],
287 float rgba2
[TGSI_NUM_CHANNELS
][TGSI_QUAD_SIZE
])
289 struct sp_tgsi_buffer
*sp_buf
= (struct sp_tgsi_buffer
*)buffer
;
290 struct pipe_shader_buffer
*bview
;
291 struct softpipe_resource
*spr
;
294 unsigned char *data_ptr
;
296 if (params
->unit
>= PIPE_MAX_SHADER_BUFFERS
)
299 bview
= &sp_buf
->sp_bview
[params
->unit
];
300 spr
= softpipe_resource(bview
->buffer
);
302 goto fail_write_all_zero
;
304 if (!get_dimensions(bview
, spr
, &width
))
305 goto fail_write_all_zero
;
307 for (j
= 0; j
< TGSI_QUAD_SIZE
; j
++) {
309 bool just_read
= false;
312 if (s_coord
>= width
) {
313 for (c
= 0; c
< 4; c
++) {
319 /* just readback the value for atomic if execmask isn't set */
320 if (!(params
->execmask
& (1 << j
))) {
324 data_ptr
= (unsigned char *)spr
->data
+ bview
->buffer_offset
+ s_coord
;
325 /* we should see atomic operations on r32 formats */
327 handle_op_uint(bview
, just_read
, data_ptr
, j
,
328 opcode
, params
->writemask
, rgba
, rgba2
);
332 memset(rgba
, 0, TGSI_NUM_CHANNELS
* TGSI_QUAD_SIZE
* 4);
337 * return size of the attached buffer for RESQ opcode.
340 sp_tgsi_get_dims(const struct tgsi_buffer
*buffer
,
341 const struct tgsi_buffer_params
*params
,
344 struct sp_tgsi_buffer
*sp_buf
= (struct sp_tgsi_buffer
*)buffer
;
345 struct pipe_shader_buffer
*bview
;
346 struct softpipe_resource
*spr
;
348 if (params
->unit
>= PIPE_MAX_SHADER_BUFFERS
)
351 bview
= &sp_buf
->sp_bview
[params
->unit
];
352 spr
= softpipe_resource(bview
->buffer
);
356 *dim
= bview
->buffer_size
;
359 struct sp_tgsi_buffer
*
360 sp_create_tgsi_buffer(void)
362 struct sp_tgsi_buffer
*buf
= CALLOC_STRUCT(sp_tgsi_buffer
);
366 buf
->base
.load
= sp_tgsi_load
;
367 buf
->base
.store
= sp_tgsi_store
;
368 buf
->base
.op
= sp_tgsi_op
;
369 buf
->base
.get_dims
= sp_tgsi_get_dims
;