• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
33 #include "svga_context.h"
34 #include "svga_cmd.h"
35 #include "svga_debug.h"
36 #include "svga_resource_buffer.h"
37 #include "svga_resource_texture.h"
38 #include "svga_surface.h"
39 #include "svga_sampler_view.h"
40 #include "svga_format.h"
41 
42 
43 /**
44  * Create a uav object for the specified shader buffer
45  */
46 SVGA3dUAViewId
svga_create_uav_buffer(struct svga_context * svga,const struct pipe_shader_buffer * buf,SVGA3dSurfaceFormat format,SVGA3dUABufferFlags bufFlag)47 svga_create_uav_buffer(struct svga_context *svga,
48                        const struct pipe_shader_buffer *buf,
49                        SVGA3dSurfaceFormat format,
50                        SVGA3dUABufferFlags bufFlag)
51 {
52    SVGA3dUAViewDesc desc;
53    unsigned uaViewId;
54 
55    assert(buf);
56 
57    /* If there is not one defined, create one. */
58    memset(&desc, 0, sizeof(desc));
59    desc.buffer.firstElement = buf->buffer_offset / sizeof(uint32);
60    desc.buffer.numElements = buf->buffer_size / sizeof(uint32);
61    desc.buffer.flags = bufFlag;
62 
63    uaViewId = svga_create_uav(svga, &desc, format,
64                               SVGA3D_RESOURCE_BUFFER,
65                               svga_buffer_handle(svga, buf->buffer,
66                                                  PIPE_BIND_SHADER_BUFFER));
67    if (uaViewId == SVGA3D_INVALID_ID)
68       return uaViewId;
69 
70    SVGA_DBG(DEBUG_UAV, "%s: resource=0x%x uaViewId=%d\n",
71             __func__, buf->buffer, uaViewId);
72 
73    /* Mark this buffer as a uav bound buffer */
74    struct svga_buffer *sbuf = svga_buffer(buf->buffer);
75    sbuf->uav = true;
76 
77    return uaViewId;
78 }
79 
80 
81 /**
82  * Set shader buffers.
83  */
84 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)85 svga_set_shader_buffers(struct pipe_context *pipe,
86                         enum pipe_shader_type shader,
87                         unsigned start, unsigned num,
88                         const struct pipe_shader_buffer *buffers,
89                         unsigned writeable_bitmask)
90 {
91    struct svga_context *svga = svga_context(pipe);
92    const struct pipe_shader_buffer *buf;
93 
94    assert(svga_have_gl43(svga));
95 
96    assert(start + num <= SVGA_MAX_SHADER_BUFFERS);
97 
98 #ifdef DEBUG
99    const struct pipe_shader_buffer *b = buffers;
100    SVGA_DBG(DEBUG_UAV, "%s: shader=%d start=%d num=%d ",
101             __func__, shader, start, num);
102    if (buffers) {
103       for (unsigned i = 0; i < num; i++, b++) {
104          SVGA_DBG(DEBUG_UAV, " 0x%x ", b);
105       }
106    }
107    SVGA_DBG(DEBUG_UAV, "\n");
108 #endif
109 
110    buf = buffers;
111    if (buffers) {
112       int last_buffer = -1;
113       for (unsigned i = start, j=0; i < start + num; i++, buf++, j++) {
114          struct svga_shader_buffer *cbuf = &svga->curr.shader_buffers[shader][i];
115 
116          if (buf && buf->buffer) {
117             cbuf->desc = *buf;
118             pipe_resource_reference(&cbuf->resource, buf->buffer);
119 
120             /* Mark the last bound shader buffer */
121             last_buffer = i;
122          }
123          else {
124             cbuf->desc.buffer = NULL;
125             pipe_resource_reference(&cbuf->resource, NULL);
126          }
127          cbuf->uav_index = -1;
128 	 cbuf->writeAccess = (writeable_bitmask & (1 << j)) != 0;
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             __func__, 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", __func__, 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             __func__, 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 
347 
348 /**
349  * Returns TRUE if the shader buffer can be bound to SRV as raw buffer.
350  * It is TRUE if the shader buffer is readonly and the surface already
351  * has the RAW_BUFFER_VIEW bind flag set.
352  */
353 bool
svga_shader_buffer_can_use_srv(struct svga_context * svga,enum pipe_shader_type shader,unsigned index,struct svga_shader_buffer * buf)354 svga_shader_buffer_can_use_srv(struct svga_context *svga,
355 			       enum pipe_shader_type shader,
356                                unsigned index,
357                                struct svga_shader_buffer *buf)
358 {
359    if (buf->resource) {
360       struct svga_buffer *sbuf = svga_buffer(buf->resource);
361       if (sbuf && !buf->writeAccess && svga_has_raw_buffer_view(sbuf)) {
362          return true;
363       }
364    }
365    return false;
366 }
367 
368 
369 #define SVGA_SSBO_SRV_START  SVGA_MAX_CONST_BUFS
370 
371 /**
372  * Bind the shader buffer as SRV raw buffer.
373  */
374 enum pipe_error
svga_shader_buffer_bind_srv(struct svga_context * svga,enum pipe_shader_type shader,unsigned index,struct svga_shader_buffer * buf)375 svga_shader_buffer_bind_srv(struct svga_context *svga,
376                             enum pipe_shader_type shader,
377                             unsigned index,
378                             struct svga_shader_buffer *buf)
379 {
380    enum pipe_error ret;
381    unsigned slot = index + SVGA_SSBO_SRV_START;
382 
383    svga->state.raw_shaderbufs[shader] |= (1 << index);
384    ret = svga_emit_rawbuf(svga, slot, shader, buf->desc.buffer_offset,
385                           buf->desc.buffer_size, buf->resource);
386    if (ret == PIPE_OK)
387       svga->state.hw_draw.enabled_raw_shaderbufs[shader] |= (1 << index);
388 
389    return ret;
390 }
391 
392 
393 /**
394  * Unbind the shader buffer SRV.
395  */
396 enum pipe_error
svga_shader_buffer_unbind_srv(struct svga_context * svga,enum pipe_shader_type shader,unsigned index,struct svga_shader_buffer * buf)397 svga_shader_buffer_unbind_srv(struct svga_context *svga,
398                               enum pipe_shader_type shader,
399                               unsigned index,
400                               struct svga_shader_buffer *buf)
401 {
402    enum pipe_error ret = PIPE_OK;
403    unsigned slot = index + SVGA_SSBO_SRV_START;
404 
405    if ((svga->state.hw_draw.enabled_raw_shaderbufs[shader] & (1 << index))
406           != 0) {
407       ret = svga_emit_rawbuf(svga, slot, shader, 0, 0, NULL);
408       if (ret == PIPE_OK)
409          svga->state.hw_draw.enabled_raw_shaderbufs[shader] &= ~(1 << index);
410    }
411    svga->state.raw_shaderbufs[shader] &= ~(1 << index);
412    return ret;
413 }
414