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