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 pipe_fence_handle *fence = NULL; 183 unsigned i; 184 enum pipe_error ret; 185 186 ret = pb_validate_validate(vswc->validate); 187 assert(ret == PIPE_OK); 188 if(ret == PIPE_OK) { 189 190 /* Apply relocations */ 191 for(i = 0; i < vswc->region.used; ++i) { 192 struct vmw_buffer_relocation *reloc = &vswc->region.relocs[i]; 193 struct SVGAGuestPtr ptr; 194 195 if(!vmw_gmr_bufmgr_region_ptr(reloc->buffer, &ptr)) 196 assert(0); 197 198 ptr.offset += reloc->offset; 199 200 if (reloc->is_mob) { 201 if (reloc->mob.id) 202 *reloc->mob.id = ptr.gmrId; 203 if (reloc->mob.offset_into_mob) 204 *reloc->mob.offset_into_mob = ptr.offset; 205 else { 206 assert(ptr.offset == 0); 207 } 208 } else 209 *reloc->region.where = ptr; 210 } 211 212 if (vswc->command.used || pfence != NULL) 213 vmw_ioctl_command(vswc->vws, 214 vswc->base.cid, 215 0, 216 vswc->command.buffer, 217 vswc->command.used, 218 &fence); 219 220 pb_validate_fence(vswc->validate, fence); 221 } 222 223 vswc->command.used = 0; 224 vswc->command.reserved = 0; 225 226 for(i = 0; i < vswc->surface.used + vswc->surface.staged; ++i) { 227 struct vmw_ctx_validate_item *isurf = &vswc->surface.items[i]; 228 if (isurf->referenced) 229 p_atomic_dec(&isurf->vsurf->validated); 230 vmw_svga_winsys_surface_reference(&isurf->vsurf, NULL); 231 } 232 233 util_hash_table_clear(vswc->hash); 234 vswc->surface.used = 0; 235 vswc->surface.reserved = 0; 236 237 for(i = 0; i < vswc->shader.used + vswc->shader.staged; ++i) { 238 struct vmw_ctx_validate_item *ishader = &vswc->shader.items[i]; 239 if (ishader->referenced) 240 p_atomic_dec(&ishader->vshader->validated); 241 vmw_svga_winsys_shader_reference(&ishader->vshader, NULL); 242 } 243 244 vswc->shader.used = 0; 245 vswc->shader.reserved = 0; 246 247 vswc->region.used = 0; 248 vswc->region.reserved = 0; 249 250 #ifdef DEBUG 251 vswc->must_flush = FALSE; 252 debug_flush_flush(vswc->fctx); 253 #endif 254 swc->hints &= ~SVGA_HINT_FLAG_CAN_PRE_FLUSH; 255 vswc->preemptive_flush = FALSE; 256 vswc->seen_surfaces = 0; 257 vswc->seen_regions = 0; 258 vswc->seen_mobs = 0; 259 260 if(pfence) 261 vmw_fence_reference(vswc->vws, pfence, fence); 262 263 vmw_fence_reference(vswc->vws, &fence, NULL); 264 265 return ret; 266 } 267 268 269 static void * 270 vmw_swc_reserve(struct svga_winsys_context *swc, 271 uint32_t nr_bytes, uint32_t nr_relocs ) 272 { 273 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 274 275 #ifdef DEBUG 276 /* Check if somebody forgot to check the previous failure */ 277 if(vswc->must_flush) { 278 debug_printf("Forgot to flush:\n"); 279 debug_backtrace_dump(vswc->must_flush_stack, VMW_MUST_FLUSH_STACK); 280 assert(!vswc->must_flush); 281 } 282 debug_flush_might_flush(vswc->fctx); 283 #endif 284 285 assert(nr_bytes <= vswc->command.size); 286 if(nr_bytes > vswc->command.size) 287 return NULL; 288 289 if(vswc->preemptive_flush || 290 vswc->command.used + nr_bytes > vswc->command.size || 291 vswc->surface.used + nr_relocs > vswc->surface.size || 292 vswc->shader.used + nr_relocs > vswc->shader.size || 293 vswc->region.used + nr_relocs > vswc->region.size) { 294 #ifdef DEBUG 295 vswc->must_flush = TRUE; 296 debug_backtrace_capture(vswc->must_flush_stack, 1, 297 VMW_MUST_FLUSH_STACK); 298 #endif 299 return NULL; 300 } 301 302 assert(vswc->command.used + nr_bytes <= vswc->command.size); 303 assert(vswc->surface.used + nr_relocs <= vswc->surface.size); 304 assert(vswc->shader.used + nr_relocs <= vswc->shader.size); 305 assert(vswc->region.used + nr_relocs <= vswc->region.size); 306 307 vswc->command.reserved = nr_bytes; 308 vswc->surface.reserved = nr_relocs; 309 vswc->surface.staged = 0; 310 vswc->shader.reserved = nr_relocs; 311 vswc->shader.staged = 0; 312 vswc->region.reserved = nr_relocs; 313 vswc->region.staged = 0; 314 315 return vswc->command.buffer + vswc->command.used; 316 } 317 318 static unsigned 319 vmw_swc_get_command_buffer_size(struct svga_winsys_context *swc) 320 { 321 const struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 322 return vswc->command.used; 323 } 324 325 static void 326 vmw_swc_context_relocation(struct svga_winsys_context *swc, 327 uint32 *cid) 328 { 329 *cid = swc->cid; 330 } 331 332 static boolean 333 vmw_swc_add_validate_buffer(struct vmw_svga_winsys_context *vswc, 334 struct pb_buffer *pb_buf, 335 unsigned flags) 336 { 337 enum pipe_error ret; 338 unsigned translated_flags; 339 340 /* 341 * TODO: Update pb_validate to provide a similar functionality 342 * (Check buffer already present before adding) 343 */ 344 if (util_hash_table_get(vswc->hash, pb_buf) != pb_buf) { 345 translated_flags = vmw_translate_to_pb_flags(flags); 346 ret = pb_validate_add_buffer(vswc->validate, pb_buf, translated_flags); 347 /* TODO: Update pipebuffer to reserve buffers and not fail here */ 348 assert(ret == PIPE_OK); 349 (void)ret; 350 (void)util_hash_table_set(vswc->hash, pb_buf, pb_buf); 351 return TRUE; 352 } 353 354 return FALSE; 355 } 356 357 static void 358 vmw_swc_region_relocation(struct svga_winsys_context *swc, 359 struct SVGAGuestPtr *where, 360 struct svga_winsys_buffer *buffer, 361 uint32 offset, 362 unsigned flags) 363 { 364 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 365 struct vmw_buffer_relocation *reloc; 366 367 assert(vswc->region.staged < vswc->region.reserved); 368 369 reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged]; 370 reloc->region.where = where; 371 372 /* 373 * pb_validate holds a refcount to the buffer, so no need to 374 * refcount it again in the relocation. 375 */ 376 reloc->buffer = vmw_pb_buffer(buffer); 377 reloc->offset = offset; 378 reloc->is_mob = FALSE; 379 ++vswc->region.staged; 380 381 if (vmw_swc_add_validate_buffer(vswc, reloc->buffer, flags)) { 382 vswc->seen_regions += reloc->buffer->size; 383 if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) && 384 vswc->seen_regions >= VMW_GMR_POOL_SIZE/5) 385 vswc->preemptive_flush = TRUE; 386 } 387 388 #ifdef DEBUG 389 if (!(flags & SVGA_RELOC_INTERNAL)) 390 debug_flush_cb_reference(vswc->fctx, vmw_debug_flush_buf(buffer)); 391 #endif 392 } 393 394 static void 395 vmw_swc_mob_relocation(struct svga_winsys_context *swc, 396 SVGAMobId *id, 397 uint32 *offset_into_mob, 398 struct svga_winsys_buffer *buffer, 399 uint32 offset, 400 unsigned flags) 401 { 402 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 403 struct vmw_buffer_relocation *reloc; 404 struct pb_buffer *pb_buffer = vmw_pb_buffer(buffer); 405 406 if (id) { 407 assert(vswc->region.staged < vswc->region.reserved); 408 409 reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged]; 410 reloc->mob.id = id; 411 reloc->mob.offset_into_mob = offset_into_mob; 412 413 /* 414 * pb_validate holds a refcount to the buffer, so no need to 415 * refcount it again in the relocation. 416 */ 417 reloc->buffer = pb_buffer; 418 reloc->offset = offset; 419 reloc->is_mob = TRUE; 420 ++vswc->region.staged; 421 } 422 423 if (vmw_swc_add_validate_buffer(vswc, pb_buffer, flags)) { 424 vswc->seen_mobs += pb_buffer->size; 425 426 if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) && 427 vswc->seen_mobs >= 428 vswc->vws->ioctl.max_mob_memory / VMW_MAX_MOB_MEM_FACTOR) 429 vswc->preemptive_flush = TRUE; 430 } 431 432 #ifdef DEBUG 433 if (!(flags & SVGA_RELOC_INTERNAL)) 434 debug_flush_cb_reference(vswc->fctx, vmw_debug_flush_buf(buffer)); 435 #endif 436 } 437 438 439 /** 440 * vmw_swc_surface_clear_reference - Clear referenced info for a surface 441 * 442 * @swc: Pointer to an svga_winsys_context 443 * @vsurf: Pointer to a vmw_svga_winsys_surface, the referenced info of which 444 * we want to clear 445 * 446 * This is primarily used by a discard surface map to indicate that the 447 * surface data is no longer referenced by a draw call, and mapping it 448 * should therefore no longer cause a flush. 449 */ 450 void 451 vmw_swc_surface_clear_reference(struct svga_winsys_context *swc, 452 struct vmw_svga_winsys_surface *vsurf) 453 { 454 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 455 struct vmw_ctx_validate_item *isrf = 456 util_hash_table_get(vswc->hash, vsurf); 457 458 if (isrf && isrf->referenced) { 459 isrf->referenced = FALSE; 460 p_atomic_dec(&vsurf->validated); 461 } 462 } 463 464 static void 465 vmw_swc_surface_only_relocation(struct svga_winsys_context *swc, 466 uint32 *where, 467 struct vmw_svga_winsys_surface *vsurf, 468 unsigned flags) 469 { 470 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 471 struct vmw_ctx_validate_item *isrf; 472 473 assert(vswc->surface.staged < vswc->surface.reserved); 474 isrf = util_hash_table_get(vswc->hash, vsurf); 475 476 if (isrf == NULL) { 477 isrf = &vswc->surface.items[vswc->surface.used + vswc->surface.staged]; 478 vmw_svga_winsys_surface_reference(&isrf->vsurf, vsurf); 479 isrf->referenced = FALSE; 480 /* 481 * Note that a failure here may just fall back to unhashed behavior 482 * and potentially cause unnecessary flushing, so ignore the 483 * return code. 484 */ 485 (void) util_hash_table_set(vswc->hash, vsurf, isrf); 486 ++vswc->surface.staged; 487 488 vswc->seen_surfaces += vsurf->size; 489 if ((swc->hints & SVGA_HINT_FLAG_CAN_PRE_FLUSH) && 490 vswc->seen_surfaces >= 491 vswc->vws->ioctl.max_surface_memory / VMW_MAX_SURF_MEM_FACTOR) 492 vswc->preemptive_flush = TRUE; 493 } 494 495 if (!(flags & SVGA_RELOC_INTERNAL) && !isrf->referenced) { 496 isrf->referenced = TRUE; 497 p_atomic_inc(&vsurf->validated); 498 } 499 500 if (where) 501 *where = vsurf->sid; 502 } 503 504 static void 505 vmw_swc_surface_relocation(struct svga_winsys_context *swc, 506 uint32 *where, 507 uint32 *mobid, 508 struct svga_winsys_surface *surface, 509 unsigned flags) 510 { 511 struct vmw_svga_winsys_surface *vsurf; 512 513 assert(swc->have_gb_objects || mobid == NULL); 514 515 if (!surface) { 516 *where = SVGA3D_INVALID_ID; 517 if (mobid) 518 *mobid = SVGA3D_INVALID_ID; 519 return; 520 } 521 522 vsurf = vmw_svga_winsys_surface(surface); 523 vmw_swc_surface_only_relocation(swc, where, vsurf, flags); 524 525 if (swc->have_gb_objects && vsurf->buf != NULL) { 526 527 /* 528 * Make sure backup buffer ends up fenced. 529 */ 530 531 pipe_mutex_lock(vsurf->mutex); 532 assert(vsurf->buf != NULL); 533 534 vmw_swc_mob_relocation(swc, mobid, NULL, (struct svga_winsys_buffer *) 535 vsurf->buf, 0, flags); 536 pipe_mutex_unlock(vsurf->mutex); 537 } 538 } 539 540 static void 541 vmw_swc_shader_relocation(struct svga_winsys_context *swc, 542 uint32 *shid, 543 uint32 *mobid, 544 uint32 *offset, 545 struct svga_winsys_gb_shader *shader, 546 unsigned flags) 547 { 548 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 549 struct vmw_winsys_screen *vws = vswc->vws; 550 struct vmw_svga_winsys_shader *vshader; 551 struct vmw_ctx_validate_item *ishader; 552 553 if(!shader) { 554 *shid = SVGA3D_INVALID_ID; 555 return; 556 } 557 558 vshader = vmw_svga_winsys_shader(shader); 559 560 if (!vws->base.have_vgpu10) { 561 assert(vswc->shader.staged < vswc->shader.reserved); 562 ishader = util_hash_table_get(vswc->hash, vshader); 563 564 if (ishader == NULL) { 565 ishader = &vswc->shader.items[vswc->shader.used + vswc->shader.staged]; 566 vmw_svga_winsys_shader_reference(&ishader->vshader, vshader); 567 ishader->referenced = FALSE; 568 /* 569 * Note that a failure here may just fall back to unhashed behavior 570 * and potentially cause unnecessary flushing, so ignore the 571 * return code. 572 */ 573 (void) util_hash_table_set(vswc->hash, vshader, ishader); 574 ++vswc->shader.staged; 575 } 576 577 if (!ishader->referenced) { 578 ishader->referenced = TRUE; 579 p_atomic_inc(&vshader->validated); 580 } 581 } 582 583 if (shid) 584 *shid = vshader->shid; 585 586 if (vshader->buf) 587 vmw_swc_mob_relocation(swc, mobid, offset, vshader->buf, 588 0, SVGA_RELOC_READ); 589 } 590 591 static void 592 vmw_swc_query_relocation(struct svga_winsys_context *swc, 593 SVGAMobId *id, 594 struct svga_winsys_gb_query *query) 595 { 596 /* Queries are backed by one big MOB */ 597 vmw_swc_mob_relocation(swc, id, NULL, query->buf, 0, 598 SVGA_RELOC_READ | SVGA_RELOC_WRITE); 599 } 600 601 static void 602 vmw_swc_commit(struct svga_winsys_context *swc) 603 { 604 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 605 606 assert(vswc->command.used + vswc->command.reserved <= vswc->command.size); 607 vswc->command.used += vswc->command.reserved; 608 vswc->command.reserved = 0; 609 610 assert(vswc->surface.staged <= vswc->surface.reserved); 611 assert(vswc->surface.used + vswc->surface.staged <= vswc->surface.size); 612 vswc->surface.used += vswc->surface.staged; 613 vswc->surface.staged = 0; 614 vswc->surface.reserved = 0; 615 616 assert(vswc->shader.staged <= vswc->shader.reserved); 617 assert(vswc->shader.used + vswc->shader.staged <= vswc->shader.size); 618 vswc->shader.used += vswc->shader.staged; 619 vswc->shader.staged = 0; 620 vswc->shader.reserved = 0; 621 622 assert(vswc->region.staged <= vswc->region.reserved); 623 assert(vswc->region.used + vswc->region.staged <= vswc->region.size); 624 vswc->region.used += vswc->region.staged; 625 vswc->region.staged = 0; 626 vswc->region.reserved = 0; 627 } 628 629 630 static void 631 vmw_swc_destroy(struct svga_winsys_context *swc) 632 { 633 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 634 unsigned i; 635 636 for(i = 0; i < vswc->surface.used; ++i) { 637 struct vmw_ctx_validate_item *isurf = &vswc->surface.items[i]; 638 if (isurf->referenced) 639 p_atomic_dec(&isurf->vsurf->validated); 640 vmw_svga_winsys_surface_reference(&isurf->vsurf, NULL); 641 } 642 643 for(i = 0; i < vswc->shader.used; ++i) { 644 struct vmw_ctx_validate_item *ishader = &vswc->shader.items[i]; 645 if (ishader->referenced) 646 p_atomic_dec(&ishader->vshader->validated); 647 vmw_svga_winsys_shader_reference(&ishader->vshader, NULL); 648 } 649 650 util_hash_table_destroy(vswc->hash); 651 pb_validate_destroy(vswc->validate); 652 vmw_ioctl_context_destroy(vswc->vws, swc->cid); 653 #ifdef DEBUG 654 debug_flush_ctx_destroy(vswc->fctx); 655 #endif 656 FREE(vswc); 657 } 658 659 static unsigned vmw_hash_ptr(void *p) 660 { 661 return (unsigned)(unsigned long)p; 662 } 663 664 static int vmw_ptr_compare(void *key1, void *key2) 665 { 666 return (key1 == key2) ? 0 : 1; 667 } 668 669 670 /** 671 * vmw_svga_winsys_vgpu10_shader_screate - The winsys shader_crate callback 672 * 673 * @swc: The winsys context. 674 * @shaderId: Previously allocated shader id. 675 * @shaderType: The shader type. 676 * @bytecode: The shader bytecode 677 * @bytecodelen: The length of the bytecode. 678 * 679 * Creates an svga_winsys_gb_shader structure and allocates a buffer for the 680 * shader code and copies the shader code into the buffer. Shader 681 * resource creation is not done. 682 */ 683 static struct svga_winsys_gb_shader * 684 vmw_svga_winsys_vgpu10_shader_create(struct svga_winsys_context *swc, 685 uint32 shaderId, 686 SVGA3dShaderType shaderType, 687 const uint32 *bytecode, 688 uint32 bytecodeLen) 689 { 690 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 691 struct vmw_svga_winsys_shader *shader; 692 struct svga_winsys_gb_shader *gb_shader = 693 vmw_svga_winsys_shader_create(&vswc->vws->base, shaderType, bytecode, 694 bytecodeLen); 695 if (!gb_shader) 696 return NULL; 697 698 shader = vmw_svga_winsys_shader(gb_shader); 699 shader->shid = shaderId; 700 701 return gb_shader; 702 } 703 704 /** 705 * vmw_svga_winsys_vgpu10_shader_destroy - The winsys shader_destroy callback. 706 * 707 * @swc: The winsys context. 708 * @shader: A shader structure previously allocated by shader_create. 709 * 710 * Frees the shader structure and the buffer holding the shader code. 711 */ 712 static void 713 vmw_svga_winsys_vgpu10_shader_destroy(struct svga_winsys_context *swc, 714 struct svga_winsys_gb_shader *shader) 715 { 716 struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); 717 718 vmw_svga_winsys_shader_destroy(&vswc->vws->base, shader); 719 } 720 721 /** 722 * vmw_svga_winsys_resource_rebind - The winsys resource_rebind callback 723 * 724 * @swc: The winsys context. 725 * @surface: The surface to be referenced. 726 * @shader: The shader to be referenced. 727 * @flags: Relocation flags. 728 * 729 * This callback is needed because shader backing buffers are sub-allocated, and 730 * hence the kernel fencing is not sufficient. The buffers need to be put on 731 * the context's validation list and fenced after command submission to avoid 732 * reuse of busy shader buffers. In addition, surfaces need to be put on the 733 * validation list in order for the driver to regard them as referenced 734 * by the command stream. 735 */ 736 static enum pipe_error 737 vmw_svga_winsys_resource_rebind(struct svga_winsys_context *swc, 738 struct svga_winsys_surface *surface, 739 struct svga_winsys_gb_shader *shader, 740 unsigned flags) 741 { 742 /** 743 * Need to reserve one validation item for either the surface or 744 * the shader. 745 */ 746 if (!vmw_swc_reserve(swc, 0, 1)) 747 return PIPE_ERROR_OUT_OF_MEMORY; 748 749 if (surface) 750 vmw_swc_surface_relocation(swc, NULL, NULL, surface, flags); 751 else if (shader) 752 vmw_swc_shader_relocation(swc, NULL, NULL, NULL, shader, flags); 753 754 vmw_swc_commit(swc); 755 756 return PIPE_OK; 757 } 758 759 struct svga_winsys_context * 760 vmw_svga_winsys_context_create(struct svga_winsys_screen *sws) 761 { 762 struct vmw_winsys_screen *vws = vmw_winsys_screen(sws); 763 struct vmw_svga_winsys_context *vswc; 764 765 vswc = CALLOC_STRUCT(vmw_svga_winsys_context); 766 if(!vswc) 767 return NULL; 768 769 vswc->base.destroy = vmw_swc_destroy; 770 vswc->base.reserve = vmw_swc_reserve; 771 vswc->base.get_command_buffer_size = vmw_swc_get_command_buffer_size; 772 vswc->base.surface_relocation = vmw_swc_surface_relocation; 773 vswc->base.region_relocation = vmw_swc_region_relocation; 774 vswc->base.mob_relocation = vmw_swc_mob_relocation; 775 vswc->base.query_relocation = vmw_swc_query_relocation; 776 vswc->base.query_bind = vmw_swc_query_bind; 777 vswc->base.context_relocation = vmw_swc_context_relocation; 778 vswc->base.shader_relocation = vmw_swc_shader_relocation; 779 vswc->base.commit = vmw_swc_commit; 780 vswc->base.flush = vmw_swc_flush; 781 vswc->base.surface_map = vmw_svga_winsys_surface_map; 782 vswc->base.surface_unmap = vmw_svga_winsys_surface_unmap; 783 784 vswc->base.shader_create = vmw_svga_winsys_vgpu10_shader_create; 785 vswc->base.shader_destroy = vmw_svga_winsys_vgpu10_shader_destroy; 786 787 vswc->base.resource_rebind = vmw_svga_winsys_resource_rebind; 788 789 if (sws->have_vgpu10) 790 vswc->base.cid = vmw_ioctl_extended_context_create(vws, sws->have_vgpu10); 791 else 792 vswc->base.cid = vmw_ioctl_context_create(vws); 793 794 if (vswc->base.cid == -1) 795 goto out_no_context; 796 797 vswc->base.have_gb_objects = sws->have_gb_objects; 798 799 vswc->vws = vws; 800 801 vswc->command.size = VMW_COMMAND_SIZE; 802 vswc->surface.size = VMW_SURFACE_RELOCS; 803 vswc->shader.size = VMW_SHADER_RELOCS; 804 vswc->region.size = VMW_REGION_RELOCS; 805 806 vswc->validate = pb_validate_create(); 807 if(!vswc->validate) 808 goto out_no_validate; 809 810 vswc->hash = util_hash_table_create(vmw_hash_ptr, vmw_ptr_compare); 811 if (!vswc->hash) 812 goto out_no_hash; 813 814 #ifdef DEBUG 815 vswc->fctx = debug_flush_ctx_create(TRUE, VMW_DEBUG_FLUSH_STACK); 816 #endif 817 818 return &vswc->base; 819 820 out_no_hash: 821 pb_validate_destroy(vswc->validate); 822 out_no_validate: 823 vmw_ioctl_context_destroy(vws, vswc->base.cid); 824 out_no_context: 825 FREE(vswc); 826 return NULL; 827 } 828