1/* $NetBSD: vmwgfx_binding.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $ */ 2 3// SPDX-License-Identifier: GPL-2.0 OR MIT 4/************************************************************************** 5 * 6 * Copyright 2015 VMware, Inc., Palo Alto, CA., USA 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sub license, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial portions 18 * of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 23 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 24 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 25 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 26 * USE OR OTHER DEALINGS IN THE SOFTWARE. 27 * 28 **************************************************************************/ 29/* 30 * This file implements the vmwgfx context binding manager, 31 * The sole reason for having to use this code is that vmware guest 32 * backed contexts can be swapped out to their backing mobs by the device 33 * at any time, also swapped in at any time. At swapin time, the device 34 * validates the context bindings to make sure they point to valid resources. 35 * It's this outside-of-drawcall validation (that can happen at any time), 36 * that makes this code necessary. 37 * 38 * We therefore need to kill any context bindings pointing to a resource 39 * when the resource is swapped out. Furthermore, if the vmwgfx driver has 40 * swapped out the context we can't swap it in again to kill bindings because 41 * of backing mob reservation lockdep violations, so as part of 42 * context swapout, also kill all bindings of a context, so that they are 43 * already killed if a resource to which a binding points 44 * needs to be swapped out. 45 * 46 * Note that a resource can be pointed to by bindings from multiple contexts, 47 * Therefore we can't easily protect this data by a per context mutex 48 * (unless we use deadlock-safe WW mutexes). So we use a global binding_mutex 49 * to protect all binding manager data. 50 * 51 * Finally, any association between a context and a global resource 52 * (surface, shader or even DX query) is conceptually a context binding that 53 * needs to be tracked by this code. 54 */ 55 56#include <sys/cdefs.h> 57__KERNEL_RCSID(0, "$NetBSD: vmwgfx_binding.c,v 1.3 2021/12/18 23:45:45 riastradh Exp $"); 58 59#include "vmwgfx_drv.h" 60#include "vmwgfx_binding.h" 61#include "device_include/svga3d_reg.h" 62 63#define VMW_BINDING_RT_BIT 0 64#define VMW_BINDING_PS_BIT 1 65#define VMW_BINDING_SO_BIT 2 66#define VMW_BINDING_VB_BIT 3 67#define VMW_BINDING_NUM_BITS 4 68 69#define VMW_BINDING_PS_SR_BIT 0 70 71/** 72 * struct vmw_ctx_binding_state - per context binding state 73 * 74 * @dev_priv: Pointer to device private structure. 75 * @list: linked list of individual active bindings. 76 * @render_targets: Render target bindings. 77 * @texture_units: Texture units bindings. 78 * @ds_view: Depth-stencil view binding. 79 * @so_targets: StreamOutput target bindings. 80 * @vertex_buffers: Vertex buffer bindings. 81 * @index_buffer: Index buffer binding. 82 * @per_shader: Per shader-type bindings. 83 * @dirty: Bitmap tracking per binding-type changes that have not yet 84 * been emitted to the device. 85 * @dirty_vb: Bitmap tracking individual vertex buffer binding changes that 86 * have not yet been emitted to the device. 87 * @bind_cmd_buffer: Scratch space used to construct binding commands. 88 * @bind_cmd_count: Number of binding command data entries in @bind_cmd_buffer 89 * @bind_first_slot: Used together with @bind_cmd_buffer to indicate the 90 * device binding slot of the first command data entry in @bind_cmd_buffer. 91 * 92 * Note that this structure also provides storage space for the individual 93 * struct vmw_ctx_binding objects, so that no dynamic allocation is needed 94 * for individual bindings. 95 * 96 */ 97struct vmw_ctx_binding_state { 98 struct vmw_private *dev_priv; 99 struct list_head list; 100 struct vmw_ctx_bindinfo_view render_targets[SVGA3D_RT_MAX]; 101 struct vmw_ctx_bindinfo_tex texture_units[SVGA3D_NUM_TEXTURE_UNITS]; 102 struct vmw_ctx_bindinfo_view ds_view; 103 struct vmw_ctx_bindinfo_so so_targets[SVGA3D_DX_MAX_SOTARGETS]; 104 struct vmw_ctx_bindinfo_vb vertex_buffers[SVGA3D_DX_MAX_VERTEXBUFFERS]; 105 struct vmw_ctx_bindinfo_ib index_buffer; 106 struct vmw_dx_shader_bindings per_shader[SVGA3D_NUM_SHADERTYPE_DX10]; 107 108 unsigned long dirty; 109 DECLARE_BITMAP(dirty_vb, SVGA3D_DX_MAX_VERTEXBUFFERS); 110 111 u32 bind_cmd_buffer[VMW_MAX_VIEW_BINDINGS]; 112 u32 bind_cmd_count; 113 u32 bind_first_slot; 114}; 115 116static int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind); 117static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi, 118 bool rebind); 119static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi, bool rebind); 120static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind); 121static int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind); 122static int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind); 123static int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind); 124static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs); 125static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi, 126 bool rebind); 127static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind); 128static int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind); 129static void vmw_binding_build_asserts(void) __attribute__ ((unused)); 130 131typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *, bool); 132 133/** 134 * struct vmw_binding_info - Per binding type information for the binding 135 * manager 136 * 137 * @size: The size of the struct binding derived from a struct vmw_ctx_bindinfo. 138 * @offsets: array[shader_slot] of offsets to the array[slot] 139 * of struct bindings for the binding type. 140 * @scrub_func: Pointer to the scrub function for this binding type. 141 * 142 * Holds static information to help optimize the binding manager and avoid 143 * an excessive amount of switch statements. 144 */ 145struct vmw_binding_info { 146 size_t size; 147 const size_t *offsets; 148 vmw_scrub_func scrub_func; 149}; 150 151/* 152 * A number of static variables that help determine the scrub func and the 153 * location of the struct vmw_ctx_bindinfo slots for each binding type. 154 */ 155static const size_t vmw_binding_shader_offsets[] = { 156 offsetof(struct vmw_ctx_binding_state, per_shader[0].shader), 157 offsetof(struct vmw_ctx_binding_state, per_shader[1].shader), 158 offsetof(struct vmw_ctx_binding_state, per_shader[2].shader), 159}; 160static const size_t vmw_binding_rt_offsets[] = { 161 offsetof(struct vmw_ctx_binding_state, render_targets), 162}; 163static const size_t vmw_binding_tex_offsets[] = { 164 offsetof(struct vmw_ctx_binding_state, texture_units), 165}; 166static const size_t vmw_binding_cb_offsets[] = { 167 offsetof(struct vmw_ctx_binding_state, per_shader[0].const_buffers), 168 offsetof(struct vmw_ctx_binding_state, per_shader[1].const_buffers), 169 offsetof(struct vmw_ctx_binding_state, per_shader[2].const_buffers), 170}; 171static const size_t vmw_binding_dx_ds_offsets[] = { 172 offsetof(struct vmw_ctx_binding_state, ds_view), 173}; 174static const size_t vmw_binding_sr_offsets[] = { 175 offsetof(struct vmw_ctx_binding_state, per_shader[0].shader_res), 176 offsetof(struct vmw_ctx_binding_state, per_shader[1].shader_res), 177 offsetof(struct vmw_ctx_binding_state, per_shader[2].shader_res), 178}; 179static const size_t vmw_binding_so_offsets[] = { 180 offsetof(struct vmw_ctx_binding_state, so_targets), 181}; 182static const size_t vmw_binding_vb_offsets[] = { 183 offsetof(struct vmw_ctx_binding_state, vertex_buffers), 184}; 185static const size_t vmw_binding_ib_offsets[] = { 186 offsetof(struct vmw_ctx_binding_state, index_buffer), 187}; 188 189static const struct vmw_binding_info vmw_binding_infos[] = { 190 [vmw_ctx_binding_shader] = { 191 .size = sizeof(struct vmw_ctx_bindinfo_shader), 192 .offsets = vmw_binding_shader_offsets, 193 .scrub_func = vmw_binding_scrub_shader}, 194 [vmw_ctx_binding_rt] = { 195 .size = sizeof(struct vmw_ctx_bindinfo_view), 196 .offsets = vmw_binding_rt_offsets, 197 .scrub_func = vmw_binding_scrub_render_target}, 198 [vmw_ctx_binding_tex] = { 199 .size = sizeof(struct vmw_ctx_bindinfo_tex), 200 .offsets = vmw_binding_tex_offsets, 201 .scrub_func = vmw_binding_scrub_texture}, 202 [vmw_ctx_binding_cb] = { 203 .size = sizeof(struct vmw_ctx_bindinfo_cb), 204 .offsets = vmw_binding_cb_offsets, 205 .scrub_func = vmw_binding_scrub_cb}, 206 [vmw_ctx_binding_dx_shader] = { 207 .size = sizeof(struct vmw_ctx_bindinfo_shader), 208 .offsets = vmw_binding_shader_offsets, 209 .scrub_func = vmw_binding_scrub_dx_shader}, 210 [vmw_ctx_binding_dx_rt] = { 211 .size = sizeof(struct vmw_ctx_bindinfo_view), 212 .offsets = vmw_binding_rt_offsets, 213 .scrub_func = vmw_binding_scrub_dx_rt}, 214 [vmw_ctx_binding_sr] = { 215 .size = sizeof(struct vmw_ctx_bindinfo_view), 216 .offsets = vmw_binding_sr_offsets, 217 .scrub_func = vmw_binding_scrub_sr}, 218 [vmw_ctx_binding_ds] = { 219 .size = sizeof(struct vmw_ctx_bindinfo_view), 220 .offsets = vmw_binding_dx_ds_offsets, 221 .scrub_func = vmw_binding_scrub_dx_rt}, 222 [vmw_ctx_binding_so] = { 223 .size = sizeof(struct vmw_ctx_bindinfo_so), 224 .offsets = vmw_binding_so_offsets, 225 .scrub_func = vmw_binding_scrub_so}, 226 [vmw_ctx_binding_vb] = { 227 .size = sizeof(struct vmw_ctx_bindinfo_vb), 228 .offsets = vmw_binding_vb_offsets, 229 .scrub_func = vmw_binding_scrub_vb}, 230 [vmw_ctx_binding_ib] = { 231 .size = sizeof(struct vmw_ctx_bindinfo_ib), 232 .offsets = vmw_binding_ib_offsets, 233 .scrub_func = vmw_binding_scrub_ib}, 234}; 235 236/** 237 * vmw_cbs_context - Return a pointer to the context resource of a 238 * context binding state tracker. 239 * 240 * @cbs: The context binding state tracker. 241 * 242 * Provided there are any active bindings, this function will return an 243 * unreferenced pointer to the context resource that owns the context 244 * binding state tracker. If there are no active bindings, this function 245 * will return NULL. Note that the caller must somehow ensure that a reference 246 * is held on the context resource prior to calling this function. 247 */ 248static const struct vmw_resource * 249vmw_cbs_context(const struct vmw_ctx_binding_state *cbs) 250{ 251 if (list_empty(&cbs->list)) 252 return NULL; 253 254 return list_first_entry(&cbs->list, struct vmw_ctx_bindinfo, 255 ctx_list)->ctx; 256} 257 258/** 259 * vmw_binding_loc - determine the struct vmw_ctx_bindinfo slot location. 260 * 261 * @cbs: Pointer to a struct vmw_ctx_binding state which holds the slot. 262 * @bt: The binding type. 263 * @shader_slot: The shader slot of the binding. If none, then set to 0. 264 * @slot: The slot of the binding. 265 */ 266static struct vmw_ctx_bindinfo * 267vmw_binding_loc(struct vmw_ctx_binding_state *cbs, 268 enum vmw_ctx_binding_type bt, u32 shader_slot, u32 slot) 269{ 270 const struct vmw_binding_info *b = &vmw_binding_infos[bt]; 271 size_t offset = b->offsets[shader_slot] + b->size*slot; 272 273 return (struct vmw_ctx_bindinfo *)((u8 *) cbs + offset); 274} 275 276/** 277 * vmw_binding_drop: Stop tracking a context binding 278 * 279 * @bi: Pointer to binding tracker storage. 280 * 281 * Stops tracking a context binding, and re-initializes its storage. 282 * Typically used when the context binding is replaced with a binding to 283 * another (or the same, for that matter) resource. 284 */ 285static void vmw_binding_drop(struct vmw_ctx_bindinfo *bi) 286{ 287 list_del(&bi->ctx_list); 288 if (!list_empty(&bi->res_list)) 289 list_del(&bi->res_list); 290 bi->ctx = NULL; 291} 292 293/** 294 * vmw_binding_add: Start tracking a context binding 295 * 296 * @cbs: Pointer to the context binding state tracker. 297 * @bi: Information about the binding to track. 298 * 299 * Starts tracking the binding in the context binding 300 * state structure @cbs. 301 */ 302void vmw_binding_add(struct vmw_ctx_binding_state *cbs, 303 const struct vmw_ctx_bindinfo *bi, 304 u32 shader_slot, u32 slot) 305{ 306 struct vmw_ctx_bindinfo *loc = 307 vmw_binding_loc(cbs, bi->bt, shader_slot, slot); 308 const struct vmw_binding_info *b = &vmw_binding_infos[bi->bt]; 309 310 if (loc->ctx != NULL) 311 vmw_binding_drop(loc); 312 313 memcpy(loc, bi, b->size); 314 loc->scrubbed = false; 315 list_add(&loc->ctx_list, &cbs->list); 316 INIT_LIST_HEAD(&loc->res_list); 317} 318 319/** 320 * vmw_binding_transfer: Transfer a context binding tracking entry. 321 * 322 * @cbs: Pointer to the persistent context binding state tracker. 323 * @bi: Information about the binding to track. 324 * 325 */ 326static void vmw_binding_transfer(struct vmw_ctx_binding_state *cbs, 327 const struct vmw_ctx_binding_state *from, 328 const struct vmw_ctx_bindinfo *bi) 329{ 330 size_t offset = (unsigned long)bi - (unsigned long)from; 331 struct vmw_ctx_bindinfo *loc = (struct vmw_ctx_bindinfo *) 332 ((unsigned long) cbs + offset); 333 334 if (loc->ctx != NULL) { 335 WARN_ON(bi->scrubbed); 336 337 vmw_binding_drop(loc); 338 } 339 340 if (bi->res != NULL) { 341 memcpy(loc, bi, vmw_binding_infos[bi->bt].size); 342 list_add_tail(&loc->ctx_list, &cbs->list); 343 list_add_tail(&loc->res_list, &loc->res->binding_head); 344 } 345} 346 347/** 348 * vmw_binding_state_kill - Kill all bindings associated with a 349 * struct vmw_ctx_binding state structure, and re-initialize the structure. 350 * 351 * @cbs: Pointer to the context binding state tracker. 352 * 353 * Emits commands to scrub all bindings associated with the 354 * context binding state tracker. Then re-initializes the whole structure. 355 */ 356void vmw_binding_state_kill(struct vmw_ctx_binding_state *cbs) 357{ 358 struct vmw_ctx_bindinfo *entry, *next; 359 360 vmw_binding_state_scrub(cbs); 361 list_for_each_entry_safe(entry, next, &cbs->list, ctx_list) 362 vmw_binding_drop(entry); 363} 364 365/** 366 * vmw_binding_state_scrub - Scrub all bindings associated with a 367 * struct vmw_ctx_binding state structure. 368 * 369 * @cbs: Pointer to the context binding state tracker. 370 * 371 * Emits commands to scrub all bindings associated with the 372 * context binding state tracker. 373 */ 374void vmw_binding_state_scrub(struct vmw_ctx_binding_state *cbs) 375{ 376 struct vmw_ctx_bindinfo *entry; 377 378 list_for_each_entry(entry, &cbs->list, ctx_list) { 379 if (!entry->scrubbed) { 380 (void) vmw_binding_infos[entry->bt].scrub_func 381 (entry, false); 382 entry->scrubbed = true; 383 } 384 } 385 386 (void) vmw_binding_emit_dirty(cbs); 387} 388 389/** 390 * vmw_binding_res_list_kill - Kill all bindings on a 391 * resource binding list 392 * 393 * @head: list head of resource binding list 394 * 395 * Kills all bindings associated with a specific resource. Typically 396 * called before the resource is destroyed. 397 */ 398void vmw_binding_res_list_kill(struct list_head *head) 399{ 400 struct vmw_ctx_bindinfo *entry, *next; 401 402 vmw_binding_res_list_scrub(head); 403 list_for_each_entry_safe(entry, next, head, res_list) 404 vmw_binding_drop(entry); 405} 406 407/** 408 * vmw_binding_res_list_scrub - Scrub all bindings on a 409 * resource binding list 410 * 411 * @head: list head of resource binding list 412 * 413 * Scrub all bindings associated with a specific resource. Typically 414 * called before the resource is evicted. 415 */ 416void vmw_binding_res_list_scrub(struct list_head *head) 417{ 418 struct vmw_ctx_bindinfo *entry; 419 420 list_for_each_entry(entry, head, res_list) { 421 if (!entry->scrubbed) { 422 (void) vmw_binding_infos[entry->bt].scrub_func 423 (entry, false); 424 entry->scrubbed = true; 425 } 426 } 427 428 list_for_each_entry(entry, head, res_list) { 429 struct vmw_ctx_binding_state *cbs = 430 vmw_context_binding_state(entry->ctx); 431 432 (void) vmw_binding_emit_dirty(cbs); 433 } 434} 435 436 437/** 438 * vmw_binding_state_commit - Commit staged binding info 439 * 440 * @ctx: Pointer to context to commit the staged binding info to. 441 * @from: Staged binding info built during execbuf. 442 * @scrubbed: Transfer only scrubbed bindings. 443 * 444 * Transfers binding info from a temporary structure 445 * (typically used by execbuf) to the persistent 446 * structure in the context. This can be done once commands have been 447 * submitted to hardware 448 */ 449void vmw_binding_state_commit(struct vmw_ctx_binding_state *to, 450 struct vmw_ctx_binding_state *from) 451{ 452 struct vmw_ctx_bindinfo *entry, *next; 453 454 list_for_each_entry_safe(entry, next, &from->list, ctx_list) { 455 vmw_binding_transfer(to, from, entry); 456 vmw_binding_drop(entry); 457 } 458} 459 460/** 461 * vmw_binding_rebind_all - Rebind all scrubbed bindings of a context 462 * 463 * @ctx: The context resource 464 * 465 * Walks through the context binding list and rebinds all scrubbed 466 * resources. 467 */ 468int vmw_binding_rebind_all(struct vmw_ctx_binding_state *cbs) 469{ 470 struct vmw_ctx_bindinfo *entry; 471 int ret; 472 473 list_for_each_entry(entry, &cbs->list, ctx_list) { 474 if (likely(!entry->scrubbed)) 475 continue; 476 477 if ((entry->res == NULL || entry->res->id == 478 SVGA3D_INVALID_ID)) 479 continue; 480 481 ret = vmw_binding_infos[entry->bt].scrub_func(entry, true); 482 if (unlikely(ret != 0)) 483 return ret; 484 485 entry->scrubbed = false; 486 } 487 488 return vmw_binding_emit_dirty(cbs); 489} 490 491/** 492 * vmw_binding_scrub_shader - scrub a shader binding from a context. 493 * 494 * @bi: single binding information. 495 * @rebind: Whether to issue a bind instead of scrub command. 496 */ 497static int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind) 498{ 499 struct vmw_ctx_bindinfo_shader *binding = 500 container_of(bi, typeof(*binding), bi); 501 struct vmw_private *dev_priv = bi->ctx->dev_priv; 502 struct { 503 SVGA3dCmdHeader header; 504 SVGA3dCmdSetShader body; 505 } *cmd; 506 507 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); 508 if (unlikely(cmd == NULL)) 509 return -ENOMEM; 510 511 cmd->header.id = SVGA_3D_CMD_SET_SHADER; 512 cmd->header.size = sizeof(cmd->body); 513 cmd->body.cid = bi->ctx->id; 514 cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 515 cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 516 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 517 518 return 0; 519} 520 521/** 522 * vmw_binding_scrub_render_target - scrub a render target binding 523 * from a context. 524 * 525 * @bi: single binding information. 526 * @rebind: Whether to issue a bind instead of scrub command. 527 */ 528static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi, 529 bool rebind) 530{ 531 struct vmw_ctx_bindinfo_view *binding = 532 container_of(bi, typeof(*binding), bi); 533 struct vmw_private *dev_priv = bi->ctx->dev_priv; 534 struct { 535 SVGA3dCmdHeader header; 536 SVGA3dCmdSetRenderTarget body; 537 } *cmd; 538 539 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); 540 if (unlikely(cmd == NULL)) 541 return -ENOMEM; 542 543 cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET; 544 cmd->header.size = sizeof(cmd->body); 545 cmd->body.cid = bi->ctx->id; 546 cmd->body.type = binding->slot; 547 cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 548 cmd->body.target.face = 0; 549 cmd->body.target.mipmap = 0; 550 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 551 552 return 0; 553} 554 555/** 556 * vmw_binding_scrub_texture - scrub a texture binding from a context. 557 * 558 * @bi: single binding information. 559 * @rebind: Whether to issue a bind instead of scrub command. 560 * 561 * TODO: Possibly complement this function with a function that takes 562 * a list of texture bindings and combines them to a single command. 563 */ 564static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi, 565 bool rebind) 566{ 567 struct vmw_ctx_bindinfo_tex *binding = 568 container_of(bi, typeof(*binding), bi); 569 struct vmw_private *dev_priv = bi->ctx->dev_priv; 570 struct { 571 SVGA3dCmdHeader header; 572 struct { 573 SVGA3dCmdSetTextureState c; 574 SVGA3dTextureState s1; 575 } body; 576 } *cmd; 577 578 cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); 579 if (unlikely(cmd == NULL)) 580 return -ENOMEM; 581 582 cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE; 583 cmd->header.size = sizeof(cmd->body); 584 cmd->body.c.cid = bi->ctx->id; 585 cmd->body.s1.stage = binding->texture_stage; 586 cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE; 587 cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 588 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 589 590 return 0; 591} 592 593/** 594 * vmw_binding_scrub_dx_shader - scrub a dx shader binding from a context. 595 * 596 * @bi: single binding information. 597 * @rebind: Whether to issue a bind instead of scrub command. 598 */ 599static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi, bool rebind) 600{ 601 struct vmw_ctx_bindinfo_shader *binding = 602 container_of(bi, typeof(*binding), bi); 603 struct vmw_private *dev_priv = bi->ctx->dev_priv; 604 struct { 605 SVGA3dCmdHeader header; 606 SVGA3dCmdDXSetShader body; 607 } *cmd; 608 609 cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); 610 if (unlikely(cmd == NULL)) 611 return -ENOMEM; 612 613 cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER; 614 cmd->header.size = sizeof(cmd->body); 615 cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 616 cmd->body.shaderId = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 617 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 618 619 return 0; 620} 621 622/** 623 * vmw_binding_scrub_cb - scrub a constant buffer binding from a context. 624 * 625 * @bi: single binding information. 626 * @rebind: Whether to issue a bind instead of scrub command. 627 */ 628static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind) 629{ 630 struct vmw_ctx_bindinfo_cb *binding = 631 container_of(bi, typeof(*binding), bi); 632 struct vmw_private *dev_priv = bi->ctx->dev_priv; 633 struct { 634 SVGA3dCmdHeader header; 635 SVGA3dCmdDXSetSingleConstantBuffer body; 636 } *cmd; 637 638 cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); 639 if (unlikely(cmd == NULL)) 640 return -ENOMEM; 641 642 cmd->header.id = SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER; 643 cmd->header.size = sizeof(cmd->body); 644 cmd->body.slot = binding->slot; 645 cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 646 if (rebind) { 647 cmd->body.offsetInBytes = binding->offset; 648 cmd->body.sizeInBytes = binding->size; 649 cmd->body.sid = bi->res->id; 650 } else { 651 cmd->body.offsetInBytes = 0; 652 cmd->body.sizeInBytes = 0; 653 cmd->body.sid = SVGA3D_INVALID_ID; 654 } 655 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 656 657 return 0; 658} 659 660/** 661 * vmw_collect_view_ids - Build view id data for a view binding command 662 * without checking which bindings actually need to be emitted 663 * 664 * @cbs: Pointer to the context's struct vmw_ctx_binding_state 665 * @bi: Pointer to where the binding info array is stored in @cbs 666 * @max_num: Maximum number of entries in the @bi array. 667 * 668 * Scans the @bi array for bindings and builds a buffer of view id data. 669 * Stops at the first non-existing binding in the @bi array. 670 * On output, @cbs->bind_cmd_count contains the number of bindings to be 671 * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer 672 * contains the command data. 673 */ 674static void vmw_collect_view_ids(struct vmw_ctx_binding_state *cbs, 675 const struct vmw_ctx_bindinfo *bi, 676 u32 max_num) 677{ 678 const struct vmw_ctx_bindinfo_view *biv = 679 container_of(bi, struct vmw_ctx_bindinfo_view, bi); 680 unsigned long i; 681 682 cbs->bind_cmd_count = 0; 683 cbs->bind_first_slot = 0; 684 685 for (i = 0; i < max_num; ++i, ++biv) { 686 if (!biv->bi.ctx) 687 break; 688 689 cbs->bind_cmd_buffer[cbs->bind_cmd_count++] = 690 ((biv->bi.scrubbed) ? 691 SVGA3D_INVALID_ID : biv->bi.res->id); 692 } 693} 694 695/** 696 * vmw_collect_dirty_view_ids - Build view id data for a view binding command 697 * 698 * @cbs: Pointer to the context's struct vmw_ctx_binding_state 699 * @bi: Pointer to where the binding info array is stored in @cbs 700 * @dirty: Bitmap indicating which bindings need to be emitted. 701 * @max_num: Maximum number of entries in the @bi array. 702 * 703 * Scans the @bi array for bindings that need to be emitted and 704 * builds a buffer of view id data. 705 * On output, @cbs->bind_cmd_count contains the number of bindings to be 706 * emitted, @cbs->bind_first_slot indicates the index of the first emitted 707 * binding, and @cbs->bind_cmd_buffer contains the command data. 708 */ 709static void vmw_collect_dirty_view_ids(struct vmw_ctx_binding_state *cbs, 710 const struct vmw_ctx_bindinfo *bi, 711 unsigned long *dirty, 712 u32 max_num) 713{ 714 const struct vmw_ctx_bindinfo_view *biv = 715 container_of(bi, struct vmw_ctx_bindinfo_view, bi); 716 unsigned long i, next_bit; 717 718 cbs->bind_cmd_count = 0; 719 i = find_first_bit(dirty, max_num); 720 next_bit = i; 721 cbs->bind_first_slot = i; 722 723 biv += i; 724 for (; i < max_num; ++i, ++biv) { 725 cbs->bind_cmd_buffer[cbs->bind_cmd_count++] = 726 ((!biv->bi.ctx || biv->bi.scrubbed) ? 727 SVGA3D_INVALID_ID : biv->bi.res->id); 728 729 if (next_bit == i) { 730 next_bit = find_next_bit(dirty, max_num, i + 1); 731 if (next_bit >= max_num) 732 break; 733 } 734 } 735} 736 737/** 738 * vmw_binding_emit_set_sr - Issue delayed DX shader resource binding commands 739 * 740 * @cbs: Pointer to the context's struct vmw_ctx_binding_state 741 */ 742static int vmw_emit_set_sr(struct vmw_ctx_binding_state *cbs, 743 int shader_slot) 744{ 745 const struct vmw_ctx_bindinfo *loc = 746 &cbs->per_shader[shader_slot].shader_res[0].bi; 747 struct { 748 SVGA3dCmdHeader header; 749 SVGA3dCmdDXSetShaderResources body; 750 } *cmd; 751 size_t cmd_size, view_id_size; 752 const struct vmw_resource *ctx = vmw_cbs_context(cbs); 753 754 vmw_collect_dirty_view_ids(cbs, loc, 755 cbs->per_shader[shader_slot].dirty_sr, 756 SVGA3D_DX_MAX_SRVIEWS); 757 if (cbs->bind_cmd_count == 0) 758 return 0; 759 760 view_id_size = cbs->bind_cmd_count*sizeof(uint32); 761 cmd_size = sizeof(*cmd) + view_id_size; 762 cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 763 if (unlikely(cmd == NULL)) 764 return -ENOMEM; 765 766 cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER_RESOURCES; 767 cmd->header.size = sizeof(cmd->body) + view_id_size; 768 cmd->body.type = shader_slot + SVGA3D_SHADERTYPE_MIN; 769 cmd->body.startView = cbs->bind_first_slot; 770 771 memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size); 772 773 vmw_fifo_commit(ctx->dev_priv, cmd_size); 774 bitmap_clear(cbs->per_shader[shader_slot].dirty_sr, 775 cbs->bind_first_slot, cbs->bind_cmd_count); 776 777 return 0; 778} 779 780/** 781 * vmw_binding_emit_set_rt - Issue delayed DX rendertarget binding commands 782 * 783 * @cbs: Pointer to the context's struct vmw_ctx_binding_state 784 */ 785static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs) 786{ 787 const struct vmw_ctx_bindinfo *loc = &cbs->render_targets[0].bi; 788 struct { 789 SVGA3dCmdHeader header; 790 SVGA3dCmdDXSetRenderTargets body; 791 } *cmd; 792 size_t cmd_size, view_id_size; 793 const struct vmw_resource *ctx = vmw_cbs_context(cbs); 794 795 vmw_collect_view_ids(cbs, loc, SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS); 796 view_id_size = cbs->bind_cmd_count*sizeof(uint32); 797 cmd_size = sizeof(*cmd) + view_id_size; 798 cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 799 if (unlikely(cmd == NULL)) 800 return -ENOMEM; 801 802 cmd->header.id = SVGA_3D_CMD_DX_SET_RENDERTARGETS; 803 cmd->header.size = sizeof(cmd->body) + view_id_size; 804 805 if (cbs->ds_view.bi.ctx && !cbs->ds_view.bi.scrubbed) 806 cmd->body.depthStencilViewId = cbs->ds_view.bi.res->id; 807 else 808 cmd->body.depthStencilViewId = SVGA3D_INVALID_ID; 809 810 memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size); 811 812 vmw_fifo_commit(ctx->dev_priv, cmd_size); 813 814 return 0; 815 816} 817 818/** 819 * vmw_collect_so_targets - Build SVGA3dSoTarget data for a binding command 820 * without checking which bindings actually need to be emitted 821 * 822 * @cbs: Pointer to the context's struct vmw_ctx_binding_state 823 * @bi: Pointer to where the binding info array is stored in @cbs 824 * @max_num: Maximum number of entries in the @bi array. 825 * 826 * Scans the @bi array for bindings and builds a buffer of SVGA3dSoTarget data. 827 * Stops at the first non-existing binding in the @bi array. 828 * On output, @cbs->bind_cmd_count contains the number of bindings to be 829 * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer 830 * contains the command data. 831 */ 832static void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs, 833 const struct vmw_ctx_bindinfo *bi, 834 u32 max_num) 835{ 836 const struct vmw_ctx_bindinfo_so *biso = 837 container_of(bi, struct vmw_ctx_bindinfo_so, bi); 838 unsigned long i; 839 SVGA3dSoTarget *so_buffer = (SVGA3dSoTarget *) cbs->bind_cmd_buffer; 840 841 cbs->bind_cmd_count = 0; 842 cbs->bind_first_slot = 0; 843 844 for (i = 0; i < max_num; ++i, ++biso, ++so_buffer, 845 ++cbs->bind_cmd_count) { 846 if (!biso->bi.ctx) 847 break; 848 849 if (!biso->bi.scrubbed) { 850 so_buffer->sid = biso->bi.res->id; 851 so_buffer->offset = biso->offset; 852 so_buffer->sizeInBytes = biso->size; 853 } else { 854 so_buffer->sid = SVGA3D_INVALID_ID; 855 so_buffer->offset = 0; 856 so_buffer->sizeInBytes = 0; 857 } 858 } 859} 860 861/** 862 * vmw_binding_emit_set_so - Issue delayed streamout binding commands 863 * 864 * @cbs: Pointer to the context's struct vmw_ctx_binding_state 865 */ 866static int vmw_emit_set_so(struct vmw_ctx_binding_state *cbs) 867{ 868 const struct vmw_ctx_bindinfo *loc = &cbs->so_targets[0].bi; 869 struct { 870 SVGA3dCmdHeader header; 871 SVGA3dCmdDXSetSOTargets body; 872 } *cmd; 873 size_t cmd_size, so_target_size; 874 const struct vmw_resource *ctx = vmw_cbs_context(cbs); 875 876 vmw_collect_so_targets(cbs, loc, SVGA3D_DX_MAX_SOTARGETS); 877 if (cbs->bind_cmd_count == 0) 878 return 0; 879 880 so_target_size = cbs->bind_cmd_count*sizeof(SVGA3dSoTarget); 881 cmd_size = sizeof(*cmd) + so_target_size; 882 cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 883 if (unlikely(cmd == NULL)) 884 return -ENOMEM; 885 886 cmd->header.id = SVGA_3D_CMD_DX_SET_SOTARGETS; 887 cmd->header.size = sizeof(cmd->body) + so_target_size; 888 memcpy(&cmd[1], cbs->bind_cmd_buffer, so_target_size); 889 890 vmw_fifo_commit(ctx->dev_priv, cmd_size); 891 892 return 0; 893 894} 895 896/** 897 * vmw_binding_emit_dirty_ps - Issue delayed per shader binding commands 898 * 899 * @cbs: Pointer to the context's struct vmw_ctx_binding_state 900 * 901 */ 902static int vmw_binding_emit_dirty_ps(struct vmw_ctx_binding_state *cbs) 903{ 904 struct vmw_dx_shader_bindings *sb = &cbs->per_shader[0]; 905 u32 i; 906 int ret; 907 908 for (i = 0; i < SVGA3D_NUM_SHADERTYPE_DX10; ++i, ++sb) { 909 if (!test_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty)) 910 continue; 911 912 ret = vmw_emit_set_sr(cbs, i); 913 if (ret) 914 break; 915 916 __clear_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty); 917 } 918 919 return 0; 920} 921 922/** 923 * vmw_collect_dirty_vbs - Build SVGA3dVertexBuffer data for a 924 * SVGA3dCmdDXSetVertexBuffers command 925 * 926 * @cbs: Pointer to the context's struct vmw_ctx_binding_state 927 * @bi: Pointer to where the binding info array is stored in @cbs 928 * @dirty: Bitmap indicating which bindings need to be emitted. 929 * @max_num: Maximum number of entries in the @bi array. 930 * 931 * Scans the @bi array for bindings that need to be emitted and 932 * builds a buffer of SVGA3dVertexBuffer data. 933 * On output, @cbs->bind_cmd_count contains the number of bindings to be 934 * emitted, @cbs->bind_first_slot indicates the index of the first emitted 935 * binding, and @cbs->bind_cmd_buffer contains the command data. 936 */ 937static void vmw_collect_dirty_vbs(struct vmw_ctx_binding_state *cbs, 938 const struct vmw_ctx_bindinfo *bi, 939 unsigned long *dirty, 940 u32 max_num) 941{ 942 const struct vmw_ctx_bindinfo_vb *biv = 943 container_of(bi, struct vmw_ctx_bindinfo_vb, bi); 944 unsigned long i, next_bit; 945 SVGA3dVertexBuffer *vbs = (SVGA3dVertexBuffer *) &cbs->bind_cmd_buffer; 946 947 cbs->bind_cmd_count = 0; 948 i = find_first_bit(dirty, max_num); 949 next_bit = i; 950 cbs->bind_first_slot = i; 951 952 biv += i; 953 for (; i < max_num; ++i, ++biv, ++vbs) { 954 if (!biv->bi.ctx || biv->bi.scrubbed) { 955 vbs->sid = SVGA3D_INVALID_ID; 956 vbs->stride = 0; 957 vbs->offset = 0; 958 } else { 959 vbs->sid = biv->bi.res->id; 960 vbs->stride = biv->stride; 961 vbs->offset = biv->offset; 962 } 963 cbs->bind_cmd_count++; 964 if (next_bit == i) { 965 next_bit = find_next_bit(dirty, max_num, i + 1); 966 if (next_bit >= max_num) 967 break; 968 } 969 } 970} 971 972/** 973 * vmw_binding_emit_set_vb - Issue delayed vertex buffer binding commands 974 * 975 * @cbs: Pointer to the context's struct vmw_ctx_binding_state 976 * 977 */ 978static int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs) 979{ 980 const struct vmw_ctx_bindinfo *loc = 981 &cbs->vertex_buffers[0].bi; 982 struct { 983 SVGA3dCmdHeader header; 984 SVGA3dCmdDXSetVertexBuffers body; 985 } *cmd; 986 size_t cmd_size, set_vb_size; 987 const struct vmw_resource *ctx = vmw_cbs_context(cbs); 988 989 vmw_collect_dirty_vbs(cbs, loc, cbs->dirty_vb, 990 SVGA3D_DX_MAX_VERTEXBUFFERS); 991 if (cbs->bind_cmd_count == 0) 992 return 0; 993 994 set_vb_size = cbs->bind_cmd_count*sizeof(SVGA3dVertexBuffer); 995 cmd_size = sizeof(*cmd) + set_vb_size; 996 cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 997 if (unlikely(cmd == NULL)) 998 return -ENOMEM; 999 1000 cmd->header.id = SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS; 1001 cmd->header.size = sizeof(cmd->body) + set_vb_size; 1002 cmd->body.startBuffer = cbs->bind_first_slot; 1003 1004 memcpy(&cmd[1], cbs->bind_cmd_buffer, set_vb_size); 1005 1006 vmw_fifo_commit(ctx->dev_priv, cmd_size); 1007 bitmap_clear(cbs->dirty_vb, 1008 cbs->bind_first_slot, cbs->bind_cmd_count); 1009 1010 return 0; 1011} 1012 1013/** 1014 * vmw_binding_emit_dirty - Issue delayed binding commands 1015 * 1016 * @cbs: Pointer to the context's struct vmw_ctx_binding_state 1017 * 1018 * This function issues the delayed binding commands that arise from 1019 * previous scrub / unscrub calls. These binding commands are typically 1020 * commands that batch a number of bindings and therefore it makes sense 1021 * to delay them. 1022 */ 1023static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs) 1024{ 1025 int ret = 0; 1026 unsigned long hit = 0; 1027 1028 while ((hit = find_next_bit(&cbs->dirty, VMW_BINDING_NUM_BITS, hit)) 1029 < VMW_BINDING_NUM_BITS) { 1030 1031 switch (hit) { 1032 case VMW_BINDING_RT_BIT: 1033 ret = vmw_emit_set_rt(cbs); 1034 break; 1035 case VMW_BINDING_PS_BIT: 1036 ret = vmw_binding_emit_dirty_ps(cbs); 1037 break; 1038 case VMW_BINDING_SO_BIT: 1039 ret = vmw_emit_set_so(cbs); 1040 break; 1041 case VMW_BINDING_VB_BIT: 1042 ret = vmw_emit_set_vb(cbs); 1043 break; 1044 default: 1045 BUG(); 1046 } 1047 if (ret) 1048 return ret; 1049 1050 __clear_bit(hit, &cbs->dirty); 1051 hit++; 1052 } 1053 1054 return 0; 1055} 1056 1057/** 1058 * vmw_binding_scrub_sr - Schedule a dx shaderresource binding 1059 * scrub from a context 1060 * 1061 * @bi: single binding information. 1062 * @rebind: Whether to issue a bind instead of scrub command. 1063 */ 1064static int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind) 1065{ 1066 struct vmw_ctx_bindinfo_view *biv = 1067 container_of(bi, struct vmw_ctx_bindinfo_view, bi); 1068 struct vmw_ctx_binding_state *cbs = 1069 vmw_context_binding_state(bi->ctx); 1070 1071 __set_bit(biv->slot, cbs->per_shader[biv->shader_slot].dirty_sr); 1072 __set_bit(VMW_BINDING_PS_SR_BIT, 1073 &cbs->per_shader[biv->shader_slot].dirty); 1074 __set_bit(VMW_BINDING_PS_BIT, &cbs->dirty); 1075 1076 return 0; 1077} 1078 1079/** 1080 * vmw_binding_scrub_dx_rt - Schedule a dx rendertarget binding 1081 * scrub from a context 1082 * 1083 * @bi: single binding information. 1084 * @rebind: Whether to issue a bind instead of scrub command. 1085 */ 1086static int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind) 1087{ 1088 struct vmw_ctx_binding_state *cbs = 1089 vmw_context_binding_state(bi->ctx); 1090 1091 __set_bit(VMW_BINDING_RT_BIT, &cbs->dirty); 1092 1093 return 0; 1094} 1095 1096/** 1097 * vmw_binding_scrub_so - Schedule a dx streamoutput buffer binding 1098 * scrub from a context 1099 * 1100 * @bi: single binding information. 1101 * @rebind: Whether to issue a bind instead of scrub command. 1102 */ 1103static int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind) 1104{ 1105 struct vmw_ctx_binding_state *cbs = 1106 vmw_context_binding_state(bi->ctx); 1107 1108 __set_bit(VMW_BINDING_SO_BIT, &cbs->dirty); 1109 1110 return 0; 1111} 1112 1113/** 1114 * vmw_binding_scrub_vb - Schedule a dx vertex buffer binding 1115 * scrub from a context 1116 * 1117 * @bi: single binding information. 1118 * @rebind: Whether to issue a bind instead of scrub command. 1119 */ 1120static int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind) 1121{ 1122 struct vmw_ctx_bindinfo_vb *bivb = 1123 container_of(bi, struct vmw_ctx_bindinfo_vb, bi); 1124 struct vmw_ctx_binding_state *cbs = 1125 vmw_context_binding_state(bi->ctx); 1126 1127 __set_bit(bivb->slot, cbs->dirty_vb); 1128 __set_bit(VMW_BINDING_VB_BIT, &cbs->dirty); 1129 1130 return 0; 1131} 1132 1133/** 1134 * vmw_binding_scrub_ib - scrub a dx index buffer binding from a context 1135 * 1136 * @bi: single binding information. 1137 * @rebind: Whether to issue a bind instead of scrub command. 1138 */ 1139static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind) 1140{ 1141 struct vmw_ctx_bindinfo_ib *binding = 1142 container_of(bi, typeof(*binding), bi); 1143 struct vmw_private *dev_priv = bi->ctx->dev_priv; 1144 struct { 1145 SVGA3dCmdHeader header; 1146 SVGA3dCmdDXSetIndexBuffer body; 1147 } *cmd; 1148 1149 cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); 1150 if (unlikely(cmd == NULL)) 1151 return -ENOMEM; 1152 1153 cmd->header.id = SVGA_3D_CMD_DX_SET_INDEX_BUFFER; 1154 cmd->header.size = sizeof(cmd->body); 1155 if (rebind) { 1156 cmd->body.sid = bi->res->id; 1157 cmd->body.format = binding->format; 1158 cmd->body.offset = binding->offset; 1159 } else { 1160 cmd->body.sid = SVGA3D_INVALID_ID; 1161 cmd->body.format = 0; 1162 cmd->body.offset = 0; 1163 } 1164 1165 vmw_fifo_commit(dev_priv, sizeof(*cmd)); 1166 1167 return 0; 1168} 1169 1170/** 1171 * vmw_binding_state_alloc - Allocate a struct vmw_ctx_binding_state with 1172 * memory accounting. 1173 * 1174 * @dev_priv: Pointer to a device private structure. 1175 * 1176 * Returns a pointer to a newly allocated struct or an error pointer on error. 1177 */ 1178struct vmw_ctx_binding_state * 1179vmw_binding_state_alloc(struct vmw_private *dev_priv) 1180{ 1181 struct vmw_ctx_binding_state *cbs; 1182 struct ttm_operation_ctx ctx = { 1183 .interruptible = false, 1184 .no_wait_gpu = false 1185 }; 1186 int ret; 1187 1188 ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), sizeof(*cbs), 1189 &ctx); 1190 if (ret) 1191 return ERR_PTR(ret); 1192 1193 cbs = vzalloc(sizeof(*cbs)); 1194 if (!cbs) { 1195 ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs)); 1196 return ERR_PTR(-ENOMEM); 1197 } 1198 1199 cbs->dev_priv = dev_priv; 1200 INIT_LIST_HEAD(&cbs->list); 1201 1202 return cbs; 1203} 1204 1205/** 1206 * vmw_binding_state_free - Free a struct vmw_ctx_binding_state and its 1207 * memory accounting info. 1208 * 1209 * @cbs: Pointer to the struct vmw_ctx_binding_state to be freed. 1210 */ 1211void vmw_binding_state_free(struct vmw_ctx_binding_state *cbs) 1212{ 1213 struct vmw_private *dev_priv = cbs->dev_priv; 1214 1215 vfree(cbs); 1216 ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs)); 1217} 1218 1219/** 1220 * vmw_binding_state_list - Get the binding list of a 1221 * struct vmw_ctx_binding_state 1222 * 1223 * @cbs: Pointer to the struct vmw_ctx_binding_state 1224 * 1225 * Returns the binding list which can be used to traverse through the bindings 1226 * and access the resource information of all bindings. 1227 */ 1228struct list_head *vmw_binding_state_list(struct vmw_ctx_binding_state *cbs) 1229{ 1230 return &cbs->list; 1231} 1232 1233/** 1234 * vmwgfx_binding_state_reset - clear a struct vmw_ctx_binding_state 1235 * 1236 * @cbs: Pointer to the struct vmw_ctx_binding_state to be cleared 1237 * 1238 * Drops all bindings registered in @cbs. No device binding actions are 1239 * performed. 1240 */ 1241void vmw_binding_state_reset(struct vmw_ctx_binding_state *cbs) 1242{ 1243 struct vmw_ctx_bindinfo *entry, *next; 1244 1245 list_for_each_entry_safe(entry, next, &cbs->list, ctx_list) 1246 vmw_binding_drop(entry); 1247} 1248 1249/** 1250 * vmw_binding_dirtying - Return whether a binding type is dirtying its resource 1251 * @binding_type: The binding type 1252 * 1253 * Each time a resource is put on the validation list as the result of a 1254 * context binding referencing it, we need to determine whether that resource 1255 * will be dirtied (written to by the GPU) as a result of the corresponding 1256 * GPU operation. Currently rendertarget-, depth-stencil-, and 1257 * stream-output-target bindings are capable of dirtying its resource. 1258 * 1259 * Return: Whether the binding type dirties the resource its binding points to. 1260 */ 1261u32 vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type) 1262{ 1263 static u32 is_binding_dirtying[vmw_ctx_binding_max] = { 1264 [vmw_ctx_binding_rt] = VMW_RES_DIRTY_SET, 1265 [vmw_ctx_binding_dx_rt] = VMW_RES_DIRTY_SET, 1266 [vmw_ctx_binding_ds] = VMW_RES_DIRTY_SET, 1267 [vmw_ctx_binding_so] = VMW_RES_DIRTY_SET, 1268 }; 1269 1270 /* Review this function as new bindings are added. */ 1271 BUILD_BUG_ON(vmw_ctx_binding_max != 11); 1272 return is_binding_dirtying[binding_type]; 1273} 1274 1275/* 1276 * This function is unused at run-time, and only used to hold various build 1277 * asserts important for code optimization assumptions. 1278 */ 1279static void vmw_binding_build_asserts(void) 1280{ 1281 BUILD_BUG_ON(SVGA3D_NUM_SHADERTYPE_DX10 != 3); 1282 BUILD_BUG_ON(SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS > SVGA3D_RT_MAX); 1283 BUILD_BUG_ON(sizeof(uint32) != sizeof(u32)); 1284 1285 /* 1286 * struct vmw_ctx_binding_state::bind_cmd_buffer is used for various 1287 * view id arrays. 1288 */ 1289 BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_RT_MAX); 1290 BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_SRVIEWS); 1291 BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_CONSTBUFFERS); 1292 1293 /* 1294 * struct vmw_ctx_binding_state::bind_cmd_buffer is used for 1295 * u32 view ids, SVGA3dSoTargets and SVGA3dVertexBuffers 1296 */ 1297 BUILD_BUG_ON(SVGA3D_DX_MAX_SOTARGETS*sizeof(SVGA3dSoTarget) > 1298 VMW_MAX_VIEW_BINDINGS*sizeof(u32)); 1299 BUILD_BUG_ON(SVGA3D_DX_MAX_VERTEXBUFFERS*sizeof(SVGA3dVertexBuffer) > 1300 VMW_MAX_VIEW_BINDINGS*sizeof(u32)); 1301} 1302