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