1 /**********************************************************
2 * Copyright 2022 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26 #include "pipe/p_defines.h"
27 #include "util/u_bitmask.h"
28 #include "util/format/u_format.h"
29 #include "util/u_inlines.h"
30 #include "util/u_math.h"
31 #include "util/u_memory.h"
32 #include "tgsi/tgsi_parse.h"
33
34 #include "svga_context.h"
35 #include "svga_cmd.h"
36 #include "svga_debug.h"
37 #include "svga_resource_buffer.h"
38 #include "svga_resource_texture.h"
39 #include "svga_surface.h"
40 #include "svga_sampler_view.h"
41 #include "svga_format.h"
42
43
44 /**
45 * Create a uav object for the specified shader buffer
46 */
47 SVGA3dUAViewId
svga_create_uav_buffer(struct svga_context * svga,const struct pipe_shader_buffer * buf,SVGA3dSurfaceFormat format,SVGA3dUABufferFlags bufFlag)48 svga_create_uav_buffer(struct svga_context *svga,
49 const struct pipe_shader_buffer *buf,
50 SVGA3dSurfaceFormat format,
51 SVGA3dUABufferFlags bufFlag)
52 {
53 SVGA3dUAViewDesc desc;
54 unsigned uaViewId;
55
56 assert(buf);
57
58 /* If there is not one defined, create one. */
59 memset(&desc, 0, sizeof(desc));
60 desc.buffer.firstElement = buf->buffer_offset / sizeof(uint32);
61 desc.buffer.numElements = buf->buffer_size / sizeof(uint32);
62 desc.buffer.flags = bufFlag;
63
64 uaViewId = svga_create_uav(svga, &desc, format,
65 SVGA3D_RESOURCE_BUFFER,
66 svga_buffer_handle(svga, buf->buffer,
67 PIPE_BIND_SHADER_BUFFER));
68 if (uaViewId == SVGA3D_INVALID_ID)
69 return uaViewId;
70
71 SVGA_DBG(DEBUG_UAV, "%s: resource=0x%x uaViewId=%d\n",
72 __FUNCTION__, buf->buffer, uaViewId);
73
74 /* Mark this buffer as a uav bound buffer */
75 struct svga_buffer *sbuf = svga_buffer(buf->buffer);
76 sbuf->uav = TRUE;
77
78 return uaViewId;
79 }
80
81
82 /**
83 * Set shader buffers.
84 */
85 static void
svga_set_shader_buffers(struct pipe_context * pipe,enum pipe_shader_type shader,unsigned start,unsigned num,const struct pipe_shader_buffer * buffers,unsigned writeable_bitmask)86 svga_set_shader_buffers(struct pipe_context *pipe,
87 enum pipe_shader_type shader,
88 unsigned start, unsigned num,
89 const struct pipe_shader_buffer *buffers,
90 unsigned writeable_bitmask)
91 {
92 struct svga_context *svga = svga_context(pipe);
93 const struct pipe_shader_buffer *buf;
94
95 assert(svga_have_gl43(svga));
96
97 assert(start + num <= SVGA_MAX_SHADER_BUFFERS);
98
99 #ifdef DEBUG
100 const struct pipe_shader_buffer *b = buffers;
101 SVGA_DBG(DEBUG_UAV, "%s: shader=%d start=%d num=%d ",
102 __FUNCTION__, shader, start, num);
103 if (buffers) {
104 for (unsigned i = 0; i < num; i++, b++) {
105 SVGA_DBG(DEBUG_UAV, " 0x%x ", b);
106 }
107 }
108 SVGA_DBG(DEBUG_UAV, "\n");
109 #endif
110
111 buf = buffers;
112 if (buffers) {
113 int last_buffer = -1;
114 for (unsigned i = start; i < start + num; i++, buf++) {
115 struct svga_shader_buffer *cbuf = &svga->curr.shader_buffers[shader][i];
116
117 if (buf && buf->buffer) {
118 cbuf->desc = *buf;
119 pipe_resource_reference(&cbuf->resource, buf->buffer);
120
121 /* Mark the last bound shader buffer */
122 last_buffer = i;
123 }
124 else {
125 cbuf->desc.buffer = NULL;
126 pipe_resource_reference(&cbuf->resource, NULL);
127 }
128 cbuf->uav_index = -1;
129 }
130 svga->curr.num_shader_buffers[shader] =
131 MAX2(svga->curr.num_shader_buffers[shader], last_buffer + 1);
132 }
133 else {
134 for (unsigned i = start; i < start + num; i++) {
135 struct svga_shader_buffer *cbuf = &svga->curr.shader_buffers[shader][i];
136 cbuf->desc.buffer = NULL;
137 cbuf->uav_index = -1;
138 pipe_resource_reference(&cbuf->resource, NULL);
139 }
140 if ((start + num) >= svga->curr.num_shader_buffers[shader])
141 svga->curr.num_shader_buffers[shader] = start;
142 }
143
144 #ifdef DEBUG
145 SVGA_DBG(DEBUG_UAV,
146 "%s: current num_shader_buffers=%d start=%d num=%d buffers=",
147 __FUNCTION__, svga->curr.num_shader_buffers[shader],
148 start, num);
149
150 for (unsigned i = start; i < start + num; i++) {
151 struct svga_shader_buffer *cbuf = &svga->curr.shader_buffers[shader][i];
152 SVGA_DBG(DEBUG_UAV, " 0x%x ", cbuf->desc.buffer);
153 }
154
155 SVGA_DBG(DEBUG_UAV, "\n");
156 #endif
157
158 /* purge any unused uav objects */
159 svga_destroy_uav(svga);
160
161 svga->dirty |= SVGA_NEW_SHADER_BUFFER;
162 }
163
164
165 /**
166 * Set HW atomic buffers.
167 */
168 static void
svga_set_hw_atomic_buffers(struct pipe_context * pipe,unsigned start,unsigned num,const struct pipe_shader_buffer * buffers)169 svga_set_hw_atomic_buffers(struct pipe_context *pipe,
170 unsigned start, unsigned num,
171 const struct pipe_shader_buffer *buffers)
172 {
173 struct svga_context *svga = svga_context(pipe);
174 const struct pipe_shader_buffer *buf = buffers;
175
176 assert(svga_have_gl43(svga));
177
178 assert(start + num <= SVGA_MAX_ATOMIC_BUFFERS);
179
180 #ifdef DEBUG
181 SVGA_DBG(DEBUG_UAV, "%s: start=%d num=%d \n", __FUNCTION__, start, num);
182 #endif
183
184 buf = buffers;
185 if (buffers) {
186 int last_buffer = -1;
187 for (unsigned i = start; i < start + num; i++, buf++) {
188 struct svga_shader_buffer *cbuf = &svga->curr.atomic_buffers[i];
189
190 if (buf && buf->buffer) {
191 cbuf->desc = *buf;
192 pipe_resource_reference(&cbuf->resource, buf->buffer);
193
194 last_buffer = i;
195
196 /* Mark the buffer as uav buffer so that a readback will
197 * be done at each read transfer. We can't rely on the
198 * dirty bit because it is reset after each read, but
199 * the uav buffer can be updated at each draw.
200 */
201 struct svga_buffer *sbuf = svga_buffer(cbuf->desc.buffer);
202 sbuf->uav = TRUE;
203 }
204 else {
205 cbuf->desc.buffer = NULL;
206 pipe_resource_reference(&cbuf->resource, NULL);
207 }
208 cbuf->uav_index = -1;
209 }
210 svga->curr.num_atomic_buffers = MAX2(svga->curr.num_atomic_buffers,
211 last_buffer + 1);
212 }
213 else {
214 for (unsigned i = start; i < start + num; i++) {
215 struct svga_shader_buffer *cbuf = &svga->curr.atomic_buffers[i];
216 cbuf->desc.buffer = NULL;
217 cbuf->uav_index = -1;
218 pipe_resource_reference(&cbuf->resource, NULL);
219 }
220 if ((start + num) >= svga->curr.num_atomic_buffers)
221 svga->curr.num_atomic_buffers = start;
222 }
223
224 #ifdef DEBUG
225 SVGA_DBG(DEBUG_UAV, "%s: current num_atomic_buffers=%d start=%d num=%d ",
226 __FUNCTION__, svga->curr.num_atomic_buffers,
227 start, num);
228
229 for (unsigned i = start; i < start + num; i++) {
230 struct svga_shader_buffer *cbuf = &svga->curr.atomic_buffers[i];
231 SVGA_DBG(DEBUG_UAV, " 0x%x ", cbuf->desc.buffer);
232 }
233
234 SVGA_DBG(DEBUG_UAV, "\n");
235 #endif
236
237 /* purge any unused uav objects */
238 svga_destroy_uav(svga);
239
240 svga->dirty |= SVGA_NEW_SHADER_BUFFER;
241 }
242
243
244 /**
245 * Initialize shader images gallium interface
246 */
247 void
svga_init_shader_buffer_functions(struct svga_context * svga)248 svga_init_shader_buffer_functions(struct svga_context *svga)
249 {
250 if (!svga_have_gl43(svga))
251 return;
252
253 svga->pipe.set_shader_buffers = svga_set_shader_buffers;
254 svga->pipe.set_hw_atomic_buffers = svga_set_hw_atomic_buffers;
255
256 /* Initialize shader buffers */
257 for (unsigned shader = 0; shader < PIPE_SHADER_TYPES; ++shader) {
258 struct svga_shader_buffer *hw_buf =
259 &svga->state.hw_draw.shader_buffers[shader][0];
260 struct svga_shader_buffer *cur_buf =
261 &svga->curr.shader_buffers[shader][0];
262
263 /* Initialize uaViewId to SVGA3D_INVALID_ID for current shader buffers
264 * and shader buffers in hw state to avoid unintentional unbinding of
265 * shader buffers with uaViewId 0.
266 */
267 for (unsigned i = 0; i < ARRAY_SIZE(svga->curr.shader_buffers[shader]);
268 i++, hw_buf++, cur_buf++) {
269 hw_buf->resource = NULL;
270 hw_buf->uav_index = -1;
271 cur_buf->desc.buffer = NULL;
272 cur_buf->resource = NULL;
273 cur_buf->uav_index = -1;
274 }
275 }
276 memset(svga->state.hw_draw.num_shader_buffers, 0,
277 sizeof(svga->state.hw_draw.num_shader_buffers));
278
279 /* Initialize atomic buffers */
280
281 /* Initialize uaViewId to SVGA3D_INVALID_ID for current atomic buffers
282 * and atomic buffers in hw state to avoid unintentional unbinding of
283 * shader buffer with uaViewId 0.
284 */
285 for (unsigned i = 0; i < ARRAY_SIZE(svga->state.hw_draw.atomic_buffers); i++) {
286 svga->curr.atomic_buffers[i].resource = NULL;
287 svga->curr.atomic_buffers[i].uav_index = -1;
288 }
289 svga->state.hw_draw.num_atomic_buffers = 0;
290 }
291
292
293 /**
294 * Cleanup shader image state
295 */
296 void
svga_cleanup_shader_buffer_state(struct svga_context * svga)297 svga_cleanup_shader_buffer_state(struct svga_context *svga)
298 {
299 if (!svga_have_gl43(svga))
300 return;
301
302 svga_destroy_uav(svga);
303 }
304
305
306 /**
307 * Validate shader buffer resources to ensure any pending changes to the
308 * buffers are emitted before they are referenced.
309 * The helper function also rebinds the buffer resources if the rebind flag
310 * is specified.
311 */
312 enum pipe_error
svga_validate_shader_buffer_resources(struct svga_context * svga,unsigned count,struct svga_shader_buffer * bufs,bool rebind)313 svga_validate_shader_buffer_resources(struct svga_context *svga,
314 unsigned count,
315 struct svga_shader_buffer *bufs,
316 bool rebind)
317 {
318 assert(svga_have_gl43(svga));
319
320 struct svga_winsys_surface *surf;
321 enum pipe_error ret;
322 unsigned i;
323
324 for (i = 0; i < count; i++) {
325 if (bufs[i].resource) {
326 assert(bufs[i].resource == bufs[i].desc.buffer);
327
328 struct svga_buffer *sbuf = svga_buffer(bufs[i].resource);
329 surf = svga_buffer_handle(svga, bufs[i].desc.buffer,
330 PIPE_BIND_SHADER_BUFFER);
331 assert(surf);
332 if (rebind) {
333 ret = svga->swc->resource_rebind(svga->swc, surf, NULL,
334 SVGA_RELOC_READ|SVGA_RELOC_WRITE);
335 if (ret != PIPE_OK)
336 return ret;
337 }
338
339 /* Mark buffer as RENDERED */
340 svga_set_buffer_rendered_to(sbuf->bufsurf);
341 }
342 }
343
344 return PIPE_OK;
345 }
346