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 */ 47void 48svga_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 */ 65static boolean 66image_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 */ 89static boolean 90shader_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 */ 101static boolean 102uav_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 */ 133static struct svga_uav * 134svga_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 */ 156static struct svga_uav * 157svga_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 */ 193static void 194svga_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 */ 208static void 209svga_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 */ 257SVGA3dUAViewId 258svga_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 */ 287void 288svga_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 */ 312enum pipe_error 313svga_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 334static int 335svga_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 */ 349static enum pipe_error 350svga_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 */ 591static void 592svga_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 */ 686static bool 687need_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 */ 744static enum pipe_error 745update_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 796done: 797 SVGA_STATS_TIME_POP(svga_sws(svga)); 798 return ret; 799} 800 801 802struct 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 */ 814static bool 815need_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 */ 855static enum pipe_error 856update_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 897done: 898 SVGA_STATS_TIME_POP(svga_sws(svga)); 899 return ret; 900} 901 902 903struct 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