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