1 /********************************************************** 2 * Copyright 2009-2015 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 27 #include "svga_cmd.h" 28 29 #include "util/u_debug.h" 30 #include "util/u_memory.h" 31 #include "util/u_debug_stack.h" 32 #include "util/u_debug_flush.h" 33 #include "util/u_hash_table.h" 34 #include "pipebuffer/pb_buffer.h" 35 #include "pipebuffer/pb_validate.h" 36 37 #include "svga_winsys.h" 38 #include "vmw_context.h" 39 #include "vmw_screen.h" 40 #include "vmw_buffer.h" 41 #include "vmw_surface.h" 42 #include "vmw_fence.h" 43 #include "vmw_shader.h" 44 #include "vmw_query.h" 45 46 #define VMW_COMMAND_SIZE (64*1024) 47 #define VMW_SURFACE_RELOCS (1024) 48 #define VMW_SHADER_RELOCS (1024) 49 #define VMW_REGION_RELOCS (512) 50 51 #define VMW_MUST_FLUSH_STACK 8 52 53 /* 54 * A factor applied to the maximum mob memory size to determine 55 * the optimial time to preemptively flush the command buffer. 56 * The constant is based on some performance trials with SpecViewperf. 57 */ 58 #define VMW_MAX_MOB_MEM_FACTOR 2 59 60 /* 61 * A factor applied to the maximum surface memory size to determine 62 * the optimial time to preemptively flush the command buffer. 63 * The constant is based on some performance trials with SpecViewperf. 64 */ 65 #define VMW_MAX_SURF_MEM_FACTOR 2 66 67 68 struct vmw_buffer_relocation 69 { 70 struct pb_buffer *buffer; 71 boolean is_mob; 72 uint32 offset; 73 74 union { 75 struct { 76 struct SVGAGuestPtr *where; 77 } region; 78 struct { 79 SVGAMobId *id; 80 uint32 *offset_into_mob; 81 } mob; 82 }; 83 }; 84 85 struct vmw_ctx_validate_item { 86 union { 87 struct vmw_svga_winsys_surface *vsurf; 88 struct vmw_svga_winsys_shader *vshader; 89 }; 90 boolean referenced; 91 }; 92 93 struct vmw_svga_winsys_context 94 { 95 struct svga_winsys_context base; 96 97 struct vmw_winsys_screen *vws; 98 struct util_hash_table *hash; 99 100 #ifdef DEBUG 101 boolean must_flush; 102 struct debug_stack_frame must_flush_stack[VMW_MUST_FLUSH_STACK]; 103 struct debug_flush_ctx *fctx; 104 #endif 105 106 struct { 107 uint8_t buffer[VMW_COMMAND_SIZE]; 108 uint32_t size; 109 uint32_t used; 110 uint32_t reserved; 111 } command; 112 113 struct { 114 struct vmw_ctx_validate_item items[VMW_SURFACE_RELOCS]; 115 uint32_t size; 116 uint32_t used; 117 uint32_t staged; 118 uint32_t reserved; 119 } surface; 120 121 struct { 122 struct vmw_buffer_relocation relocs[VMW_REGION_RELOCS]; 123 uint32_t size; 124 uint32_t used; 125 uint32_t staged; 126 uint32_t reserved; 127 } region; 128 129 struct { 130 struct vmw_ctx_validate_item items[VMW_SHADER_RELOCS]; 131 uint32_t size; 132 uint32_t used; 133 uint32_t staged; 134 uint32_t reserved; 135 } shader; 136 137 struct pb_validate *validate; 138 139 /** 140 * The amount of surface, GMR or MOB memory that is referred by the commands 141 * currently batched in the context command buffer. 142 */ 143 uint64_t seen_surfaces; 144 uint64_t seen_regions; 145 uint64_t seen_mobs; 146 147 /** 148 * Whether this context should fail to reserve more commands, not because it 149 * ran out of command space, but because a substantial ammount of GMR was 150 * referred. 151 */ 152 boolean preemptive_flush; 153 }; 154 155 156 static inline struct vmw_svga_winsys_context * 157 vmw_svga_winsys_context(struct svga_winsys_context *swc) 158 { 159 assert(swc); 160 return (struct vmw_svga_winsys_context *)swc; 161 } 162 163 164 static inline unsigned 165 vmw_translate_to_pb_flags(unsigned flags) 166 { 167 unsigned f = 0; 168 if (flags & SVGA_RELOC_READ) 169 f |= PB_USAGE_GPU_READ; 170 171 if (flags & SVGA_RELOC_WRITE) 172 f |= PB_USAGE_GPU_WRITE; 173 174 return f; 175 } 176 177 static enum pipe_error 178 vmw_swc_flush(struct svga_winsys_context *swc, 179 struct pipe_fence_handle **pfence) 180 { 181 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 182 struct vmw_winsys_screen *vws = vswc->vws; 183 struct pipe_fence_handle *fence = NULL; 184 unsigned i; 185 enum pipe_error ret; 186 187 /* 188 * If we hit a retry, lock the mutex and retry immediately. 189 * If we then still hit a retry, sleep until another thread 190 * wakes us up after it has released its buffers from the 191 * validate list. 192 * 193 * If we hit another error condition, we still need to broadcast since 194 * pb_validate_validate releases validated buffers in its error path. 195 */ 196 197 ret = pb_validate_validate(vswc->validate); 198 if (ret != PIPE_OK) { 199 mtx_lock(&vws->cs_mutex); 200 while (ret == PIPE_ERROR_RETRY) { 201 ret = pb_validate_validate(vswc->validate); 202 if (ret == PIPE_ERROR_RETRY) { 203 cnd_wait(&vws->cs_cond, &vws->cs_mutex); 204 } 205 } 206 if (ret != PIPE_OK) { 207 cnd_broadcast(&vws->cs_cond); 208 } 209 mtx_unlock(&vws->cs_mutex); 210 } 211 212 assert(ret == PIPE_OK); 213 if(ret == PIPE_OK) { 214 215 /* Apply relocations */ 216 for(i = 0; i < vswc->region.used; ++i) { 217 struct vmw_buffer_relocation *reloc = &vswc->region.relocs[i]; 218 struct SVGAGuestPtr ptr; 219 220 if(!vmw_gmr_bufmgr_region_ptr(reloc->buffer, &ptr)) 221 assert(0); 222 223 ptr.offset += reloc->offset; 224 225 if (reloc->is_mob) { 226 if (reloc->mob.id) 227 *reloc->mob.id = ptr.gmrId; 228 if (reloc->mob.offset_into_mob) 229 *reloc->mob.offset_into_mob = ptr.offset; 230 else { 231 assert(ptr.offset == 0); 232 } 233 } else 234 *reloc->region.where = ptr; 235 } 236 237 if (vswc->command.used || pfence != NULL) 238 vmw_ioctl_command(vws, 239 vswc->base.cid, 240 0, 241 vswc->command.buffer, 242 vswc->command.used, 243 &fence, 244 vswc->base.imported_fence_fd, 245 vswc->base.hints); 246 247 pb_validate_fence(vswc->validate, fence); 248 mtx_lock(&vws->cs_mutex); 249 cnd_broadcast(&vws->cs_cond); 250 mtx_unlock(&vws->cs_mutex); 251 } 252 253 vswc->command.used = 0; 254 vswc->command.reserved = 0; 255 256 for(i = 0; i < vswc->surface.used + vswc->surface.staged; ++i) { 257 struct vmw_ctx_validate_item *isurf = &vswc->surface.items[i]; 258 if (isurf->referenced) 259 p_atomic_dec(&isurf->vsurf->validated); 260 vmw_svga_winsys_surface_reference(&isurf->vsurf, NULL); 261 } 262 263 util_hash_table_clear(vswc->hash); 264 vswc->surface.used = 0; 265 vswc->surface.reserved = 0; 266 267 for(i = 0; i < vswc->shader.used + vswc->shader.staged; ++i) { 268 struct vmw_ctx_validate_item *ishader = &vswc->shader.items[i]; 269 if (ishader->referenced) 270 p_atomic_dec(&ishader->vshader->validated); 271 vmw_svga_winsys_shader_reference(&ishader->vshader, NULL); 272 } 273 274 vswc->shader.used = 0; 275 vswc->shader.reserved = 0; 276 277 vswc->region.used = 0; 278 vswc->region.reserved = 0; 279 280 #ifdef DEBUG 281 vswc->must_flush = FALSE; 282 debug_flush_flush(vswc->fctx); 283 #endif 284 swc->hints &= ~SVGA_HINT_FLAG_CAN_PRE_FLUSH; 285 swc->hints &= ~SVGA_HINT_FLAG_EXPORT_FENCE_FD; 286 vswc->preemptive_flush = FALSE; 287 vswc->seen_surfaces = 0; 288 vswc->seen_regions = 0; 289 vswc->seen_mobs = 0; 290 291 if (vswc->base.imported_fence_fd != -1) { 292 close(vswc->base.imported_fence_fd); 293 vswc->base.imported_fence_fd = -1; 294 } 295 296 if(pfence) 297 vmw_fence_reference(vswc->vws, pfence, fence); 298 299 vmw_fence_reference(vswc->vws, &fence, NULL); 300 301 return ret; 302 } 303 304 305 static void * 306 vmw_swc_reserve(struct svga_winsys_context *swc, 307 uint32_t nr_bytes, uint32_t nr_relocs ) 308 { 309 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 310 311 #ifdef DEBUG 312 /* Check if somebody forgot to check the previous failure */ 313 if(vswc->must_flush) { 314 debug_printf("Forgot to flush:\n"); 315 debug_backtrace_dump(vswc->must_flush_stack, VMW_MUST_FLUSH_STACK); 316 assert(!vswc->must_flush); 317 } 318 debug_flush_might_flush(vswc->fctx); 319 #endif 320 321 assert(nr_bytes <= vswc->command.size); 322 if(nr_bytes > vswc->command.size) 323 return NULL; 324 325 if(vswc->preemptive_flush || 326 vswc->command.used + nr_bytes > vswc->command.size || 327 vswc->surface.used + nr_relocs > vswc->surface.size || 328 vswc->shader.used + nr_relocs > vswc->shader.size || 329 vswc->region.used + nr_relocs > vswc->region.size) { 330 #ifdef DEBUG 331 vswc->must_flush = TRUE; 332 debug_backtrace_capture(vswc->must_flush_stack, 1, 333 VMW_MUST_FLUSH_STACK); 334 #endif 335 return NULL; 336 } 337 338 assert(vswc->command.used + nr_bytes <= vswc->command.size); 339 assert(vswc->surface.used + nr_relocs <= vswc->surface.size); 340 assert(vswc->shader.used + nr_relocs <= vswc->shader.size); 341 assert(vswc->region.used + nr_relocs <= vswc->region.size); 342 343 vswc->command.reserved = nr_bytes; 344 vswc->surface.reserved = nr_relocs; 345 vswc->surface.staged = 0; 346 vswc->shader.reserved = nr_relocs; 347 vswc->shader.staged = 0; 348 vswc->region.reserved = nr_relocs; 349 vswc->region.staged = 0; 350 351 return vswc->command.buffer + vswc->command.used; 352 } 353 354 static unsigned 355 vmw_swc_get_command_buffer_size(struct svga_winsys_context *swc) 356 { 357 const struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 358 return vswc->command.used; 359 } 360 361 static void 362 vmw_swc_context_relocation(struct svga_winsys_context *swc, 363 uint32 *cid) 364 { 365 *cid = swc->cid; 366 } 367 368 static boolean 369 vmw_swc_add_validate_buffer(struct vmw_svga_winsys_context *vswc, 370 struct pb_buffer *pb_buf, 371 unsigned flags) 372 { 373 enum pipe_error ret; 374 unsigned translated_flags; 375 376 /* 377 * TODO: Update pb_validate to provide a similar functionality 378 * (Check buffer already present before adding) 379 */ 380 if (util_hash_table_get(vswc->hash, pb_buf) != pb_buf) { 381 translated_flags = vmw_translate_to_pb_flags(flags); 382 ret = pb_validate_add_buffer(vswc->validate, pb_buf, translated_flags); 383 /* TODO: Update pipebuffer to reserve buffers and not fail here */ 384 assert(ret == PIPE_OK); 385 (void)ret; 386 (void)util_hash_table_set(vswc->hash, pb_buf, pb_buf); 387 return TRUE; 388 } 389 390 return FALSE; 391 } 392 393 static void 394 vmw_swc_region_relocation(struct svga_winsys_context *swc, 395 struct SVGAGuestPtr *where, 396 struct svga_winsys_buffer *buffer, 397 uint32 offset, 398 unsigned flags) 399 { 400 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 401 struct vmw_buffer_relocation *reloc; 402 403 assert(vswc->region.staged < vswc->region.reserved); 404 405 reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged]; 406 reloc->region.where = where; 407 408 /* 409 * pb_validate holds a refcount to the buffer, so no need to 410 * refcount it again in the relocation. 411 */ 412 reloc->buffer = vmw_pb_buffer(buffer); 413 reloc->offset = offset; 414 reloc->is_mob = FALSE; 415 ++vswc->region.staged; 416 417 if (vmw_swc_add_validate_buffer(vswc, reloc->buffer, flags)) { 418 vswc->seen_regions += reloc->buffer->size; 419 if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) && 420 vswc->seen_regions >= VMW_GMR_POOL_SIZE/5) 421 vswc->preemptive_flush = TRUE; 422 } 423 424 #ifdef DEBUG 425 if (!(flags & SVGA_RELOC_INTERNAL)) 426 debug_flush_cb_reference(vswc->fctx, vmw_debug_flush_buf(buffer)); 427 #endif 428 } 429 430 static void 431 vmw_swc_mob_relocation(struct svga_winsys_context *swc, 432 SVGAMobId *id, 433 uint32 *offset_into_mob, 434 struct svga_winsys_buffer *buffer, 435 uint32 offset, 436 unsigned flags) 437 { 438 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 439 struct vmw_buffer_relocation *reloc; 440 struct pb_buffer *pb_buffer = vmw_pb_buffer(buffer); 441 442 if (id) { 443 assert(vswc->region.staged < vswc->region.reserved); 444 445 reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged]; 446 reloc->mob.id = id; 447 reloc->mob.offset_into_mob = offset_into_mob; 448 449 /* 450 * pb_validate holds a refcount to the buffer, so no need to 451 * refcount it again in the relocation. 452 */ 453 reloc->buffer = pb_buffer; 454 reloc->offset = offset; 455 reloc->is_mob = TRUE; 456 ++vswc->region.staged; 457 } 458 459 if (vmw_swc_add_validate_buffer(vswc, pb_buffer, flags)) { 460 vswc->seen_mobs += pb_buffer->size; 461 462 if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) && 463 vswc->seen_mobs >= 464 vswc->vws->ioctl.max_mob_memory / VMW_MAX_MOB_MEM_FACTOR) 465 vswc->preemptive_flush = TRUE; 466 } 467 468 #ifdef DEBUG 469 if (!(flags & SVGA_RELOC_INTERNAL)) 470 debug_flush_cb_reference(vswc->fctx, vmw_debug_flush_buf(buffer)); 471 #endif 472 } 473 474 475 /** 476 * vmw_swc_surface_clear_reference - Clear referenced info for a surface 477 * 478 * @swc: Pointer to an svga_winsys_context 479 * @vsurf: Pointer to a vmw_svga_winsys_surface, the referenced info of which 480 * we want to clear 481 * 482 * This is primarily used by a discard surface map to indicate that the 483 * surface data is no longer referenced by a draw call, and mapping it 484 * should therefore no longer cause a flush. 485 */ 486 void 487 vmw_swc_surface_clear_reference(struct svga_winsys_context *swc, 488 struct vmw_svga_winsys_surface *vsurf) 489 { 490 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 491 struct vmw_ctx_validate_item *isrf = 492 util_hash_table_get(vswc->hash, vsurf); 493 494 if (isrf && isrf->referenced) { 495 isrf->referenced = FALSE; 496 p_atomic_dec(&vsurf->validated); 497 } 498 } 499 500 static void 501 vmw_swc_surface_only_relocation(struct svga_winsys_context *swc, 502 uint32 *where, 503 struct vmw_svga_winsys_surface *vsurf, 504 unsigned flags) 505 { 506 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 507 struct vmw_ctx_validate_item *isrf; 508 509 assert(vswc->surface.staged < vswc->surface.reserved); 510 isrf = util_hash_table_get(vswc->hash, vsurf); 511 512 if (isrf == NULL) { 513 isrf = &vswc->surface.items[vswc->surface.used + vswc->surface.staged]; 514 vmw_svga_winsys_surface_reference(&isrf->vsurf, vsurf); 515 isrf->referenced = FALSE; 516 /* 517 * Note that a failure here may just fall back to unhashed behavior 518 * and potentially cause unnecessary flushing, so ignore the 519 * return code. 520 */ 521 (void) util_hash_table_set(vswc->hash, vsurf, isrf); 522 ++vswc->surface.staged; 523 524 vswc->seen_surfaces += vsurf->size; 525 if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) && 526 vswc->seen_surfaces >= 527 vswc->vws->ioctl.max_surface_memory / VMW_MAX_SURF_MEM_FACTOR) 528 vswc->preemptive_flush = TRUE; 529 } 530 531 if (!(flags & SVGA_RELOC_INTERNAL) && !isrf->referenced) { 532 isrf->referenced = TRUE; 533 p_atomic_inc(&vsurf->validated); 534 } 535 536 if (where) 537 *where = vsurf->sid; 538 } 539 540 static void 541 vmw_swc_surface_relocation(struct svga_winsys_context *swc, 542 uint32 *where, 543 uint32 *mobid, 544 struct svga_winsys_surface *surface, 545 unsigned flags) 546 { 547 struct vmw_svga_winsys_surface *vsurf; 548 549 assert(swc->have_gb_objects || mobid == NULL); 550 551 if (!surface) { 552 *where = SVGA3D_INVALID_ID; 553 if (mobid) 554 *mobid = SVGA3D_INVALID_ID; 555 return; 556 } 557 558 vsurf = vmw_svga_winsys_surface(surface); 559 vmw_swc_surface_only_relocation(swc, where, vsurf, flags); 560 561 if (swc->have_gb_objects && vsurf->buf != NULL) { 562 563 /* 564 * Make sure backup buffer ends up fenced. 565 */ 566 567 mtx_lock(&vsurf->mutex); 568 assert(vsurf->buf != NULL); 569 570 vmw_swc_mob_relocation(swc, mobid, NULL, (struct svga_winsys_buffer *) 571 vsurf->buf, 0, flags); 572 mtx_unlock(&vsurf->mutex); 573 } 574 } 575 576 static void 577 vmw_swc_shader_relocation(struct svga_winsys_context *swc, 578 uint32 *shid, 579 uint32 *mobid, 580 uint32 *offset, 581 struct svga_winsys_gb_shader *shader, 582 unsigned flags) 583 { 584 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 585 struct vmw_winsys_screen *vws = vswc->vws; 586 struct vmw_svga_winsys_shader *vshader; 587 struct vmw_ctx_validate_item *ishader; 588 589 if(!shader) { 590 *shid = SVGA3D_INVALID_ID; 591 return; 592 } 593 594 vshader = vmw_svga_winsys_shader(shader); 595 596 if (!vws->base.have_vgpu10) { 597 assert(vswc->shader.staged < vswc->shader.reserved); 598 ishader = util_hash_table_get(vswc->hash, vshader); 599 600 if (ishader == NULL) { 601 ishader = &vswc->shader.items[vswc->shader.used + vswc->shader.staged]; 602 vmw_svga_winsys_shader_reference(&ishader->vshader, vshader); 603 ishader->referenced = FALSE; 604 /* 605 * Note that a failure here may just fall back to unhashed behavior 606 * and potentially cause unnecessary flushing, so ignore the 607 * return code. 608 */ 609 (void) util_hash_table_set(vswc->hash, vshader, ishader); 610 ++vswc->shader.staged; 611 } 612 613 if (!ishader->referenced) { 614 ishader->referenced = TRUE; 615 p_atomic_inc(&vshader->validated); 616 } 617 } 618 619 if (shid) 620 *shid = vshader->shid; 621 622 if (vshader->buf) 623 vmw_swc_mob_relocation(swc, mobid, offset, vshader->buf, 624 0, SVGA_RELOC_READ); 625 } 626 627 static void 628 vmw_swc_query_relocation(struct svga_winsys_context *swc, 629 SVGAMobId *id, 630 struct svga_winsys_gb_query *query) 631 { 632 /* Queries are backed by one big MOB */ 633 vmw_swc_mob_relocation(swc, id, NULL, query->buf, 0, 634 SVGA_RELOC_READ | SVGA_RELOC_WRITE); 635 } 636 637 static void 638 vmw_swc_commit(struct svga_winsys_context *swc) 639 { 640 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 641 642 assert(vswc->command.used + vswc->command.reserved <= vswc->command.size); 643 vswc->command.used += vswc->command.reserved; 644 vswc->command.reserved = 0; 645 646 assert(vswc->surface.staged <= vswc->surface.reserved); 647 assert(vswc->surface.used + vswc->surface.staged <= vswc->surface.size); 648 vswc->surface.used += vswc->surface.staged; 649 vswc->surface.staged = 0; 650 vswc->surface.reserved = 0; 651 652 assert(vswc->shader.staged <= vswc->shader.reserved); 653 assert(vswc->shader.used + vswc->shader.staged <= vswc->shader.size); 654 vswc->shader.used += vswc->shader.staged; 655 vswc->shader.staged = 0; 656 vswc->shader.reserved = 0; 657 658 assert(vswc->region.staged <= vswc->region.reserved); 659 assert(vswc->region.used + vswc->region.staged <= vswc->region.size); 660 vswc->region.used += vswc->region.staged; 661 vswc->region.staged = 0; 662 vswc->region.reserved = 0; 663 } 664 665 666 static void 667 vmw_swc_destroy(struct svga_winsys_context *swc) 668 { 669 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 670 unsigned i; 671 672 for(i = 0; i < vswc->surface.used; ++i) { 673 struct vmw_ctx_validate_item *isurf = &vswc->surface.items[i]; 674 if (isurf->referenced) 675 p_atomic_dec(&isurf->vsurf->validated); 676 vmw_svga_winsys_surface_reference(&isurf->vsurf, NULL); 677 } 678 679 for(i = 0; i < vswc->shader.used; ++i) { 680 struct vmw_ctx_validate_item *ishader = &vswc->shader.items[i]; 681 if (ishader->referenced) 682 p_atomic_dec(&ishader->vshader->validated); 683 vmw_svga_winsys_shader_reference(&ishader->vshader, NULL); 684 } 685 686 util_hash_table_destroy(vswc->hash); 687 pb_validate_destroy(vswc->validate); 688 vmw_ioctl_context_destroy(vswc->vws, swc->cid); 689 #ifdef DEBUG 690 debug_flush_ctx_destroy(vswc->fctx); 691 #endif 692 FREE(vswc); 693 } 694 695 static unsigned vmw_hash_ptr(void *p) 696 { 697 return (unsigned)(unsigned long)p; 698 } 699 700 static int vmw_ptr_compare(void *key1, void *key2) 701 { 702 return (key1 == key2) ? 0 : 1; 703 } 704 705 706 /** 707 * vmw_svga_winsys_vgpu10_shader_screate - The winsys shader_crate callback 708 * 709 * @swc: The winsys context. 710 * @shaderId: Previously allocated shader id. 711 * @shaderType: The shader type. 712 * @bytecode: The shader bytecode 713 * @bytecodelen: The length of the bytecode. 714 * 715 * Creates an svga_winsys_gb_shader structure and allocates a buffer for the 716 * shader code and copies the shader code into the buffer. Shader 717 * resource creation is not done. 718 */ 719 static struct svga_winsys_gb_shader * 720 vmw_svga_winsys_vgpu10_shader_create(struct svga_winsys_context *swc, 721 uint32 shaderId, 722 SVGA3dShaderType shaderType, 723 const uint32 *bytecode, 724 uint32 bytecodeLen) 725 { 726 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 727 struct vmw_svga_winsys_shader *shader; 728 struct svga_winsys_gb_shader *gb_shader = 729 vmw_svga_winsys_shader_create(&vswc->vws->base, shaderType, bytecode, 730 bytecodeLen); 731 if (!gb_shader) 732 return NULL; 733 734 shader = vmw_svga_winsys_shader(gb_shader); 735 shader->shid = shaderId; 736 737 return gb_shader; 738 } 739 740 /** 741 * vmw_svga_winsys_vgpu10_shader_destroy - The winsys shader_destroy callback. 742 * 743 * @swc: The winsys context. 744 * @shader: A shader structure previously allocated by shader_create. 745 * 746 * Frees the shader structure and the buffer holding the shader code. 747 */ 748 static void 749 vmw_svga_winsys_vgpu10_shader_destroy(struct svga_winsys_context *swc, 750 struct svga_winsys_gb_shader *shader) 751 { 752 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 753 754 vmw_svga_winsys_shader_destroy(&vswc->vws->base, shader); 755 } 756 757 /** 758 * vmw_svga_winsys_resource_rebind - The winsys resource_rebind callback 759 * 760 * @swc: The winsys context. 761 * @surface: The surface to be referenced. 762 * @shader: The shader to be referenced. 763 * @flags: Relocation flags. 764 * 765 * This callback is needed because shader backing buffers are sub-allocated, and 766 * hence the kernel fencing is not sufficient. The buffers need to be put on 767 * the context's validation list and fenced after command submission to avoid 768 * reuse of busy shader buffers. In addition, surfaces need to be put on the 769 * validation list in order for the driver to regard them as referenced 770 * by the command stream. 771 */ 772 static enum pipe_error 773 vmw_svga_winsys_resource_rebind(struct svga_winsys_context *swc, 774 struct svga_winsys_surface *surface, 775 struct svga_winsys_gb_shader *shader, 776 unsigned flags) 777 { 778 /** 779 * Need to reserve one validation item for either the surface or 780 * the shader. 781 */ 782 if (!vmw_swc_reserve(swc, 0, 1)) 783 return PIPE_ERROR_OUT_OF_MEMORY; 784 785 if (surface) 786 vmw_swc_surface_relocation(swc, NULL, NULL, surface, flags); 787 else if (shader) 788 vmw_swc_shader_relocation(swc, NULL, NULL, NULL, shader, flags); 789 790 vmw_swc_commit(swc); 791 792 return PIPE_OK; 793 } 794 795 struct svga_winsys_context * 796 vmw_svga_winsys_context_create(struct svga_winsys_screen *sws) 797 { 798 struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); 799 struct vmw_svga_winsys_context *vswc; 800 801 vswc = CALLOC_STRUCT(vmw_svga_winsys_context); 802 if(!vswc) 803 return NULL; 804 805 vswc->base.destroy = vmw_swc_destroy; 806 vswc->base.reserve = vmw_swc_reserve; 807 vswc->base.get_command_buffer_size = vmw_swc_get_command_buffer_size; 808 vswc->base.surface_relocation = vmw_swc_surface_relocation; 809 vswc->base.region_relocation = vmw_swc_region_relocation; 810 vswc->base.mob_relocation = vmw_swc_mob_relocation; 811 vswc->base.query_relocation = vmw_swc_query_relocation; 812 vswc->base.query_bind = vmw_swc_query_bind; 813 vswc->base.context_relocation = vmw_swc_context_relocation; 814 vswc->base.shader_relocation = vmw_swc_shader_relocation; 815 vswc->base.commit = vmw_swc_commit; 816 vswc->base.flush = vmw_swc_flush; 817 vswc->base.surface_map = vmw_svga_winsys_surface_map; 818 vswc->base.surface_unmap = vmw_svga_winsys_surface_unmap; 819 vswc->base.surface_invalidate = vmw_svga_winsys_surface_invalidate; 820 821 vswc->base.shader_create = vmw_svga_winsys_vgpu10_shader_create; 822 vswc->base.shader_destroy = vmw_svga_winsys_vgpu10_shader_destroy; 823 824 vswc->base.resource_rebind = vmw_svga_winsys_resource_rebind; 825 826 if (sws->have_vgpu10) 827 vswc->base.cid = vmw_ioctl_extended_context_create(vws, sws->have_vgpu10); 828 else 829 vswc->base.cid = vmw_ioctl_context_create(vws); 830 831 if (vswc->base.cid == -1) 832 goto out_no_context; 833 834 vswc->base.imported_fence_fd = -1; 835 836 vswc->base.have_gb_objects = sws->have_gb_objects; 837 838 vswc->vws = vws; 839 840 vswc->command.size = VMW_COMMAND_SIZE; 841 vswc->surface.size = VMW_SURFACE_RELOCS; 842 vswc->shader.size = VMW_SHADER_RELOCS; 843 vswc->region.size = VMW_REGION_RELOCS; 844 845 vswc->validate = pb_validate_create(); 846 if(!vswc->validate) 847 goto out_no_validate; 848 849 vswc->hash = util_hash_table_create(vmw_hash_ptr, vmw_ptr_compare); 850 if (!vswc->hash) 851 goto out_no_hash; 852 853 #ifdef DEBUG 854 vswc->fctx = debug_flush_ctx_create(TRUE, VMW_DEBUG_FLUSH_STACK); 855 #endif 856 857 return &vswc->base; 858 859 out_no_hash: 860 pb_validate_destroy(vswc->validate); 861 out_no_validate: 862 vmw_ioctl_context_destroy(vws, vswc->base.cid); 863 out_no_context: 864 FREE(vswc); 865 return NULL; 866 } 867