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 */
47SVGA3dUAViewId
48svga_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 */
85static void
86svga_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 */
168static void
169svga_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 */
247void
248svga_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 */
296void
297svga_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 */
312enum pipe_error
313svga_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