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 * Initialize uav cache.
46bf215546Sopenharmony_ci */
47bf215546Sopenharmony_civoid
48bf215546Sopenharmony_cisvga_uav_cache_init(struct svga_context *svga)
49bf215546Sopenharmony_ci{
50bf215546Sopenharmony_ci   struct svga_cache_uav *cache = &svga->cache_uav;
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci   for (unsigned i = 0; i < ARRAY_SIZE(cache->uaViews); i++) {
53bf215546Sopenharmony_ci      cache->uaViews[i].uaViewId = SVGA3D_INVALID_ID;
54bf215546Sopenharmony_ci      cache->uaViews[i].next_uaView = i + 1;
55bf215546Sopenharmony_ci   }
56bf215546Sopenharmony_ci   cache->num_uaViews = 0;
57bf215546Sopenharmony_ci   cache->next_uaView = 0;
58bf215546Sopenharmony_ci}
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_ci/**
62bf215546Sopenharmony_ci * Helper function to compare two image view descriptions.
63bf215546Sopenharmony_ci * Return TRUE if they are identical.
64bf215546Sopenharmony_ci */
65bf215546Sopenharmony_cistatic boolean
66bf215546Sopenharmony_ciimage_view_desc_identical(struct pipe_image_view *img1,
67bf215546Sopenharmony_ci                          struct pipe_image_view *img2)
68bf215546Sopenharmony_ci{
69bf215546Sopenharmony_ci   if ((img1->resource != img2->resource) ||
70bf215546Sopenharmony_ci       (img1->format != img2->format) ||
71bf215546Sopenharmony_ci       (img1->access != img2->access) ||
72bf215546Sopenharmony_ci       (img1->shader_access != img2->shader_access))
73bf215546Sopenharmony_ci      return FALSE;
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   if (img1->resource->target == PIPE_BUFFER) {
76bf215546Sopenharmony_ci      if ((img1->u.buf.offset != img2->u.buf.offset) ||
77bf215546Sopenharmony_ci          (img1->u.buf.size != img2->u.buf.size))
78bf215546Sopenharmony_ci         return FALSE;
79bf215546Sopenharmony_ci   }
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci   return TRUE;
82bf215546Sopenharmony_ci}
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci/**
86bf215546Sopenharmony_ci * Helper function to compare two shader buffer descriptions.
87bf215546Sopenharmony_ci * Return TRUE if they are identical.
88bf215546Sopenharmony_ci */
89bf215546Sopenharmony_cistatic boolean
90bf215546Sopenharmony_cishader_buffer_desc_identical(struct pipe_shader_buffer *buf1,
91bf215546Sopenharmony_ci                             struct pipe_shader_buffer *buf2)
92bf215546Sopenharmony_ci{
93bf215546Sopenharmony_ci   return memcmp(buf1, buf2, sizeof(*buf1)) == 0;
94bf215546Sopenharmony_ci}
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci/**
98bf215546Sopenharmony_ci * Helper function to compare two uav cache entry descriptions.
99bf215546Sopenharmony_ci * Return TRUE if they are identical.
100bf215546Sopenharmony_ci */
101bf215546Sopenharmony_cistatic boolean
102bf215546Sopenharmony_ciuav_desc_identical(enum svga_uav_type uav_type,
103bf215546Sopenharmony_ci                   void *desc, void *uav_desc)
104bf215546Sopenharmony_ci{
105bf215546Sopenharmony_ci   if (uav_type == SVGA_IMAGE_VIEW) {
106bf215546Sopenharmony_ci      struct svga_image_view *img = (struct svga_image_view *)desc;
107bf215546Sopenharmony_ci      struct svga_image_view *uav_img = (struct svga_image_view *)uav_desc;
108bf215546Sopenharmony_ci      if (img->resource != uav_img->resource)
109bf215546Sopenharmony_ci         return FALSE;
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci      return image_view_desc_identical(&img->desc, &uav_img->desc);
112bf215546Sopenharmony_ci   }
113bf215546Sopenharmony_ci   else {
114bf215546Sopenharmony_ci      struct svga_shader_buffer *buf = (struct svga_shader_buffer *)desc;
115bf215546Sopenharmony_ci      struct svga_shader_buffer *uav_buf =
116bf215546Sopenharmony_ci         (struct svga_shader_buffer *)uav_desc;
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci      if (buf->resource != uav_buf->resource)
119bf215546Sopenharmony_ci         return FALSE;
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci      if (buf->handle != uav_buf->handle)
122bf215546Sopenharmony_ci         return FALSE;
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci      return shader_buffer_desc_identical(&buf->desc, &uav_buf->desc);
125bf215546Sopenharmony_ci   }
126bf215546Sopenharmony_ci}
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci/**
130bf215546Sopenharmony_ci * Find a uav object for the specified image view or shader buffer.
131bf215546Sopenharmony_ci * Returns uav entry if there is a match; otherwise returns NULL.
132bf215546Sopenharmony_ci */
133bf215546Sopenharmony_cistatic struct svga_uav *
134bf215546Sopenharmony_cisvga_uav_cache_find_uav(struct svga_context *svga,
135bf215546Sopenharmony_ci                        enum svga_uav_type uav_type,
136bf215546Sopenharmony_ci                        void *desc,
137bf215546Sopenharmony_ci                        unsigned desc_len)
138bf215546Sopenharmony_ci{
139bf215546Sopenharmony_ci   struct svga_cache_uav *cache = &svga->cache_uav;
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci   for (unsigned i = 0; i < cache->num_uaViews; i++) {
142bf215546Sopenharmony_ci      if ((cache->uaViews[i].type == uav_type) &&
143bf215546Sopenharmony_ci          (cache->uaViews[i].uaViewId != SVGA3D_INVALID_ID) &&
144bf215546Sopenharmony_ci          uav_desc_identical(uav_type, desc, &cache->uaViews[i].desc)) {
145bf215546Sopenharmony_ci         return &cache->uaViews[i];
146bf215546Sopenharmony_ci      }
147bf215546Sopenharmony_ci   }
148bf215546Sopenharmony_ci   return NULL;
149bf215546Sopenharmony_ci}
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci/**
153bf215546Sopenharmony_ci * Add a uav entry to the cache for the specified image view or
154bf215546Sopenharmony_ci * shaderr bufferr.
155bf215546Sopenharmony_ci */
156bf215546Sopenharmony_cistatic struct svga_uav *
157bf215546Sopenharmony_cisvga_uav_cache_add_uav(struct svga_context *svga,
158bf215546Sopenharmony_ci                       enum svga_uav_type uav_type,
159bf215546Sopenharmony_ci                       void *desc,
160bf215546Sopenharmony_ci                       unsigned desc_len,
161bf215546Sopenharmony_ci                       struct pipe_resource *res,
162bf215546Sopenharmony_ci                       SVGA3dUAViewId uaViewId)
163bf215546Sopenharmony_ci{
164bf215546Sopenharmony_ci   struct svga_cache_uav *cache = &svga->cache_uav;
165bf215546Sopenharmony_ci   unsigned i = cache->next_uaView;
166bf215546Sopenharmony_ci   struct svga_uav *uav;
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   if (i > ARRAY_SIZE(cache->uaViews)) {
169bf215546Sopenharmony_ci      debug_printf("No room to add uav to the cache.\n");
170bf215546Sopenharmony_ci      return NULL;
171bf215546Sopenharmony_ci   }
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   uav = &cache->uaViews[i];
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci   /* update the next available uav slot index */
176bf215546Sopenharmony_ci   cache->next_uaView = uav->next_uaView;
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   uav->type = uav_type;
179bf215546Sopenharmony_ci   memcpy(&uav->desc, desc, desc_len);
180bf215546Sopenharmony_ci   pipe_resource_reference(&uav->resource, res);
181bf215546Sopenharmony_ci   uav->uaViewId = uaViewId;
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci   cache->num_uaViews = MAX2(i+1, cache->num_uaViews);
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   return uav;
186bf215546Sopenharmony_ci}
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci/**
190bf215546Sopenharmony_ci * Bump the timestamp of the specified uav for the specified pipeline,
191bf215546Sopenharmony_ci * so the uav will not be prematurely purged.
192bf215546Sopenharmony_ci */
193bf215546Sopenharmony_cistatic void
194bf215546Sopenharmony_cisvga_uav_cache_use_uav(struct svga_context *svga,
195bf215546Sopenharmony_ci                       enum svga_pipe_type pipe_type,
196bf215546Sopenharmony_ci                       struct svga_uav *uav)
197bf215546Sopenharmony_ci{
198bf215546Sopenharmony_ci   assert(uav != NULL);
199bf215546Sopenharmony_ci   assert(uav->uaViewId != SVGA3D_INVALID_ID);
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci   uav->timestamp[pipe_type] = svga->state.uav_timestamp[pipe_type];
202bf215546Sopenharmony_ci}
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci/**
206bf215546Sopenharmony_ci * Purge any unused uav from the cache.
207bf215546Sopenharmony_ci */
208bf215546Sopenharmony_cistatic void
209bf215546Sopenharmony_cisvga_uav_cache_purge(struct svga_context *svga, enum svga_pipe_type pipe_type)
210bf215546Sopenharmony_ci{
211bf215546Sopenharmony_ci   struct svga_cache_uav *cache = &svga->cache_uav;
212bf215546Sopenharmony_ci   unsigned timestamp = svga->state.uav_timestamp[pipe_type];
213bf215546Sopenharmony_ci   unsigned other_pipe_type = !pipe_type;
214bf215546Sopenharmony_ci   struct svga_uav *uav = &cache->uaViews[0];
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   unsigned last_uav = -1;
217bf215546Sopenharmony_ci   for (unsigned i = 0; i < cache->num_uaViews; i++, uav++) {
218bf215546Sopenharmony_ci      if (uav->uaViewId != SVGA3D_INVALID_ID) {
219bf215546Sopenharmony_ci         last_uav = i;
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci         if (uav->timestamp[pipe_type] < timestamp) {
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci            /* Reset the timestamp for this uav in the specified
224bf215546Sopenharmony_ci             * pipeline first.
225bf215546Sopenharmony_ci             */
226bf215546Sopenharmony_ci            uav->timestamp[pipe_type] = 0;
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci            /* Then check if the uav is currently in use in other pipeline.
229bf215546Sopenharmony_ci             * If yes, then don't delete the uav yet.
230bf215546Sopenharmony_ci             * If no, then we can mark the uav as to be destroyed.
231bf215546Sopenharmony_ci             */
232bf215546Sopenharmony_ci            if (uav->timestamp[other_pipe_type] == 0) {
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci               /* The unused uav can be destroyed, but will be destroyed
235bf215546Sopenharmony_ci                * in the next set_image_views or set_shader_buffers,
236bf215546Sopenharmony_ci                * or at context destroy time, because we do not want to
237bf215546Sopenharmony_ci                * restart the state update if the Destroy command cannot be
238bf215546Sopenharmony_ci                * executed in this command buffer.
239bf215546Sopenharmony_ci                */
240bf215546Sopenharmony_ci               util_bitmask_set(svga->uav_to_free_id_bm, uav->uaViewId);
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci               /* Mark this entry as available */
243bf215546Sopenharmony_ci               uav->next_uaView = cache->next_uaView;
244bf215546Sopenharmony_ci               uav->uaViewId = SVGA3D_INVALID_ID;
245bf215546Sopenharmony_ci               cache->next_uaView = i;
246bf215546Sopenharmony_ci            }
247bf215546Sopenharmony_ci         }
248bf215546Sopenharmony_ci      }
249bf215546Sopenharmony_ci   }
250bf215546Sopenharmony_ci   cache->num_uaViews = last_uav + 1;
251bf215546Sopenharmony_ci}
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci/**
255bf215546Sopenharmony_ci * A helper function to create an uav.
256bf215546Sopenharmony_ci */
257bf215546Sopenharmony_ciSVGA3dUAViewId
258bf215546Sopenharmony_cisvga_create_uav(struct svga_context *svga,
259bf215546Sopenharmony_ci                SVGA3dUAViewDesc *desc,
260bf215546Sopenharmony_ci                SVGA3dSurfaceFormat svga_format,
261bf215546Sopenharmony_ci                unsigned resourceDim,
262bf215546Sopenharmony_ci                struct svga_winsys_surface *surf)
263bf215546Sopenharmony_ci{
264bf215546Sopenharmony_ci   SVGA3dUAViewId uaViewId;
265bf215546Sopenharmony_ci   enum pipe_error ret;
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci   /* allocate a uav id */
268bf215546Sopenharmony_ci   uaViewId = util_bitmask_add(svga->uav_id_bm);
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci   SVGA_DBG(DEBUG_UAV, "%s: uavId=%d surf=0x%x\n", __FUNCTION__, uaViewId, surf);
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci   ret = SVGA3D_sm5_DefineUAView(svga->swc, uaViewId, surf,
273bf215546Sopenharmony_ci                                 svga_format, resourceDim, desc);
274bf215546Sopenharmony_ci
275bf215546Sopenharmony_ci   if (ret != PIPE_OK) {
276bf215546Sopenharmony_ci      util_bitmask_clear(svga->uav_id_bm, uaViewId);
277bf215546Sopenharmony_ci      uaViewId = SVGA3D_INVALID_ID;
278bf215546Sopenharmony_ci   }
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   return uaViewId;
281bf215546Sopenharmony_ci}
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci/**
285bf215546Sopenharmony_ci * Destroy any pending unused uav
286bf215546Sopenharmony_ci */
287bf215546Sopenharmony_civoid
288bf215546Sopenharmony_cisvga_destroy_uav(struct svga_context *svga)
289bf215546Sopenharmony_ci{
290bf215546Sopenharmony_ci   unsigned index = 0;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   SVGA_DBG(DEBUG_UAV, "%s: ", __FUNCTION__);
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_ci   while ((index = util_bitmask_get_next_index(svga->uav_to_free_id_bm, index))
295bf215546Sopenharmony_ci          != UTIL_BITMASK_INVALID_INDEX) {
296bf215546Sopenharmony_ci      SVGA_DBG(DEBUG_UAV, "%d ", index);
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci      SVGA_RETRY(svga, SVGA3D_sm5_DestroyUAView(svga->swc, index));
299bf215546Sopenharmony_ci      util_bitmask_clear(svga->uav_id_bm, index);
300bf215546Sopenharmony_ci      util_bitmask_clear(svga->uav_to_free_id_bm, index);
301bf215546Sopenharmony_ci   }
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   SVGA_DBG(DEBUG_UAV, "\n");
304bf215546Sopenharmony_ci}
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci/**
308bf215546Sopenharmony_ci * Rebind ua views.
309bf215546Sopenharmony_ci * This function is called at the beginning of each new command buffer to make sure
310bf215546Sopenharmony_ci * the resources associated with the ua views are properly paged-in.
311bf215546Sopenharmony_ci */
312bf215546Sopenharmony_cienum pipe_error
313bf215546Sopenharmony_cisvga_rebind_uav(struct svga_context *svga)
314bf215546Sopenharmony_ci{
315bf215546Sopenharmony_ci   struct svga_winsys_context *swc = svga->swc;
316bf215546Sopenharmony_ci   struct svga_hw_draw_state *hw = &svga->state.hw_draw;
317bf215546Sopenharmony_ci   enum pipe_error ret;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   assert(svga_have_sm5(svga));
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci   for (unsigned i = 0; i < hw->num_uavs; i++) {
322bf215546Sopenharmony_ci      if (hw->uaViews[i]) {
323bf215546Sopenharmony_ci         ret = swc->resource_rebind(swc, hw->uaViews[i], NULL,
324bf215546Sopenharmony_ci                                    SVGA_RELOC_READ | SVGA_RELOC_WRITE);
325bf215546Sopenharmony_ci         if (ret != PIPE_OK)
326bf215546Sopenharmony_ci            return ret;
327bf215546Sopenharmony_ci      }
328bf215546Sopenharmony_ci   }
329bf215546Sopenharmony_ci   svga->rebind.flags.uav = 0;
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   return PIPE_OK;
332bf215546Sopenharmony_ci}
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_cistatic int
335bf215546Sopenharmony_cisvga_find_uav_from_list(struct svga_context *svga, SVGA3dUAViewId uaViewId,
336bf215546Sopenharmony_ci                        unsigned num_uavs, SVGA3dUAViewId *uaViewsId)
337bf215546Sopenharmony_ci{
338bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_uavs; i++) {
339bf215546Sopenharmony_ci      if (uaViewsId[i] == uaViewId)
340bf215546Sopenharmony_ci         return i;
341bf215546Sopenharmony_ci   }
342bf215546Sopenharmony_ci   return -1;
343bf215546Sopenharmony_ci}
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci/**
346bf215546Sopenharmony_ci * A helper function to create the uaView lists from the
347bf215546Sopenharmony_ci * bound shader images and shader buffers.
348bf215546Sopenharmony_ci */
349bf215546Sopenharmony_cistatic enum pipe_error
350bf215546Sopenharmony_cisvga_create_uav_list(struct svga_context *svga,
351bf215546Sopenharmony_ci                     enum svga_pipe_type pipe_type,
352bf215546Sopenharmony_ci                     unsigned num_free_uavs,
353bf215546Sopenharmony_ci                     unsigned *num_uavs,
354bf215546Sopenharmony_ci                     SVGA3dUAViewId *uaViewIds,
355bf215546Sopenharmony_ci                     struct svga_winsys_surface **uaViews)
356bf215546Sopenharmony_ci{
357bf215546Sopenharmony_ci   enum pipe_shader_type first_shader, last_shader;
358bf215546Sopenharmony_ci   struct svga_uav *uav;
359bf215546Sopenharmony_ci   int uav_index = -1;
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_ci   /* Increase uav timestamp */
362bf215546Sopenharmony_ci   svga->state.uav_timestamp[pipe_type]++;
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci   if (pipe_type == SVGA_PIPE_GRAPHICS) {
365bf215546Sopenharmony_ci      first_shader = PIPE_SHADER_VERTEX;
366bf215546Sopenharmony_ci      last_shader = PIPE_SHADER_TESS_EVAL;
367bf215546Sopenharmony_ci   } else {
368bf215546Sopenharmony_ci      first_shader = PIPE_SHADER_COMPUTE;
369bf215546Sopenharmony_ci      last_shader = PIPE_SHADER_COMPUTE;
370bf215546Sopenharmony_ci   }
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci   for (enum pipe_shader_type shader = first_shader;
373bf215546Sopenharmony_ci        shader <= last_shader; shader++) {
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci      unsigned num_image_views = svga->curr.num_image_views[shader];
376bf215546Sopenharmony_ci      unsigned num_shader_buffers = svga->curr.num_shader_buffers[shader];
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci      SVGA_DBG(DEBUG_UAV,
379bf215546Sopenharmony_ci            "%s: shader=%d num_image_views=%d num_shader_buffers=%d\n",
380bf215546Sopenharmony_ci            __FUNCTION__, shader, num_image_views, num_shader_buffers);
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci      /* add enabled shader images to the uav list */
383bf215546Sopenharmony_ci      if (num_image_views) {
384bf215546Sopenharmony_ci         num_image_views = MIN2(num_image_views, num_free_uavs-*num_uavs);
385bf215546Sopenharmony_ci         for (unsigned i = 0; i < num_image_views; i++) {
386bf215546Sopenharmony_ci            struct svga_image_view *cur_image_view =
387bf215546Sopenharmony_ci                &svga->curr.image_views[shader][i];
388bf215546Sopenharmony_ci            struct pipe_resource *res = cur_image_view->resource;
389bf215546Sopenharmony_ci            SVGA3dUAViewId uaViewId;
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci            if (res) {
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_ci               /* First check if there is already a uav defined for this
394bf215546Sopenharmony_ci                * image view.
395bf215546Sopenharmony_ci                */
396bf215546Sopenharmony_ci               uav = svga_uav_cache_find_uav(svga, SVGA_IMAGE_VIEW,
397bf215546Sopenharmony_ci                                             cur_image_view,
398bf215546Sopenharmony_ci                                             sizeof(*cur_image_view));
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci               /* If there isn't one, create a uav for this image view. */
401bf215546Sopenharmony_ci               if (uav == NULL) {
402bf215546Sopenharmony_ci                  uaViewId = svga_create_uav_image(svga, &cur_image_view->desc);
403bf215546Sopenharmony_ci                  if (uaViewId == SVGA3D_INVALID_ID)
404bf215546Sopenharmony_ci                     return PIPE_ERROR_OUT_OF_MEMORY;
405bf215546Sopenharmony_ci
406bf215546Sopenharmony_ci                  /* Add the uav to the cache */
407bf215546Sopenharmony_ci                  uav = svga_uav_cache_add_uav(svga, SVGA_IMAGE_VIEW,
408bf215546Sopenharmony_ci                                               cur_image_view,
409bf215546Sopenharmony_ci                                               sizeof(*cur_image_view),
410bf215546Sopenharmony_ci                                               res,
411bf215546Sopenharmony_ci                                               uaViewId);
412bf215546Sopenharmony_ci                  if (uav == NULL)
413bf215546Sopenharmony_ci                     return PIPE_ERROR_OUT_OF_MEMORY;
414bf215546Sopenharmony_ci               }
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_ci               /* Mark this uav as being used */
417bf215546Sopenharmony_ci               svga_uav_cache_use_uav(svga, pipe_type, uav);
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci               /* Check if the uav is already bound in the uav list */
420bf215546Sopenharmony_ci               uav_index = svga_find_uav_from_list(svga, uav->uaViewId,
421bf215546Sopenharmony_ci                                                   *num_uavs, uaViewIds);
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci               /* The uav is not already on the uaView list, add it */
424bf215546Sopenharmony_ci               if (uav_index == -1) {
425bf215546Sopenharmony_ci                  uav_index = *num_uavs;
426bf215546Sopenharmony_ci                  (*num_uavs)++;
427bf215546Sopenharmony_ci                  if (res->target == PIPE_BUFFER)
428bf215546Sopenharmony_ci                     uaViews[uav_index] = svga_buffer(res)->handle;
429bf215546Sopenharmony_ci                  else
430bf215546Sopenharmony_ci                     uaViews[uav_index] = svga_texture(res)->handle;
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci                  uaViewIds[uav_index] = uav->uaViewId;
433bf215546Sopenharmony_ci               }
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_ci               /* Save the uav slot index for the image view for later reference
436bf215546Sopenharmony_ci                * to create the uav mapping in the shader key.
437bf215546Sopenharmony_ci                */
438bf215546Sopenharmony_ci               cur_image_view->uav_index = uav_index;
439bf215546Sopenharmony_ci            }
440bf215546Sopenharmony_ci         }
441bf215546Sopenharmony_ci      }
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci      /* add enabled shader buffers to the uav list */
444bf215546Sopenharmony_ci      if (num_shader_buffers) {
445bf215546Sopenharmony_ci         num_shader_buffers = MIN2(num_shader_buffers, num_free_uavs-*num_uavs);
446bf215546Sopenharmony_ci         for (unsigned i = 0; i < num_shader_buffers; i++) {
447bf215546Sopenharmony_ci            struct svga_shader_buffer *cur_sbuf =
448bf215546Sopenharmony_ci                &svga->curr.shader_buffers[shader][i];
449bf215546Sopenharmony_ci            struct pipe_resource *res = cur_sbuf->resource;
450bf215546Sopenharmony_ci            SVGA3dUAViewId uaViewId;
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci            if (res) {
453bf215546Sopenharmony_ci               /* Get the buffer handle that can be bound as uav. */
454bf215546Sopenharmony_ci               cur_sbuf->handle = svga_buffer_handle(svga, res,
455bf215546Sopenharmony_ci                                                    PIPE_BIND_SHADER_BUFFER);
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci               /* First check if there is already a uav defined for this
458bf215546Sopenharmony_ci                * shader buffer.
459bf215546Sopenharmony_ci                */
460bf215546Sopenharmony_ci               uav = svga_uav_cache_find_uav(svga, SVGA_SHADER_BUFFER,
461bf215546Sopenharmony_ci                                             cur_sbuf,
462bf215546Sopenharmony_ci                                             sizeof(*cur_sbuf));
463bf215546Sopenharmony_ci
464bf215546Sopenharmony_ci               /* If there isn't one, create a uav for this shader buffer. */
465bf215546Sopenharmony_ci               if (uav == NULL) {
466bf215546Sopenharmony_ci                  uaViewId = svga_create_uav_buffer(svga, &cur_sbuf->desc,
467bf215546Sopenharmony_ci                                                    SVGA3D_R32_TYPELESS,
468bf215546Sopenharmony_ci                                                    SVGA3D_UABUFFER_RAW);
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci                  if (uaViewId == SVGA3D_INVALID_ID)
471bf215546Sopenharmony_ci                     return PIPE_ERROR_OUT_OF_MEMORY;
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci                  /* Add the uav to the cache */
474bf215546Sopenharmony_ci                  uav = svga_uav_cache_add_uav(svga, SVGA_SHADER_BUFFER,
475bf215546Sopenharmony_ci                                               cur_sbuf,
476bf215546Sopenharmony_ci                                               sizeof(*cur_sbuf),
477bf215546Sopenharmony_ci                                               res,
478bf215546Sopenharmony_ci                                               uaViewId);
479bf215546Sopenharmony_ci                  if (uav == NULL)
480bf215546Sopenharmony_ci                     return PIPE_ERROR_OUT_OF_MEMORY;
481bf215546Sopenharmony_ci               }
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci               /* Mark this uav as being used */
484bf215546Sopenharmony_ci               svga_uav_cache_use_uav(svga, pipe_type, uav);
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci               uav_index = svga_find_uav_from_list(svga, uav->uaViewId,
487bf215546Sopenharmony_ci                                                   *num_uavs, uaViewIds);
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_ci               /* The uav is not already on the uaView list, add it */
490bf215546Sopenharmony_ci               if (uav_index == -1) {
491bf215546Sopenharmony_ci                  uav_index = *num_uavs;
492bf215546Sopenharmony_ci                  (*num_uavs)++;
493bf215546Sopenharmony_ci                  uaViews[uav_index] = svga_buffer(res)->handle;
494bf215546Sopenharmony_ci                  uaViewIds[uav_index] = uav->uaViewId;
495bf215546Sopenharmony_ci               }
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci               /* Save the uav slot index for later reference
498bf215546Sopenharmony_ci                * to create the uav mapping in the shader key.
499bf215546Sopenharmony_ci                */
500bf215546Sopenharmony_ci               cur_sbuf->uav_index = uav_index;
501bf215546Sopenharmony_ci            }
502bf215546Sopenharmony_ci         }
503bf215546Sopenharmony_ci      }
504bf215546Sopenharmony_ci   }
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_ci   /* Since atomic buffers are not specific to a particular shader type,
507bf215546Sopenharmony_ci    * add any enabled atomic buffers to the uav list when we are done adding
508bf215546Sopenharmony_ci    * shader specific uavs.
509bf215546Sopenharmony_ci    */
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci   unsigned num_atomic_buffers = svga->curr.num_atomic_buffers;
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci   SVGA_DBG(DEBUG_UAV,
514bf215546Sopenharmony_ci            "%s: num_atomic_buffers=%d\n", __FUNCTION__, num_atomic_buffers);
515bf215546Sopenharmony_ci
516bf215546Sopenharmony_ci   if (num_atomic_buffers) {
517bf215546Sopenharmony_ci      num_atomic_buffers = MIN2(num_atomic_buffers, num_free_uavs-*num_uavs);
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_ci      for (unsigned i = 0; i < num_atomic_buffers; i++) {
520bf215546Sopenharmony_ci         struct svga_shader_buffer *cur_sbuf = &svga->curr.atomic_buffers[i];
521bf215546Sopenharmony_ci         struct pipe_resource *res = cur_sbuf->resource;
522bf215546Sopenharmony_ci         SVGA3dUAViewId uaViewId;
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci         if (res) {
525bf215546Sopenharmony_ci            /* Get the buffer handle that can be bound as uav. */
526bf215546Sopenharmony_ci            cur_sbuf->handle = svga_buffer_handle(svga, res,
527bf215546Sopenharmony_ci                                                  PIPE_BIND_SHADER_BUFFER);
528bf215546Sopenharmony_ci
529bf215546Sopenharmony_ci            /* First check if there is already a uav defined for this
530bf215546Sopenharmony_ci             * shader buffer.
531bf215546Sopenharmony_ci             */
532bf215546Sopenharmony_ci            uav = svga_uav_cache_find_uav(svga, SVGA_SHADER_BUFFER,
533bf215546Sopenharmony_ci                                          cur_sbuf,
534bf215546Sopenharmony_ci                                          sizeof(*cur_sbuf));
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci            /* If there isn't one, create a uav for this shader buffer. */
537bf215546Sopenharmony_ci            if (uav == NULL) {
538bf215546Sopenharmony_ci               uaViewId = svga_create_uav_buffer(svga, &cur_sbuf->desc,
539bf215546Sopenharmony_ci                                                 SVGA3D_R32_TYPELESS,
540bf215546Sopenharmony_ci                                                 SVGA3D_UABUFFER_RAW);
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci               if (uaViewId == SVGA3D_INVALID_ID)
543bf215546Sopenharmony_ci                  return PIPE_ERROR_OUT_OF_MEMORY;
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci               /* Add the uav to the cache */
546bf215546Sopenharmony_ci               uav = svga_uav_cache_add_uav(svga, SVGA_SHADER_BUFFER,
547bf215546Sopenharmony_ci                                            cur_sbuf,
548bf215546Sopenharmony_ci                                            sizeof(*cur_sbuf),
549bf215546Sopenharmony_ci                                            res,
550bf215546Sopenharmony_ci                                            uaViewId);
551bf215546Sopenharmony_ci               if (uav == NULL)
552bf215546Sopenharmony_ci                  return PIPE_ERROR_OUT_OF_MEMORY;
553bf215546Sopenharmony_ci            }
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci            /* Mark this uav as being used */
556bf215546Sopenharmony_ci            svga_uav_cache_use_uav(svga, pipe_type, uav);
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci            uav_index = svga_find_uav_from_list(svga, uav->uaViewId,
559bf215546Sopenharmony_ci                                                *num_uavs, uaViewIds);
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci            /* The uav is not already on the uaView list, add it */
562bf215546Sopenharmony_ci            if (uav_index == -1) {
563bf215546Sopenharmony_ci               uav_index = *num_uavs;
564bf215546Sopenharmony_ci               (*num_uavs)++;
565bf215546Sopenharmony_ci               uaViews[uav_index] = svga_buffer(res)->handle;
566bf215546Sopenharmony_ci               uaViewIds[uav_index] = uav->uaViewId;
567bf215546Sopenharmony_ci            }
568bf215546Sopenharmony_ci         }
569bf215546Sopenharmony_ci
570bf215546Sopenharmony_ci         /* Save the uav slot index for the atomic buffer for later reference
571bf215546Sopenharmony_ci          * to create the uav mapping in the shader key.
572bf215546Sopenharmony_ci          */
573bf215546Sopenharmony_ci         cur_sbuf->uav_index = uav_index;
574bf215546Sopenharmony_ci      }
575bf215546Sopenharmony_ci   }
576bf215546Sopenharmony_ci
577bf215546Sopenharmony_ci   /* Reset the rest of the ua views list */
578bf215546Sopenharmony_ci   for (unsigned u = *num_uavs;
579bf215546Sopenharmony_ci        u < ARRAY_SIZE(svga->state.hw_draw.uaViewIds); u++) {
580bf215546Sopenharmony_ci      uaViewIds[u] = SVGA3D_INVALID_ID;
581bf215546Sopenharmony_ci      uaViews[u] = NULL;
582bf215546Sopenharmony_ci   }
583bf215546Sopenharmony_ci
584bf215546Sopenharmony_ci   return PIPE_OK;
585bf215546Sopenharmony_ci}
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci/**
589bf215546Sopenharmony_ci * A helper function to save the current hw uav state.
590bf215546Sopenharmony_ci */
591bf215546Sopenharmony_cistatic void
592bf215546Sopenharmony_cisvga_save_uav_state(struct svga_context *svga,
593bf215546Sopenharmony_ci                    enum svga_pipe_type pipe_type,
594bf215546Sopenharmony_ci                    unsigned num_uavs,
595bf215546Sopenharmony_ci                    SVGA3dUAViewId *uaViewIds,
596bf215546Sopenharmony_ci                    struct svga_winsys_surface **uaViews)
597bf215546Sopenharmony_ci{
598bf215546Sopenharmony_ci   enum pipe_shader_type first_shader, last_shader;
599bf215546Sopenharmony_ci   unsigned i;
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci   if (pipe_type == SVGA_PIPE_GRAPHICS) {
602bf215546Sopenharmony_ci      first_shader = PIPE_SHADER_VERTEX;
603bf215546Sopenharmony_ci      last_shader = PIPE_SHADER_TESS_EVAL;
604bf215546Sopenharmony_ci   } else {
605bf215546Sopenharmony_ci      first_shader = PIPE_SHADER_COMPUTE;
606bf215546Sopenharmony_ci      last_shader = PIPE_SHADER_COMPUTE;
607bf215546Sopenharmony_ci   }
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci   for (enum pipe_shader_type shader = first_shader;
610bf215546Sopenharmony_ci        shader <= last_shader; shader++) {
611bf215546Sopenharmony_ci
612bf215546Sopenharmony_ci      /**
613bf215546Sopenharmony_ci       * Save the current shader images
614bf215546Sopenharmony_ci       */
615bf215546Sopenharmony_ci      for (i = 0; i < ARRAY_SIZE(svga->curr.image_views[0]); i++) {
616bf215546Sopenharmony_ci         struct svga_image_view *cur_image_view =
617bf215546Sopenharmony_ci            &svga->curr.image_views[shader][i];
618bf215546Sopenharmony_ci         struct svga_image_view *hw_image_view =
619bf215546Sopenharmony_ci            &svga->state.hw_draw.image_views[shader][i];
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci         /* Save the hw state for image view */
622bf215546Sopenharmony_ci         *hw_image_view = *cur_image_view;
623bf215546Sopenharmony_ci      }
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci      /**
626bf215546Sopenharmony_ci       * Save the current shader buffers
627bf215546Sopenharmony_ci       */
628bf215546Sopenharmony_ci      for (i = 0; i < ARRAY_SIZE(svga->curr.shader_buffers[0]); i++) {
629bf215546Sopenharmony_ci         struct svga_shader_buffer *cur_shader_buffer =
630bf215546Sopenharmony_ci            &svga->curr.shader_buffers[shader][i];
631bf215546Sopenharmony_ci         struct svga_shader_buffer *hw_shader_buffer =
632bf215546Sopenharmony_ci            &svga->state.hw_draw.shader_buffers[shader][i];
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci         /* Save the hw state for image view */
635bf215546Sopenharmony_ci         *hw_shader_buffer = *cur_shader_buffer;
636bf215546Sopenharmony_ci      }
637bf215546Sopenharmony_ci
638bf215546Sopenharmony_ci      svga->state.hw_draw.num_image_views[shader] =
639bf215546Sopenharmony_ci         svga->curr.num_image_views[shader];
640bf215546Sopenharmony_ci      svga->state.hw_draw.num_shader_buffers[shader] =
641bf215546Sopenharmony_ci         svga->curr.num_shader_buffers[shader];
642bf215546Sopenharmony_ci   }
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_ci   /**
645bf215546Sopenharmony_ci    * Save the current atomic buffers
646bf215546Sopenharmony_ci    */
647bf215546Sopenharmony_ci   for (i = 0; i < ARRAY_SIZE(svga->curr.atomic_buffers); i++) {
648bf215546Sopenharmony_ci      struct svga_shader_buffer *cur_buf = &svga->curr.atomic_buffers[i];
649bf215546Sopenharmony_ci      struct svga_shader_buffer *hw_buf = &svga->state.hw_draw.atomic_buffers[i];
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci      /* Save the hw state for atomic buffers */
652bf215546Sopenharmony_ci      *hw_buf = *cur_buf;
653bf215546Sopenharmony_ci   }
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ci   svga->state.hw_draw.num_atomic_buffers = svga->curr.num_atomic_buffers;
656bf215546Sopenharmony_ci
657bf215546Sopenharmony_ci   /**
658bf215546Sopenharmony_ci    * Save the hw state for uaviews
659bf215546Sopenharmony_ci    */
660bf215546Sopenharmony_ci   if (pipe_type == SVGA_PIPE_COMPUTE) {
661bf215546Sopenharmony_ci      svga->state.hw_draw.num_cs_uavs = num_uavs;
662bf215546Sopenharmony_ci      memcpy(svga->state.hw_draw.csUAViewIds, uaViewIds,
663bf215546Sopenharmony_ci             sizeof svga->state.hw_draw.csUAViewIds);
664bf215546Sopenharmony_ci      memcpy(svga->state.hw_draw.csUAViews, uaViews,
665bf215546Sopenharmony_ci             sizeof svga->state.hw_draw.csUAViews);
666bf215546Sopenharmony_ci   }
667bf215546Sopenharmony_ci   else {
668bf215546Sopenharmony_ci      svga->state.hw_draw.num_uavs = num_uavs;
669bf215546Sopenharmony_ci      memcpy(svga->state.hw_draw.uaViewIds, uaViewIds,
670bf215546Sopenharmony_ci             sizeof svga->state.hw_draw.uaViewIds);
671bf215546Sopenharmony_ci      memcpy(svga->state.hw_draw.uaViews, uaViews,
672bf215546Sopenharmony_ci             sizeof svga->state.hw_draw.uaViews);
673bf215546Sopenharmony_ci   }
674bf215546Sopenharmony_ci
675bf215546Sopenharmony_ci   /* purge the uav cache */
676bf215546Sopenharmony_ci   svga_uav_cache_purge(svga, pipe_type);
677bf215546Sopenharmony_ci}
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci
680bf215546Sopenharmony_ci/**
681bf215546Sopenharmony_ci * A helper function to determine if we need to resend the SetUAViews command.
682bf215546Sopenharmony_ci * We need to resend the SetUAViews command when uavSpliceIndex is to
683bf215546Sopenharmony_ci * be changed because the existing index overlaps with render target views, or
684bf215546Sopenharmony_ci * the image views/shader buffers are changed.
685bf215546Sopenharmony_ci */
686bf215546Sopenharmony_cistatic bool
687bf215546Sopenharmony_cineed_to_set_uav(struct svga_context *svga,
688bf215546Sopenharmony_ci                int uavSpliceIndex,
689bf215546Sopenharmony_ci                unsigned num_uavs,
690bf215546Sopenharmony_ci                SVGA3dUAViewId *uaViewIds,
691bf215546Sopenharmony_ci                struct svga_winsys_surface **uaViews)
692bf215546Sopenharmony_ci{
693bf215546Sopenharmony_ci   /* If number of render target views changed */
694bf215546Sopenharmony_ci   if (uavSpliceIndex != svga->state.hw_draw.uavSpliceIndex)
695bf215546Sopenharmony_ci      return true;
696bf215546Sopenharmony_ci
697bf215546Sopenharmony_ci   /* If number of render target views + number of ua views exceeds
698bf215546Sopenharmony_ci    * the max uav count, we will need to trim the ua views.
699bf215546Sopenharmony_ci    */
700bf215546Sopenharmony_ci   if ((uavSpliceIndex + num_uavs) > SVGA_MAX_UAVIEWS)
701bf215546Sopenharmony_ci      return true;
702bf215546Sopenharmony_ci
703bf215546Sopenharmony_ci   /* If uavs are different */
704bf215546Sopenharmony_ci   if (memcmp(svga->state.hw_draw.uaViewIds, uaViewIds,
705bf215546Sopenharmony_ci              sizeof svga->state.hw_draw.uaViewIds) ||
706bf215546Sopenharmony_ci       memcmp(svga->state.hw_draw.uaViews, uaViews,
707bf215546Sopenharmony_ci              sizeof svga->state.hw_draw.uaViews))
708bf215546Sopenharmony_ci      return true;
709bf215546Sopenharmony_ci
710bf215546Sopenharmony_ci   /* If image views are different */
711bf215546Sopenharmony_ci   for (enum pipe_shader_type shader = PIPE_SHADER_VERTEX;
712bf215546Sopenharmony_ci        shader < PIPE_SHADER_COMPUTE; shader++) {
713bf215546Sopenharmony_ci      unsigned num_image_views = svga->curr.num_image_views[shader];
714bf215546Sopenharmony_ci      if ((num_image_views != svga->state.hw_draw.num_image_views[shader]) ||
715bf215546Sopenharmony_ci          memcmp(svga->state.hw_draw.image_views[shader],
716bf215546Sopenharmony_ci                 svga->curr.image_views[shader],
717bf215546Sopenharmony_ci                 num_image_views * sizeof(struct svga_image_view)))
718bf215546Sopenharmony_ci         return true;
719bf215546Sopenharmony_ci
720bf215546Sopenharmony_ci      /* If shader buffers are different */
721bf215546Sopenharmony_ci      unsigned num_shader_buffers = svga->curr.num_shader_buffers[shader];
722bf215546Sopenharmony_ci      if ((num_shader_buffers != svga->state.hw_draw.num_shader_buffers[shader]) ||
723bf215546Sopenharmony_ci          memcmp(svga->state.hw_draw.shader_buffers[shader],
724bf215546Sopenharmony_ci                 svga->curr.shader_buffers[shader],
725bf215546Sopenharmony_ci                 num_shader_buffers * sizeof(struct svga_shader_buffer)))
726bf215546Sopenharmony_ci         return true;
727bf215546Sopenharmony_ci   }
728bf215546Sopenharmony_ci
729bf215546Sopenharmony_ci   /* If atomic buffers are different */
730bf215546Sopenharmony_ci   unsigned num_atomic_buffers = svga->curr.num_atomic_buffers;
731bf215546Sopenharmony_ci   if ((num_atomic_buffers != svga->state.hw_draw.num_atomic_buffers) ||
732bf215546Sopenharmony_ci       memcmp(svga->state.hw_draw.atomic_buffers, svga->curr.atomic_buffers,
733bf215546Sopenharmony_ci              num_atomic_buffers * sizeof(struct svga_shader_buffer)))
734bf215546Sopenharmony_ci      return true;
735bf215546Sopenharmony_ci
736bf215546Sopenharmony_ci   return false;
737bf215546Sopenharmony_ci}
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci
740bf215546Sopenharmony_ci/**
741bf215546Sopenharmony_ci * Update ua views in the HW for the draw pipeline by sending the
742bf215546Sopenharmony_ci * SetUAViews command.
743bf215546Sopenharmony_ci */
744bf215546Sopenharmony_cistatic enum pipe_error
745bf215546Sopenharmony_ciupdate_uav(struct svga_context *svga, uint64_t dirty)
746bf215546Sopenharmony_ci{
747bf215546Sopenharmony_ci   enum pipe_error ret = PIPE_OK;
748bf215546Sopenharmony_ci   unsigned num_uavs = 0;
749bf215546Sopenharmony_ci   SVGA3dUAViewId uaViewIds[SVGA_MAX_UAVIEWS];
750bf215546Sopenharmony_ci   struct svga_winsys_surface *uaViews[SVGA_MAX_UAVIEWS];
751bf215546Sopenharmony_ci
752bf215546Sopenharmony_ci   /* Determine the uavSpliceIndex since uav and render targets view share the
753bf215546Sopenharmony_ci    * same bind points.
754bf215546Sopenharmony_ci    */
755bf215546Sopenharmony_ci   int uavSpliceIndex = svga->state.hw_clear.num_rendertargets;
756bf215546Sopenharmony_ci
757bf215546Sopenharmony_ci   /* Number of free uav entries available for shader images and buffers */
758bf215546Sopenharmony_ci   unsigned num_free_uavs = SVGA_MAX_UAVIEWS - uavSpliceIndex;
759bf215546Sopenharmony_ci
760bf215546Sopenharmony_ci   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_UPDATEUAV);
761bf215546Sopenharmony_ci
762bf215546Sopenharmony_ci   /* Create the uav list for graphics pipeline */
763bf215546Sopenharmony_ci   ret = svga_create_uav_list(svga, SVGA_PIPE_GRAPHICS, num_free_uavs,
764bf215546Sopenharmony_ci                              &num_uavs, uaViewIds, uaViews);
765bf215546Sopenharmony_ci   if (ret != PIPE_OK)
766bf215546Sopenharmony_ci      goto done;
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_ci   /* check to see if we need to resend the SetUAViews command */
769bf215546Sopenharmony_ci   if (!need_to_set_uav(svga, uavSpliceIndex, num_uavs, uaViewIds, uaViews))
770bf215546Sopenharmony_ci      goto done;
771bf215546Sopenharmony_ci
772bf215546Sopenharmony_ci   /* Send the SetUAViews command */
773bf215546Sopenharmony_ci   SVGA_DBG(DEBUG_UAV, "%s: SetUAViews uavSpliceIndex=%d", __FUNCTION__,
774bf215546Sopenharmony_ci            uavSpliceIndex);
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ci#ifdef DEBUG
777bf215546Sopenharmony_ci   for (unsigned i = 0; i < ARRAY_SIZE(uaViewIds); i++) {
778bf215546Sopenharmony_ci      SVGA_DBG(DEBUG_UAV, " %d ", uaViewIds[i]);
779bf215546Sopenharmony_ci   }
780bf215546Sopenharmony_ci   SVGA_DBG(DEBUG_UAV, "\n");
781bf215546Sopenharmony_ci#endif
782bf215546Sopenharmony_ci
783bf215546Sopenharmony_ci   ret = SVGA3D_sm5_SetUAViews(svga->swc, uavSpliceIndex, SVGA_MAX_UAVIEWS,
784bf215546Sopenharmony_ci                               uaViewIds, uaViews);
785bf215546Sopenharmony_ci   if (ret != PIPE_OK)
786bf215546Sopenharmony_ci      goto done;
787bf215546Sopenharmony_ci
788bf215546Sopenharmony_ci   /* Save the uav hw state */
789bf215546Sopenharmony_ci   svga_save_uav_state(svga, SVGA_PIPE_GRAPHICS, num_uavs, uaViewIds, uaViews);
790bf215546Sopenharmony_ci
791bf215546Sopenharmony_ci   /* Save the uavSpliceIndex as this determines the starting register index
792bf215546Sopenharmony_ci    * for the first uav used in the shader
793bf215546Sopenharmony_ci    */
794bf215546Sopenharmony_ci   svga->state.hw_draw.uavSpliceIndex = uavSpliceIndex;
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_cidone:
797bf215546Sopenharmony_ci   SVGA_STATS_TIME_POP(svga_sws(svga));
798bf215546Sopenharmony_ci   return ret;
799bf215546Sopenharmony_ci}
800bf215546Sopenharmony_ci
801bf215546Sopenharmony_ci
802bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_uav = {
803bf215546Sopenharmony_ci   "shader image view",
804bf215546Sopenharmony_ci   (SVGA_NEW_IMAGE_VIEW |
805bf215546Sopenharmony_ci    SVGA_NEW_SHADER_BUFFER |
806bf215546Sopenharmony_ci    SVGA_NEW_FRAME_BUFFER),
807bf215546Sopenharmony_ci   update_uav
808bf215546Sopenharmony_ci};
809bf215546Sopenharmony_ci
810bf215546Sopenharmony_ci
811bf215546Sopenharmony_ci/**
812bf215546Sopenharmony_ci * A helper function to determine if we need to resend the SetCSUAViews command.
813bf215546Sopenharmony_ci */
814bf215546Sopenharmony_cistatic bool
815bf215546Sopenharmony_cineed_to_set_cs_uav(struct svga_context *svga,
816bf215546Sopenharmony_ci                   unsigned num_uavs,
817bf215546Sopenharmony_ci                   SVGA3dUAViewId *uaViewIds,
818bf215546Sopenharmony_ci                   struct svga_winsys_surface **uaViews)
819bf215546Sopenharmony_ci{
820bf215546Sopenharmony_ci   enum pipe_shader_type shader = PIPE_SHADER_COMPUTE;
821bf215546Sopenharmony_ci
822bf215546Sopenharmony_ci   if (svga->state.hw_draw.num_cs_uavs != num_uavs)
823bf215546Sopenharmony_ci      return true;
824bf215546Sopenharmony_ci
825bf215546Sopenharmony_ci   /* If uavs are different */
826bf215546Sopenharmony_ci   if (memcmp(svga->state.hw_draw.csUAViewIds, uaViewIds,
827bf215546Sopenharmony_ci              sizeof svga->state.hw_draw.csUAViewIds) ||
828bf215546Sopenharmony_ci       memcmp(svga->state.hw_draw.csUAViews, uaViews,
829bf215546Sopenharmony_ci              sizeof svga->state.hw_draw.csUAViews))
830bf215546Sopenharmony_ci      return true;
831bf215546Sopenharmony_ci
832bf215546Sopenharmony_ci   /* If image views are different */
833bf215546Sopenharmony_ci   unsigned num_image_views = svga->curr.num_image_views[shader];
834bf215546Sopenharmony_ci   if ((num_image_views != svga->state.hw_draw.num_image_views[shader]) ||
835bf215546Sopenharmony_ci       memcmp(svga->state.hw_draw.image_views[shader],
836bf215546Sopenharmony_ci              svga->curr.image_views[shader],
837bf215546Sopenharmony_ci              num_image_views * sizeof(struct svga_image_view)))
838bf215546Sopenharmony_ci      return true;
839bf215546Sopenharmony_ci
840bf215546Sopenharmony_ci   /* If atomic buffers are different */
841bf215546Sopenharmony_ci   unsigned num_atomic_buffers = svga->curr.num_atomic_buffers;
842bf215546Sopenharmony_ci   if ((num_atomic_buffers != svga->state.hw_draw.num_atomic_buffers) ||
843bf215546Sopenharmony_ci       memcmp(svga->state.hw_draw.atomic_buffers, svga->curr.atomic_buffers,
844bf215546Sopenharmony_ci              num_atomic_buffers * sizeof(struct svga_shader_buffer)))
845bf215546Sopenharmony_ci      return true;
846bf215546Sopenharmony_ci
847bf215546Sopenharmony_ci   return false;
848bf215546Sopenharmony_ci}
849bf215546Sopenharmony_ci
850bf215546Sopenharmony_ci
851bf215546Sopenharmony_ci/**
852bf215546Sopenharmony_ci * Update ua views in the HW for the compute pipeline by sending the
853bf215546Sopenharmony_ci * SetCSUAViews command.
854bf215546Sopenharmony_ci */
855bf215546Sopenharmony_cistatic enum pipe_error
856bf215546Sopenharmony_ciupdate_cs_uav(struct svga_context *svga, uint64_t dirty)
857bf215546Sopenharmony_ci{
858bf215546Sopenharmony_ci   enum pipe_error ret = PIPE_OK;
859bf215546Sopenharmony_ci   unsigned num_uavs = 0;
860bf215546Sopenharmony_ci   SVGA3dUAViewId uaViewIds[SVGA_MAX_UAVIEWS];
861bf215546Sopenharmony_ci   struct svga_winsys_surface *uaViews[SVGA_MAX_UAVIEWS];
862bf215546Sopenharmony_ci
863bf215546Sopenharmony_ci   /* Number of free uav entries available for shader images and buffers */
864bf215546Sopenharmony_ci   unsigned num_free_uavs = SVGA_MAX_UAVIEWS;
865bf215546Sopenharmony_ci
866bf215546Sopenharmony_ci   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_UPDATECSUAV);
867bf215546Sopenharmony_ci
868bf215546Sopenharmony_ci   /* Create the uav list */
869bf215546Sopenharmony_ci   ret = svga_create_uav_list(svga, SVGA_PIPE_COMPUTE, num_free_uavs,
870bf215546Sopenharmony_ci                              &num_uavs, uaViewIds, uaViews);
871bf215546Sopenharmony_ci   if (ret != PIPE_OK)
872bf215546Sopenharmony_ci      goto done;
873bf215546Sopenharmony_ci
874bf215546Sopenharmony_ci   /* Check to see if we need to resend the CSSetUAViews command */
875bf215546Sopenharmony_ci   if (!need_to_set_cs_uav(svga, num_uavs, uaViewIds, uaViews))
876bf215546Sopenharmony_ci      goto done;
877bf215546Sopenharmony_ci
878bf215546Sopenharmony_ci   /* Send the uaviews to compute */
879bf215546Sopenharmony_ci
880bf215546Sopenharmony_ci   SVGA_DBG(DEBUG_UAV, "%s: SetCSUAViews", __FUNCTION__);
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ci#ifdef DEBUG
883bf215546Sopenharmony_ci   for (unsigned i = 0; i < ARRAY_SIZE(uaViewIds); i++) {
884bf215546Sopenharmony_ci      SVGA_DBG(DEBUG_UAV, " %d ", uaViewIds[i]);
885bf215546Sopenharmony_ci   }
886bf215546Sopenharmony_ci   SVGA_DBG(DEBUG_UAV, "\n");
887bf215546Sopenharmony_ci#endif
888bf215546Sopenharmony_ci
889bf215546Sopenharmony_ci   ret = SVGA3D_sm5_SetCSUAViews(svga->swc, SVGA_MAX_UAVIEWS,
890bf215546Sopenharmony_ci                                 uaViewIds, uaViews);
891bf215546Sopenharmony_ci   if (ret != PIPE_OK)
892bf215546Sopenharmony_ci      goto done;
893bf215546Sopenharmony_ci
894bf215546Sopenharmony_ci   /* Save the uav hw state */
895bf215546Sopenharmony_ci   svga_save_uav_state(svga, SVGA_PIPE_COMPUTE, num_uavs, uaViewIds, uaViews);
896bf215546Sopenharmony_ci
897bf215546Sopenharmony_cidone:
898bf215546Sopenharmony_ci   SVGA_STATS_TIME_POP(svga_sws(svga));
899bf215546Sopenharmony_ci   return ret;
900bf215546Sopenharmony_ci}
901bf215546Sopenharmony_ci
902bf215546Sopenharmony_ci
903bf215546Sopenharmony_cistruct svga_tracked_state svga_hw_cs_uav = {
904bf215546Sopenharmony_ci   "shader image view",
905bf215546Sopenharmony_ci   (SVGA_NEW_IMAGE_VIEW |
906bf215546Sopenharmony_ci    SVGA_NEW_SHADER_BUFFER |
907bf215546Sopenharmony_ci    SVGA_NEW_FRAME_BUFFER),
908bf215546Sopenharmony_ci   update_cs_uav
909bf215546Sopenharmony_ci};
910