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