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; 101d2e90ab3SDeepak Rawat struct vmw_dx_shader_bindings per_shader[SVGA3D_NUM_SHADERTYPE]; 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), 154d2e90ab3SDeepak Rawat offsetof(struct vmw_ctx_binding_state, per_shader[3].shader), 155d2e90ab3SDeepak Rawat offsetof(struct vmw_ctx_binding_state, per_shader[4].shader), 156d2e90ab3SDeepak Rawat offsetof(struct vmw_ctx_binding_state, per_shader[5].shader), 157d80efd5cSThomas Hellstrom }; 158d80efd5cSThomas Hellstrom static const size_t vmw_binding_rt_offsets[] = { 159d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, render_targets), 160d80efd5cSThomas Hellstrom }; 161d80efd5cSThomas Hellstrom static const size_t vmw_binding_tex_offsets[] = { 162d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, texture_units), 163d80efd5cSThomas Hellstrom }; 164d80efd5cSThomas Hellstrom static const size_t vmw_binding_cb_offsets[] = { 165d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, per_shader[0].const_buffers), 166d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, per_shader[1].const_buffers), 167d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, per_shader[2].const_buffers), 168d2e90ab3SDeepak Rawat offsetof(struct vmw_ctx_binding_state, per_shader[3].const_buffers), 169d2e90ab3SDeepak Rawat offsetof(struct vmw_ctx_binding_state, per_shader[4].const_buffers), 170d2e90ab3SDeepak Rawat offsetof(struct vmw_ctx_binding_state, per_shader[5].const_buffers), 171d80efd5cSThomas Hellstrom }; 172d80efd5cSThomas Hellstrom static const size_t vmw_binding_dx_ds_offsets[] = { 173d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, ds_view), 174d80efd5cSThomas Hellstrom }; 175d80efd5cSThomas Hellstrom static const size_t vmw_binding_sr_offsets[] = { 176d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, per_shader[0].shader_res), 177d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, per_shader[1].shader_res), 178d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, per_shader[2].shader_res), 179d2e90ab3SDeepak Rawat offsetof(struct vmw_ctx_binding_state, per_shader[3].shader_res), 180d2e90ab3SDeepak Rawat offsetof(struct vmw_ctx_binding_state, per_shader[4].shader_res), 181d2e90ab3SDeepak Rawat offsetof(struct vmw_ctx_binding_state, per_shader[5].shader_res), 182d80efd5cSThomas Hellstrom }; 183d80efd5cSThomas Hellstrom static const size_t vmw_binding_so_offsets[] = { 184d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, so_targets), 185d80efd5cSThomas Hellstrom }; 186d80efd5cSThomas Hellstrom static const size_t vmw_binding_vb_offsets[] = { 187d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, vertex_buffers), 188d80efd5cSThomas Hellstrom }; 189d80efd5cSThomas Hellstrom static const size_t vmw_binding_ib_offsets[] = { 190d80efd5cSThomas Hellstrom offsetof(struct vmw_ctx_binding_state, index_buffer), 191d80efd5cSThomas Hellstrom }; 192d80efd5cSThomas Hellstrom 193d80efd5cSThomas Hellstrom static const struct vmw_binding_info vmw_binding_infos[] = { 194d80efd5cSThomas Hellstrom [vmw_ctx_binding_shader] = { 195d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_shader), 196d80efd5cSThomas Hellstrom .offsets = vmw_binding_shader_offsets, 197d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_shader}, 198d80efd5cSThomas Hellstrom [vmw_ctx_binding_rt] = { 199d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_view), 200d80efd5cSThomas Hellstrom .offsets = vmw_binding_rt_offsets, 201d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_render_target}, 202d80efd5cSThomas Hellstrom [vmw_ctx_binding_tex] = { 203d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_tex), 204d80efd5cSThomas Hellstrom .offsets = vmw_binding_tex_offsets, 205d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_texture}, 206d80efd5cSThomas Hellstrom [vmw_ctx_binding_cb] = { 207d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_cb), 208d80efd5cSThomas Hellstrom .offsets = vmw_binding_cb_offsets, 209d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_cb}, 210d80efd5cSThomas Hellstrom [vmw_ctx_binding_dx_shader] = { 211d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_shader), 212d80efd5cSThomas Hellstrom .offsets = vmw_binding_shader_offsets, 213d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_dx_shader}, 214d80efd5cSThomas Hellstrom [vmw_ctx_binding_dx_rt] = { 215d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_view), 216d80efd5cSThomas Hellstrom .offsets = vmw_binding_rt_offsets, 217d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_dx_rt}, 218d80efd5cSThomas Hellstrom [vmw_ctx_binding_sr] = { 219d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_view), 220d80efd5cSThomas Hellstrom .offsets = vmw_binding_sr_offsets, 221d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_sr}, 222d80efd5cSThomas Hellstrom [vmw_ctx_binding_ds] = { 223d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_view), 224d80efd5cSThomas Hellstrom .offsets = vmw_binding_dx_ds_offsets, 225d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_dx_rt}, 226d80efd5cSThomas Hellstrom [vmw_ctx_binding_so] = { 227d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_so), 228d80efd5cSThomas Hellstrom .offsets = vmw_binding_so_offsets, 229d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_so}, 230d80efd5cSThomas Hellstrom [vmw_ctx_binding_vb] = { 231d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_vb), 232d80efd5cSThomas Hellstrom .offsets = vmw_binding_vb_offsets, 233d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_vb}, 234d80efd5cSThomas Hellstrom [vmw_ctx_binding_ib] = { 235d80efd5cSThomas Hellstrom .size = sizeof(struct vmw_ctx_bindinfo_ib), 236d80efd5cSThomas Hellstrom .offsets = vmw_binding_ib_offsets, 237d80efd5cSThomas Hellstrom .scrub_func = vmw_binding_scrub_ib}, 238d80efd5cSThomas Hellstrom }; 239d80efd5cSThomas Hellstrom 240d80efd5cSThomas Hellstrom /** 241d80efd5cSThomas Hellstrom * vmw_cbs_context - Return a pointer to the context resource of a 242d80efd5cSThomas Hellstrom * context binding state tracker. 243d80efd5cSThomas Hellstrom * 244d80efd5cSThomas Hellstrom * @cbs: The context binding state tracker. 245d80efd5cSThomas Hellstrom * 246d80efd5cSThomas Hellstrom * Provided there are any active bindings, this function will return an 247d80efd5cSThomas Hellstrom * unreferenced pointer to the context resource that owns the context 248d80efd5cSThomas Hellstrom * binding state tracker. If there are no active bindings, this function 249d80efd5cSThomas Hellstrom * will return NULL. Note that the caller must somehow ensure that a reference 250d80efd5cSThomas Hellstrom * is held on the context resource prior to calling this function. 251d80efd5cSThomas Hellstrom */ 252d80efd5cSThomas Hellstrom static const struct vmw_resource * 253d80efd5cSThomas Hellstrom vmw_cbs_context(const struct vmw_ctx_binding_state *cbs) 254d80efd5cSThomas Hellstrom { 255d80efd5cSThomas Hellstrom if (list_empty(&cbs->list)) 256d80efd5cSThomas Hellstrom return NULL; 257d80efd5cSThomas Hellstrom 258d80efd5cSThomas Hellstrom return list_first_entry(&cbs->list, struct vmw_ctx_bindinfo, 259d80efd5cSThomas Hellstrom ctx_list)->ctx; 260d80efd5cSThomas Hellstrom } 261d80efd5cSThomas Hellstrom 262d80efd5cSThomas Hellstrom /** 263d80efd5cSThomas Hellstrom * vmw_binding_loc - determine the struct vmw_ctx_bindinfo slot location. 264d80efd5cSThomas Hellstrom * 265d80efd5cSThomas Hellstrom * @cbs: Pointer to a struct vmw_ctx_binding state which holds the slot. 266d80efd5cSThomas Hellstrom * @bt: The binding type. 267d80efd5cSThomas Hellstrom * @shader_slot: The shader slot of the binding. If none, then set to 0. 268d80efd5cSThomas Hellstrom * @slot: The slot of the binding. 269d80efd5cSThomas Hellstrom */ 270d80efd5cSThomas Hellstrom static struct vmw_ctx_bindinfo * 271d80efd5cSThomas Hellstrom vmw_binding_loc(struct vmw_ctx_binding_state *cbs, 272d80efd5cSThomas Hellstrom enum vmw_ctx_binding_type bt, u32 shader_slot, u32 slot) 273d80efd5cSThomas Hellstrom { 274d80efd5cSThomas Hellstrom const struct vmw_binding_info *b = &vmw_binding_infos[bt]; 275d80efd5cSThomas Hellstrom size_t offset = b->offsets[shader_slot] + b->size*slot; 276d80efd5cSThomas Hellstrom 277d80efd5cSThomas Hellstrom return (struct vmw_ctx_bindinfo *)((u8 *) cbs + offset); 278d80efd5cSThomas Hellstrom } 279d80efd5cSThomas Hellstrom 280d80efd5cSThomas Hellstrom /** 281d80efd5cSThomas Hellstrom * vmw_binding_drop: Stop tracking a context binding 282d80efd5cSThomas Hellstrom * 283d80efd5cSThomas Hellstrom * @bi: Pointer to binding tracker storage. 284d80efd5cSThomas Hellstrom * 285d80efd5cSThomas Hellstrom * Stops tracking a context binding, and re-initializes its storage. 286d80efd5cSThomas Hellstrom * Typically used when the context binding is replaced with a binding to 287d80efd5cSThomas Hellstrom * another (or the same, for that matter) resource. 288d80efd5cSThomas Hellstrom */ 289d80efd5cSThomas Hellstrom static void vmw_binding_drop(struct vmw_ctx_bindinfo *bi) 290d80efd5cSThomas Hellstrom { 291d80efd5cSThomas Hellstrom list_del(&bi->ctx_list); 292d80efd5cSThomas Hellstrom if (!list_empty(&bi->res_list)) 293d80efd5cSThomas Hellstrom list_del(&bi->res_list); 294d80efd5cSThomas Hellstrom bi->ctx = NULL; 295d80efd5cSThomas Hellstrom } 296d80efd5cSThomas Hellstrom 297d80efd5cSThomas Hellstrom /** 298d80efd5cSThomas Hellstrom * vmw_binding_add: Start tracking a context binding 299d80efd5cSThomas Hellstrom * 300d80efd5cSThomas Hellstrom * @cbs: Pointer to the context binding state tracker. 301d80efd5cSThomas Hellstrom * @bi: Information about the binding to track. 302d80efd5cSThomas Hellstrom * 303d80efd5cSThomas Hellstrom * Starts tracking the binding in the context binding 304d80efd5cSThomas Hellstrom * state structure @cbs. 305d80efd5cSThomas Hellstrom */ 306d80efd5cSThomas Hellstrom void vmw_binding_add(struct vmw_ctx_binding_state *cbs, 307d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *bi, 308d80efd5cSThomas Hellstrom u32 shader_slot, u32 slot) 309d80efd5cSThomas Hellstrom { 310d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo *loc = 311d80efd5cSThomas Hellstrom vmw_binding_loc(cbs, bi->bt, shader_slot, slot); 312d80efd5cSThomas Hellstrom const struct vmw_binding_info *b = &vmw_binding_infos[bi->bt]; 313d80efd5cSThomas Hellstrom 314d80efd5cSThomas Hellstrom if (loc->ctx != NULL) 315d80efd5cSThomas Hellstrom vmw_binding_drop(loc); 316d80efd5cSThomas Hellstrom 317d80efd5cSThomas Hellstrom memcpy(loc, bi, b->size); 318d80efd5cSThomas Hellstrom loc->scrubbed = false; 319d80efd5cSThomas Hellstrom list_add(&loc->ctx_list, &cbs->list); 320d80efd5cSThomas Hellstrom INIT_LIST_HEAD(&loc->res_list); 321d80efd5cSThomas Hellstrom } 322d80efd5cSThomas Hellstrom 323d80efd5cSThomas Hellstrom /** 324d80efd5cSThomas Hellstrom * vmw_binding_transfer: Transfer a context binding tracking entry. 325d80efd5cSThomas Hellstrom * 326d80efd5cSThomas Hellstrom * @cbs: Pointer to the persistent context binding state tracker. 327d80efd5cSThomas Hellstrom * @bi: Information about the binding to track. 328d80efd5cSThomas Hellstrom * 329d80efd5cSThomas Hellstrom */ 330d80efd5cSThomas Hellstrom static void vmw_binding_transfer(struct vmw_ctx_binding_state *cbs, 331d80efd5cSThomas Hellstrom const struct vmw_ctx_binding_state *from, 332d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *bi) 333d80efd5cSThomas Hellstrom { 334d80efd5cSThomas Hellstrom size_t offset = (unsigned long)bi - (unsigned long)from; 335d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo *loc = (struct vmw_ctx_bindinfo *) 336d80efd5cSThomas Hellstrom ((unsigned long) cbs + offset); 337d80efd5cSThomas Hellstrom 338d80efd5cSThomas Hellstrom if (loc->ctx != NULL) { 339d80efd5cSThomas Hellstrom WARN_ON(bi->scrubbed); 340d80efd5cSThomas Hellstrom 341d80efd5cSThomas Hellstrom vmw_binding_drop(loc); 342d80efd5cSThomas Hellstrom } 343d80efd5cSThomas Hellstrom 344d80efd5cSThomas Hellstrom if (bi->res != NULL) { 345d80efd5cSThomas Hellstrom memcpy(loc, bi, vmw_binding_infos[bi->bt].size); 346d80efd5cSThomas Hellstrom list_add_tail(&loc->ctx_list, &cbs->list); 347d80efd5cSThomas Hellstrom list_add_tail(&loc->res_list, &loc->res->binding_head); 348d80efd5cSThomas Hellstrom } 349d80efd5cSThomas Hellstrom } 350d80efd5cSThomas Hellstrom 351d80efd5cSThomas Hellstrom /** 352d80efd5cSThomas Hellstrom * vmw_binding_state_kill - Kill all bindings associated with a 353d80efd5cSThomas Hellstrom * struct vmw_ctx_binding state structure, and re-initialize the structure. 354d80efd5cSThomas Hellstrom * 355d80efd5cSThomas Hellstrom * @cbs: Pointer to the context binding state tracker. 356d80efd5cSThomas Hellstrom * 357d80efd5cSThomas Hellstrom * Emits commands to scrub all bindings associated with the 358d80efd5cSThomas Hellstrom * context binding state tracker. Then re-initializes the whole structure. 359d80efd5cSThomas Hellstrom */ 360d80efd5cSThomas Hellstrom void vmw_binding_state_kill(struct vmw_ctx_binding_state *cbs) 361d80efd5cSThomas Hellstrom { 362d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo *entry, *next; 363d80efd5cSThomas Hellstrom 364d80efd5cSThomas Hellstrom vmw_binding_state_scrub(cbs); 365d80efd5cSThomas Hellstrom list_for_each_entry_safe(entry, next, &cbs->list, ctx_list) 366d80efd5cSThomas Hellstrom vmw_binding_drop(entry); 367d80efd5cSThomas Hellstrom } 368d80efd5cSThomas Hellstrom 369d80efd5cSThomas Hellstrom /** 370d80efd5cSThomas Hellstrom * vmw_binding_state_scrub - Scrub all bindings associated with a 371d80efd5cSThomas Hellstrom * struct vmw_ctx_binding state structure. 372d80efd5cSThomas Hellstrom * 373d80efd5cSThomas Hellstrom * @cbs: Pointer to the context binding state tracker. 374d80efd5cSThomas Hellstrom * 375d80efd5cSThomas Hellstrom * Emits commands to scrub all bindings associated with the 376d80efd5cSThomas Hellstrom * context binding state tracker. 377d80efd5cSThomas Hellstrom */ 378d80efd5cSThomas Hellstrom void vmw_binding_state_scrub(struct vmw_ctx_binding_state *cbs) 379d80efd5cSThomas Hellstrom { 380d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo *entry; 381d80efd5cSThomas Hellstrom 382d80efd5cSThomas Hellstrom list_for_each_entry(entry, &cbs->list, ctx_list) { 383d80efd5cSThomas Hellstrom if (!entry->scrubbed) { 384d80efd5cSThomas Hellstrom (void) vmw_binding_infos[entry->bt].scrub_func 385d80efd5cSThomas Hellstrom (entry, false); 386d80efd5cSThomas Hellstrom entry->scrubbed = true; 387d80efd5cSThomas Hellstrom } 388d80efd5cSThomas Hellstrom } 389d80efd5cSThomas Hellstrom 390d80efd5cSThomas Hellstrom (void) vmw_binding_emit_dirty(cbs); 391d80efd5cSThomas Hellstrom } 392d80efd5cSThomas Hellstrom 393d80efd5cSThomas Hellstrom /** 394d80efd5cSThomas Hellstrom * vmw_binding_res_list_kill - Kill all bindings on a 395d80efd5cSThomas Hellstrom * resource binding list 396d80efd5cSThomas Hellstrom * 397d80efd5cSThomas Hellstrom * @head: list head of resource binding list 398d80efd5cSThomas Hellstrom * 399d80efd5cSThomas Hellstrom * Kills all bindings associated with a specific resource. Typically 400d80efd5cSThomas Hellstrom * called before the resource is destroyed. 401d80efd5cSThomas Hellstrom */ 402d80efd5cSThomas Hellstrom void vmw_binding_res_list_kill(struct list_head *head) 403d80efd5cSThomas Hellstrom { 404d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo *entry, *next; 405d80efd5cSThomas Hellstrom 406d80efd5cSThomas Hellstrom vmw_binding_res_list_scrub(head); 407d80efd5cSThomas Hellstrom list_for_each_entry_safe(entry, next, head, res_list) 408d80efd5cSThomas Hellstrom vmw_binding_drop(entry); 409d80efd5cSThomas Hellstrom } 410d80efd5cSThomas Hellstrom 411d80efd5cSThomas Hellstrom /** 412d80efd5cSThomas Hellstrom * vmw_binding_res_list_scrub - Scrub all bindings on a 413d80efd5cSThomas Hellstrom * resource binding list 414d80efd5cSThomas Hellstrom * 415d80efd5cSThomas Hellstrom * @head: list head of resource binding list 416d80efd5cSThomas Hellstrom * 417d80efd5cSThomas Hellstrom * Scrub all bindings associated with a specific resource. Typically 418d80efd5cSThomas Hellstrom * called before the resource is evicted. 419d80efd5cSThomas Hellstrom */ 420d80efd5cSThomas Hellstrom void vmw_binding_res_list_scrub(struct list_head *head) 421d80efd5cSThomas Hellstrom { 422d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo *entry; 423d80efd5cSThomas Hellstrom 424d80efd5cSThomas Hellstrom list_for_each_entry(entry, head, res_list) { 425d80efd5cSThomas Hellstrom if (!entry->scrubbed) { 426d80efd5cSThomas Hellstrom (void) vmw_binding_infos[entry->bt].scrub_func 427d80efd5cSThomas Hellstrom (entry, false); 428d80efd5cSThomas Hellstrom entry->scrubbed = true; 429d80efd5cSThomas Hellstrom } 430d80efd5cSThomas Hellstrom } 431d80efd5cSThomas Hellstrom 432d80efd5cSThomas Hellstrom list_for_each_entry(entry, head, res_list) { 433d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *cbs = 434d80efd5cSThomas Hellstrom vmw_context_binding_state(entry->ctx); 435d80efd5cSThomas Hellstrom 436d80efd5cSThomas Hellstrom (void) vmw_binding_emit_dirty(cbs); 437d80efd5cSThomas Hellstrom } 438d80efd5cSThomas Hellstrom } 439d80efd5cSThomas Hellstrom 440d80efd5cSThomas Hellstrom 441d80efd5cSThomas Hellstrom /** 442d80efd5cSThomas Hellstrom * vmw_binding_state_commit - Commit staged binding info 443d80efd5cSThomas Hellstrom * 444d80efd5cSThomas Hellstrom * @ctx: Pointer to context to commit the staged binding info to. 445d80efd5cSThomas Hellstrom * @from: Staged binding info built during execbuf. 446d80efd5cSThomas Hellstrom * @scrubbed: Transfer only scrubbed bindings. 447d80efd5cSThomas Hellstrom * 448d80efd5cSThomas Hellstrom * Transfers binding info from a temporary structure 449d80efd5cSThomas Hellstrom * (typically used by execbuf) to the persistent 450d80efd5cSThomas Hellstrom * structure in the context. This can be done once commands have been 451d80efd5cSThomas Hellstrom * submitted to hardware 452d80efd5cSThomas Hellstrom */ 453d80efd5cSThomas Hellstrom void vmw_binding_state_commit(struct vmw_ctx_binding_state *to, 454d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *from) 455d80efd5cSThomas Hellstrom { 456d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo *entry, *next; 457d80efd5cSThomas Hellstrom 458d80efd5cSThomas Hellstrom list_for_each_entry_safe(entry, next, &from->list, ctx_list) { 459d80efd5cSThomas Hellstrom vmw_binding_transfer(to, from, entry); 460d80efd5cSThomas Hellstrom vmw_binding_drop(entry); 461d80efd5cSThomas Hellstrom } 462d80efd5cSThomas Hellstrom } 463d80efd5cSThomas Hellstrom 464d80efd5cSThomas Hellstrom /** 465d80efd5cSThomas Hellstrom * vmw_binding_rebind_all - Rebind all scrubbed bindings of a context 466d80efd5cSThomas Hellstrom * 467d80efd5cSThomas Hellstrom * @ctx: The context resource 468d80efd5cSThomas Hellstrom * 469d80efd5cSThomas Hellstrom * Walks through the context binding list and rebinds all scrubbed 470d80efd5cSThomas Hellstrom * resources. 471d80efd5cSThomas Hellstrom */ 472d80efd5cSThomas Hellstrom int vmw_binding_rebind_all(struct vmw_ctx_binding_state *cbs) 473d80efd5cSThomas Hellstrom { 474d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo *entry; 475d80efd5cSThomas Hellstrom int ret; 476d80efd5cSThomas Hellstrom 477d80efd5cSThomas Hellstrom list_for_each_entry(entry, &cbs->list, ctx_list) { 478d80efd5cSThomas Hellstrom if (likely(!entry->scrubbed)) 479d80efd5cSThomas Hellstrom continue; 480d80efd5cSThomas Hellstrom 481d80efd5cSThomas Hellstrom if ((entry->res == NULL || entry->res->id == 482d80efd5cSThomas Hellstrom SVGA3D_INVALID_ID)) 483d80efd5cSThomas Hellstrom continue; 484d80efd5cSThomas Hellstrom 485d80efd5cSThomas Hellstrom ret = vmw_binding_infos[entry->bt].scrub_func(entry, true); 486d80efd5cSThomas Hellstrom if (unlikely(ret != 0)) 487d80efd5cSThomas Hellstrom return ret; 488d80efd5cSThomas Hellstrom 489d80efd5cSThomas Hellstrom entry->scrubbed = false; 490d80efd5cSThomas Hellstrom } 491d80efd5cSThomas Hellstrom 492d80efd5cSThomas Hellstrom return vmw_binding_emit_dirty(cbs); 493d80efd5cSThomas Hellstrom } 494d80efd5cSThomas Hellstrom 495d80efd5cSThomas Hellstrom /** 496d80efd5cSThomas Hellstrom * vmw_binding_scrub_shader - scrub a shader binding from a context. 497d80efd5cSThomas Hellstrom * 498d80efd5cSThomas Hellstrom * @bi: single binding information. 499d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 500d80efd5cSThomas Hellstrom */ 501d80efd5cSThomas Hellstrom static int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind) 502d80efd5cSThomas Hellstrom { 503d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_shader *binding = 504d80efd5cSThomas Hellstrom container_of(bi, typeof(*binding), bi); 505d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = bi->ctx->dev_priv; 506d80efd5cSThomas Hellstrom struct { 507d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 508d80efd5cSThomas Hellstrom SVGA3dCmdSetShader body; 509d80efd5cSThomas Hellstrom } *cmd; 510d80efd5cSThomas Hellstrom 51111c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); 51211c45419SDeepak Rawat if (unlikely(cmd == NULL)) 513d80efd5cSThomas Hellstrom return -ENOMEM; 514d80efd5cSThomas Hellstrom 515d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_SET_SHADER; 516d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 517d80efd5cSThomas Hellstrom cmd->body.cid = bi->ctx->id; 518d80efd5cSThomas Hellstrom cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 519d80efd5cSThomas Hellstrom cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 520d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 521d80efd5cSThomas Hellstrom 522d80efd5cSThomas Hellstrom return 0; 523d80efd5cSThomas Hellstrom } 524d80efd5cSThomas Hellstrom 525d80efd5cSThomas Hellstrom /** 526d80efd5cSThomas Hellstrom * vmw_binding_scrub_render_target - scrub a render target binding 527d80efd5cSThomas Hellstrom * from a context. 528d80efd5cSThomas Hellstrom * 529d80efd5cSThomas Hellstrom * @bi: single binding information. 530d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 531d80efd5cSThomas Hellstrom */ 532d80efd5cSThomas Hellstrom static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi, 533d80efd5cSThomas Hellstrom bool rebind) 534d80efd5cSThomas Hellstrom { 535d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_view *binding = 536d80efd5cSThomas Hellstrom container_of(bi, typeof(*binding), bi); 537d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = bi->ctx->dev_priv; 538d80efd5cSThomas Hellstrom struct { 539d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 540d80efd5cSThomas Hellstrom SVGA3dCmdSetRenderTarget body; 541d80efd5cSThomas Hellstrom } *cmd; 542d80efd5cSThomas Hellstrom 54311c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); 54411c45419SDeepak Rawat if (unlikely(cmd == NULL)) 545d80efd5cSThomas Hellstrom return -ENOMEM; 546d80efd5cSThomas Hellstrom 547d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET; 548d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 549d80efd5cSThomas Hellstrom cmd->body.cid = bi->ctx->id; 550d80efd5cSThomas Hellstrom cmd->body.type = binding->slot; 551d80efd5cSThomas Hellstrom cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 552d80efd5cSThomas Hellstrom cmd->body.target.face = 0; 553d80efd5cSThomas Hellstrom cmd->body.target.mipmap = 0; 554d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 555d80efd5cSThomas Hellstrom 556d80efd5cSThomas Hellstrom return 0; 557d80efd5cSThomas Hellstrom } 558d80efd5cSThomas Hellstrom 559d80efd5cSThomas Hellstrom /** 560d80efd5cSThomas Hellstrom * vmw_binding_scrub_texture - scrub a texture binding from a context. 561d80efd5cSThomas Hellstrom * 562d80efd5cSThomas Hellstrom * @bi: single binding information. 563d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 564d80efd5cSThomas Hellstrom * 565d80efd5cSThomas Hellstrom * TODO: Possibly complement this function with a function that takes 566d80efd5cSThomas Hellstrom * a list of texture bindings and combines them to a single command. 567d80efd5cSThomas Hellstrom */ 568d80efd5cSThomas Hellstrom static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi, 569d80efd5cSThomas Hellstrom bool rebind) 570d80efd5cSThomas Hellstrom { 571d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_tex *binding = 572d80efd5cSThomas Hellstrom container_of(bi, typeof(*binding), bi); 573d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = bi->ctx->dev_priv; 574d80efd5cSThomas Hellstrom struct { 575d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 576d80efd5cSThomas Hellstrom struct { 577d80efd5cSThomas Hellstrom SVGA3dCmdSetTextureState c; 578d80efd5cSThomas Hellstrom SVGA3dTextureState s1; 579d80efd5cSThomas Hellstrom } body; 580d80efd5cSThomas Hellstrom } *cmd; 581d80efd5cSThomas Hellstrom 58211c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); 58311c45419SDeepak Rawat if (unlikely(cmd == NULL)) 584d80efd5cSThomas Hellstrom return -ENOMEM; 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 61311c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); 61411c45419SDeepak Rawat if (unlikely(cmd == NULL)) 615d80efd5cSThomas Hellstrom return -ENOMEM; 61611c45419SDeepak Rawat 617d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER; 618d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 619d80efd5cSThomas Hellstrom cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 620d80efd5cSThomas Hellstrom cmd->body.shaderId = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 621d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 622d80efd5cSThomas Hellstrom 623d80efd5cSThomas Hellstrom return 0; 624d80efd5cSThomas Hellstrom } 625d80efd5cSThomas Hellstrom 626d80efd5cSThomas Hellstrom /** 627d80efd5cSThomas Hellstrom * vmw_binding_scrub_cb - scrub a constant buffer binding from a context. 628d80efd5cSThomas Hellstrom * 629d80efd5cSThomas Hellstrom * @bi: single binding information. 630d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 631d80efd5cSThomas Hellstrom */ 632d80efd5cSThomas Hellstrom static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind) 633d80efd5cSThomas Hellstrom { 634d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_cb *binding = 635d80efd5cSThomas Hellstrom container_of(bi, typeof(*binding), bi); 636d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = bi->ctx->dev_priv; 637d80efd5cSThomas Hellstrom struct { 638d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 639d80efd5cSThomas Hellstrom SVGA3dCmdDXSetSingleConstantBuffer body; 640d80efd5cSThomas Hellstrom } *cmd; 641d80efd5cSThomas Hellstrom 64211c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); 64311c45419SDeepak Rawat if (unlikely(cmd == NULL)) 644d80efd5cSThomas Hellstrom return -ENOMEM; 645d80efd5cSThomas Hellstrom 646d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER; 647d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 648d80efd5cSThomas Hellstrom cmd->body.slot = binding->slot; 649d80efd5cSThomas Hellstrom cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 650d80efd5cSThomas Hellstrom if (rebind) { 651d80efd5cSThomas Hellstrom cmd->body.offsetInBytes = binding->offset; 652d80efd5cSThomas Hellstrom cmd->body.sizeInBytes = binding->size; 653d80efd5cSThomas Hellstrom cmd->body.sid = bi->res->id; 654d80efd5cSThomas Hellstrom } else { 655d80efd5cSThomas Hellstrom cmd->body.offsetInBytes = 0; 656d80efd5cSThomas Hellstrom cmd->body.sizeInBytes = 0; 657d80efd5cSThomas Hellstrom cmd->body.sid = SVGA3D_INVALID_ID; 658d80efd5cSThomas Hellstrom } 659d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 660d80efd5cSThomas Hellstrom 661d80efd5cSThomas Hellstrom return 0; 662d80efd5cSThomas Hellstrom } 663d80efd5cSThomas Hellstrom 664d80efd5cSThomas Hellstrom /** 665d80efd5cSThomas Hellstrom * vmw_collect_view_ids - Build view id data for a view binding command 666d80efd5cSThomas Hellstrom * without checking which bindings actually need to be emitted 667d80efd5cSThomas Hellstrom * 668d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 669d80efd5cSThomas Hellstrom * @bi: Pointer to where the binding info array is stored in @cbs 670d80efd5cSThomas Hellstrom * @max_num: Maximum number of entries in the @bi array. 671d80efd5cSThomas Hellstrom * 672d80efd5cSThomas Hellstrom * Scans the @bi array for bindings and builds a buffer of view id data. 673d80efd5cSThomas Hellstrom * Stops at the first non-existing binding in the @bi array. 674d80efd5cSThomas Hellstrom * On output, @cbs->bind_cmd_count contains the number of bindings to be 675d80efd5cSThomas Hellstrom * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer 676d80efd5cSThomas Hellstrom * contains the command data. 677d80efd5cSThomas Hellstrom */ 678d80efd5cSThomas Hellstrom static void vmw_collect_view_ids(struct vmw_ctx_binding_state *cbs, 679d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *bi, 680d80efd5cSThomas Hellstrom u32 max_num) 681d80efd5cSThomas Hellstrom { 682d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo_view *biv = 683d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_view, bi); 684d80efd5cSThomas Hellstrom unsigned long i; 685d80efd5cSThomas Hellstrom 686d80efd5cSThomas Hellstrom cbs->bind_cmd_count = 0; 687d80efd5cSThomas Hellstrom cbs->bind_first_slot = 0; 688d80efd5cSThomas Hellstrom 689d80efd5cSThomas Hellstrom for (i = 0; i < max_num; ++i, ++biv) { 690d80efd5cSThomas Hellstrom if (!biv->bi.ctx) 691d80efd5cSThomas Hellstrom break; 692d80efd5cSThomas Hellstrom 693d80efd5cSThomas Hellstrom cbs->bind_cmd_buffer[cbs->bind_cmd_count++] = 694d80efd5cSThomas Hellstrom ((biv->bi.scrubbed) ? 695d80efd5cSThomas Hellstrom SVGA3D_INVALID_ID : biv->bi.res->id); 696d80efd5cSThomas Hellstrom } 697d80efd5cSThomas Hellstrom } 698d80efd5cSThomas Hellstrom 699d80efd5cSThomas Hellstrom /** 700d80efd5cSThomas Hellstrom * vmw_collect_dirty_view_ids - Build view id data for a view binding command 701d80efd5cSThomas Hellstrom * 702d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 703d80efd5cSThomas Hellstrom * @bi: Pointer to where the binding info array is stored in @cbs 704d80efd5cSThomas Hellstrom * @dirty: Bitmap indicating which bindings need to be emitted. 705d80efd5cSThomas Hellstrom * @max_num: Maximum number of entries in the @bi array. 706d80efd5cSThomas Hellstrom * 707d80efd5cSThomas Hellstrom * Scans the @bi array for bindings that need to be emitted and 708d80efd5cSThomas Hellstrom * builds a buffer of view id data. 709d80efd5cSThomas Hellstrom * On output, @cbs->bind_cmd_count contains the number of bindings to be 710d80efd5cSThomas Hellstrom * emitted, @cbs->bind_first_slot indicates the index of the first emitted 711d80efd5cSThomas Hellstrom * binding, and @cbs->bind_cmd_buffer contains the command data. 712d80efd5cSThomas Hellstrom */ 713d80efd5cSThomas Hellstrom static void vmw_collect_dirty_view_ids(struct vmw_ctx_binding_state *cbs, 714d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *bi, 715d80efd5cSThomas Hellstrom unsigned long *dirty, 716d80efd5cSThomas Hellstrom u32 max_num) 717d80efd5cSThomas Hellstrom { 718d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo_view *biv = 719d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_view, bi); 720d80efd5cSThomas Hellstrom unsigned long i, next_bit; 721d80efd5cSThomas Hellstrom 722d80efd5cSThomas Hellstrom cbs->bind_cmd_count = 0; 723d80efd5cSThomas Hellstrom i = find_first_bit(dirty, max_num); 724d80efd5cSThomas Hellstrom next_bit = i; 725d80efd5cSThomas Hellstrom cbs->bind_first_slot = i; 726d80efd5cSThomas Hellstrom 727d80efd5cSThomas Hellstrom biv += i; 728d80efd5cSThomas Hellstrom for (; i < max_num; ++i, ++biv) { 729d80efd5cSThomas Hellstrom cbs->bind_cmd_buffer[cbs->bind_cmd_count++] = 730d80efd5cSThomas Hellstrom ((!biv->bi.ctx || biv->bi.scrubbed) ? 731d80efd5cSThomas Hellstrom SVGA3D_INVALID_ID : biv->bi.res->id); 732d80efd5cSThomas Hellstrom 733d80efd5cSThomas Hellstrom if (next_bit == i) { 734d80efd5cSThomas Hellstrom next_bit = find_next_bit(dirty, max_num, i + 1); 735d80efd5cSThomas Hellstrom if (next_bit >= max_num) 736d80efd5cSThomas Hellstrom break; 737d80efd5cSThomas Hellstrom } 738d80efd5cSThomas Hellstrom } 739d80efd5cSThomas Hellstrom } 740d80efd5cSThomas Hellstrom 741d80efd5cSThomas Hellstrom /** 742d80efd5cSThomas Hellstrom * vmw_binding_emit_set_sr - Issue delayed DX shader resource binding commands 743d80efd5cSThomas Hellstrom * 744d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 745d80efd5cSThomas Hellstrom */ 746d80efd5cSThomas Hellstrom static int vmw_emit_set_sr(struct vmw_ctx_binding_state *cbs, 747d80efd5cSThomas Hellstrom int shader_slot) 748d80efd5cSThomas Hellstrom { 749d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *loc = 750d80efd5cSThomas Hellstrom &cbs->per_shader[shader_slot].shader_res[0].bi; 751d80efd5cSThomas Hellstrom struct { 752d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 753d80efd5cSThomas Hellstrom SVGA3dCmdDXSetShaderResources body; 754d80efd5cSThomas Hellstrom } *cmd; 755d80efd5cSThomas Hellstrom size_t cmd_size, view_id_size; 756d80efd5cSThomas Hellstrom const struct vmw_resource *ctx = vmw_cbs_context(cbs); 757d80efd5cSThomas Hellstrom 758d80efd5cSThomas Hellstrom vmw_collect_dirty_view_ids(cbs, loc, 759d80efd5cSThomas Hellstrom cbs->per_shader[shader_slot].dirty_sr, 760d80efd5cSThomas Hellstrom SVGA3D_DX_MAX_SRVIEWS); 761d80efd5cSThomas Hellstrom if (cbs->bind_cmd_count == 0) 762d80efd5cSThomas Hellstrom return 0; 763d80efd5cSThomas Hellstrom 764d80efd5cSThomas Hellstrom view_id_size = cbs->bind_cmd_count*sizeof(uint32); 765d80efd5cSThomas Hellstrom cmd_size = sizeof(*cmd) + view_id_size; 76611c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 76711c45419SDeepak Rawat if (unlikely(cmd == NULL)) 768d80efd5cSThomas Hellstrom return -ENOMEM; 769d80efd5cSThomas Hellstrom 770d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER_RESOURCES; 771d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body) + view_id_size; 772d80efd5cSThomas Hellstrom cmd->body.type = shader_slot + SVGA3D_SHADERTYPE_MIN; 773d80efd5cSThomas Hellstrom cmd->body.startView = cbs->bind_first_slot; 774d80efd5cSThomas Hellstrom 775d80efd5cSThomas Hellstrom memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size); 776d80efd5cSThomas Hellstrom 777d80efd5cSThomas Hellstrom vmw_fifo_commit(ctx->dev_priv, cmd_size); 778d80efd5cSThomas Hellstrom bitmap_clear(cbs->per_shader[shader_slot].dirty_sr, 779d80efd5cSThomas Hellstrom cbs->bind_first_slot, cbs->bind_cmd_count); 780d80efd5cSThomas Hellstrom 781d80efd5cSThomas Hellstrom return 0; 782d80efd5cSThomas Hellstrom } 783d80efd5cSThomas Hellstrom 784d80efd5cSThomas Hellstrom /** 785d80efd5cSThomas Hellstrom * vmw_binding_emit_set_rt - Issue delayed DX rendertarget binding commands 786d80efd5cSThomas Hellstrom * 787d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 788d80efd5cSThomas Hellstrom */ 789d80efd5cSThomas Hellstrom static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs) 790d80efd5cSThomas Hellstrom { 791d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *loc = &cbs->render_targets[0].bi; 792d80efd5cSThomas Hellstrom struct { 793d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 794d80efd5cSThomas Hellstrom SVGA3dCmdDXSetRenderTargets body; 795d80efd5cSThomas Hellstrom } *cmd; 796d80efd5cSThomas Hellstrom size_t cmd_size, view_id_size; 797d80efd5cSThomas Hellstrom const struct vmw_resource *ctx = vmw_cbs_context(cbs); 798d80efd5cSThomas Hellstrom 799d80efd5cSThomas Hellstrom vmw_collect_view_ids(cbs, loc, SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS); 800d80efd5cSThomas Hellstrom view_id_size = cbs->bind_cmd_count*sizeof(uint32); 801d80efd5cSThomas Hellstrom cmd_size = sizeof(*cmd) + view_id_size; 80211c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 80311c45419SDeepak Rawat if (unlikely(cmd == NULL)) 804d80efd5cSThomas Hellstrom return -ENOMEM; 805d80efd5cSThomas Hellstrom 806d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_RENDERTARGETS; 807d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body) + view_id_size; 808d80efd5cSThomas Hellstrom 809d80efd5cSThomas Hellstrom if (cbs->ds_view.bi.ctx && !cbs->ds_view.bi.scrubbed) 810d80efd5cSThomas Hellstrom cmd->body.depthStencilViewId = cbs->ds_view.bi.res->id; 811d80efd5cSThomas Hellstrom else 812d80efd5cSThomas Hellstrom cmd->body.depthStencilViewId = SVGA3D_INVALID_ID; 813d80efd5cSThomas Hellstrom 814d80efd5cSThomas Hellstrom memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size); 815d80efd5cSThomas Hellstrom 816d80efd5cSThomas Hellstrom vmw_fifo_commit(ctx->dev_priv, cmd_size); 817d80efd5cSThomas Hellstrom 818d80efd5cSThomas Hellstrom return 0; 819d80efd5cSThomas Hellstrom 820d80efd5cSThomas Hellstrom } 821d80efd5cSThomas Hellstrom 822d80efd5cSThomas Hellstrom /** 823d80efd5cSThomas Hellstrom * vmw_collect_so_targets - Build SVGA3dSoTarget data for a binding command 824d80efd5cSThomas Hellstrom * without checking which bindings actually need to be emitted 825d80efd5cSThomas Hellstrom * 826d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 827d80efd5cSThomas Hellstrom * @bi: Pointer to where the binding info array is stored in @cbs 828d80efd5cSThomas Hellstrom * @max_num: Maximum number of entries in the @bi array. 829d80efd5cSThomas Hellstrom * 830d80efd5cSThomas Hellstrom * Scans the @bi array for bindings and builds a buffer of SVGA3dSoTarget data. 831d80efd5cSThomas Hellstrom * Stops at the first non-existing binding in the @bi array. 832d80efd5cSThomas Hellstrom * On output, @cbs->bind_cmd_count contains the number of bindings to be 833d80efd5cSThomas Hellstrom * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer 834d80efd5cSThomas Hellstrom * contains the command data. 835d80efd5cSThomas Hellstrom */ 836d80efd5cSThomas Hellstrom static void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs, 837d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *bi, 838d80efd5cSThomas Hellstrom u32 max_num) 839d80efd5cSThomas Hellstrom { 840d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo_so *biso = 841d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_so, bi); 842d80efd5cSThomas Hellstrom unsigned long i; 843d80efd5cSThomas Hellstrom SVGA3dSoTarget *so_buffer = (SVGA3dSoTarget *) cbs->bind_cmd_buffer; 844d80efd5cSThomas Hellstrom 845d80efd5cSThomas Hellstrom cbs->bind_cmd_count = 0; 846d80efd5cSThomas Hellstrom cbs->bind_first_slot = 0; 847d80efd5cSThomas Hellstrom 848d80efd5cSThomas Hellstrom for (i = 0; i < max_num; ++i, ++biso, ++so_buffer, 849d80efd5cSThomas Hellstrom ++cbs->bind_cmd_count) { 850d80efd5cSThomas Hellstrom if (!biso->bi.ctx) 851d80efd5cSThomas Hellstrom break; 852d80efd5cSThomas Hellstrom 853d80efd5cSThomas Hellstrom if (!biso->bi.scrubbed) { 854d80efd5cSThomas Hellstrom so_buffer->sid = biso->bi.res->id; 855d80efd5cSThomas Hellstrom so_buffer->offset = biso->offset; 856d80efd5cSThomas Hellstrom so_buffer->sizeInBytes = biso->size; 857d80efd5cSThomas Hellstrom } else { 858d80efd5cSThomas Hellstrom so_buffer->sid = SVGA3D_INVALID_ID; 859d80efd5cSThomas Hellstrom so_buffer->offset = 0; 860d80efd5cSThomas Hellstrom so_buffer->sizeInBytes = 0; 861d80efd5cSThomas Hellstrom } 862d80efd5cSThomas Hellstrom } 863d80efd5cSThomas Hellstrom } 864d80efd5cSThomas Hellstrom 865d80efd5cSThomas Hellstrom /** 866d80efd5cSThomas Hellstrom * vmw_binding_emit_set_so - Issue delayed streamout binding commands 867d80efd5cSThomas Hellstrom * 868d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 869d80efd5cSThomas Hellstrom */ 870d80efd5cSThomas Hellstrom static int vmw_emit_set_so(struct vmw_ctx_binding_state *cbs) 871d80efd5cSThomas Hellstrom { 872d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *loc = &cbs->so_targets[0].bi; 873d80efd5cSThomas Hellstrom struct { 874d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 875d80efd5cSThomas Hellstrom SVGA3dCmdDXSetSOTargets body; 876d80efd5cSThomas Hellstrom } *cmd; 877d80efd5cSThomas Hellstrom size_t cmd_size, so_target_size; 878d80efd5cSThomas Hellstrom const struct vmw_resource *ctx = vmw_cbs_context(cbs); 879d80efd5cSThomas Hellstrom 880d80efd5cSThomas Hellstrom vmw_collect_so_targets(cbs, loc, SVGA3D_DX_MAX_SOTARGETS); 881d80efd5cSThomas Hellstrom if (cbs->bind_cmd_count == 0) 882d80efd5cSThomas Hellstrom return 0; 883d80efd5cSThomas Hellstrom 884d80efd5cSThomas Hellstrom so_target_size = cbs->bind_cmd_count*sizeof(SVGA3dSoTarget); 885d80efd5cSThomas Hellstrom cmd_size = sizeof(*cmd) + so_target_size; 88611c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 88711c45419SDeepak Rawat if (unlikely(cmd == NULL)) 888d80efd5cSThomas Hellstrom return -ENOMEM; 889d80efd5cSThomas Hellstrom 890d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_SOTARGETS; 891d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body) + so_target_size; 892d80efd5cSThomas Hellstrom memcpy(&cmd[1], cbs->bind_cmd_buffer, so_target_size); 893d80efd5cSThomas Hellstrom 894d80efd5cSThomas Hellstrom vmw_fifo_commit(ctx->dev_priv, cmd_size); 895d80efd5cSThomas Hellstrom 896d80efd5cSThomas Hellstrom return 0; 897d80efd5cSThomas Hellstrom 898d80efd5cSThomas Hellstrom } 899d80efd5cSThomas Hellstrom 900d80efd5cSThomas Hellstrom /** 901d80efd5cSThomas Hellstrom * vmw_binding_emit_dirty_ps - Issue delayed per shader binding commands 902d80efd5cSThomas Hellstrom * 903d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 904d80efd5cSThomas Hellstrom * 905d80efd5cSThomas Hellstrom */ 906d80efd5cSThomas Hellstrom static int vmw_binding_emit_dirty_ps(struct vmw_ctx_binding_state *cbs) 907d80efd5cSThomas Hellstrom { 908d80efd5cSThomas Hellstrom struct vmw_dx_shader_bindings *sb = &cbs->per_shader[0]; 909d80efd5cSThomas Hellstrom u32 i; 910d80efd5cSThomas Hellstrom int ret; 911d80efd5cSThomas Hellstrom 912d80efd5cSThomas Hellstrom for (i = 0; i < SVGA3D_NUM_SHADERTYPE_DX10; ++i, ++sb) { 913d80efd5cSThomas Hellstrom if (!test_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty)) 914d80efd5cSThomas Hellstrom continue; 915d80efd5cSThomas Hellstrom 916d80efd5cSThomas Hellstrom ret = vmw_emit_set_sr(cbs, i); 917d80efd5cSThomas Hellstrom if (ret) 918d80efd5cSThomas Hellstrom break; 919d80efd5cSThomas Hellstrom 920d80efd5cSThomas Hellstrom __clear_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty); 921d80efd5cSThomas Hellstrom } 922d80efd5cSThomas Hellstrom 923d80efd5cSThomas Hellstrom return 0; 924d80efd5cSThomas Hellstrom } 925d80efd5cSThomas Hellstrom 926d80efd5cSThomas Hellstrom /** 927d80efd5cSThomas Hellstrom * vmw_collect_dirty_vbs - Build SVGA3dVertexBuffer data for a 928d80efd5cSThomas Hellstrom * SVGA3dCmdDXSetVertexBuffers command 929d80efd5cSThomas Hellstrom * 930d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 931d80efd5cSThomas Hellstrom * @bi: Pointer to where the binding info array is stored in @cbs 932d80efd5cSThomas Hellstrom * @dirty: Bitmap indicating which bindings need to be emitted. 933d80efd5cSThomas Hellstrom * @max_num: Maximum number of entries in the @bi array. 934d80efd5cSThomas Hellstrom * 935d80efd5cSThomas Hellstrom * Scans the @bi array for bindings that need to be emitted and 936d80efd5cSThomas Hellstrom * builds a buffer of SVGA3dVertexBuffer data. 937d80efd5cSThomas Hellstrom * On output, @cbs->bind_cmd_count contains the number of bindings to be 938d80efd5cSThomas Hellstrom * emitted, @cbs->bind_first_slot indicates the index of the first emitted 939d80efd5cSThomas Hellstrom * binding, and @cbs->bind_cmd_buffer contains the command data. 940d80efd5cSThomas Hellstrom */ 941d80efd5cSThomas Hellstrom static void vmw_collect_dirty_vbs(struct vmw_ctx_binding_state *cbs, 942d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *bi, 943d80efd5cSThomas Hellstrom unsigned long *dirty, 944d80efd5cSThomas Hellstrom u32 max_num) 945d80efd5cSThomas Hellstrom { 946d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo_vb *biv = 947d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_vb, bi); 948d80efd5cSThomas Hellstrom unsigned long i, next_bit; 949d80efd5cSThomas Hellstrom SVGA3dVertexBuffer *vbs = (SVGA3dVertexBuffer *) &cbs->bind_cmd_buffer; 950d80efd5cSThomas Hellstrom 951d80efd5cSThomas Hellstrom cbs->bind_cmd_count = 0; 952d80efd5cSThomas Hellstrom i = find_first_bit(dirty, max_num); 953d80efd5cSThomas Hellstrom next_bit = i; 954d80efd5cSThomas Hellstrom cbs->bind_first_slot = i; 955d80efd5cSThomas Hellstrom 956d80efd5cSThomas Hellstrom biv += i; 957d80efd5cSThomas Hellstrom for (; i < max_num; ++i, ++biv, ++vbs) { 958d80efd5cSThomas Hellstrom if (!biv->bi.ctx || biv->bi.scrubbed) { 959d80efd5cSThomas Hellstrom vbs->sid = SVGA3D_INVALID_ID; 960d80efd5cSThomas Hellstrom vbs->stride = 0; 961d80efd5cSThomas Hellstrom vbs->offset = 0; 962d80efd5cSThomas Hellstrom } else { 963d80efd5cSThomas Hellstrom vbs->sid = biv->bi.res->id; 964d80efd5cSThomas Hellstrom vbs->stride = biv->stride; 965d80efd5cSThomas Hellstrom vbs->offset = biv->offset; 966d80efd5cSThomas Hellstrom } 967d80efd5cSThomas Hellstrom cbs->bind_cmd_count++; 968d80efd5cSThomas Hellstrom if (next_bit == i) { 969d80efd5cSThomas Hellstrom next_bit = find_next_bit(dirty, max_num, i + 1); 970d80efd5cSThomas Hellstrom if (next_bit >= max_num) 971d80efd5cSThomas Hellstrom break; 972d80efd5cSThomas Hellstrom } 973d80efd5cSThomas Hellstrom } 974d80efd5cSThomas Hellstrom } 975d80efd5cSThomas Hellstrom 976d80efd5cSThomas Hellstrom /** 977d80efd5cSThomas Hellstrom * vmw_binding_emit_set_vb - Issue delayed vertex buffer binding commands 978d80efd5cSThomas Hellstrom * 979d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 980d80efd5cSThomas Hellstrom * 981d80efd5cSThomas Hellstrom */ 982d80efd5cSThomas Hellstrom static int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs) 983d80efd5cSThomas Hellstrom { 984d80efd5cSThomas Hellstrom const struct vmw_ctx_bindinfo *loc = 985d80efd5cSThomas Hellstrom &cbs->vertex_buffers[0].bi; 986d80efd5cSThomas Hellstrom struct { 987d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 988d80efd5cSThomas Hellstrom SVGA3dCmdDXSetVertexBuffers body; 989d80efd5cSThomas Hellstrom } *cmd; 990d80efd5cSThomas Hellstrom size_t cmd_size, set_vb_size; 991d80efd5cSThomas Hellstrom const struct vmw_resource *ctx = vmw_cbs_context(cbs); 992d80efd5cSThomas Hellstrom 993d80efd5cSThomas Hellstrom vmw_collect_dirty_vbs(cbs, loc, cbs->dirty_vb, 994d80efd5cSThomas Hellstrom SVGA3D_DX_MAX_VERTEXBUFFERS); 995d80efd5cSThomas Hellstrom if (cbs->bind_cmd_count == 0) 996d80efd5cSThomas Hellstrom return 0; 997d80efd5cSThomas Hellstrom 998d80efd5cSThomas Hellstrom set_vb_size = cbs->bind_cmd_count*sizeof(SVGA3dVertexBuffer); 999d80efd5cSThomas Hellstrom cmd_size = sizeof(*cmd) + set_vb_size; 100011c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(ctx->dev_priv, cmd_size, ctx->id); 100111c45419SDeepak Rawat if (unlikely(cmd == NULL)) 1002d80efd5cSThomas Hellstrom return -ENOMEM; 1003d80efd5cSThomas Hellstrom 1004d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS; 1005d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body) + set_vb_size; 1006d80efd5cSThomas Hellstrom cmd->body.startBuffer = cbs->bind_first_slot; 1007d80efd5cSThomas Hellstrom 1008d80efd5cSThomas Hellstrom memcpy(&cmd[1], cbs->bind_cmd_buffer, set_vb_size); 1009d80efd5cSThomas Hellstrom 1010d80efd5cSThomas Hellstrom vmw_fifo_commit(ctx->dev_priv, cmd_size); 1011d80efd5cSThomas Hellstrom bitmap_clear(cbs->dirty_vb, 1012d80efd5cSThomas Hellstrom cbs->bind_first_slot, cbs->bind_cmd_count); 1013d80efd5cSThomas Hellstrom 1014d80efd5cSThomas Hellstrom return 0; 1015d80efd5cSThomas Hellstrom } 1016d80efd5cSThomas Hellstrom 1017d80efd5cSThomas Hellstrom /** 1018d80efd5cSThomas Hellstrom * vmw_binding_emit_dirty - Issue delayed binding commands 1019d80efd5cSThomas Hellstrom * 1020d80efd5cSThomas Hellstrom * @cbs: Pointer to the context's struct vmw_ctx_binding_state 1021d80efd5cSThomas Hellstrom * 1022d80efd5cSThomas Hellstrom * This function issues the delayed binding commands that arise from 1023d80efd5cSThomas Hellstrom * previous scrub / unscrub calls. These binding commands are typically 1024d80efd5cSThomas Hellstrom * commands that batch a number of bindings and therefore it makes sense 1025d80efd5cSThomas Hellstrom * to delay them. 1026d80efd5cSThomas Hellstrom */ 1027d80efd5cSThomas Hellstrom static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs) 1028d80efd5cSThomas Hellstrom { 1029d80efd5cSThomas Hellstrom int ret = 0; 1030d80efd5cSThomas Hellstrom unsigned long hit = 0; 1031d80efd5cSThomas Hellstrom 1032d80efd5cSThomas Hellstrom while ((hit = find_next_bit(&cbs->dirty, VMW_BINDING_NUM_BITS, hit)) 1033d80efd5cSThomas Hellstrom < VMW_BINDING_NUM_BITS) { 1034d80efd5cSThomas Hellstrom 1035d80efd5cSThomas Hellstrom switch (hit) { 1036d80efd5cSThomas Hellstrom case VMW_BINDING_RT_BIT: 1037d80efd5cSThomas Hellstrom ret = vmw_emit_set_rt(cbs); 1038d80efd5cSThomas Hellstrom break; 1039d80efd5cSThomas Hellstrom case VMW_BINDING_PS_BIT: 1040d80efd5cSThomas Hellstrom ret = vmw_binding_emit_dirty_ps(cbs); 1041d80efd5cSThomas Hellstrom break; 1042d80efd5cSThomas Hellstrom case VMW_BINDING_SO_BIT: 1043d80efd5cSThomas Hellstrom ret = vmw_emit_set_so(cbs); 1044d80efd5cSThomas Hellstrom break; 1045d80efd5cSThomas Hellstrom case VMW_BINDING_VB_BIT: 1046d80efd5cSThomas Hellstrom ret = vmw_emit_set_vb(cbs); 1047d80efd5cSThomas Hellstrom break; 1048d80efd5cSThomas Hellstrom default: 1049d80efd5cSThomas Hellstrom BUG(); 1050d80efd5cSThomas Hellstrom } 1051d80efd5cSThomas Hellstrom if (ret) 1052d80efd5cSThomas Hellstrom return ret; 1053d80efd5cSThomas Hellstrom 1054d80efd5cSThomas Hellstrom __clear_bit(hit, &cbs->dirty); 1055d80efd5cSThomas Hellstrom hit++; 1056d80efd5cSThomas Hellstrom } 1057d80efd5cSThomas Hellstrom 1058d80efd5cSThomas Hellstrom return 0; 1059d80efd5cSThomas Hellstrom } 1060d80efd5cSThomas Hellstrom 1061d80efd5cSThomas Hellstrom /** 1062d80efd5cSThomas Hellstrom * vmw_binding_scrub_sr - Schedule a dx shaderresource binding 1063d80efd5cSThomas Hellstrom * scrub from a context 1064d80efd5cSThomas Hellstrom * 1065d80efd5cSThomas Hellstrom * @bi: single binding information. 1066d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 1067d80efd5cSThomas Hellstrom */ 1068d80efd5cSThomas Hellstrom static int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind) 1069d80efd5cSThomas Hellstrom { 1070d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_view *biv = 1071d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_view, bi); 1072d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *cbs = 1073d80efd5cSThomas Hellstrom vmw_context_binding_state(bi->ctx); 1074d80efd5cSThomas Hellstrom 1075d80efd5cSThomas Hellstrom __set_bit(biv->slot, cbs->per_shader[biv->shader_slot].dirty_sr); 1076d80efd5cSThomas Hellstrom __set_bit(VMW_BINDING_PS_SR_BIT, 1077d80efd5cSThomas Hellstrom &cbs->per_shader[biv->shader_slot].dirty); 1078d80efd5cSThomas Hellstrom __set_bit(VMW_BINDING_PS_BIT, &cbs->dirty); 1079d80efd5cSThomas Hellstrom 1080d80efd5cSThomas Hellstrom return 0; 1081d80efd5cSThomas Hellstrom } 1082d80efd5cSThomas Hellstrom 1083d80efd5cSThomas Hellstrom /** 1084d80efd5cSThomas Hellstrom * vmw_binding_scrub_dx_rt - Schedule a dx rendertarget binding 1085d80efd5cSThomas Hellstrom * scrub from a context 1086d80efd5cSThomas Hellstrom * 1087d80efd5cSThomas Hellstrom * @bi: single binding information. 1088d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 1089d80efd5cSThomas Hellstrom */ 1090d80efd5cSThomas Hellstrom static int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind) 1091d80efd5cSThomas Hellstrom { 1092d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *cbs = 1093d80efd5cSThomas Hellstrom vmw_context_binding_state(bi->ctx); 1094d80efd5cSThomas Hellstrom 1095d80efd5cSThomas Hellstrom __set_bit(VMW_BINDING_RT_BIT, &cbs->dirty); 1096d80efd5cSThomas Hellstrom 1097d80efd5cSThomas Hellstrom return 0; 1098d80efd5cSThomas Hellstrom } 1099d80efd5cSThomas Hellstrom 1100d80efd5cSThomas Hellstrom /** 1101d80efd5cSThomas Hellstrom * vmw_binding_scrub_so - Schedule a dx streamoutput buffer 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_so(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_SO_BIT, &cbs->dirty); 1113d80efd5cSThomas Hellstrom 1114d80efd5cSThomas Hellstrom return 0; 1115d80efd5cSThomas Hellstrom } 1116d80efd5cSThomas Hellstrom 1117d80efd5cSThomas Hellstrom /** 1118d80efd5cSThomas Hellstrom * vmw_binding_scrub_vb - Schedule a dx vertex 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_vb(struct vmw_ctx_bindinfo *bi, bool rebind) 1125d80efd5cSThomas Hellstrom { 1126d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_vb *bivb = 1127d80efd5cSThomas Hellstrom container_of(bi, struct vmw_ctx_bindinfo_vb, bi); 1128d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *cbs = 1129d80efd5cSThomas Hellstrom vmw_context_binding_state(bi->ctx); 1130d80efd5cSThomas Hellstrom 1131d80efd5cSThomas Hellstrom __set_bit(bivb->slot, cbs->dirty_vb); 1132d80efd5cSThomas Hellstrom __set_bit(VMW_BINDING_VB_BIT, &cbs->dirty); 1133d80efd5cSThomas Hellstrom 1134d80efd5cSThomas Hellstrom return 0; 1135d80efd5cSThomas Hellstrom } 1136d80efd5cSThomas Hellstrom 1137d80efd5cSThomas Hellstrom /** 1138d80efd5cSThomas Hellstrom * vmw_binding_scrub_ib - scrub a dx index buffer binding from a context 1139d80efd5cSThomas Hellstrom * 1140d80efd5cSThomas Hellstrom * @bi: single binding information. 1141d80efd5cSThomas Hellstrom * @rebind: Whether to issue a bind instead of scrub command. 1142d80efd5cSThomas Hellstrom */ 1143d80efd5cSThomas Hellstrom static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind) 1144d80efd5cSThomas Hellstrom { 1145d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo_ib *binding = 1146d80efd5cSThomas Hellstrom container_of(bi, typeof(*binding), bi); 1147d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = bi->ctx->dev_priv; 1148d80efd5cSThomas Hellstrom struct { 1149d80efd5cSThomas Hellstrom SVGA3dCmdHeader header; 1150d80efd5cSThomas Hellstrom SVGA3dCmdDXSetIndexBuffer body; 1151d80efd5cSThomas Hellstrom } *cmd; 1152d80efd5cSThomas Hellstrom 115311c45419SDeepak Rawat cmd = VMW_FIFO_RESERVE_DX(dev_priv, sizeof(*cmd), bi->ctx->id); 115411c45419SDeepak Rawat if (unlikely(cmd == NULL)) 1155d80efd5cSThomas Hellstrom return -ENOMEM; 115611c45419SDeepak Rawat 1157d80efd5cSThomas Hellstrom cmd->header.id = SVGA_3D_CMD_DX_SET_INDEX_BUFFER; 1158d80efd5cSThomas Hellstrom cmd->header.size = sizeof(cmd->body); 1159d80efd5cSThomas Hellstrom if (rebind) { 1160d80efd5cSThomas Hellstrom cmd->body.sid = bi->res->id; 1161d80efd5cSThomas Hellstrom cmd->body.format = binding->format; 1162d80efd5cSThomas Hellstrom cmd->body.offset = binding->offset; 1163d80efd5cSThomas Hellstrom } else { 1164d80efd5cSThomas Hellstrom cmd->body.sid = SVGA3D_INVALID_ID; 1165d80efd5cSThomas Hellstrom cmd->body.format = 0; 1166d80efd5cSThomas Hellstrom cmd->body.offset = 0; 1167d80efd5cSThomas Hellstrom } 1168d80efd5cSThomas Hellstrom 1169d80efd5cSThomas Hellstrom vmw_fifo_commit(dev_priv, sizeof(*cmd)); 1170d80efd5cSThomas Hellstrom 1171d80efd5cSThomas Hellstrom return 0; 1172d80efd5cSThomas Hellstrom } 1173d80efd5cSThomas Hellstrom 1174d80efd5cSThomas Hellstrom /** 1175d80efd5cSThomas Hellstrom * vmw_binding_state_alloc - Allocate a struct vmw_ctx_binding_state with 1176d80efd5cSThomas Hellstrom * memory accounting. 1177d80efd5cSThomas Hellstrom * 1178d80efd5cSThomas Hellstrom * @dev_priv: Pointer to a device private structure. 1179d80efd5cSThomas Hellstrom * 1180d80efd5cSThomas Hellstrom * Returns a pointer to a newly allocated struct or an error pointer on error. 1181d80efd5cSThomas Hellstrom */ 1182d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state * 1183d80efd5cSThomas Hellstrom vmw_binding_state_alloc(struct vmw_private *dev_priv) 1184d80efd5cSThomas Hellstrom { 1185d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *cbs; 1186279c01f6SRoger He struct ttm_operation_ctx ctx = { 1187279c01f6SRoger He .interruptible = false, 1188279c01f6SRoger He .no_wait_gpu = false 1189279c01f6SRoger He }; 1190d80efd5cSThomas Hellstrom int ret; 1191d80efd5cSThomas Hellstrom 1192d80efd5cSThomas Hellstrom ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), sizeof(*cbs), 1193279c01f6SRoger He &ctx); 1194d80efd5cSThomas Hellstrom if (ret) 1195d80efd5cSThomas Hellstrom return ERR_PTR(ret); 1196d80efd5cSThomas Hellstrom 1197d80efd5cSThomas Hellstrom cbs = vzalloc(sizeof(*cbs)); 1198d80efd5cSThomas Hellstrom if (!cbs) { 1199d80efd5cSThomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs)); 1200d80efd5cSThomas Hellstrom return ERR_PTR(-ENOMEM); 1201d80efd5cSThomas Hellstrom } 1202d80efd5cSThomas Hellstrom 1203d80efd5cSThomas Hellstrom cbs->dev_priv = dev_priv; 1204d80efd5cSThomas Hellstrom INIT_LIST_HEAD(&cbs->list); 1205d80efd5cSThomas Hellstrom 1206d80efd5cSThomas Hellstrom return cbs; 1207d80efd5cSThomas Hellstrom } 1208d80efd5cSThomas Hellstrom 1209d80efd5cSThomas Hellstrom /** 1210d80efd5cSThomas Hellstrom * vmw_binding_state_free - Free a struct vmw_ctx_binding_state and its 1211d80efd5cSThomas Hellstrom * memory accounting info. 1212d80efd5cSThomas Hellstrom * 1213d80efd5cSThomas Hellstrom * @cbs: Pointer to the struct vmw_ctx_binding_state to be freed. 1214d80efd5cSThomas Hellstrom */ 1215d80efd5cSThomas Hellstrom void vmw_binding_state_free(struct vmw_ctx_binding_state *cbs) 1216d80efd5cSThomas Hellstrom { 1217d80efd5cSThomas Hellstrom struct vmw_private *dev_priv = cbs->dev_priv; 1218d80efd5cSThomas Hellstrom 1219d80efd5cSThomas Hellstrom vfree(cbs); 1220d80efd5cSThomas Hellstrom ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs)); 1221d80efd5cSThomas Hellstrom } 1222d80efd5cSThomas Hellstrom 1223d80efd5cSThomas Hellstrom /** 1224d80efd5cSThomas Hellstrom * vmw_binding_state_list - Get the binding list of a 1225d80efd5cSThomas Hellstrom * struct vmw_ctx_binding_state 1226d80efd5cSThomas Hellstrom * 1227d80efd5cSThomas Hellstrom * @cbs: Pointer to the struct vmw_ctx_binding_state 1228d80efd5cSThomas Hellstrom * 1229d80efd5cSThomas Hellstrom * Returns the binding list which can be used to traverse through the bindings 1230d80efd5cSThomas Hellstrom * and access the resource information of all bindings. 1231d80efd5cSThomas Hellstrom */ 1232d80efd5cSThomas Hellstrom struct list_head *vmw_binding_state_list(struct vmw_ctx_binding_state *cbs) 1233d80efd5cSThomas Hellstrom { 1234d80efd5cSThomas Hellstrom return &cbs->list; 1235d80efd5cSThomas Hellstrom } 1236d80efd5cSThomas Hellstrom 1237d80efd5cSThomas Hellstrom /** 1238d80efd5cSThomas Hellstrom * vmwgfx_binding_state_reset - clear a struct vmw_ctx_binding_state 1239d80efd5cSThomas Hellstrom * 1240d80efd5cSThomas Hellstrom * @cbs: Pointer to the struct vmw_ctx_binding_state to be cleared 1241d80efd5cSThomas Hellstrom * 1242d80efd5cSThomas Hellstrom * Drops all bindings registered in @cbs. No device binding actions are 1243d80efd5cSThomas Hellstrom * performed. 1244d80efd5cSThomas Hellstrom */ 1245d80efd5cSThomas Hellstrom void vmw_binding_state_reset(struct vmw_ctx_binding_state *cbs) 1246d80efd5cSThomas Hellstrom { 1247d80efd5cSThomas Hellstrom struct vmw_ctx_bindinfo *entry, *next; 1248d80efd5cSThomas Hellstrom 1249d80efd5cSThomas Hellstrom list_for_each_entry_safe(entry, next, &cbs->list, ctx_list) 1250d80efd5cSThomas Hellstrom vmw_binding_drop(entry); 1251d80efd5cSThomas Hellstrom } 1252d80efd5cSThomas Hellstrom 1253a9f58c45SThomas Hellstrom /** 1254a9f58c45SThomas Hellstrom * vmw_binding_dirtying - Return whether a binding type is dirtying its resource 1255a9f58c45SThomas Hellstrom * @binding_type: The binding type 1256a9f58c45SThomas Hellstrom * 1257a9f58c45SThomas Hellstrom * Each time a resource is put on the validation list as the result of a 1258a9f58c45SThomas Hellstrom * context binding referencing it, we need to determine whether that resource 1259a9f58c45SThomas Hellstrom * will be dirtied (written to by the GPU) as a result of the corresponding 1260a9f58c45SThomas Hellstrom * GPU operation. Currently rendertarget-, depth-stencil-, and 1261a9f58c45SThomas Hellstrom * stream-output-target bindings are capable of dirtying its resource. 1262a9f58c45SThomas Hellstrom * 1263a9f58c45SThomas Hellstrom * Return: Whether the binding type dirties the resource its binding points to. 1264a9f58c45SThomas Hellstrom */ 1265a9f58c45SThomas Hellstrom u32 vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type) 1266a9f58c45SThomas Hellstrom { 1267a9f58c45SThomas Hellstrom static u32 is_binding_dirtying[vmw_ctx_binding_max] = { 1268a9f58c45SThomas Hellstrom [vmw_ctx_binding_rt] = VMW_RES_DIRTY_SET, 1269a9f58c45SThomas Hellstrom [vmw_ctx_binding_dx_rt] = VMW_RES_DIRTY_SET, 1270a9f58c45SThomas Hellstrom [vmw_ctx_binding_ds] = VMW_RES_DIRTY_SET, 1271a9f58c45SThomas Hellstrom [vmw_ctx_binding_so] = VMW_RES_DIRTY_SET, 1272a9f58c45SThomas Hellstrom }; 1273a9f58c45SThomas Hellstrom 1274a9f58c45SThomas Hellstrom /* Review this function as new bindings are added. */ 1275a9f58c45SThomas Hellstrom BUILD_BUG_ON(vmw_ctx_binding_max != 11); 1276a9f58c45SThomas Hellstrom return is_binding_dirtying[binding_type]; 1277a9f58c45SThomas Hellstrom } 1278a9f58c45SThomas Hellstrom 1279d80efd5cSThomas Hellstrom /* 1280d80efd5cSThomas Hellstrom * This function is unused at run-time, and only used to hold various build 1281d80efd5cSThomas Hellstrom * asserts important for code optimization assumptions. 1282d80efd5cSThomas Hellstrom */ 1283d80efd5cSThomas Hellstrom static void vmw_binding_build_asserts(void) 1284d80efd5cSThomas Hellstrom { 1285d80efd5cSThomas Hellstrom BUILD_BUG_ON(SVGA3D_NUM_SHADERTYPE_DX10 != 3); 1286d80efd5cSThomas Hellstrom BUILD_BUG_ON(SVGA3D_MAX_SIMULTANEOUS_RENDER_TARGETS > SVGA3D_RT_MAX); 1287d80efd5cSThomas Hellstrom BUILD_BUG_ON(sizeof(uint32) != sizeof(u32)); 1288d80efd5cSThomas Hellstrom 1289d80efd5cSThomas Hellstrom /* 1290d80efd5cSThomas Hellstrom * struct vmw_ctx_binding_state::bind_cmd_buffer is used for various 1291d80efd5cSThomas Hellstrom * view id arrays. 1292d80efd5cSThomas Hellstrom */ 1293d80efd5cSThomas Hellstrom BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_RT_MAX); 1294d80efd5cSThomas Hellstrom BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_SRVIEWS); 1295d80efd5cSThomas Hellstrom BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_CONSTBUFFERS); 1296d80efd5cSThomas Hellstrom 1297d80efd5cSThomas Hellstrom /* 1298d80efd5cSThomas Hellstrom * struct vmw_ctx_binding_state::bind_cmd_buffer is used for 1299d80efd5cSThomas Hellstrom * u32 view ids, SVGA3dSoTargets and SVGA3dVertexBuffers 1300d80efd5cSThomas Hellstrom */ 1301d80efd5cSThomas Hellstrom BUILD_BUG_ON(SVGA3D_DX_MAX_SOTARGETS*sizeof(SVGA3dSoTarget) > 1302d80efd5cSThomas Hellstrom VMW_MAX_VIEW_BINDINGS*sizeof(u32)); 1303d80efd5cSThomas Hellstrom BUILD_BUG_ON(SVGA3D_DX_MAX_VERTEXBUFFERS*sizeof(SVGA3dVertexBuffer) > 1304d80efd5cSThomas Hellstrom VMW_MAX_VIEW_BINDINGS*sizeof(u32)); 1305d80efd5cSThomas Hellstrom } 1306