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
;
60 unsigned char *data_ptr
;
61 const struct util_format_description
*format_desc
= util_format_description(PIPE_FORMAT_R32_UINT
);
63 if (params
->unit
>= PIPE_MAX_SHADER_BUFFERS
)
64 goto fail_write_all_zero
;
66 bview
= &sp_buf
->sp_bview
[params
->unit
];
67 ncomp
= util_format_get_nr_components(bview
->buffer
->format
);
69 spr
= softpipe_resource(bview
->buffer
);
71 goto fail_write_all_zero
;
73 if (!get_dimensions(bview
, spr
, &width
))
76 for (j
= 0; j
< TGSI_QUAD_SIZE
; j
++) {
78 bool fill_zero
= false;
81 if (!(params
->execmask
& (1 << j
)))
89 for (c
= 0; c
< 4; c
++)
93 data_ptr
= (unsigned char *)spr
->data
+ bview
->buffer_offset
+ s_coord
;
94 for (c
= 0; c
< ncomp
; c
++) {
95 format_desc
->fetch_rgba_uint(sdata
, data_ptr
, 0, 0);
96 ((uint32_t *)rgba
[c
])[j
] = sdata
[0];
102 memset(rgba
, 0, TGSI_NUM_CHANNELS
* TGSI_QUAD_SIZE
* 4);
107 * Implement the buffer STORE operation.
110 sp_tgsi_store(const struct tgsi_buffer
*buffer
,
111 const struct tgsi_buffer_params
*params
,
112 const int s
[TGSI_QUAD_SIZE
],
113 float rgba
[TGSI_NUM_CHANNELS
][TGSI_QUAD_SIZE
])
115 struct sp_tgsi_buffer
*sp_buf
= (struct sp_tgsi_buffer
*)buffer
;
116 struct pipe_shader_buffer
*bview
;
117 struct softpipe_resource
*spr
;
119 unsigned char *data_ptr
;
121 const struct util_format_description
*format_desc
= util_format_description(PIPE_FORMAT_R32_UINT
);
123 if (params
->unit
>= PIPE_MAX_SHADER_BUFFERS
)
126 bview
= &sp_buf
->sp_bview
[params
->unit
];
127 spr
= softpipe_resource(bview
->buffer
);
131 if (!get_dimensions(bview
, spr
, &width
))
134 for (j
= 0; j
< TGSI_QUAD_SIZE
; j
++) {
137 if (!(params
->execmask
& (1 << j
)))
141 if (s_coord
>= width
)
144 data_ptr
= (unsigned char *)spr
->data
+ bview
->buffer_offset
+ s_coord
;
146 for (c
= 0; c
< 4; c
++) {
147 if (params
->writemask
& (1 << c
)) {
149 unsigned char *dptr
= data_ptr
+ (c
* 4);
150 temp
[0] = ((uint32_t *)rgba
[c
])[j
];
151 format_desc
->pack_rgba_uint(dptr
, 0, temp
, 0, 1, 1);
158 * Implement atomic operations on unsigned integers.
161 handle_op_atomic(const struct pipe_shader_buffer
*bview
,
163 unsigned char *data_ptr
,
165 enum tgsi_opcode opcode
,
167 float rgba
[TGSI_NUM_CHANNELS
][TGSI_QUAD_SIZE
],
168 float rgba2
[TGSI_NUM_CHANNELS
][TGSI_QUAD_SIZE
])
171 const struct util_format_description
*format_desc
= util_format_description(PIPE_FORMAT_R32_UINT
);
174 for (c
= 0; c
< 4; c
++) {
176 unsigned char *dptr
= data_ptr
+ (c
* 4);
177 format_desc
->fetch_rgba_uint(temp
, dptr
, 0, 0);
182 for (c
= 0; c
< 4; c
++) {
183 ((uint32_t *)rgba
[c
])[qi
] = sdata
[c
];
189 case TGSI_OPCODE_ATOMUADD
:
190 for (c
= 0; c
< 4; c
++) {
191 unsigned temp
= sdata
[c
];
192 sdata
[c
] += ((uint32_t *)rgba
[c
])[qi
];
193 ((uint32_t *)rgba
[c
])[qi
] = temp
;
196 case TGSI_OPCODE_ATOMXCHG
:
197 for (c
= 0; c
< 4; c
++) {
198 unsigned temp
= sdata
[c
];
199 sdata
[c
] = ((uint32_t *)rgba
[c
])[qi
];
200 ((uint32_t *)rgba
[c
])[qi
] = temp
;
203 case TGSI_OPCODE_ATOMCAS
:
204 for (c
= 0; c
< 4; c
++) {
205 unsigned dst_x
= sdata
[c
];
206 unsigned cmp_x
= ((uint32_t *)rgba
[c
])[qi
];
207 unsigned src_x
= ((uint32_t *)rgba2
[c
])[qi
];
208 unsigned temp
= sdata
[c
];
209 sdata
[c
] = (dst_x
== cmp_x
) ? src_x
: dst_x
;
210 ((uint32_t *)rgba
[c
])[qi
] = temp
;
213 case TGSI_OPCODE_ATOMAND
:
214 for (c
= 0; c
< 4; c
++) {
215 unsigned temp
= sdata
[c
];
216 sdata
[c
] &= ((uint32_t *)rgba
[c
])[qi
];
217 ((uint32_t *)rgba
[c
])[qi
] = temp
;
220 case TGSI_OPCODE_ATOMOR
:
221 for (c
= 0; c
< 4; c
++) {
222 unsigned temp
= sdata
[c
];
223 sdata
[c
] |= ((uint32_t *)rgba
[c
])[qi
];
224 ((uint32_t *)rgba
[c
])[qi
] = temp
;
227 case TGSI_OPCODE_ATOMXOR
:
228 for (c
= 0; c
< 4; c
++) {
229 unsigned temp
= sdata
[c
];
230 sdata
[c
] ^= ((uint32_t *)rgba
[c
])[qi
];
231 ((uint32_t *)rgba
[c
])[qi
] = temp
;
234 case TGSI_OPCODE_ATOMUMIN
:
235 for (c
= 0; c
< 4; c
++) {
236 unsigned dst_x
= sdata
[c
];
237 unsigned src_x
= ((uint32_t *)rgba
[c
])[qi
];
238 sdata
[c
] = MIN2(dst_x
, src_x
);
239 ((uint32_t *)rgba
[c
])[qi
] = dst_x
;
242 case TGSI_OPCODE_ATOMUMAX
:
243 for (c
= 0; c
< 4; c
++) {
244 unsigned dst_x
= sdata
[c
];
245 unsigned src_x
= ((uint32_t *)rgba
[c
])[qi
];
246 sdata
[c
] = MAX2(dst_x
, src_x
);
247 ((uint32_t *)rgba
[c
])[qi
] = dst_x
;
250 case TGSI_OPCODE_ATOMIMIN
:
251 for (c
= 0; c
< 4; c
++) {
252 int dst_x
= sdata
[c
];
253 int src_x
= ((uint32_t *)rgba
[c
])[qi
];
254 sdata
[c
] = MIN2(dst_x
, src_x
);
255 ((uint32_t *)rgba
[c
])[qi
] = dst_x
;
258 case TGSI_OPCODE_ATOMIMAX
:
259 for (c
= 0; c
< 4; c
++) {
260 int dst_x
= sdata
[c
];
261 int src_x
= ((uint32_t *)rgba
[c
])[qi
];
262 sdata
[c
] = MAX2(dst_x
, src_x
);
263 ((uint32_t *)rgba
[c
])[qi
] = dst_x
;
266 case TGSI_OPCODE_ATOMFADD
:
267 for (c
= 0; c
< 4; c
++) {
268 float temp
= uif(sdata
[c
]);
269 sdata
[c
] = fui(temp
+ rgba
[c
][qi
]);
274 assert(!"Unexpected TGSI opcode in sp_tgsi_op");
278 for (c
= 0; c
< 4; c
++) {
279 if (writemask
& (1 << c
)) {
281 unsigned char *dptr
= data_ptr
+ (c
* 4);
283 format_desc
->pack_rgba_uint(dptr
, 0, temp
, 0, 1, 1);
289 * Implement atomic buffer operations.
292 sp_tgsi_op(const struct tgsi_buffer
*buffer
,
293 const struct tgsi_buffer_params
*params
,
294 enum tgsi_opcode opcode
,
295 const int s
[TGSI_QUAD_SIZE
],
296 float rgba
[TGSI_NUM_CHANNELS
][TGSI_QUAD_SIZE
],
297 float rgba2
[TGSI_NUM_CHANNELS
][TGSI_QUAD_SIZE
])
299 struct sp_tgsi_buffer
*sp_buf
= (struct sp_tgsi_buffer
*)buffer
;
300 struct pipe_shader_buffer
*bview
;
301 struct softpipe_resource
*spr
;
304 unsigned char *data_ptr
;
306 if (params
->unit
>= PIPE_MAX_SHADER_BUFFERS
)
309 bview
= &sp_buf
->sp_bview
[params
->unit
];
310 spr
= softpipe_resource(bview
->buffer
);
312 goto fail_write_all_zero
;
314 if (!get_dimensions(bview
, spr
, &width
))
315 goto fail_write_all_zero
;
317 for (j
= 0; j
< TGSI_QUAD_SIZE
; j
++) {
319 bool just_read
= false;
322 if (s_coord
>= width
) {
323 for (c
= 0; c
< 4; c
++) {
329 /* just readback the value for atomic if execmask isn't set */
330 if (!(params
->execmask
& (1 << j
))) {
334 data_ptr
= (unsigned char *)spr
->data
+ bview
->buffer_offset
+ s_coord
;
335 /* we should see atomic operations on r32 formats */
337 handle_op_atomic(bview
, just_read
, data_ptr
, j
,
338 opcode
, params
->writemask
, rgba
, rgba2
);
342 memset(rgba
, 0, TGSI_NUM_CHANNELS
* TGSI_QUAD_SIZE
* 4);
347 * return size of the attached buffer for RESQ opcode.
350 sp_tgsi_get_dims(const struct tgsi_buffer
*buffer
,
351 const struct tgsi_buffer_params
*params
,
354 struct sp_tgsi_buffer
*sp_buf
= (struct sp_tgsi_buffer
*)buffer
;
355 struct pipe_shader_buffer
*bview
;
356 struct softpipe_resource
*spr
;
358 if (params
->unit
>= PIPE_MAX_SHADER_BUFFERS
)
361 bview
= &sp_buf
->sp_bview
[params
->unit
];
362 spr
= softpipe_resource(bview
->buffer
);
366 *dim
= bview
->buffer_size
;
369 struct sp_tgsi_buffer
*
370 sp_create_tgsi_buffer(void)
372 struct sp_tgsi_buffer
*buf
= CALLOC_STRUCT(sp_tgsi_buffer
);
376 buf
->base
.load
= sp_tgsi_load
;
377 buf
->base
.store
= sp_tgsi_store
;
378 buf
->base
.op
= sp_tgsi_op
;
379 buf
->base
.get_dims
= sp_tgsi_get_dims
;