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