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