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