• 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 #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