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 50211c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); 50311c45419SDeepak Rawat if (unlikely(cmd == NULL)) 504d80efd5cSThomas Hellstrom return -ENOMEM; 505d80efd5cSThomas Hellstrom 506d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_SET_SHADER; 507d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 508d80efd5cSThomas Hellstrom cmd->body.cid = bi->ctx->id; 509d80efd5cSThomas Hellstrom cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 510d80efd5cSThomas Hellstrom cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 511d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 512d80efd5cSThomas Hellstrom 513d80efd5cSThomas Hellstrom return 0; 514d80efd5cSThomas Hellstrom } 515d80efd5cSThomas Hellstrom 516d80efd5cSThomas Hellstrom /** 517d80efd5cSThomas Hellstrom * vmw_binding_scrub_render_target - scrub a render target binding 518d80efd5cSThomas Hellstrom * from a context. 519d80efd5cSThomas Hellstrom * 520d80efd5cSThomas Hellstrom * @bi: single binding information. 521d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 522d80efd5cSThomas Hellstrom */ 523d80efd5cSThomas Hellstrom static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi, 524d80efd5cSThomas Hellstrom bool rebind) 525d80efd5cSThomas Hellstrom { 526d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_view *binding = 527d80efd5cSThomas Hellstrom container_of(bi, typeof(*binding), bi); 528d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = bi->ctx->dev_priv; 529d80efd5cSThomas Hellstrom struct { 530d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 531d80efd5cSThomas Hellstrom SVGA3dCmdSetRenderTarget body; 532d80efd5cSThomas Hellstrom } *cmd; 533d80efd5cSThomas Hellstrom 53411c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); 53511c45419SDeepak Rawat if (unlikely(cmd == NULL)) 536d80efd5cSThomas Hellstrom return -ENOMEM; 537d80efd5cSThomas Hellstrom 538d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET; 539d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 540d80efd5cSThomas Hellstrom cmd->body.cid = bi->ctx->id; 541d80efd5cSThomas Hellstrom cmd->body.type = binding->slot; 542d80efd5cSThomas Hellstrom cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 543d80efd5cSThomas Hellstrom cmd->body.target.face = 0; 544d80efd5cSThomas Hellstrom cmd->body.target.mipmap = 0; 545d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 546d80efd5cSThomas Hellstrom 547d80efd5cSThomas Hellstrom return 0; 548d80efd5cSThomas Hellstrom } 549d80efd5cSThomas Hellstrom 550d80efd5cSThomas Hellstrom /** 551d80efd5cSThomas Hellstrom * vmw_binding_scrub_texture - scrub a texture binding from a context. 552d80efd5cSThomas Hellstrom * 553d80efd5cSThomas Hellstrom * @bi: single binding information. 554d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 555d80efd5cSThomas Hellstrom * 556d80efd5cSThomas Hellstrom * TODO: Possibly complement this function with a function that takes 557d80efd5cSThomas Hellstrom * a list of texture bindings and combines them to a single command. 558d80efd5cSThomas Hellstrom */ 559d80efd5cSThomas Hellstrom static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi, 560d80efd5cSThomas Hellstrom bool rebind) 561d80efd5cSThomas Hellstrom { 562d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_tex *binding = 563d80efd5cSThomas Hellstrom container_of(bi, typeof(*binding), bi); 564d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = bi->ctx->dev_priv; 565d80efd5cSThomas Hellstrom struct { 566d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 567d80efd5cSThomas Hellstrom struct { 568d80efd5cSThomas Hellstrom SVGA3dCmdSetTextureState c; 569d80efd5cSThomas Hellstrom SVGA3dTextureState s1; 570d80efd5cSThomas Hellstrom } body; 571d80efd5cSThomas Hellstrom } *cmd; 572d80efd5cSThomas Hellstrom 57311c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); 57411c45419SDeepak Rawat if (unlikely(cmd == NULL)) 575d80efd5cSThomas Hellstrom return -ENOMEM; 576d80efd5cSThomas Hellstrom 577d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE; 578d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 579d80efd5cSThomas Hellstrom cmd->body.c.cid = bi->ctx->id; 580d80efd5cSThomas Hellstrom cmd->body.s1.stage = binding->texture_stage; 581d80efd5cSThomas Hellstrom cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE; 582d80efd5cSThomas Hellstrom cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 583d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 584d80efd5cSThomas Hellstrom 585d80efd5cSThomas Hellstrom return 0; 586d80efd5cSThomas Hellstrom } 587d80efd5cSThomas Hellstrom 588d80efd5cSThomas Hellstrom /** 589d80efd5cSThomas Hellstrom * vmw_binding_scrub_dx_shader - scrub a dx shader binding from a context. 590d80efd5cSThomas Hellstrom * 591d80efd5cSThomas Hellstrom * @bi: single binding information. 592d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 593d80efd5cSThomas Hellstrom */ 594d80efd5cSThomas Hellstrom static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi, bool rebind) 595d80efd5cSThomas Hellstrom { 596d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_shader *binding = 597d80efd5cSThomas Hellstrom container_of(bi, typeof(*binding), bi); 598d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = bi->ctx->dev_priv; 599d80efd5cSThomas Hellstrom struct { 600d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 601d80efd5cSThomas Hellstrom SVGA3dCmdDXSetShader body; 602d80efd5cSThomas Hellstrom } *cmd; 603d80efd5cSThomas Hellstrom 60411c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); 60511c45419SDeepak Rawat if (unlikely(cmd == NULL)) 606d80efd5cSThomas Hellstrom return -ENOMEM; 60711c45419SDeepak Rawat 608d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER; 609d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 610d80efd5cSThomas Hellstrom cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 611d80efd5cSThomas Hellstrom cmd->body.shaderId = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 612d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 613d80efd5cSThomas Hellstrom 614d80efd5cSThomas Hellstrom return 0; 615d80efd5cSThomas Hellstrom } 616d80efd5cSThomas Hellstrom 617d80efd5cSThomas Hellstrom /** 618d80efd5cSThomas Hellstrom * vmw_binding_scrub_cb - scrub a constant buffer binding from a context. 619d80efd5cSThomas Hellstrom * 620d80efd5cSThomas Hellstrom * @bi: single binding information. 621d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 622d80efd5cSThomas Hellstrom */ 623d80efd5cSThomas Hellstrom static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind) 624d80efd5cSThomas Hellstrom { 625d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_cb *binding = 626d80efd5cSThomas Hellstrom container_of(bi, typeof(*binding), bi); 627d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = bi->ctx->dev_priv; 628d80efd5cSThomas Hellstrom struct { 629d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 630d80efd5cSThomas Hellstrom SVGA3dCmdDXSetSingleConstantBuffer body; 631d80efd5cSThomas Hellstrom } *cmd; 632d80efd5cSThomas Hellstrom 63311c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); 63411c45419SDeepak Rawat if (unlikely(cmd == NULL)) 635d80efd5cSThomas Hellstrom return -ENOMEM; 636d80efd5cSThomas Hellstrom 637d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER; 638d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 639d80efd5cSThomas Hellstrom cmd->body.slot = binding->slot; 640d80efd5cSThomas Hellstrom cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 641d80efd5cSThomas Hellstrom if (rebind) { 642d80efd5cSThomas Hellstrom cmd->body.offsetInBytes = binding->offset; 643d80efd5cSThomas Hellstrom cmd->body.sizeInBytes = binding->size; 644d80efd5cSThomas Hellstrom cmd->body.sid = bi->res->id; 645d80efd5cSThomas Hellstrom } else { 646d80efd5cSThomas Hellstrom cmd->body.offsetInBytes = 0; 647d80efd5cSThomas Hellstrom cmd->body.sizeInBytes = 0; 648d80efd5cSThomas Hellstrom cmd->body.sid = SVGA3D_INVALID_ID; 649d80efd5cSThomas Hellstrom } 650d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 651d80efd5cSThomas Hellstrom 652d80efd5cSThomas Hellstrom return 0; 653d80efd5cSThomas Hellstrom } 654d80efd5cSThomas Hellstrom 655d80efd5cSThomas Hellstrom /** 656d80efd5cSThomas Hellstrom * vmw_collect_view_ids - Build view id data for a view binding command 657d80efd5cSThomas Hellstrom * without checking which bindings actually need to be emitted 658d80efd5cSThomas Hellstrom * 659d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 660d80efd5cSThomas Hellstrom * @bi: Pointer to where the binding info array is stored in @cbs 661d80efd5cSThomas Hellstrom * @max_num: Maximum number of entries in the @bi array. 662d80efd5cSThomas Hellstrom * 663d80efd5cSThomas Hellstrom * Scans the @bi array for bindings and builds a buffer of view id data. 664d80efd5cSThomas Hellstrom * Stops at the first non-existing binding in the @bi array. 665d80efd5cSThomas Hellstrom * On output, @cbs->bind_cmd_count contains the number of bindings to be 666d80efd5cSThomas Hellstrom * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer 667d80efd5cSThomas Hellstrom * contains the command data. 668d80efd5cSThomas Hellstrom */ 669d80efd5cSThomas Hellstrom static void vmw_collect_view_ids(struct vmw_ctx_binding_state *cbs, 670d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *bi, 671d80efd5cSThomas Hellstrom u32 max_num) 672d80efd5cSThomas Hellstrom { 673d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo_view *biv = 674d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_view, bi); 675d80efd5cSThomas Hellstrom unsigned long i; 676d80efd5cSThomas Hellstrom 677d80efd5cSThomas Hellstrom cbs->bind_cmd_count = 0; 678d80efd5cSThomas Hellstrom cbs->bind_first_slot = 0; 679d80efd5cSThomas Hellstrom 680d80efd5cSThomas Hellstrom for (i = 0; i < max_num; ++i, ++biv) { 681d80efd5cSThomas Hellstrom if (!biv->bi.ctx) 682d80efd5cSThomas Hellstrom break; 683d80efd5cSThomas Hellstrom 684d80efd5cSThomas Hellstrom cbs->bind_cmd_buffer[cbs->bind_cmd_count++] = 685d80efd5cSThomas Hellstrom ((biv->bi.scrubbed) ? 686d80efd5cSThomas Hellstrom SVGA3D_INVALID_ID : biv->bi.res->id); 687d80efd5cSThomas Hellstrom } 688d80efd5cSThomas Hellstrom } 689d80efd5cSThomas Hellstrom 690d80efd5cSThomas Hellstrom /** 691d80efd5cSThomas Hellstrom * vmw_collect_dirty_view_ids - Build view id data for a view binding command 692d80efd5cSThomas Hellstrom * 693d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 694d80efd5cSThomas Hellstrom * @bi: Pointer to where the binding info array is stored in @cbs 695d80efd5cSThomas Hellstrom * @dirty: Bitmap indicating which bindings need to be emitted. 696d80efd5cSThomas Hellstrom * @max_num: Maximum number of entries in the @bi array. 697d80efd5cSThomas Hellstrom * 698d80efd5cSThomas Hellstrom * Scans the @bi array for bindings that need to be emitted and 699d80efd5cSThomas Hellstrom * builds a buffer of view id data. 700d80efd5cSThomas Hellstrom * On output, @cbs->bind_cmd_count contains the number of bindings to be 701d80efd5cSThomas Hellstrom * emitted, @cbs->bind_first_slot indicates the index of the first emitted 702d80efd5cSThomas Hellstrom * binding, and @cbs->bind_cmd_buffer contains the command data. 703d80efd5cSThomas Hellstrom */ 704d80efd5cSThomas Hellstrom static void vmw_collect_dirty_view_ids(struct vmw_ctx_binding_state *cbs, 705d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *bi, 706d80efd5cSThomas Hellstrom unsigned long *dirty, 707d80efd5cSThomas Hellstrom u32 max_num) 708d80efd5cSThomas Hellstrom { 709d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo_view *biv = 710d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_view, bi); 711d80efd5cSThomas Hellstrom unsigned long i, next_bit; 712d80efd5cSThomas Hellstrom 713d80efd5cSThomas Hellstrom cbs->bind_cmd_count = 0; 714d80efd5cSThomas Hellstrom i = find_first_bit(dirty, max_num); 715d80efd5cSThomas Hellstrom next_bit = i; 716d80efd5cSThomas Hellstrom cbs->bind_first_slot = i; 717d80efd5cSThomas Hellstrom 718d80efd5cSThomas Hellstrom biv += i; 719d80efd5cSThomas Hellstrom for (; i < max_num; ++i, ++biv) { 720d80efd5cSThomas Hellstrom cbs->bind_cmd_buffer[cbs->bind_cmd_count++] = 721d80efd5cSThomas Hellstrom ((!biv->bi.ctx || biv->bi.scrubbed) ? 722d80efd5cSThomas Hellstrom SVGA3D_INVALID_ID : biv->bi.res->id); 723d80efd5cSThomas Hellstrom 724d80efd5cSThomas Hellstrom if (next_bit == i) { 725d80efd5cSThomas Hellstrom next_bit = find_next_bit(dirty, max_num, i + 1); 726d80efd5cSThomas Hellstrom if (next_bit >= max_num) 727d80efd5cSThomas Hellstrom break; 728d80efd5cSThomas Hellstrom } 729d80efd5cSThomas Hellstrom } 730d80efd5cSThomas Hellstrom } 731d80efd5cSThomas Hellstrom 732d80efd5cSThomas Hellstrom /** 733d80efd5cSThomas Hellstrom * vmw_binding_emit_set_sr - Issue delayed DX shader resource binding commands 734d80efd5cSThomas Hellstrom * 735d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 736d80efd5cSThomas Hellstrom */ 737d80efd5cSThomas Hellstrom static int vmw_emit_set_sr(struct vmw_ctx_binding_state *cbs, 738d80efd5cSThomas Hellstrom int shader_slot) 739d80efd5cSThomas Hellstrom { 740d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *loc = 741d80efd5cSThomas Hellstrom &cbs->per_shader[shader_slot].shader_res[0].bi; 742d80efd5cSThomas Hellstrom struct { 743d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 744d80efd5cSThomas Hellstrom SVGA3dCmdDXSetShaderResources body; 745d80efd5cSThomas Hellstrom } *cmd; 746d80efd5cSThomas Hellstrom size_t cmd_size, view_id_size; 747d80efd5cSThomas Hellstrom const struct vmw_resource *ctx = vmw_cbs_context(cbs); 748d80efd5cSThomas Hellstrom 749d80efd5cSThomas Hellstrom vmw_collect_dirty_view_ids(cbs, loc, 750d80efd5cSThomas Hellstrom cbs->per_shader[shader_slot].dirty_sr, 751d80efd5cSThomas Hellstrom SVGA3D_DX_MAX_SRVIEWS); 752d80efd5cSThomas Hellstrom if (cbs->bind_cmd_count == 0) 753d80efd5cSThomas Hellstrom return 0; 754d80efd5cSThomas Hellstrom 755d80efd5cSThomas Hellstrom view_id_size = cbs->bind_cmd_count*sizeof(uint32); 756d80efd5cSThomas Hellstrom cmd_size = sizeof(*cmd) + view_id_size; 75711c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 75811c45419SDeepak Rawat if (unlikely(cmd == NULL)) 759d80efd5cSThomas Hellstrom return -ENOMEM; 760d80efd5cSThomas Hellstrom 761d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER_RESOURCES; 762d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body) + view_id_size; 763d80efd5cSThomas Hellstrom cmd->body.type = shader_slot + SVGA3D_SHADERTYPE_MIN; 764d80efd5cSThomas Hellstrom cmd->body.startView = cbs->bind_first_slot; 765d80efd5cSThomas Hellstrom 766d80efd5cSThomas Hellstrom memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size); 767d80efd5cSThomas Hellstrom 768d80efd5cSThomas Hellstrom vmw_fifo_commit(ctx->dev_priv, cmd_size); 769d80efd5cSThomas Hellstrom bitmap_clear(cbs->per_shader[shader_slot].dirty_sr, 770d80efd5cSThomas Hellstrom cbs->bind_first_slot, cbs->bind_cmd_count); 771d80efd5cSThomas Hellstrom 772d80efd5cSThomas Hellstrom return 0; 773d80efd5cSThomas Hellstrom } 774d80efd5cSThomas Hellstrom 775d80efd5cSThomas Hellstrom /** 776d80efd5cSThomas Hellstrom * vmw_binding_emit_set_rt - Issue delayed DX rendertarget binding commands 777d80efd5cSThomas Hellstrom * 778d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 779d80efd5cSThomas Hellstrom */ 780d80efd5cSThomas Hellstrom static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs) 781d80efd5cSThomas Hellstrom { 782d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *loc = &cbs->render_targets[0].bi; 783d80efd5cSThomas Hellstrom struct { 784d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 785d80efd5cSThomas Hellstrom SVGA3dCmdDXSetRenderTargets body; 786d80efd5cSThomas Hellstrom } *cmd; 787d80efd5cSThomas Hellstrom size_t cmd_size, view_id_size; 788d80efd5cSThomas Hellstrom const struct vmw_resource *ctx = vmw_cbs_context(cbs); 789d80efd5cSThomas Hellstrom 790d80efd5cSThomas Hellstrom vmw_collect_view_ids(cbs, loc, SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS); 791d80efd5cSThomas Hellstrom view_id_size = cbs->bind_cmd_count*sizeof(uint32); 792d80efd5cSThomas Hellstrom cmd_size = sizeof(*cmd) + view_id_size; 79311c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 79411c45419SDeepak Rawat if (unlikely(cmd == NULL)) 795d80efd5cSThomas Hellstrom return -ENOMEM; 796d80efd5cSThomas Hellstrom 797d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_RENDERTARGETS; 798d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body) + view_id_size; 799d80efd5cSThomas Hellstrom 800d80efd5cSThomas Hellstrom if (cbs->ds_view.bi.ctx && !cbs->ds_view.bi.scrubbed) 801d80efd5cSThomas Hellstrom cmd->body.depthStencilViewId = cbs->ds_view.bi.res->id; 802d80efd5cSThomas Hellstrom else 803d80efd5cSThomas Hellstrom cmd->body.depthStencilViewId = SVGA3D_INVALID_ID; 804d80efd5cSThomas Hellstrom 805d80efd5cSThomas Hellstrom memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size); 806d80efd5cSThomas Hellstrom 807d80efd5cSThomas Hellstrom vmw_fifo_commit(ctx->dev_priv, cmd_size); 808d80efd5cSThomas Hellstrom 809d80efd5cSThomas Hellstrom return 0; 810d80efd5cSThomas Hellstrom 811d80efd5cSThomas Hellstrom } 812d80efd5cSThomas Hellstrom 813d80efd5cSThomas Hellstrom /** 814d80efd5cSThomas Hellstrom * vmw_collect_so_targets - Build SVGA3dSoTarget data for a binding command 815d80efd5cSThomas Hellstrom * without checking which bindings actually need to be emitted 816d80efd5cSThomas Hellstrom * 817d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 818d80efd5cSThomas Hellstrom * @bi: Pointer to where the binding info array is stored in @cbs 819d80efd5cSThomas Hellstrom * @max_num: Maximum number of entries in the @bi array. 820d80efd5cSThomas Hellstrom * 821d80efd5cSThomas Hellstrom * Scans the @bi array for bindings and builds a buffer of SVGA3dSoTarget data. 822d80efd5cSThomas Hellstrom * Stops at the first non-existing binding in the @bi array. 823d80efd5cSThomas Hellstrom * On output, @cbs->bind_cmd_count contains the number of bindings to be 824d80efd5cSThomas Hellstrom * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer 825d80efd5cSThomas Hellstrom * contains the command data. 826d80efd5cSThomas Hellstrom */ 827d80efd5cSThomas Hellstrom static void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs, 828d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *bi, 829d80efd5cSThomas Hellstrom u32 max_num) 830d80efd5cSThomas Hellstrom { 831d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo_so *biso = 832d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_so, bi); 833d80efd5cSThomas Hellstrom unsigned long i; 834d80efd5cSThomas Hellstrom SVGA3dSoTarget *so_buffer = (SVGA3dSoTarget *) cbs->bind_cmd_buffer; 835d80efd5cSThomas Hellstrom 836d80efd5cSThomas Hellstrom cbs->bind_cmd_count = 0; 837d80efd5cSThomas Hellstrom cbs->bind_first_slot = 0; 838d80efd5cSThomas Hellstrom 839d80efd5cSThomas Hellstrom for (i = 0; i < max_num; ++i, ++biso, ++so_buffer, 840d80efd5cSThomas Hellstrom ++cbs->bind_cmd_count) { 841d80efd5cSThomas Hellstrom if (!biso->bi.ctx) 842d80efd5cSThomas Hellstrom break; 843d80efd5cSThomas Hellstrom 844d80efd5cSThomas Hellstrom if (!biso->bi.scrubbed) { 845d80efd5cSThomas Hellstrom so_buffer->sid = biso->bi.res->id; 846d80efd5cSThomas Hellstrom so_buffer->offset = biso->offset; 847d80efd5cSThomas Hellstrom so_buffer->sizeInBytes = biso->size; 848d80efd5cSThomas Hellstrom } else { 849d80efd5cSThomas Hellstrom so_buffer->sid = SVGA3D_INVALID_ID; 850d80efd5cSThomas Hellstrom so_buffer->offset = 0; 851d80efd5cSThomas Hellstrom so_buffer->sizeInBytes = 0; 852d80efd5cSThomas Hellstrom } 853d80efd5cSThomas Hellstrom } 854d80efd5cSThomas Hellstrom } 855d80efd5cSThomas Hellstrom 856d80efd5cSThomas Hellstrom /** 857d80efd5cSThomas Hellstrom * vmw_binding_emit_set_so - Issue delayed streamout binding commands 858d80efd5cSThomas Hellstrom * 859d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 860d80efd5cSThomas Hellstrom */ 861d80efd5cSThomas Hellstrom static int vmw_emit_set_so(struct vmw_ctx_binding_state *cbs) 862d80efd5cSThomas Hellstrom { 863d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *loc = &cbs->so_targets[0].bi; 864d80efd5cSThomas Hellstrom struct { 865d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 866d80efd5cSThomas Hellstrom SVGA3dCmdDXSetSOTargets body; 867d80efd5cSThomas Hellstrom } *cmd; 868d80efd5cSThomas Hellstrom size_t cmd_size, so_target_size; 869d80efd5cSThomas Hellstrom const struct vmw_resource *ctx = vmw_cbs_context(cbs); 870d80efd5cSThomas Hellstrom 871d80efd5cSThomas Hellstrom vmw_collect_so_targets(cbs, loc, SVGA3D_DX_MAX_SOTARGETS); 872d80efd5cSThomas Hellstrom if (cbs->bind_cmd_count == 0) 873d80efd5cSThomas Hellstrom return 0; 874d80efd5cSThomas Hellstrom 875d80efd5cSThomas Hellstrom so_target_size = cbs->bind_cmd_count*sizeof(SVGA3dSoTarget); 876d80efd5cSThomas Hellstrom cmd_size = sizeof(*cmd) + so_target_size; 87711c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 87811c45419SDeepak Rawat if (unlikely(cmd == NULL)) 879d80efd5cSThomas Hellstrom return -ENOMEM; 880d80efd5cSThomas Hellstrom 881d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_SOTARGETS; 882d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body) + so_target_size; 883d80efd5cSThomas Hellstrom memcpy(&cmd[1], cbs->bind_cmd_buffer, so_target_size); 884d80efd5cSThomas Hellstrom 885d80efd5cSThomas Hellstrom vmw_fifo_commit(ctx->dev_priv, cmd_size); 886d80efd5cSThomas Hellstrom 887d80efd5cSThomas Hellstrom return 0; 888d80efd5cSThomas Hellstrom 889d80efd5cSThomas Hellstrom } 890d80efd5cSThomas Hellstrom 891d80efd5cSThomas Hellstrom /** 892d80efd5cSThomas Hellstrom * vmw_binding_emit_dirty_ps - Issue delayed per shader binding commands 893d80efd5cSThomas Hellstrom * 894d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 895d80efd5cSThomas Hellstrom * 896d80efd5cSThomas Hellstrom */ 897d80efd5cSThomas Hellstrom static int vmw_binding_emit_dirty_ps(struct vmw_ctx_binding_state *cbs) 898d80efd5cSThomas Hellstrom { 899d80efd5cSThomas Hellstrom struct vmw_dx_shader_bindings *sb = &cbs->per_shader[0]; 900d80efd5cSThomas Hellstrom u32 i; 901d80efd5cSThomas Hellstrom int ret; 902d80efd5cSThomas Hellstrom 903d80efd5cSThomas Hellstrom for (i = 0; i < SVGA3D_NUM_SHADERTYPE_DX10; ++i, ++sb) { 904d80efd5cSThomas Hellstrom if (!test_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty)) 905d80efd5cSThomas Hellstrom continue; 906d80efd5cSThomas Hellstrom 907d80efd5cSThomas Hellstrom ret = vmw_emit_set_sr(cbs, i); 908d80efd5cSThomas Hellstrom if (ret) 909d80efd5cSThomas Hellstrom break; 910d80efd5cSThomas Hellstrom 911d80efd5cSThomas Hellstrom __clear_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty); 912d80efd5cSThomas Hellstrom } 913d80efd5cSThomas Hellstrom 914d80efd5cSThomas Hellstrom return 0; 915d80efd5cSThomas Hellstrom } 916d80efd5cSThomas Hellstrom 917d80efd5cSThomas Hellstrom /** 918d80efd5cSThomas Hellstrom * vmw_collect_dirty_vbs - Build SVGA3dVertexBuffer data for a 919d80efd5cSThomas Hellstrom * SVGA3dCmdDXSetVertexBuffers command 920d80efd5cSThomas Hellstrom * 921d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 922d80efd5cSThomas Hellstrom * @bi: Pointer to where the binding info array is stored in @cbs 923d80efd5cSThomas Hellstrom * @dirty: Bitmap indicating which bindings need to be emitted. 924d80efd5cSThomas Hellstrom * @max_num: Maximum number of entries in the @bi array. 925d80efd5cSThomas Hellstrom * 926d80efd5cSThomas Hellstrom * Scans the @bi array for bindings that need to be emitted and 927d80efd5cSThomas Hellstrom * builds a buffer of SVGA3dVertexBuffer data. 928d80efd5cSThomas Hellstrom * On output, @cbs->bind_cmd_count contains the number of bindings to be 929d80efd5cSThomas Hellstrom * emitted, @cbs->bind_first_slot indicates the index of the first emitted 930d80efd5cSThomas Hellstrom * binding, and @cbs->bind_cmd_buffer contains the command data. 931d80efd5cSThomas Hellstrom */ 932d80efd5cSThomas Hellstrom static void vmw_collect_dirty_vbs(struct vmw_ctx_binding_state *cbs, 933d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *bi, 934d80efd5cSThomas Hellstrom unsigned long *dirty, 935d80efd5cSThomas Hellstrom u32 max_num) 936d80efd5cSThomas Hellstrom { 937d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo_vb *biv = 938d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_vb, bi); 939d80efd5cSThomas Hellstrom unsigned long i, next_bit; 940d80efd5cSThomas Hellstrom SVGA3dVertexBuffer *vbs = (SVGA3dVertexBuffer *) &cbs->bind_cmd_buffer; 941d80efd5cSThomas Hellstrom 942d80efd5cSThomas Hellstrom cbs->bind_cmd_count = 0; 943d80efd5cSThomas Hellstrom i = find_first_bit(dirty, max_num); 944d80efd5cSThomas Hellstrom next_bit = i; 945d80efd5cSThomas Hellstrom cbs->bind_first_slot = i; 946d80efd5cSThomas Hellstrom 947d80efd5cSThomas Hellstrom biv += i; 948d80efd5cSThomas Hellstrom for (; i < max_num; ++i, ++biv, ++vbs) { 949d80efd5cSThomas Hellstrom if (!biv->bi.ctx || biv->bi.scrubbed) { 950d80efd5cSThomas Hellstrom vbs->sid = SVGA3D_INVALID_ID; 951d80efd5cSThomas Hellstrom vbs->stride = 0; 952d80efd5cSThomas Hellstrom vbs->offset = 0; 953d80efd5cSThomas Hellstrom } else { 954d80efd5cSThomas Hellstrom vbs->sid = biv->bi.res->id; 955d80efd5cSThomas Hellstrom vbs->stride = biv->stride; 956d80efd5cSThomas Hellstrom vbs->offset = biv->offset; 957d80efd5cSThomas Hellstrom } 958d80efd5cSThomas Hellstrom cbs->bind_cmd_count++; 959d80efd5cSThomas Hellstrom if (next_bit == i) { 960d80efd5cSThomas Hellstrom next_bit = find_next_bit(dirty, max_num, i + 1); 961d80efd5cSThomas Hellstrom if (next_bit >= max_num) 962d80efd5cSThomas Hellstrom break; 963d80efd5cSThomas Hellstrom } 964d80efd5cSThomas Hellstrom } 965d80efd5cSThomas Hellstrom } 966d80efd5cSThomas Hellstrom 967d80efd5cSThomas Hellstrom /** 968d80efd5cSThomas Hellstrom * vmw_binding_emit_set_vb - Issue delayed vertex buffer binding commands 969d80efd5cSThomas Hellstrom * 970d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 971d80efd5cSThomas Hellstrom * 972d80efd5cSThomas Hellstrom */ 973d80efd5cSThomas Hellstrom static int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs) 974d80efd5cSThomas Hellstrom { 975d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *loc = 976d80efd5cSThomas Hellstrom &cbs->vertex_buffers[0].bi; 977d80efd5cSThomas Hellstrom struct { 978d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 979d80efd5cSThomas Hellstrom SVGA3dCmdDXSetVertexBuffers body; 980d80efd5cSThomas Hellstrom } *cmd; 981d80efd5cSThomas Hellstrom size_t cmd_size, set_vb_size; 982d80efd5cSThomas Hellstrom const struct vmw_resource *ctx = vmw_cbs_context(cbs); 983d80efd5cSThomas Hellstrom 984d80efd5cSThomas Hellstrom vmw_collect_dirty_vbs(cbs, loc, cbs->dirty_vb, 985d80efd5cSThomas Hellstrom SVGA3D_DX_MAX_VERTEXBUFFERS); 986d80efd5cSThomas Hellstrom if (cbs->bind_cmd_count == 0) 987d80efd5cSThomas Hellstrom return 0; 988d80efd5cSThomas Hellstrom 989d80efd5cSThomas Hellstrom set_vb_size = cbs->bind_cmd_count*sizeof(SVGA3dVertexBuffer); 990d80efd5cSThomas Hellstrom cmd_size = sizeof(*cmd) + set_vb_size; 99111c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 99211c45419SDeepak Rawat if (unlikely(cmd == NULL)) 993d80efd5cSThomas Hellstrom return -ENOMEM; 994d80efd5cSThomas Hellstrom 995d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS; 996d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body) + set_vb_size; 997d80efd5cSThomas Hellstrom cmd->body.startBuffer = cbs->bind_first_slot; 998d80efd5cSThomas Hellstrom 999d80efd5cSThomas Hellstrom memcpy(&cmd[1], cbs->bind_cmd_buffer, set_vb_size); 1000d80efd5cSThomas Hellstrom 1001d80efd5cSThomas Hellstrom vmw_fifo_commit(ctx->dev_priv, cmd_size); 1002d80efd5cSThomas Hellstrom bitmap_clear(cbs->dirty_vb, 1003d80efd5cSThomas Hellstrom cbs->bind_first_slot, cbs->bind_cmd_count); 1004d80efd5cSThomas Hellstrom 1005d80efd5cSThomas Hellstrom return 0; 1006d80efd5cSThomas Hellstrom } 1007d80efd5cSThomas Hellstrom 1008d80efd5cSThomas Hellstrom /** 1009d80efd5cSThomas Hellstrom * vmw_binding_emit_dirty - Issue delayed binding commands 1010d80efd5cSThomas Hellstrom * 1011d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 1012d80efd5cSThomas Hellstrom * 1013d80efd5cSThomas Hellstrom * This function issues the delayed binding commands that arise from 1014d80efd5cSThomas Hellstrom * previous scrub / unscrub calls. These binding commands are typically 1015d80efd5cSThomas Hellstrom * commands that batch a number of bindings and therefore it makes sense 1016d80efd5cSThomas Hellstrom * to delay them. 1017d80efd5cSThomas Hellstrom */ 1018d80efd5cSThomas Hellstrom static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs) 1019d80efd5cSThomas Hellstrom { 1020d80efd5cSThomas Hellstrom int ret = 0; 1021d80efd5cSThomas Hellstrom unsigned long hit = 0; 1022d80efd5cSThomas Hellstrom 1023d80efd5cSThomas Hellstrom while ((hit = find_next_bit(&cbs->dirty, VMW_BINDING_NUM_BITS, hit)) 1024d80efd5cSThomas Hellstrom < VMW_BINDING_NUM_BITS) { 1025d80efd5cSThomas Hellstrom 1026d80efd5cSThomas Hellstrom switch (hit) { 1027d80efd5cSThomas Hellstrom case VMW_BINDING_RT_BIT: 1028d80efd5cSThomas Hellstrom ret = vmw_emit_set_rt(cbs); 1029d80efd5cSThomas Hellstrom break; 1030d80efd5cSThomas Hellstrom case VMW_BINDING_PS_BIT: 1031d80efd5cSThomas Hellstrom ret = vmw_binding_emit_dirty_ps(cbs); 1032d80efd5cSThomas Hellstrom break; 1033d80efd5cSThomas Hellstrom case VMW_BINDING_SO_BIT: 1034d80efd5cSThomas Hellstrom ret = vmw_emit_set_so(cbs); 1035d80efd5cSThomas Hellstrom break; 1036d80efd5cSThomas Hellstrom case VMW_BINDING_VB_BIT: 1037d80efd5cSThomas Hellstrom ret = vmw_emit_set_vb(cbs); 1038d80efd5cSThomas Hellstrom break; 1039d80efd5cSThomas Hellstrom default: 1040d80efd5cSThomas Hellstrom BUG(); 1041d80efd5cSThomas Hellstrom } 1042d80efd5cSThomas Hellstrom if (ret) 1043d80efd5cSThomas Hellstrom return ret; 1044d80efd5cSThomas Hellstrom 1045d80efd5cSThomas Hellstrom __clear_bit(hit, &cbs->dirty); 1046d80efd5cSThomas Hellstrom hit++; 1047d80efd5cSThomas Hellstrom } 1048d80efd5cSThomas Hellstrom 1049d80efd5cSThomas Hellstrom return 0; 1050d80efd5cSThomas Hellstrom } 1051d80efd5cSThomas Hellstrom 1052d80efd5cSThomas Hellstrom /** 1053d80efd5cSThomas Hellstrom * vmw_binding_scrub_sr - Schedule a dx shaderresource binding 1054d80efd5cSThomas Hellstrom * scrub from a context 1055d80efd5cSThomas Hellstrom * 1056d80efd5cSThomas Hellstrom * @bi: single binding information. 1057d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 1058d80efd5cSThomas Hellstrom */ 1059d80efd5cSThomas Hellstrom static int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind) 1060d80efd5cSThomas Hellstrom { 1061d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_view *biv = 1062d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_view, bi); 1063d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *cbs = 1064d80efd5cSThomas Hellstrom vmw_context_binding_state(bi->ctx); 1065d80efd5cSThomas Hellstrom 1066d80efd5cSThomas Hellstrom __set_bit(biv->slot, cbs->per_shader[biv->shader_slot].dirty_sr); 1067d80efd5cSThomas Hellstrom __set_bit(VMW_BINDING_PS_SR_BIT, 1068d80efd5cSThomas Hellstrom &cbs->per_shader[biv->shader_slot].dirty); 1069d80efd5cSThomas Hellstrom __set_bit(VMW_BINDING_PS_BIT, &cbs->dirty); 1070d80efd5cSThomas Hellstrom 1071d80efd5cSThomas Hellstrom return 0; 1072d80efd5cSThomas Hellstrom } 1073d80efd5cSThomas Hellstrom 1074d80efd5cSThomas Hellstrom /** 1075d80efd5cSThomas Hellstrom * vmw_binding_scrub_dx_rt - Schedule a dx rendertarget binding 1076d80efd5cSThomas Hellstrom * scrub from a context 1077d80efd5cSThomas Hellstrom * 1078d80efd5cSThomas Hellstrom * @bi: single binding information. 1079d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 1080d80efd5cSThomas Hellstrom */ 1081d80efd5cSThomas Hellstrom static int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind) 1082d80efd5cSThomas Hellstrom { 1083d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *cbs = 1084d80efd5cSThomas Hellstrom vmw_context_binding_state(bi->ctx); 1085d80efd5cSThomas Hellstrom 1086d80efd5cSThomas Hellstrom __set_bit(VMW_BINDING_RT_BIT, &cbs->dirty); 1087d80efd5cSThomas Hellstrom 1088d80efd5cSThomas Hellstrom return 0; 1089d80efd5cSThomas Hellstrom } 1090d80efd5cSThomas Hellstrom 1091d80efd5cSThomas Hellstrom /** 1092d80efd5cSThomas Hellstrom * vmw_binding_scrub_so - Schedule a dx streamoutput buffer binding 1093d80efd5cSThomas Hellstrom * scrub from a context 1094d80efd5cSThomas Hellstrom * 1095d80efd5cSThomas Hellstrom * @bi: single binding information. 1096d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 1097d80efd5cSThomas Hellstrom */ 1098d80efd5cSThomas Hellstrom static int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind) 1099d80efd5cSThomas Hellstrom { 1100d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *cbs = 1101d80efd5cSThomas Hellstrom vmw_context_binding_state(bi->ctx); 1102d80efd5cSThomas Hellstrom 1103d80efd5cSThomas Hellstrom __set_bit(VMW_BINDING_SO_BIT, &cbs->dirty); 1104d80efd5cSThomas Hellstrom 1105d80efd5cSThomas Hellstrom return 0; 1106d80efd5cSThomas Hellstrom } 1107d80efd5cSThomas Hellstrom 1108d80efd5cSThomas Hellstrom /** 1109d80efd5cSThomas Hellstrom * vmw_binding_scrub_vb - Schedule a dx vertex buffer binding 1110d80efd5cSThomas Hellstrom * scrub from a context 1111d80efd5cSThomas Hellstrom * 1112d80efd5cSThomas Hellstrom * @bi: single binding information. 1113d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 1114d80efd5cSThomas Hellstrom */ 1115d80efd5cSThomas Hellstrom static int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind) 1116d80efd5cSThomas Hellstrom { 1117d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_vb *bivb = 1118d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_vb, bi); 1119d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *cbs = 1120d80efd5cSThomas Hellstrom vmw_context_binding_state(bi->ctx); 1121d80efd5cSThomas Hellstrom 1122d80efd5cSThomas Hellstrom __set_bit(bivb->slot, cbs->dirty_vb); 1123d80efd5cSThomas Hellstrom __set_bit(VMW_BINDING_VB_BIT, &cbs->dirty); 1124d80efd5cSThomas Hellstrom 1125d80efd5cSThomas Hellstrom return 0; 1126d80efd5cSThomas Hellstrom } 1127d80efd5cSThomas Hellstrom 1128d80efd5cSThomas Hellstrom /** 1129d80efd5cSThomas Hellstrom * vmw_binding_scrub_ib - scrub a dx index buffer binding from a context 1130d80efd5cSThomas Hellstrom * 1131d80efd5cSThomas Hellstrom * @bi: single binding information. 1132d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 1133d80efd5cSThomas Hellstrom */ 1134d80efd5cSThomas Hellstrom static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind) 1135d80efd5cSThomas Hellstrom { 1136d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_ib *binding = 1137d80efd5cSThomas Hellstrom container_of(bi, typeof(*binding), bi); 1138d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = bi->ctx->dev_priv; 1139d80efd5cSThomas Hellstrom struct { 1140d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 1141d80efd5cSThomas Hellstrom SVGA3dCmdDXSetIndexBuffer body; 1142d80efd5cSThomas Hellstrom } *cmd; 1143d80efd5cSThomas Hellstrom 114411c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); 114511c45419SDeepak Rawat if (unlikely(cmd == NULL)) 1146d80efd5cSThomas Hellstrom return -ENOMEM; 114711c45419SDeepak Rawat 1148d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_INDEX_BUFFER; 1149d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 1150d80efd5cSThomas Hellstrom if (rebind) { 1151d80efd5cSThomas Hellstrom cmd->body.sid = bi->res->id; 1152d80efd5cSThomas Hellstrom cmd->body.format = binding->format; 1153d80efd5cSThomas Hellstrom cmd->body.offset = binding->offset; 1154d80efd5cSThomas Hellstrom } else { 1155d80efd5cSThomas Hellstrom cmd->body.sid = SVGA3D_INVALID_ID; 1156d80efd5cSThomas Hellstrom cmd->body.format = 0; 1157d80efd5cSThomas Hellstrom cmd->body.offset = 0; 1158d80efd5cSThomas Hellstrom } 1159d80efd5cSThomas Hellstrom 1160d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 1161d80efd5cSThomas Hellstrom 1162d80efd5cSThomas Hellstrom return 0; 1163d80efd5cSThomas Hellstrom } 1164d80efd5cSThomas Hellstrom 1165d80efd5cSThomas Hellstrom /** 1166d80efd5cSThomas Hellstrom * vmw_binding_state_alloc - Allocate a struct vmw_ctx_binding_state with 1167d80efd5cSThomas Hellstrom * memory accounting. 1168d80efd5cSThomas Hellstrom * 1169d80efd5cSThomas Hellstrom * @dev_priv: Pointer to a device private structure. 1170d80efd5cSThomas Hellstrom * 1171d80efd5cSThomas Hellstrom * Returns a pointer to a newly allocated struct or an error pointer on error. 1172d80efd5cSThomas Hellstrom */ 1173d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state * 1174d80efd5cSThomas Hellstrom vmw_binding_state_alloc(struct vmw_private *dev_priv) 1175d80efd5cSThomas Hellstrom { 1176d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *cbs; 1177279c01f6SRoger He struct ttm_operation_ctx ctx = { 1178279c01f6SRoger He .interruptible = false, 1179279c01f6SRoger He .no_wait_gpu = false 1180279c01f6SRoger He }; 1181d80efd5cSThomas Hellstrom int ret; 1182d80efd5cSThomas Hellstrom 1183d80efd5cSThomas Hellstrom ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), sizeof(*cbs), 1184279c01f6SRoger He &ctx); 1185d80efd5cSThomas Hellstrom if (ret) 1186d80efd5cSThomas Hellstrom return ERR_PTR(ret); 1187d80efd5cSThomas Hellstrom 1188d80efd5cSThomas Hellstrom cbs = vzalloc(sizeof(*cbs)); 1189d80efd5cSThomas Hellstrom if (!cbs) { 1190d80efd5cSThomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs)); 1191d80efd5cSThomas Hellstrom return ERR_PTR(-ENOMEM); 1192d80efd5cSThomas Hellstrom } 1193d80efd5cSThomas Hellstrom 1194d80efd5cSThomas Hellstrom cbs->dev_priv = dev_priv; 1195d80efd5cSThomas Hellstrom INIT_LIST_HEAD(&cbs->list); 1196d80efd5cSThomas Hellstrom 1197d80efd5cSThomas Hellstrom return cbs; 1198d80efd5cSThomas Hellstrom } 1199d80efd5cSThomas Hellstrom 1200d80efd5cSThomas Hellstrom /** 1201d80efd5cSThomas Hellstrom * vmw_binding_state_free - Free a struct vmw_ctx_binding_state and its 1202d80efd5cSThomas Hellstrom * memory accounting info. 1203d80efd5cSThomas Hellstrom * 1204d80efd5cSThomas Hellstrom * @cbs: Pointer to the struct vmw_ctx_binding_state to be freed. 1205d80efd5cSThomas Hellstrom */ 1206d80efd5cSThomas Hellstrom void vmw_binding_state_free(struct vmw_ctx_binding_state *cbs) 1207d80efd5cSThomas Hellstrom { 1208d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = cbs->dev_priv; 1209d80efd5cSThomas Hellstrom 1210d80efd5cSThomas Hellstrom vfree(cbs); 1211d80efd5cSThomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs)); 1212d80efd5cSThomas Hellstrom } 1213d80efd5cSThomas Hellstrom 1214d80efd5cSThomas Hellstrom /** 1215d80efd5cSThomas Hellstrom * vmw_binding_state_list - Get the binding list of a 1216d80efd5cSThomas Hellstrom * struct vmw_ctx_binding_state 1217d80efd5cSThomas Hellstrom * 1218d80efd5cSThomas Hellstrom * @cbs: Pointer to the struct vmw_ctx_binding_state 1219d80efd5cSThomas Hellstrom * 1220d80efd5cSThomas Hellstrom * Returns the binding list which can be used to traverse through the bindings 1221d80efd5cSThomas Hellstrom * and access the resource information of all bindings. 1222d80efd5cSThomas Hellstrom */ 1223d80efd5cSThomas Hellstrom struct list_head *vmw_binding_state_list(struct vmw_ctx_binding_state *cbs) 1224d80efd5cSThomas Hellstrom { 1225d80efd5cSThomas Hellstrom return &cbs->list; 1226d80efd5cSThomas Hellstrom } 1227d80efd5cSThomas Hellstrom 1228d80efd5cSThomas Hellstrom /** 1229d80efd5cSThomas Hellstrom * vmwgfx_binding_state_reset - clear a struct vmw_ctx_binding_state 1230d80efd5cSThomas Hellstrom * 1231d80efd5cSThomas Hellstrom * @cbs: Pointer to the struct vmw_ctx_binding_state to be cleared 1232d80efd5cSThomas Hellstrom * 1233d80efd5cSThomas Hellstrom * Drops all bindings registered in @cbs. No device binding actions are 1234d80efd5cSThomas Hellstrom * performed. 1235d80efd5cSThomas Hellstrom */ 1236d80efd5cSThomas Hellstrom void vmw_binding_state_reset(struct vmw_ctx_binding_state *cbs) 1237d80efd5cSThomas Hellstrom { 1238d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo *entry, *next; 1239d80efd5cSThomas Hellstrom 1240d80efd5cSThomas Hellstrom list_for_each_entry_safe(entry, next, &cbs->list, ctx_list) 1241d80efd5cSThomas Hellstrom vmw_binding_drop(entry); 1242d80efd5cSThomas Hellstrom } 1243d80efd5cSThomas Hellstrom 1244a9f58c45SThomas Hellstrom /** 1245a9f58c45SThomas Hellstrom * vmw_binding_dirtying - Return whether a binding type is dirtying its resource 1246a9f58c45SThomas Hellstrom * @binding_type: The binding type 1247a9f58c45SThomas Hellstrom * 1248a9f58c45SThomas Hellstrom * Each time a resource is put on the validation list as the result of a 1249a9f58c45SThomas Hellstrom * context binding referencing it, we need to determine whether that resource 1250a9f58c45SThomas Hellstrom * will be dirtied (written to by the GPU) as a result of the corresponding 1251a9f58c45SThomas Hellstrom * GPU operation. Currently rendertarget-, depth-stencil-, and 1252a9f58c45SThomas Hellstrom * stream-output-target bindings are capable of dirtying its resource. 1253a9f58c45SThomas Hellstrom * 1254a9f58c45SThomas Hellstrom * Return: Whether the binding type dirties the resource its binding points to. 1255a9f58c45SThomas Hellstrom */ 1256a9f58c45SThomas Hellstrom u32 vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type) 1257a9f58c45SThomas Hellstrom { 1258a9f58c45SThomas Hellstrom static u32 is_binding_dirtying[vmw_ctx_binding_max] = { 1259a9f58c45SThomas Hellstrom [vmw_ctx_binding_rt] = VMW_RES_DIRTY_SET, 1260a9f58c45SThomas Hellstrom [vmw_ctx_binding_dx_rt] = VMW_RES_DIRTY_SET, 1261a9f58c45SThomas Hellstrom [vmw_ctx_binding_ds] = VMW_RES_DIRTY_SET, 1262a9f58c45SThomas Hellstrom [vmw_ctx_binding_so] = VMW_RES_DIRTY_SET, 1263a9f58c45SThomas Hellstrom }; 1264a9f58c45SThomas Hellstrom 1265a9f58c45SThomas Hellstrom /* Review this function as new bindings are added. */ 1266a9f58c45SThomas Hellstrom BUILD_BUG_ON(vmw_ctx_binding_max != 11); 1267a9f58c45SThomas Hellstrom return is_binding_dirtying[binding_type]; 1268a9f58c45SThomas Hellstrom } 1269a9f58c45SThomas Hellstrom 1270d80efd5cSThomas Hellstrom /* 1271d80efd5cSThomas Hellstrom * This function is unused at run-time, and only used to hold various build 1272d80efd5cSThomas Hellstrom * asserts important for code optimization assumptions. 1273d80efd5cSThomas Hellstrom */ 1274d80efd5cSThomas Hellstrom static void vmw_binding_build_asserts(void) 1275d80efd5cSThomas Hellstrom { 1276d80efd5cSThomas Hellstrom BUILD_BUG_ON(SVGA3D_NUM_SHADERTYPE_DX10 != 3); 1277d80efd5cSThomas Hellstrom BUILD_BUG_ON(SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS > SVGA3D_RT_MAX); 1278d80efd5cSThomas Hellstrom BUILD_BUG_ON(sizeof(uint32) != sizeof(u32)); 1279d80efd5cSThomas Hellstrom 1280d80efd5cSThomas Hellstrom /* 1281d80efd5cSThomas Hellstrom * struct vmw_ctx_binding_state::bind_cmd_buffer is used for various 1282d80efd5cSThomas Hellstrom * view id arrays. 1283d80efd5cSThomas Hellstrom */ 1284d80efd5cSThomas Hellstrom BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_RT_MAX); 1285d80efd5cSThomas Hellstrom BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_SRVIEWS); 1286d80efd5cSThomas Hellstrom BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_CONSTBUFFERS); 1287d80efd5cSThomas Hellstrom 1288d80efd5cSThomas Hellstrom /* 1289d80efd5cSThomas Hellstrom * struct vmw_ctx_binding_state::bind_cmd_buffer is used for 1290d80efd5cSThomas Hellstrom * u32 view ids, SVGA3dSoTargets and SVGA3dVertexBuffers 1291d80efd5cSThomas Hellstrom */ 1292d80efd5cSThomas Hellstrom BUILD_BUG_ON(SVGA3D_DX_MAX_SOTARGETS*sizeof(SVGA3dSoTarget) > 1293d80efd5cSThomas Hellstrom VMW_MAX_VIEW_BINDINGS*sizeof(u32)); 1294d80efd5cSThomas Hellstrom BUILD_BUG_ON(SVGA3D_DX_MAX_VERTEXBUFFERS*sizeof(SVGA3dVertexBuffer) > 1295d80efd5cSThomas Hellstrom VMW_MAX_VIEW_BINDINGS*sizeof(u32)); 1296d80efd5cSThomas Hellstrom } 1297