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