162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR MIT 262306a36Sopenharmony_ci/************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright 2015 VMware, Inc., Palo Alto, CA., USA 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 762306a36Sopenharmony_ci * copy of this software and associated documentation files (the 862306a36Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 962306a36Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 1062306a36Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 1162306a36Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 1262306a36Sopenharmony_ci * the following conditions: 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * The above copyright notice and this permission notice (including the 1562306a36Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 1662306a36Sopenharmony_ci * of the Software. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1962306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2062306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 2162306a36Sopenharmony_ci * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 2262306a36Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2362306a36Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2462306a36Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci **************************************************************************/ 2762306a36Sopenharmony_ci/* 2862306a36Sopenharmony_ci * This file implements the vmwgfx context binding manager, 2962306a36Sopenharmony_ci * The sole reason for having to use this code is that vmware guest 3062306a36Sopenharmony_ci * backed contexts can be swapped out to their backing mobs by the device 3162306a36Sopenharmony_ci * at any time, also swapped in at any time. At swapin time, the device 3262306a36Sopenharmony_ci * validates the context bindings to make sure they point to valid resources. 3362306a36Sopenharmony_ci * It's this outside-of-drawcall validation (that can happen at any time), 3462306a36Sopenharmony_ci * that makes this code necessary. 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * We therefore need to kill any context bindings pointing to a resource 3762306a36Sopenharmony_ci * when the resource is swapped out. Furthermore, if the vmwgfx driver has 3862306a36Sopenharmony_ci * swapped out the context we can't swap it in again to kill bindings because 3962306a36Sopenharmony_ci * of backing mob reservation lockdep violations, so as part of 4062306a36Sopenharmony_ci * context swapout, also kill all bindings of a context, so that they are 4162306a36Sopenharmony_ci * already killed if a resource to which a binding points 4262306a36Sopenharmony_ci * needs to be swapped out. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * Note that a resource can be pointed to by bindings from multiple contexts, 4562306a36Sopenharmony_ci * Therefore we can't easily protect this data by a per context mutex 4662306a36Sopenharmony_ci * (unless we use deadlock-safe WW mutexes). So we use a global binding_mutex 4762306a36Sopenharmony_ci * to protect all binding manager data. 4862306a36Sopenharmony_ci * 4962306a36Sopenharmony_ci * Finally, any association between a context and a global resource 5062306a36Sopenharmony_ci * (surface, shader or even DX query) is conceptually a context binding that 5162306a36Sopenharmony_ci * needs to be tracked by this code. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#include "vmwgfx_drv.h" 5562306a36Sopenharmony_ci#include "vmwgfx_binding.h" 5662306a36Sopenharmony_ci#include "device_include/svga3d_reg.h" 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define VMW_BINDING_RT_BIT 0 5962306a36Sopenharmony_ci#define VMW_BINDING_PS_BIT 1 6062306a36Sopenharmony_ci#define VMW_BINDING_SO_T_BIT 2 6162306a36Sopenharmony_ci#define VMW_BINDING_VB_BIT 3 6262306a36Sopenharmony_ci#define VMW_BINDING_UAV_BIT 4 6362306a36Sopenharmony_ci#define VMW_BINDING_CS_UAV_BIT 5 6462306a36Sopenharmony_ci#define VMW_BINDING_NUM_BITS 6 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define VMW_BINDING_PS_SR_BIT 0 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/** 6962306a36Sopenharmony_ci * struct vmw_ctx_binding_state - per context binding state 7062306a36Sopenharmony_ci * 7162306a36Sopenharmony_ci * @dev_priv: Pointer to device private structure. 7262306a36Sopenharmony_ci * @list: linked list of individual active bindings. 7362306a36Sopenharmony_ci * @render_targets: Render target bindings. 7462306a36Sopenharmony_ci * @texture_units: Texture units bindings. 7562306a36Sopenharmony_ci * @ds_view: Depth-stencil view binding. 7662306a36Sopenharmony_ci * @so_targets: StreamOutput target bindings. 7762306a36Sopenharmony_ci * @vertex_buffers: Vertex buffer bindings. 7862306a36Sopenharmony_ci * @index_buffer: Index buffer binding. 7962306a36Sopenharmony_ci * @per_shader: Per shader-type bindings. 8062306a36Sopenharmony_ci * @ua_views: UAV bindings. 8162306a36Sopenharmony_ci * @so_state: StreamOutput bindings. 8262306a36Sopenharmony_ci * @dirty: Bitmap tracking per binding-type changes that have not yet 8362306a36Sopenharmony_ci * been emitted to the device. 8462306a36Sopenharmony_ci * @dirty_vb: Bitmap tracking individual vertex buffer binding changes that 8562306a36Sopenharmony_ci * have not yet been emitted to the device. 8662306a36Sopenharmony_ci * @bind_cmd_buffer: Scratch space used to construct binding commands. 8762306a36Sopenharmony_ci * @bind_cmd_count: Number of binding command data entries in @bind_cmd_buffer 8862306a36Sopenharmony_ci * @bind_first_slot: Used together with @bind_cmd_buffer to indicate the 8962306a36Sopenharmony_ci * device binding slot of the first command data entry in @bind_cmd_buffer. 9062306a36Sopenharmony_ci * 9162306a36Sopenharmony_ci * Note that this structure also provides storage space for the individual 9262306a36Sopenharmony_ci * struct vmw_ctx_binding objects, so that no dynamic allocation is needed 9362306a36Sopenharmony_ci * for individual bindings. 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_cistruct vmw_ctx_binding_state { 9762306a36Sopenharmony_ci struct vmw_private *dev_priv; 9862306a36Sopenharmony_ci struct list_head list; 9962306a36Sopenharmony_ci struct vmw_ctx_bindinfo_view render_targets[SVGA3D_RT_MAX]; 10062306a36Sopenharmony_ci struct vmw_ctx_bindinfo_tex texture_units[SVGA3D_NUM_TEXTURE_UNITS]; 10162306a36Sopenharmony_ci struct vmw_ctx_bindinfo_view ds_view; 10262306a36Sopenharmony_ci struct vmw_ctx_bindinfo_so_target so_targets[SVGA3D_DX_MAX_SOTARGETS]; 10362306a36Sopenharmony_ci struct vmw_ctx_bindinfo_vb vertex_buffers[SVGA3D_DX_MAX_VERTEXBUFFERS]; 10462306a36Sopenharmony_ci struct vmw_ctx_bindinfo_ib index_buffer; 10562306a36Sopenharmony_ci struct vmw_dx_shader_bindings per_shader[SVGA3D_NUM_SHADERTYPE]; 10662306a36Sopenharmony_ci struct vmw_ctx_bindinfo_uav ua_views[VMW_MAX_UAV_BIND_TYPE]; 10762306a36Sopenharmony_ci struct vmw_ctx_bindinfo_so so_state; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci unsigned long dirty; 11062306a36Sopenharmony_ci DECLARE_BITMAP(dirty_vb, SVGA3D_DX_MAX_VERTEXBUFFERS); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci u32 bind_cmd_buffer[VMW_MAX_VIEW_BINDINGS]; 11362306a36Sopenharmony_ci u32 bind_cmd_count; 11462306a36Sopenharmony_ci u32 bind_first_slot; 11562306a36Sopenharmony_ci}; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind); 11862306a36Sopenharmony_cistatic int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi, 11962306a36Sopenharmony_ci bool rebind); 12062306a36Sopenharmony_cistatic int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi, bool rebind); 12162306a36Sopenharmony_cistatic int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind); 12262306a36Sopenharmony_cistatic int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind); 12362306a36Sopenharmony_cistatic int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind); 12462306a36Sopenharmony_cistatic int vmw_binding_scrub_so_target(struct vmw_ctx_bindinfo *bi, bool rebind); 12562306a36Sopenharmony_cistatic int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs); 12662306a36Sopenharmony_cistatic int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi, 12762306a36Sopenharmony_ci bool rebind); 12862306a36Sopenharmony_cistatic int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind); 12962306a36Sopenharmony_cistatic int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind); 13062306a36Sopenharmony_cistatic int vmw_binding_scrub_uav(struct vmw_ctx_bindinfo *bi, bool rebind); 13162306a36Sopenharmony_cistatic int vmw_binding_scrub_cs_uav(struct vmw_ctx_bindinfo *bi, bool rebind); 13262306a36Sopenharmony_cistatic int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistatic void vmw_binding_build_asserts(void) __attribute__ ((unused)); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_citypedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *, bool); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci/** 13962306a36Sopenharmony_ci * struct vmw_binding_info - Per binding type information for the binding 14062306a36Sopenharmony_ci * manager 14162306a36Sopenharmony_ci * 14262306a36Sopenharmony_ci * @size: The size of the struct binding derived from a struct vmw_ctx_bindinfo. 14362306a36Sopenharmony_ci * @offsets: array[shader_slot] of offsets to the array[slot] 14462306a36Sopenharmony_ci * of struct bindings for the binding type. 14562306a36Sopenharmony_ci * @scrub_func: Pointer to the scrub function for this binding type. 14662306a36Sopenharmony_ci * 14762306a36Sopenharmony_ci * Holds static information to help optimize the binding manager and avoid 14862306a36Sopenharmony_ci * an excessive amount of switch statements. 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_cistruct vmw_binding_info { 15162306a36Sopenharmony_ci size_t size; 15262306a36Sopenharmony_ci const size_t *offsets; 15362306a36Sopenharmony_ci vmw_scrub_func scrub_func; 15462306a36Sopenharmony_ci}; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci/* 15762306a36Sopenharmony_ci * A number of static variables that help determine the scrub func and the 15862306a36Sopenharmony_ci * location of the struct vmw_ctx_bindinfo slots for each binding type. 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_cistatic const size_t vmw_binding_shader_offsets[] = { 16162306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[0].shader), 16262306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[1].shader), 16362306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[2].shader), 16462306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[3].shader), 16562306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[4].shader), 16662306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[5].shader), 16762306a36Sopenharmony_ci}; 16862306a36Sopenharmony_cistatic const size_t vmw_binding_rt_offsets[] = { 16962306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, render_targets), 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_cistatic const size_t vmw_binding_tex_offsets[] = { 17262306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, texture_units), 17362306a36Sopenharmony_ci}; 17462306a36Sopenharmony_cistatic const size_t vmw_binding_cb_offsets[] = { 17562306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[0].const_buffers), 17662306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[1].const_buffers), 17762306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[2].const_buffers), 17862306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[3].const_buffers), 17962306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[4].const_buffers), 18062306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[5].const_buffers), 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_cistatic const size_t vmw_binding_dx_ds_offsets[] = { 18362306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, ds_view), 18462306a36Sopenharmony_ci}; 18562306a36Sopenharmony_cistatic const size_t vmw_binding_sr_offsets[] = { 18662306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[0].shader_res), 18762306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[1].shader_res), 18862306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[2].shader_res), 18962306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[3].shader_res), 19062306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[4].shader_res), 19162306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, per_shader[5].shader_res), 19262306a36Sopenharmony_ci}; 19362306a36Sopenharmony_cistatic const size_t vmw_binding_so_target_offsets[] = { 19462306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, so_targets), 19562306a36Sopenharmony_ci}; 19662306a36Sopenharmony_cistatic const size_t vmw_binding_vb_offsets[] = { 19762306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, vertex_buffers), 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_cistatic const size_t vmw_binding_ib_offsets[] = { 20062306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, index_buffer), 20162306a36Sopenharmony_ci}; 20262306a36Sopenharmony_cistatic const size_t vmw_binding_uav_offsets[] = { 20362306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, ua_views[0].views), 20462306a36Sopenharmony_ci}; 20562306a36Sopenharmony_cistatic const size_t vmw_binding_cs_uav_offsets[] = { 20662306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, ua_views[1].views), 20762306a36Sopenharmony_ci}; 20862306a36Sopenharmony_cistatic const size_t vmw_binding_so_offsets[] = { 20962306a36Sopenharmony_ci offsetof(struct vmw_ctx_binding_state, so_state), 21062306a36Sopenharmony_ci}; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic const struct vmw_binding_info vmw_binding_infos[] = { 21362306a36Sopenharmony_ci [vmw_ctx_binding_shader] = { 21462306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_shader), 21562306a36Sopenharmony_ci .offsets = vmw_binding_shader_offsets, 21662306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_shader}, 21762306a36Sopenharmony_ci [vmw_ctx_binding_rt] = { 21862306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_view), 21962306a36Sopenharmony_ci .offsets = vmw_binding_rt_offsets, 22062306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_render_target}, 22162306a36Sopenharmony_ci [vmw_ctx_binding_tex] = { 22262306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_tex), 22362306a36Sopenharmony_ci .offsets = vmw_binding_tex_offsets, 22462306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_texture}, 22562306a36Sopenharmony_ci [vmw_ctx_binding_cb] = { 22662306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_cb), 22762306a36Sopenharmony_ci .offsets = vmw_binding_cb_offsets, 22862306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_cb}, 22962306a36Sopenharmony_ci [vmw_ctx_binding_dx_shader] = { 23062306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_shader), 23162306a36Sopenharmony_ci .offsets = vmw_binding_shader_offsets, 23262306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_dx_shader}, 23362306a36Sopenharmony_ci [vmw_ctx_binding_dx_rt] = { 23462306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_view), 23562306a36Sopenharmony_ci .offsets = vmw_binding_rt_offsets, 23662306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_dx_rt}, 23762306a36Sopenharmony_ci [vmw_ctx_binding_sr] = { 23862306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_view), 23962306a36Sopenharmony_ci .offsets = vmw_binding_sr_offsets, 24062306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_sr}, 24162306a36Sopenharmony_ci [vmw_ctx_binding_ds] = { 24262306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_view), 24362306a36Sopenharmony_ci .offsets = vmw_binding_dx_ds_offsets, 24462306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_dx_rt}, 24562306a36Sopenharmony_ci [vmw_ctx_binding_so_target] = { 24662306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_so_target), 24762306a36Sopenharmony_ci .offsets = vmw_binding_so_target_offsets, 24862306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_so_target}, 24962306a36Sopenharmony_ci [vmw_ctx_binding_vb] = { 25062306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_vb), 25162306a36Sopenharmony_ci .offsets = vmw_binding_vb_offsets, 25262306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_vb}, 25362306a36Sopenharmony_ci [vmw_ctx_binding_ib] = { 25462306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_ib), 25562306a36Sopenharmony_ci .offsets = vmw_binding_ib_offsets, 25662306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_ib}, 25762306a36Sopenharmony_ci [vmw_ctx_binding_uav] = { 25862306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_view), 25962306a36Sopenharmony_ci .offsets = vmw_binding_uav_offsets, 26062306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_uav}, 26162306a36Sopenharmony_ci [vmw_ctx_binding_cs_uav] = { 26262306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_view), 26362306a36Sopenharmony_ci .offsets = vmw_binding_cs_uav_offsets, 26462306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_cs_uav}, 26562306a36Sopenharmony_ci [vmw_ctx_binding_so] = { 26662306a36Sopenharmony_ci .size = sizeof(struct vmw_ctx_bindinfo_so), 26762306a36Sopenharmony_ci .offsets = vmw_binding_so_offsets, 26862306a36Sopenharmony_ci .scrub_func = vmw_binding_scrub_so}, 26962306a36Sopenharmony_ci}; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/** 27262306a36Sopenharmony_ci * vmw_cbs_context - Return a pointer to the context resource of a 27362306a36Sopenharmony_ci * context binding state tracker. 27462306a36Sopenharmony_ci * 27562306a36Sopenharmony_ci * @cbs: The context binding state tracker. 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * Provided there are any active bindings, this function will return an 27862306a36Sopenharmony_ci * unreferenced pointer to the context resource that owns the context 27962306a36Sopenharmony_ci * binding state tracker. If there are no active bindings, this function 28062306a36Sopenharmony_ci * will return NULL. Note that the caller must somehow ensure that a reference 28162306a36Sopenharmony_ci * is held on the context resource prior to calling this function. 28262306a36Sopenharmony_ci */ 28362306a36Sopenharmony_cistatic const struct vmw_resource * 28462306a36Sopenharmony_civmw_cbs_context(const struct vmw_ctx_binding_state *cbs) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci if (list_empty(&cbs->list)) 28762306a36Sopenharmony_ci return NULL; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci return list_first_entry(&cbs->list, struct vmw_ctx_bindinfo, 29062306a36Sopenharmony_ci ctx_list)->ctx; 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci/** 29462306a36Sopenharmony_ci * vmw_binding_loc - determine the struct vmw_ctx_bindinfo slot location. 29562306a36Sopenharmony_ci * 29662306a36Sopenharmony_ci * @cbs: Pointer to a struct vmw_ctx_binding state which holds the slot. 29762306a36Sopenharmony_ci * @bt: The binding type. 29862306a36Sopenharmony_ci * @shader_slot: The shader slot of the binding. If none, then set to 0. 29962306a36Sopenharmony_ci * @slot: The slot of the binding. 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_cistatic struct vmw_ctx_bindinfo * 30262306a36Sopenharmony_civmw_binding_loc(struct vmw_ctx_binding_state *cbs, 30362306a36Sopenharmony_ci enum vmw_ctx_binding_type bt, u32 shader_slot, u32 slot) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci const struct vmw_binding_info *b = &vmw_binding_infos[bt]; 30662306a36Sopenharmony_ci size_t offset = b->offsets[shader_slot] + b->size*slot; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci return (struct vmw_ctx_bindinfo *)((u8 *) cbs + offset); 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/** 31262306a36Sopenharmony_ci * vmw_binding_drop: Stop tracking a context binding 31362306a36Sopenharmony_ci * 31462306a36Sopenharmony_ci * @bi: Pointer to binding tracker storage. 31562306a36Sopenharmony_ci * 31662306a36Sopenharmony_ci * Stops tracking a context binding, and re-initializes its storage. 31762306a36Sopenharmony_ci * Typically used when the context binding is replaced with a binding to 31862306a36Sopenharmony_ci * another (or the same, for that matter) resource. 31962306a36Sopenharmony_ci */ 32062306a36Sopenharmony_cistatic void vmw_binding_drop(struct vmw_ctx_bindinfo *bi) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci list_del(&bi->ctx_list); 32362306a36Sopenharmony_ci if (!list_empty(&bi->res_list)) 32462306a36Sopenharmony_ci list_del(&bi->res_list); 32562306a36Sopenharmony_ci bi->ctx = NULL; 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci/** 32962306a36Sopenharmony_ci * vmw_binding_add: Start tracking a context binding 33062306a36Sopenharmony_ci * 33162306a36Sopenharmony_ci * @cbs: Pointer to the context binding state tracker. 33262306a36Sopenharmony_ci * @bi: Information about the binding to track. 33362306a36Sopenharmony_ci * @shader_slot: The shader slot of the binding. 33462306a36Sopenharmony_ci * @slot: The slot of the binding. 33562306a36Sopenharmony_ci * 33662306a36Sopenharmony_ci * Starts tracking the binding in the context binding 33762306a36Sopenharmony_ci * state structure @cbs. 33862306a36Sopenharmony_ci */ 33962306a36Sopenharmony_civoid vmw_binding_add(struct vmw_ctx_binding_state *cbs, 34062306a36Sopenharmony_ci const struct vmw_ctx_bindinfo *bi, 34162306a36Sopenharmony_ci u32 shader_slot, u32 slot) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci struct vmw_ctx_bindinfo *loc = 34462306a36Sopenharmony_ci vmw_binding_loc(cbs, bi->bt, shader_slot, slot); 34562306a36Sopenharmony_ci const struct vmw_binding_info *b = &vmw_binding_infos[bi->bt]; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci if (loc->ctx != NULL) 34862306a36Sopenharmony_ci vmw_binding_drop(loc); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci memcpy(loc, bi, b->size); 35162306a36Sopenharmony_ci loc->scrubbed = false; 35262306a36Sopenharmony_ci list_add(&loc->ctx_list, &cbs->list); 35362306a36Sopenharmony_ci INIT_LIST_HEAD(&loc->res_list); 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci/** 35762306a36Sopenharmony_ci * vmw_binding_cb_offset_update: Update the offset of a cb binding 35862306a36Sopenharmony_ci * 35962306a36Sopenharmony_ci * @cbs: Pointer to the context binding state tracker. 36062306a36Sopenharmony_ci * @shader_slot: The shader slot of the binding. 36162306a36Sopenharmony_ci * @slot: The slot of the binding. 36262306a36Sopenharmony_ci * @offsetInBytes: The new offset of the binding. 36362306a36Sopenharmony_ci * 36462306a36Sopenharmony_ci * Updates the offset of an existing cb binding in the context binding 36562306a36Sopenharmony_ci * state structure @cbs. 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_civoid vmw_binding_cb_offset_update(struct vmw_ctx_binding_state *cbs, 36862306a36Sopenharmony_ci u32 shader_slot, u32 slot, u32 offsetInBytes) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci struct vmw_ctx_bindinfo *loc = 37162306a36Sopenharmony_ci vmw_binding_loc(cbs, vmw_ctx_binding_cb, shader_slot, slot); 37262306a36Sopenharmony_ci struct vmw_ctx_bindinfo_cb *loc_cb = 37362306a36Sopenharmony_ci (struct vmw_ctx_bindinfo_cb *)((u8 *) loc); 37462306a36Sopenharmony_ci loc_cb->offset = offsetInBytes; 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci/** 37862306a36Sopenharmony_ci * vmw_binding_add_uav_index - Add UAV index for tracking. 37962306a36Sopenharmony_ci * @cbs: Pointer to the context binding state tracker. 38062306a36Sopenharmony_ci * @slot: UAV type to which bind this index. 38162306a36Sopenharmony_ci * @index: The splice index to track. 38262306a36Sopenharmony_ci */ 38362306a36Sopenharmony_civoid vmw_binding_add_uav_index(struct vmw_ctx_binding_state *cbs, uint32 slot, 38462306a36Sopenharmony_ci uint32 index) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci cbs->ua_views[slot].index = index; 38762306a36Sopenharmony_ci} 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci/** 39062306a36Sopenharmony_ci * vmw_binding_transfer: Transfer a context binding tracking entry. 39162306a36Sopenharmony_ci * 39262306a36Sopenharmony_ci * @cbs: Pointer to the persistent context binding state tracker. 39362306a36Sopenharmony_ci * @from: Staged binding info built during execbuf 39462306a36Sopenharmony_ci * @bi: Information about the binding to track. 39562306a36Sopenharmony_ci * 39662306a36Sopenharmony_ci */ 39762306a36Sopenharmony_cistatic void vmw_binding_transfer(struct vmw_ctx_binding_state *cbs, 39862306a36Sopenharmony_ci const struct vmw_ctx_binding_state *from, 39962306a36Sopenharmony_ci const struct vmw_ctx_bindinfo *bi) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci size_t offset = (unsigned long)bi - (unsigned long)from; 40262306a36Sopenharmony_ci struct vmw_ctx_bindinfo *loc = (struct vmw_ctx_bindinfo *) 40362306a36Sopenharmony_ci ((unsigned long) cbs + offset); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (loc->ctx != NULL) { 40662306a36Sopenharmony_ci WARN_ON(bi->scrubbed); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci vmw_binding_drop(loc); 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci if (bi->res != NULL) { 41262306a36Sopenharmony_ci memcpy(loc, bi, vmw_binding_infos[bi->bt].size); 41362306a36Sopenharmony_ci list_add_tail(&loc->ctx_list, &cbs->list); 41462306a36Sopenharmony_ci list_add_tail(&loc->res_list, &loc->res->binding_head); 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci/** 41962306a36Sopenharmony_ci * vmw_binding_state_kill - Kill all bindings associated with a 42062306a36Sopenharmony_ci * struct vmw_ctx_binding state structure, and re-initialize the structure. 42162306a36Sopenharmony_ci * 42262306a36Sopenharmony_ci * @cbs: Pointer to the context binding state tracker. 42362306a36Sopenharmony_ci * 42462306a36Sopenharmony_ci * Emits commands to scrub all bindings associated with the 42562306a36Sopenharmony_ci * context binding state tracker. Then re-initializes the whole structure. 42662306a36Sopenharmony_ci */ 42762306a36Sopenharmony_civoid vmw_binding_state_kill(struct vmw_ctx_binding_state *cbs) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci struct vmw_ctx_bindinfo *entry, *next; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci vmw_binding_state_scrub(cbs); 43262306a36Sopenharmony_ci list_for_each_entry_safe(entry, next, &cbs->list, ctx_list) 43362306a36Sopenharmony_ci vmw_binding_drop(entry); 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci/** 43762306a36Sopenharmony_ci * vmw_binding_state_scrub - Scrub all bindings associated with a 43862306a36Sopenharmony_ci * struct vmw_ctx_binding state structure. 43962306a36Sopenharmony_ci * 44062306a36Sopenharmony_ci * @cbs: Pointer to the context binding state tracker. 44162306a36Sopenharmony_ci * 44262306a36Sopenharmony_ci * Emits commands to scrub all bindings associated with the 44362306a36Sopenharmony_ci * context binding state tracker. 44462306a36Sopenharmony_ci */ 44562306a36Sopenharmony_civoid vmw_binding_state_scrub(struct vmw_ctx_binding_state *cbs) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci struct vmw_ctx_bindinfo *entry; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci list_for_each_entry(entry, &cbs->list, ctx_list) { 45062306a36Sopenharmony_ci if (!entry->scrubbed) { 45162306a36Sopenharmony_ci (void) vmw_binding_infos[entry->bt].scrub_func 45262306a36Sopenharmony_ci (entry, false); 45362306a36Sopenharmony_ci entry->scrubbed = true; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci (void) vmw_binding_emit_dirty(cbs); 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci/** 46162306a36Sopenharmony_ci * vmw_binding_res_list_kill - Kill all bindings on a 46262306a36Sopenharmony_ci * resource binding list 46362306a36Sopenharmony_ci * 46462306a36Sopenharmony_ci * @head: list head of resource binding list 46562306a36Sopenharmony_ci * 46662306a36Sopenharmony_ci * Kills all bindings associated with a specific resource. Typically 46762306a36Sopenharmony_ci * called before the resource is destroyed. 46862306a36Sopenharmony_ci */ 46962306a36Sopenharmony_civoid vmw_binding_res_list_kill(struct list_head *head) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci struct vmw_ctx_bindinfo *entry, *next; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci vmw_binding_res_list_scrub(head); 47462306a36Sopenharmony_ci list_for_each_entry_safe(entry, next, head, res_list) 47562306a36Sopenharmony_ci vmw_binding_drop(entry); 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci/** 47962306a36Sopenharmony_ci * vmw_binding_res_list_scrub - Scrub all bindings on a 48062306a36Sopenharmony_ci * resource binding list 48162306a36Sopenharmony_ci * 48262306a36Sopenharmony_ci * @head: list head of resource binding list 48362306a36Sopenharmony_ci * 48462306a36Sopenharmony_ci * Scrub all bindings associated with a specific resource. Typically 48562306a36Sopenharmony_ci * called before the resource is evicted. 48662306a36Sopenharmony_ci */ 48762306a36Sopenharmony_civoid vmw_binding_res_list_scrub(struct list_head *head) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci struct vmw_ctx_bindinfo *entry; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci list_for_each_entry(entry, head, res_list) { 49262306a36Sopenharmony_ci if (!entry->scrubbed) { 49362306a36Sopenharmony_ci (void) vmw_binding_infos[entry->bt].scrub_func 49462306a36Sopenharmony_ci (entry, false); 49562306a36Sopenharmony_ci entry->scrubbed = true; 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci list_for_each_entry(entry, head, res_list) { 50062306a36Sopenharmony_ci struct vmw_ctx_binding_state *cbs = 50162306a36Sopenharmony_ci vmw_context_binding_state(entry->ctx); 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci (void) vmw_binding_emit_dirty(cbs); 50462306a36Sopenharmony_ci } 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci/** 50962306a36Sopenharmony_ci * vmw_binding_state_commit - Commit staged binding info 51062306a36Sopenharmony_ci * 51162306a36Sopenharmony_ci * @to: Staged binding info area to copy into to. 51262306a36Sopenharmony_ci * @from: Staged binding info built during execbuf. 51362306a36Sopenharmony_ci * 51462306a36Sopenharmony_ci * Transfers binding info from a temporary structure 51562306a36Sopenharmony_ci * (typically used by execbuf) to the persistent 51662306a36Sopenharmony_ci * structure in the context. This can be done once commands have been 51762306a36Sopenharmony_ci * submitted to hardware 51862306a36Sopenharmony_ci */ 51962306a36Sopenharmony_civoid vmw_binding_state_commit(struct vmw_ctx_binding_state *to, 52062306a36Sopenharmony_ci struct vmw_ctx_binding_state *from) 52162306a36Sopenharmony_ci{ 52262306a36Sopenharmony_ci struct vmw_ctx_bindinfo *entry, *next; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci list_for_each_entry_safe(entry, next, &from->list, ctx_list) { 52562306a36Sopenharmony_ci vmw_binding_transfer(to, from, entry); 52662306a36Sopenharmony_ci vmw_binding_drop(entry); 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci /* Also transfer uav splice indices */ 53062306a36Sopenharmony_ci to->ua_views[0].index = from->ua_views[0].index; 53162306a36Sopenharmony_ci to->ua_views[1].index = from->ua_views[1].index; 53262306a36Sopenharmony_ci} 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci/** 53562306a36Sopenharmony_ci * vmw_binding_rebind_all - Rebind all scrubbed bindings of a context 53662306a36Sopenharmony_ci * 53762306a36Sopenharmony_ci * @cbs: Pointer to the context binding state tracker. 53862306a36Sopenharmony_ci * 53962306a36Sopenharmony_ci * Walks through the context binding list and rebinds all scrubbed 54062306a36Sopenharmony_ci * resources. 54162306a36Sopenharmony_ci */ 54262306a36Sopenharmony_ciint vmw_binding_rebind_all(struct vmw_ctx_binding_state *cbs) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci struct vmw_ctx_bindinfo *entry; 54562306a36Sopenharmony_ci int ret; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci list_for_each_entry(entry, &cbs->list, ctx_list) { 54862306a36Sopenharmony_ci if (likely(!entry->scrubbed)) 54962306a36Sopenharmony_ci continue; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci if ((entry->res == NULL || entry->res->id == 55262306a36Sopenharmony_ci SVGA3D_INVALID_ID)) 55362306a36Sopenharmony_ci continue; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci ret = vmw_binding_infos[entry->bt].scrub_func(entry, true); 55662306a36Sopenharmony_ci if (unlikely(ret != 0)) 55762306a36Sopenharmony_ci return ret; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci entry->scrubbed = false; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci return vmw_binding_emit_dirty(cbs); 56362306a36Sopenharmony_ci} 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci/** 56662306a36Sopenharmony_ci * vmw_binding_scrub_shader - scrub a shader binding from a context. 56762306a36Sopenharmony_ci * 56862306a36Sopenharmony_ci * @bi: single binding information. 56962306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 57062306a36Sopenharmony_ci */ 57162306a36Sopenharmony_cistatic int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind) 57262306a36Sopenharmony_ci{ 57362306a36Sopenharmony_ci struct vmw_ctx_bindinfo_shader *binding = 57462306a36Sopenharmony_ci container_of(bi, typeof(*binding), bi); 57562306a36Sopenharmony_ci struct vmw_private *dev_priv = bi->ctx->dev_priv; 57662306a36Sopenharmony_ci struct { 57762306a36Sopenharmony_ci SVGA3dCmdHeader header; 57862306a36Sopenharmony_ci SVGA3dCmdSetShader body; 57962306a36Sopenharmony_ci } *cmd; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); 58262306a36Sopenharmony_ci if (unlikely(cmd == NULL)) 58362306a36Sopenharmony_ci return -ENOMEM; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_SET_SHADER; 58662306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 58762306a36Sopenharmony_ci cmd->body.cid = bi->ctx->id; 58862306a36Sopenharmony_ci cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 58962306a36Sopenharmony_ci cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 59062306a36Sopenharmony_ci vmw_cmd_commit(dev_priv, sizeof(*cmd)); 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci return 0; 59362306a36Sopenharmony_ci} 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci/** 59662306a36Sopenharmony_ci * vmw_binding_scrub_render_target - scrub a render target binding 59762306a36Sopenharmony_ci * from a context. 59862306a36Sopenharmony_ci * 59962306a36Sopenharmony_ci * @bi: single binding information. 60062306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 60162306a36Sopenharmony_ci */ 60262306a36Sopenharmony_cistatic int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi, 60362306a36Sopenharmony_ci bool rebind) 60462306a36Sopenharmony_ci{ 60562306a36Sopenharmony_ci struct vmw_ctx_bindinfo_view *binding = 60662306a36Sopenharmony_ci container_of(bi, typeof(*binding), bi); 60762306a36Sopenharmony_ci struct vmw_private *dev_priv = bi->ctx->dev_priv; 60862306a36Sopenharmony_ci struct { 60962306a36Sopenharmony_ci SVGA3dCmdHeader header; 61062306a36Sopenharmony_ci SVGA3dCmdSetRenderTarget body; 61162306a36Sopenharmony_ci } *cmd; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); 61462306a36Sopenharmony_ci if (unlikely(cmd == NULL)) 61562306a36Sopenharmony_ci return -ENOMEM; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET; 61862306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 61962306a36Sopenharmony_ci cmd->body.cid = bi->ctx->id; 62062306a36Sopenharmony_ci cmd->body.type = binding->slot; 62162306a36Sopenharmony_ci cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 62262306a36Sopenharmony_ci cmd->body.target.face = 0; 62362306a36Sopenharmony_ci cmd->body.target.mipmap = 0; 62462306a36Sopenharmony_ci vmw_cmd_commit(dev_priv, sizeof(*cmd)); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci return 0; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci/** 63062306a36Sopenharmony_ci * vmw_binding_scrub_texture - scrub a texture binding from a context. 63162306a36Sopenharmony_ci * 63262306a36Sopenharmony_ci * @bi: single binding information. 63362306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 63462306a36Sopenharmony_ci * 63562306a36Sopenharmony_ci * TODO: Possibly complement this function with a function that takes 63662306a36Sopenharmony_ci * a list of texture bindings and combines them to a single command. 63762306a36Sopenharmony_ci */ 63862306a36Sopenharmony_cistatic int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi, 63962306a36Sopenharmony_ci bool rebind) 64062306a36Sopenharmony_ci{ 64162306a36Sopenharmony_ci struct vmw_ctx_bindinfo_tex *binding = 64262306a36Sopenharmony_ci container_of(bi, typeof(*binding), bi); 64362306a36Sopenharmony_ci struct vmw_private *dev_priv = bi->ctx->dev_priv; 64462306a36Sopenharmony_ci struct { 64562306a36Sopenharmony_ci SVGA3dCmdHeader header; 64662306a36Sopenharmony_ci struct { 64762306a36Sopenharmony_ci SVGA3dCmdSetTextureState c; 64862306a36Sopenharmony_ci SVGA3dTextureState s1; 64962306a36Sopenharmony_ci } body; 65062306a36Sopenharmony_ci } *cmd; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd)); 65362306a36Sopenharmony_ci if (unlikely(cmd == NULL)) 65462306a36Sopenharmony_ci return -ENOMEM; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE; 65762306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 65862306a36Sopenharmony_ci cmd->body.c.cid = bi->ctx->id; 65962306a36Sopenharmony_ci cmd->body.s1.stage = binding->texture_stage; 66062306a36Sopenharmony_ci cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE; 66162306a36Sopenharmony_ci cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 66262306a36Sopenharmony_ci vmw_cmd_commit(dev_priv, sizeof(*cmd)); 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci return 0; 66562306a36Sopenharmony_ci} 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci/** 66862306a36Sopenharmony_ci * vmw_binding_scrub_dx_shader - scrub a dx shader binding from a context. 66962306a36Sopenharmony_ci * 67062306a36Sopenharmony_ci * @bi: single binding information. 67162306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 67262306a36Sopenharmony_ci */ 67362306a36Sopenharmony_cistatic int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi, bool rebind) 67462306a36Sopenharmony_ci{ 67562306a36Sopenharmony_ci struct vmw_ctx_bindinfo_shader *binding = 67662306a36Sopenharmony_ci container_of(bi, typeof(*binding), bi); 67762306a36Sopenharmony_ci struct vmw_private *dev_priv = bi->ctx->dev_priv; 67862306a36Sopenharmony_ci struct { 67962306a36Sopenharmony_ci SVGA3dCmdHeader header; 68062306a36Sopenharmony_ci SVGA3dCmdDXSetShader body; 68162306a36Sopenharmony_ci } *cmd; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), bi->ctx->id); 68462306a36Sopenharmony_ci if (unlikely(cmd == NULL)) 68562306a36Sopenharmony_ci return -ENOMEM; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER; 68862306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 68962306a36Sopenharmony_ci cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 69062306a36Sopenharmony_ci cmd->body.shaderId = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID); 69162306a36Sopenharmony_ci vmw_cmd_commit(dev_priv, sizeof(*cmd)); 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci return 0; 69462306a36Sopenharmony_ci} 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci/** 69762306a36Sopenharmony_ci * vmw_binding_scrub_cb - scrub a constant buffer binding from a context. 69862306a36Sopenharmony_ci * 69962306a36Sopenharmony_ci * @bi: single binding information. 70062306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 70162306a36Sopenharmony_ci */ 70262306a36Sopenharmony_cistatic int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind) 70362306a36Sopenharmony_ci{ 70462306a36Sopenharmony_ci struct vmw_ctx_bindinfo_cb *binding = 70562306a36Sopenharmony_ci container_of(bi, typeof(*binding), bi); 70662306a36Sopenharmony_ci struct vmw_private *dev_priv = bi->ctx->dev_priv; 70762306a36Sopenharmony_ci struct { 70862306a36Sopenharmony_ci SVGA3dCmdHeader header; 70962306a36Sopenharmony_ci SVGA3dCmdDXSetSingleConstantBuffer body; 71062306a36Sopenharmony_ci } *cmd; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), bi->ctx->id); 71362306a36Sopenharmony_ci if (unlikely(cmd == NULL)) 71462306a36Sopenharmony_ci return -ENOMEM; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER; 71762306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 71862306a36Sopenharmony_ci cmd->body.slot = binding->slot; 71962306a36Sopenharmony_ci cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN; 72062306a36Sopenharmony_ci if (rebind) { 72162306a36Sopenharmony_ci cmd->body.offsetInBytes = binding->offset; 72262306a36Sopenharmony_ci cmd->body.sizeInBytes = binding->size; 72362306a36Sopenharmony_ci cmd->body.sid = bi->res->id; 72462306a36Sopenharmony_ci } else { 72562306a36Sopenharmony_ci cmd->body.offsetInBytes = 0; 72662306a36Sopenharmony_ci cmd->body.sizeInBytes = 0; 72762306a36Sopenharmony_ci cmd->body.sid = SVGA3D_INVALID_ID; 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci vmw_cmd_commit(dev_priv, sizeof(*cmd)); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci return 0; 73262306a36Sopenharmony_ci} 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci/** 73562306a36Sopenharmony_ci * vmw_collect_view_ids - Build view id data for a view binding command 73662306a36Sopenharmony_ci * without checking which bindings actually need to be emitted 73762306a36Sopenharmony_ci * 73862306a36Sopenharmony_ci * @cbs: Pointer to the context's struct vmw_ctx_binding_state 73962306a36Sopenharmony_ci * @biv: Pointer to where the binding info array is stored in @cbs 74062306a36Sopenharmony_ci * @max_num: Maximum number of entries in the @bi array. 74162306a36Sopenharmony_ci * 74262306a36Sopenharmony_ci * Scans the @bi array for bindings and builds a buffer of view id data. 74362306a36Sopenharmony_ci * Stops at the first non-existing binding in the @bi array. 74462306a36Sopenharmony_ci * On output, @cbs->bind_cmd_count contains the number of bindings to be 74562306a36Sopenharmony_ci * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer 74662306a36Sopenharmony_ci * contains the command data. 74762306a36Sopenharmony_ci */ 74862306a36Sopenharmony_cistatic void vmw_collect_view_ids(struct vmw_ctx_binding_state *cbs, 74962306a36Sopenharmony_ci const struct vmw_ctx_bindinfo_view *biv, 75062306a36Sopenharmony_ci u32 max_num) 75162306a36Sopenharmony_ci{ 75262306a36Sopenharmony_ci unsigned long i; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci cbs->bind_cmd_count = 0; 75562306a36Sopenharmony_ci cbs->bind_first_slot = 0; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci for (i = 0; i < max_num; ++i, ++biv) { 75862306a36Sopenharmony_ci if (!biv->bi.ctx) 75962306a36Sopenharmony_ci break; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci cbs->bind_cmd_buffer[cbs->bind_cmd_count++] = 76262306a36Sopenharmony_ci ((biv->bi.scrubbed) ? 76362306a36Sopenharmony_ci SVGA3D_INVALID_ID : biv->bi.res->id); 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci} 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci/** 76862306a36Sopenharmony_ci * vmw_collect_dirty_view_ids - Build view id data for a view binding command 76962306a36Sopenharmony_ci * 77062306a36Sopenharmony_ci * @cbs: Pointer to the context's struct vmw_ctx_binding_state 77162306a36Sopenharmony_ci * @bi: Pointer to where the binding info array is stored in @cbs 77262306a36Sopenharmony_ci * @dirty: Bitmap indicating which bindings need to be emitted. 77362306a36Sopenharmony_ci * @max_num: Maximum number of entries in the @bi array. 77462306a36Sopenharmony_ci * 77562306a36Sopenharmony_ci * Scans the @bi array for bindings that need to be emitted and 77662306a36Sopenharmony_ci * builds a buffer of view id data. 77762306a36Sopenharmony_ci * On output, @cbs->bind_cmd_count contains the number of bindings to be 77862306a36Sopenharmony_ci * emitted, @cbs->bind_first_slot indicates the index of the first emitted 77962306a36Sopenharmony_ci * binding, and @cbs->bind_cmd_buffer contains the command data. 78062306a36Sopenharmony_ci */ 78162306a36Sopenharmony_cistatic void vmw_collect_dirty_view_ids(struct vmw_ctx_binding_state *cbs, 78262306a36Sopenharmony_ci const struct vmw_ctx_bindinfo *bi, 78362306a36Sopenharmony_ci unsigned long *dirty, 78462306a36Sopenharmony_ci u32 max_num) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci const struct vmw_ctx_bindinfo_view *biv = 78762306a36Sopenharmony_ci container_of(bi, struct vmw_ctx_bindinfo_view, bi); 78862306a36Sopenharmony_ci unsigned long i, next_bit; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci cbs->bind_cmd_count = 0; 79162306a36Sopenharmony_ci i = find_first_bit(dirty, max_num); 79262306a36Sopenharmony_ci next_bit = i; 79362306a36Sopenharmony_ci cbs->bind_first_slot = i; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci biv += i; 79662306a36Sopenharmony_ci for (; i < max_num; ++i, ++biv) { 79762306a36Sopenharmony_ci cbs->bind_cmd_buffer[cbs->bind_cmd_count++] = 79862306a36Sopenharmony_ci ((!biv->bi.ctx || biv->bi.scrubbed) ? 79962306a36Sopenharmony_ci SVGA3D_INVALID_ID : biv->bi.res->id); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci if (next_bit == i) { 80262306a36Sopenharmony_ci next_bit = find_next_bit(dirty, max_num, i + 1); 80362306a36Sopenharmony_ci if (next_bit >= max_num) 80462306a36Sopenharmony_ci break; 80562306a36Sopenharmony_ci } 80662306a36Sopenharmony_ci } 80762306a36Sopenharmony_ci} 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci/** 81062306a36Sopenharmony_ci * vmw_emit_set_sr - Issue delayed DX shader resource binding commands 81162306a36Sopenharmony_ci * 81262306a36Sopenharmony_ci * @cbs: Pointer to the context's struct vmw_ctx_binding_state 81362306a36Sopenharmony_ci * @shader_slot: The shader slot of the binding. 81462306a36Sopenharmony_ci */ 81562306a36Sopenharmony_cistatic int vmw_emit_set_sr(struct vmw_ctx_binding_state *cbs, 81662306a36Sopenharmony_ci int shader_slot) 81762306a36Sopenharmony_ci{ 81862306a36Sopenharmony_ci const struct vmw_ctx_bindinfo *loc = 81962306a36Sopenharmony_ci &cbs->per_shader[shader_slot].shader_res[0].bi; 82062306a36Sopenharmony_ci struct { 82162306a36Sopenharmony_ci SVGA3dCmdHeader header; 82262306a36Sopenharmony_ci SVGA3dCmdDXSetShaderResources body; 82362306a36Sopenharmony_ci } *cmd; 82462306a36Sopenharmony_ci size_t cmd_size, view_id_size; 82562306a36Sopenharmony_ci const struct vmw_resource *ctx = vmw_cbs_context(cbs); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci vmw_collect_dirty_view_ids(cbs, loc, 82862306a36Sopenharmony_ci cbs->per_shader[shader_slot].dirty_sr, 82962306a36Sopenharmony_ci SVGA3D_DX_MAX_SRVIEWS); 83062306a36Sopenharmony_ci if (cbs->bind_cmd_count == 0) 83162306a36Sopenharmony_ci return 0; 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci view_id_size = cbs->bind_cmd_count*sizeof(uint32); 83462306a36Sopenharmony_ci cmd_size = sizeof(*cmd) + view_id_size; 83562306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id); 83662306a36Sopenharmony_ci if (unlikely(cmd == NULL)) 83762306a36Sopenharmony_ci return -ENOMEM; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER_RESOURCES; 84062306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body) + view_id_size; 84162306a36Sopenharmony_ci cmd->body.type = shader_slot + SVGA3D_SHADERTYPE_MIN; 84262306a36Sopenharmony_ci cmd->body.startView = cbs->bind_first_slot; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size); 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci vmw_cmd_commit(ctx->dev_priv, cmd_size); 84762306a36Sopenharmony_ci bitmap_clear(cbs->per_shader[shader_slot].dirty_sr, 84862306a36Sopenharmony_ci cbs->bind_first_slot, cbs->bind_cmd_count); 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci return 0; 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci/** 85462306a36Sopenharmony_ci * vmw_emit_set_rt - Issue delayed DX rendertarget binding commands 85562306a36Sopenharmony_ci * 85662306a36Sopenharmony_ci * @cbs: Pointer to the context's struct vmw_ctx_binding_state 85762306a36Sopenharmony_ci */ 85862306a36Sopenharmony_cistatic int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs) 85962306a36Sopenharmony_ci{ 86062306a36Sopenharmony_ci const struct vmw_ctx_bindinfo_view *loc = &cbs->render_targets[0]; 86162306a36Sopenharmony_ci struct { 86262306a36Sopenharmony_ci SVGA3dCmdHeader header; 86362306a36Sopenharmony_ci SVGA3dCmdDXSetRenderTargets body; 86462306a36Sopenharmony_ci } *cmd; 86562306a36Sopenharmony_ci size_t cmd_size, view_id_size; 86662306a36Sopenharmony_ci const struct vmw_resource *ctx = vmw_cbs_context(cbs); 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci vmw_collect_view_ids(cbs, loc, SVGA3D_DX_MAX_RENDER_TARGETS); 86962306a36Sopenharmony_ci view_id_size = cbs->bind_cmd_count*sizeof(uint32); 87062306a36Sopenharmony_ci cmd_size = sizeof(*cmd) + view_id_size; 87162306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id); 87262306a36Sopenharmony_ci if (unlikely(cmd == NULL)) 87362306a36Sopenharmony_ci return -ENOMEM; 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_SET_RENDERTARGETS; 87662306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body) + view_id_size; 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci if (cbs->ds_view.bi.ctx && !cbs->ds_view.bi.scrubbed) 87962306a36Sopenharmony_ci cmd->body.depthStencilViewId = cbs->ds_view.bi.res->id; 88062306a36Sopenharmony_ci else 88162306a36Sopenharmony_ci cmd->body.depthStencilViewId = SVGA3D_INVALID_ID; 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci vmw_cmd_commit(ctx->dev_priv, cmd_size); 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci return 0; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_ci} 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci/** 89262306a36Sopenharmony_ci * vmw_collect_so_targets - Build SVGA3dSoTarget data for a binding command 89362306a36Sopenharmony_ci * without checking which bindings actually need to be emitted 89462306a36Sopenharmony_ci * 89562306a36Sopenharmony_ci * @cbs: Pointer to the context's struct vmw_ctx_binding_state 89662306a36Sopenharmony_ci * @biso: Pointer to where the binding info array is stored in @cbs 89762306a36Sopenharmony_ci * @max_num: Maximum number of entries in the @bi array. 89862306a36Sopenharmony_ci * 89962306a36Sopenharmony_ci * Scans the @bi array for bindings and builds a buffer of SVGA3dSoTarget data. 90062306a36Sopenharmony_ci * Stops at the first non-existing binding in the @bi array. 90162306a36Sopenharmony_ci * On output, @cbs->bind_cmd_count contains the number of bindings to be 90262306a36Sopenharmony_ci * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer 90362306a36Sopenharmony_ci * contains the command data. 90462306a36Sopenharmony_ci */ 90562306a36Sopenharmony_cistatic void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs, 90662306a36Sopenharmony_ci const struct vmw_ctx_bindinfo_so_target *biso, 90762306a36Sopenharmony_ci u32 max_num) 90862306a36Sopenharmony_ci{ 90962306a36Sopenharmony_ci unsigned long i; 91062306a36Sopenharmony_ci SVGA3dSoTarget *so_buffer = (SVGA3dSoTarget *) cbs->bind_cmd_buffer; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci cbs->bind_cmd_count = 0; 91362306a36Sopenharmony_ci cbs->bind_first_slot = 0; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci for (i = 0; i < max_num; ++i, ++biso, ++so_buffer, 91662306a36Sopenharmony_ci ++cbs->bind_cmd_count) { 91762306a36Sopenharmony_ci if (!biso->bi.ctx) 91862306a36Sopenharmony_ci break; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci if (!biso->bi.scrubbed) { 92162306a36Sopenharmony_ci so_buffer->sid = biso->bi.res->id; 92262306a36Sopenharmony_ci so_buffer->offset = biso->offset; 92362306a36Sopenharmony_ci so_buffer->sizeInBytes = biso->size; 92462306a36Sopenharmony_ci } else { 92562306a36Sopenharmony_ci so_buffer->sid = SVGA3D_INVALID_ID; 92662306a36Sopenharmony_ci so_buffer->offset = 0; 92762306a36Sopenharmony_ci so_buffer->sizeInBytes = 0; 92862306a36Sopenharmony_ci } 92962306a36Sopenharmony_ci } 93062306a36Sopenharmony_ci} 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci/** 93362306a36Sopenharmony_ci * vmw_emit_set_so_target - Issue delayed streamout binding commands 93462306a36Sopenharmony_ci * 93562306a36Sopenharmony_ci * @cbs: Pointer to the context's struct vmw_ctx_binding_state 93662306a36Sopenharmony_ci */ 93762306a36Sopenharmony_cistatic int vmw_emit_set_so_target(struct vmw_ctx_binding_state *cbs) 93862306a36Sopenharmony_ci{ 93962306a36Sopenharmony_ci const struct vmw_ctx_bindinfo_so_target *loc = &cbs->so_targets[0]; 94062306a36Sopenharmony_ci struct { 94162306a36Sopenharmony_ci SVGA3dCmdHeader header; 94262306a36Sopenharmony_ci SVGA3dCmdDXSetSOTargets body; 94362306a36Sopenharmony_ci } *cmd; 94462306a36Sopenharmony_ci size_t cmd_size, so_target_size; 94562306a36Sopenharmony_ci const struct vmw_resource *ctx = vmw_cbs_context(cbs); 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci vmw_collect_so_targets(cbs, loc, SVGA3D_DX_MAX_SOTARGETS); 94862306a36Sopenharmony_ci if (cbs->bind_cmd_count == 0) 94962306a36Sopenharmony_ci return 0; 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci so_target_size = cbs->bind_cmd_count*sizeof(SVGA3dSoTarget); 95262306a36Sopenharmony_ci cmd_size = sizeof(*cmd) + so_target_size; 95362306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id); 95462306a36Sopenharmony_ci if (unlikely(cmd == NULL)) 95562306a36Sopenharmony_ci return -ENOMEM; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_SET_SOTARGETS; 95862306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body) + so_target_size; 95962306a36Sopenharmony_ci memcpy(&cmd[1], cbs->bind_cmd_buffer, so_target_size); 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci vmw_cmd_commit(ctx->dev_priv, cmd_size); 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci return 0; 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci} 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci/** 96862306a36Sopenharmony_ci * vmw_binding_emit_dirty_ps - Issue delayed per shader binding commands 96962306a36Sopenharmony_ci * 97062306a36Sopenharmony_ci * @cbs: Pointer to the context's struct vmw_ctx_binding_state 97162306a36Sopenharmony_ci * 97262306a36Sopenharmony_ci */ 97362306a36Sopenharmony_cistatic int vmw_binding_emit_dirty_ps(struct vmw_ctx_binding_state *cbs) 97462306a36Sopenharmony_ci{ 97562306a36Sopenharmony_ci struct vmw_dx_shader_bindings *sb = &cbs->per_shader[0]; 97662306a36Sopenharmony_ci u32 i; 97762306a36Sopenharmony_ci int ret; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci for (i = 0; i < SVGA3D_NUM_SHADERTYPE_DX10; ++i, ++sb) { 98062306a36Sopenharmony_ci if (!test_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty)) 98162306a36Sopenharmony_ci continue; 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci ret = vmw_emit_set_sr(cbs, i); 98462306a36Sopenharmony_ci if (ret) 98562306a36Sopenharmony_ci break; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci __clear_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty); 98862306a36Sopenharmony_ci } 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_ci return 0; 99162306a36Sopenharmony_ci} 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci/** 99462306a36Sopenharmony_ci * vmw_collect_dirty_vbs - Build SVGA3dVertexBuffer data for a 99562306a36Sopenharmony_ci * SVGA3dCmdDXSetVertexBuffers command 99662306a36Sopenharmony_ci * 99762306a36Sopenharmony_ci * @cbs: Pointer to the context's struct vmw_ctx_binding_state 99862306a36Sopenharmony_ci * @bi: Pointer to where the binding info array is stored in @cbs 99962306a36Sopenharmony_ci * @dirty: Bitmap indicating which bindings need to be emitted. 100062306a36Sopenharmony_ci * @max_num: Maximum number of entries in the @bi array. 100162306a36Sopenharmony_ci * 100262306a36Sopenharmony_ci * Scans the @bi array for bindings that need to be emitted and 100362306a36Sopenharmony_ci * builds a buffer of SVGA3dVertexBuffer data. 100462306a36Sopenharmony_ci * On output, @cbs->bind_cmd_count contains the number of bindings to be 100562306a36Sopenharmony_ci * emitted, @cbs->bind_first_slot indicates the index of the first emitted 100662306a36Sopenharmony_ci * binding, and @cbs->bind_cmd_buffer contains the command data. 100762306a36Sopenharmony_ci */ 100862306a36Sopenharmony_cistatic void vmw_collect_dirty_vbs(struct vmw_ctx_binding_state *cbs, 100962306a36Sopenharmony_ci const struct vmw_ctx_bindinfo *bi, 101062306a36Sopenharmony_ci unsigned long *dirty, 101162306a36Sopenharmony_ci u32 max_num) 101262306a36Sopenharmony_ci{ 101362306a36Sopenharmony_ci const struct vmw_ctx_bindinfo_vb *biv = 101462306a36Sopenharmony_ci container_of(bi, struct vmw_ctx_bindinfo_vb, bi); 101562306a36Sopenharmony_ci unsigned long i, next_bit; 101662306a36Sopenharmony_ci SVGA3dVertexBuffer *vbs = (SVGA3dVertexBuffer *) &cbs->bind_cmd_buffer; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci cbs->bind_cmd_count = 0; 101962306a36Sopenharmony_ci i = find_first_bit(dirty, max_num); 102062306a36Sopenharmony_ci next_bit = i; 102162306a36Sopenharmony_ci cbs->bind_first_slot = i; 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci biv += i; 102462306a36Sopenharmony_ci for (; i < max_num; ++i, ++biv, ++vbs) { 102562306a36Sopenharmony_ci if (!biv->bi.ctx || biv->bi.scrubbed) { 102662306a36Sopenharmony_ci vbs->sid = SVGA3D_INVALID_ID; 102762306a36Sopenharmony_ci vbs->stride = 0; 102862306a36Sopenharmony_ci vbs->offset = 0; 102962306a36Sopenharmony_ci } else { 103062306a36Sopenharmony_ci vbs->sid = biv->bi.res->id; 103162306a36Sopenharmony_ci vbs->stride = biv->stride; 103262306a36Sopenharmony_ci vbs->offset = biv->offset; 103362306a36Sopenharmony_ci } 103462306a36Sopenharmony_ci cbs->bind_cmd_count++; 103562306a36Sopenharmony_ci if (next_bit == i) { 103662306a36Sopenharmony_ci next_bit = find_next_bit(dirty, max_num, i + 1); 103762306a36Sopenharmony_ci if (next_bit >= max_num) 103862306a36Sopenharmony_ci break; 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci } 104162306a36Sopenharmony_ci} 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci/** 104462306a36Sopenharmony_ci * vmw_emit_set_vb - Issue delayed vertex buffer binding commands 104562306a36Sopenharmony_ci * 104662306a36Sopenharmony_ci * @cbs: Pointer to the context's struct vmw_ctx_binding_state 104762306a36Sopenharmony_ci * 104862306a36Sopenharmony_ci */ 104962306a36Sopenharmony_cistatic int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs) 105062306a36Sopenharmony_ci{ 105162306a36Sopenharmony_ci const struct vmw_ctx_bindinfo *loc = 105262306a36Sopenharmony_ci &cbs->vertex_buffers[0].bi; 105362306a36Sopenharmony_ci struct { 105462306a36Sopenharmony_ci SVGA3dCmdHeader header; 105562306a36Sopenharmony_ci SVGA3dCmdDXSetVertexBuffers body; 105662306a36Sopenharmony_ci } *cmd; 105762306a36Sopenharmony_ci size_t cmd_size, set_vb_size; 105862306a36Sopenharmony_ci const struct vmw_resource *ctx = vmw_cbs_context(cbs); 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci vmw_collect_dirty_vbs(cbs, loc, cbs->dirty_vb, 106162306a36Sopenharmony_ci SVGA3D_DX_MAX_VERTEXBUFFERS); 106262306a36Sopenharmony_ci if (cbs->bind_cmd_count == 0) 106362306a36Sopenharmony_ci return 0; 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci set_vb_size = cbs->bind_cmd_count*sizeof(SVGA3dVertexBuffer); 106662306a36Sopenharmony_ci cmd_size = sizeof(*cmd) + set_vb_size; 106762306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id); 106862306a36Sopenharmony_ci if (unlikely(cmd == NULL)) 106962306a36Sopenharmony_ci return -ENOMEM; 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS; 107262306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body) + set_vb_size; 107362306a36Sopenharmony_ci cmd->body.startBuffer = cbs->bind_first_slot; 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci memcpy(&cmd[1], cbs->bind_cmd_buffer, set_vb_size); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci vmw_cmd_commit(ctx->dev_priv, cmd_size); 107862306a36Sopenharmony_ci bitmap_clear(cbs->dirty_vb, 107962306a36Sopenharmony_ci cbs->bind_first_slot, cbs->bind_cmd_count); 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci return 0; 108262306a36Sopenharmony_ci} 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_cistatic int vmw_emit_set_uav(struct vmw_ctx_binding_state *cbs) 108562306a36Sopenharmony_ci{ 108662306a36Sopenharmony_ci const struct vmw_ctx_bindinfo_view *loc = &cbs->ua_views[0].views[0]; 108762306a36Sopenharmony_ci struct { 108862306a36Sopenharmony_ci SVGA3dCmdHeader header; 108962306a36Sopenharmony_ci SVGA3dCmdDXSetUAViews body; 109062306a36Sopenharmony_ci } *cmd; 109162306a36Sopenharmony_ci size_t cmd_size, view_id_size; 109262306a36Sopenharmony_ci const struct vmw_resource *ctx = vmw_cbs_context(cbs); 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci vmw_collect_view_ids(cbs, loc, vmw_max_num_uavs(cbs->dev_priv)); 109562306a36Sopenharmony_ci view_id_size = cbs->bind_cmd_count*sizeof(uint32); 109662306a36Sopenharmony_ci cmd_size = sizeof(*cmd) + view_id_size; 109762306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id); 109862306a36Sopenharmony_ci if (!cmd) 109962306a36Sopenharmony_ci return -ENOMEM; 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_SET_UA_VIEWS; 110262306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body) + view_id_size; 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci /* Splice index is specified user-space */ 110562306a36Sopenharmony_ci cmd->body.uavSpliceIndex = cbs->ua_views[0].index; 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_ci memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size); 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci vmw_cmd_commit(ctx->dev_priv, cmd_size); 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci return 0; 111262306a36Sopenharmony_ci} 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_cistatic int vmw_emit_set_cs_uav(struct vmw_ctx_binding_state *cbs) 111562306a36Sopenharmony_ci{ 111662306a36Sopenharmony_ci const struct vmw_ctx_bindinfo_view *loc = &cbs->ua_views[1].views[0]; 111762306a36Sopenharmony_ci struct { 111862306a36Sopenharmony_ci SVGA3dCmdHeader header; 111962306a36Sopenharmony_ci SVGA3dCmdDXSetCSUAViews body; 112062306a36Sopenharmony_ci } *cmd; 112162306a36Sopenharmony_ci size_t cmd_size, view_id_size; 112262306a36Sopenharmony_ci const struct vmw_resource *ctx = vmw_cbs_context(cbs); 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci vmw_collect_view_ids(cbs, loc, vmw_max_num_uavs(cbs->dev_priv)); 112562306a36Sopenharmony_ci view_id_size = cbs->bind_cmd_count*sizeof(uint32); 112662306a36Sopenharmony_ci cmd_size = sizeof(*cmd) + view_id_size; 112762306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id); 112862306a36Sopenharmony_ci if (!cmd) 112962306a36Sopenharmony_ci return -ENOMEM; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_SET_CS_UA_VIEWS; 113262306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body) + view_id_size; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci /* Start index is specified user-space */ 113562306a36Sopenharmony_ci cmd->body.startIndex = cbs->ua_views[1].index; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size); 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci vmw_cmd_commit(ctx->dev_priv, cmd_size); 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci return 0; 114262306a36Sopenharmony_ci} 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci/** 114562306a36Sopenharmony_ci * vmw_binding_emit_dirty - Issue delayed binding commands 114662306a36Sopenharmony_ci * 114762306a36Sopenharmony_ci * @cbs: Pointer to the context's struct vmw_ctx_binding_state 114862306a36Sopenharmony_ci * 114962306a36Sopenharmony_ci * This function issues the delayed binding commands that arise from 115062306a36Sopenharmony_ci * previous scrub / unscrub calls. These binding commands are typically 115162306a36Sopenharmony_ci * commands that batch a number of bindings and therefore it makes sense 115262306a36Sopenharmony_ci * to delay them. 115362306a36Sopenharmony_ci */ 115462306a36Sopenharmony_cistatic int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs) 115562306a36Sopenharmony_ci{ 115662306a36Sopenharmony_ci int ret = 0; 115762306a36Sopenharmony_ci unsigned long hit = 0; 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci while ((hit = find_next_bit(&cbs->dirty, VMW_BINDING_NUM_BITS, hit)) 116062306a36Sopenharmony_ci < VMW_BINDING_NUM_BITS) { 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci switch (hit) { 116362306a36Sopenharmony_ci case VMW_BINDING_RT_BIT: 116462306a36Sopenharmony_ci ret = vmw_emit_set_rt(cbs); 116562306a36Sopenharmony_ci break; 116662306a36Sopenharmony_ci case VMW_BINDING_PS_BIT: 116762306a36Sopenharmony_ci ret = vmw_binding_emit_dirty_ps(cbs); 116862306a36Sopenharmony_ci break; 116962306a36Sopenharmony_ci case VMW_BINDING_SO_T_BIT: 117062306a36Sopenharmony_ci ret = vmw_emit_set_so_target(cbs); 117162306a36Sopenharmony_ci break; 117262306a36Sopenharmony_ci case VMW_BINDING_VB_BIT: 117362306a36Sopenharmony_ci ret = vmw_emit_set_vb(cbs); 117462306a36Sopenharmony_ci break; 117562306a36Sopenharmony_ci case VMW_BINDING_UAV_BIT: 117662306a36Sopenharmony_ci ret = vmw_emit_set_uav(cbs); 117762306a36Sopenharmony_ci break; 117862306a36Sopenharmony_ci case VMW_BINDING_CS_UAV_BIT: 117962306a36Sopenharmony_ci ret = vmw_emit_set_cs_uav(cbs); 118062306a36Sopenharmony_ci break; 118162306a36Sopenharmony_ci default: 118262306a36Sopenharmony_ci BUG(); 118362306a36Sopenharmony_ci } 118462306a36Sopenharmony_ci if (ret) 118562306a36Sopenharmony_ci return ret; 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci __clear_bit(hit, &cbs->dirty); 118862306a36Sopenharmony_ci hit++; 118962306a36Sopenharmony_ci } 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci return 0; 119262306a36Sopenharmony_ci} 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci/** 119562306a36Sopenharmony_ci * vmw_binding_scrub_sr - Schedule a dx shaderresource binding 119662306a36Sopenharmony_ci * scrub from a context 119762306a36Sopenharmony_ci * 119862306a36Sopenharmony_ci * @bi: single binding information. 119962306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 120062306a36Sopenharmony_ci */ 120162306a36Sopenharmony_cistatic int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind) 120262306a36Sopenharmony_ci{ 120362306a36Sopenharmony_ci struct vmw_ctx_bindinfo_view *biv = 120462306a36Sopenharmony_ci container_of(bi, struct vmw_ctx_bindinfo_view, bi); 120562306a36Sopenharmony_ci struct vmw_ctx_binding_state *cbs = 120662306a36Sopenharmony_ci vmw_context_binding_state(bi->ctx); 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci __set_bit(biv->slot, cbs->per_shader[biv->shader_slot].dirty_sr); 120962306a36Sopenharmony_ci __set_bit(VMW_BINDING_PS_SR_BIT, 121062306a36Sopenharmony_ci &cbs->per_shader[biv->shader_slot].dirty); 121162306a36Sopenharmony_ci __set_bit(VMW_BINDING_PS_BIT, &cbs->dirty); 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci return 0; 121462306a36Sopenharmony_ci} 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci/** 121762306a36Sopenharmony_ci * vmw_binding_scrub_dx_rt - Schedule a dx rendertarget binding 121862306a36Sopenharmony_ci * scrub from a context 121962306a36Sopenharmony_ci * 122062306a36Sopenharmony_ci * @bi: single binding information. 122162306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 122262306a36Sopenharmony_ci */ 122362306a36Sopenharmony_cistatic int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind) 122462306a36Sopenharmony_ci{ 122562306a36Sopenharmony_ci struct vmw_ctx_binding_state *cbs = 122662306a36Sopenharmony_ci vmw_context_binding_state(bi->ctx); 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci __set_bit(VMW_BINDING_RT_BIT, &cbs->dirty); 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci return 0; 123162306a36Sopenharmony_ci} 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci/** 123462306a36Sopenharmony_ci * vmw_binding_scrub_so_target - Schedule a dx streamoutput buffer binding 123562306a36Sopenharmony_ci * scrub from a context 123662306a36Sopenharmony_ci * 123762306a36Sopenharmony_ci * @bi: single binding information. 123862306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 123962306a36Sopenharmony_ci */ 124062306a36Sopenharmony_cistatic int vmw_binding_scrub_so_target(struct vmw_ctx_bindinfo *bi, bool rebind) 124162306a36Sopenharmony_ci{ 124262306a36Sopenharmony_ci struct vmw_ctx_binding_state *cbs = 124362306a36Sopenharmony_ci vmw_context_binding_state(bi->ctx); 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci __set_bit(VMW_BINDING_SO_T_BIT, &cbs->dirty); 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci return 0; 124862306a36Sopenharmony_ci} 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci/** 125162306a36Sopenharmony_ci * vmw_binding_scrub_vb - Schedule a dx vertex buffer binding 125262306a36Sopenharmony_ci * scrub from a context 125362306a36Sopenharmony_ci * 125462306a36Sopenharmony_ci * @bi: single binding information. 125562306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 125662306a36Sopenharmony_ci */ 125762306a36Sopenharmony_cistatic int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind) 125862306a36Sopenharmony_ci{ 125962306a36Sopenharmony_ci struct vmw_ctx_bindinfo_vb *bivb = 126062306a36Sopenharmony_ci container_of(bi, struct vmw_ctx_bindinfo_vb, bi); 126162306a36Sopenharmony_ci struct vmw_ctx_binding_state *cbs = 126262306a36Sopenharmony_ci vmw_context_binding_state(bi->ctx); 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci __set_bit(bivb->slot, cbs->dirty_vb); 126562306a36Sopenharmony_ci __set_bit(VMW_BINDING_VB_BIT, &cbs->dirty); 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci return 0; 126862306a36Sopenharmony_ci} 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci/** 127162306a36Sopenharmony_ci * vmw_binding_scrub_ib - scrub a dx index buffer binding from a context 127262306a36Sopenharmony_ci * 127362306a36Sopenharmony_ci * @bi: single binding information. 127462306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 127562306a36Sopenharmony_ci */ 127662306a36Sopenharmony_cistatic int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind) 127762306a36Sopenharmony_ci{ 127862306a36Sopenharmony_ci struct vmw_ctx_bindinfo_ib *binding = 127962306a36Sopenharmony_ci container_of(bi, typeof(*binding), bi); 128062306a36Sopenharmony_ci struct vmw_private *dev_priv = bi->ctx->dev_priv; 128162306a36Sopenharmony_ci struct { 128262306a36Sopenharmony_ci SVGA3dCmdHeader header; 128362306a36Sopenharmony_ci SVGA3dCmdDXSetIndexBuffer body; 128462306a36Sopenharmony_ci } *cmd; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), bi->ctx->id); 128762306a36Sopenharmony_ci if (unlikely(cmd == NULL)) 128862306a36Sopenharmony_ci return -ENOMEM; 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_SET_INDEX_BUFFER; 129162306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 129262306a36Sopenharmony_ci if (rebind) { 129362306a36Sopenharmony_ci cmd->body.sid = bi->res->id; 129462306a36Sopenharmony_ci cmd->body.format = binding->format; 129562306a36Sopenharmony_ci cmd->body.offset = binding->offset; 129662306a36Sopenharmony_ci } else { 129762306a36Sopenharmony_ci cmd->body.sid = SVGA3D_INVALID_ID; 129862306a36Sopenharmony_ci cmd->body.format = 0; 129962306a36Sopenharmony_ci cmd->body.offset = 0; 130062306a36Sopenharmony_ci } 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci vmw_cmd_commit(dev_priv, sizeof(*cmd)); 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_ci return 0; 130562306a36Sopenharmony_ci} 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_cistatic int vmw_binding_scrub_uav(struct vmw_ctx_bindinfo *bi, bool rebind) 130862306a36Sopenharmony_ci{ 130962306a36Sopenharmony_ci struct vmw_ctx_binding_state *cbs = vmw_context_binding_state(bi->ctx); 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci __set_bit(VMW_BINDING_UAV_BIT, &cbs->dirty); 131262306a36Sopenharmony_ci return 0; 131362306a36Sopenharmony_ci} 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_cistatic int vmw_binding_scrub_cs_uav(struct vmw_ctx_bindinfo *bi, bool rebind) 131662306a36Sopenharmony_ci{ 131762306a36Sopenharmony_ci struct vmw_ctx_binding_state *cbs = vmw_context_binding_state(bi->ctx); 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci __set_bit(VMW_BINDING_CS_UAV_BIT, &cbs->dirty); 132062306a36Sopenharmony_ci return 0; 132162306a36Sopenharmony_ci} 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ci/** 132462306a36Sopenharmony_ci * vmw_binding_scrub_so - Scrub a streamoutput binding from context. 132562306a36Sopenharmony_ci * @bi: Single binding information. 132662306a36Sopenharmony_ci * @rebind: Whether to issue a bind instead of scrub command. 132762306a36Sopenharmony_ci */ 132862306a36Sopenharmony_cistatic int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind) 132962306a36Sopenharmony_ci{ 133062306a36Sopenharmony_ci struct vmw_ctx_bindinfo_so *binding = 133162306a36Sopenharmony_ci container_of(bi, typeof(*binding), bi); 133262306a36Sopenharmony_ci struct vmw_private *dev_priv = bi->ctx->dev_priv; 133362306a36Sopenharmony_ci struct { 133462306a36Sopenharmony_ci SVGA3dCmdHeader header; 133562306a36Sopenharmony_ci SVGA3dCmdDXSetStreamOutput body; 133662306a36Sopenharmony_ci } *cmd; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), bi->ctx->id); 133962306a36Sopenharmony_ci if (!cmd) 134062306a36Sopenharmony_ci return -ENOMEM; 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci cmd->header.id = SVGA_3D_CMD_DX_SET_STREAMOUTPUT; 134362306a36Sopenharmony_ci cmd->header.size = sizeof(cmd->body); 134462306a36Sopenharmony_ci cmd->body.soid = rebind ? bi->res->id : SVGA3D_INVALID_ID; 134562306a36Sopenharmony_ci vmw_cmd_commit(dev_priv, sizeof(*cmd)); 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci return 0; 134862306a36Sopenharmony_ci} 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci/** 135162306a36Sopenharmony_ci * vmw_binding_state_alloc - Allocate a struct vmw_ctx_binding_state. 135262306a36Sopenharmony_ci * 135362306a36Sopenharmony_ci * @dev_priv: Pointer to a device private structure. 135462306a36Sopenharmony_ci * 135562306a36Sopenharmony_ci * Returns a pointer to a newly allocated struct or an error pointer on error. 135662306a36Sopenharmony_ci */ 135762306a36Sopenharmony_cistruct vmw_ctx_binding_state * 135862306a36Sopenharmony_civmw_binding_state_alloc(struct vmw_private *dev_priv) 135962306a36Sopenharmony_ci{ 136062306a36Sopenharmony_ci struct vmw_ctx_binding_state *cbs; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci cbs = vzalloc(sizeof(*cbs)); 136362306a36Sopenharmony_ci if (!cbs) { 136462306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 136562306a36Sopenharmony_ci } 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci cbs->dev_priv = dev_priv; 136862306a36Sopenharmony_ci INIT_LIST_HEAD(&cbs->list); 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci return cbs; 137162306a36Sopenharmony_ci} 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci/** 137462306a36Sopenharmony_ci * vmw_binding_state_free - Free a struct vmw_ctx_binding_state. 137562306a36Sopenharmony_ci * 137662306a36Sopenharmony_ci * @cbs: Pointer to the struct vmw_ctx_binding_state to be freed. 137762306a36Sopenharmony_ci */ 137862306a36Sopenharmony_civoid vmw_binding_state_free(struct vmw_ctx_binding_state *cbs) 137962306a36Sopenharmony_ci{ 138062306a36Sopenharmony_ci vfree(cbs); 138162306a36Sopenharmony_ci} 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci/** 138462306a36Sopenharmony_ci * vmw_binding_state_list - Get the binding list of a 138562306a36Sopenharmony_ci * struct vmw_ctx_binding_state 138662306a36Sopenharmony_ci * 138762306a36Sopenharmony_ci * @cbs: Pointer to the struct vmw_ctx_binding_state 138862306a36Sopenharmony_ci * 138962306a36Sopenharmony_ci * Returns the binding list which can be used to traverse through the bindings 139062306a36Sopenharmony_ci * and access the resource information of all bindings. 139162306a36Sopenharmony_ci */ 139262306a36Sopenharmony_cistruct list_head *vmw_binding_state_list(struct vmw_ctx_binding_state *cbs) 139362306a36Sopenharmony_ci{ 139462306a36Sopenharmony_ci return &cbs->list; 139562306a36Sopenharmony_ci} 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci/** 139862306a36Sopenharmony_ci * vmw_binding_state_reset - clear a struct vmw_ctx_binding_state 139962306a36Sopenharmony_ci * 140062306a36Sopenharmony_ci * @cbs: Pointer to the struct vmw_ctx_binding_state to be cleared 140162306a36Sopenharmony_ci * 140262306a36Sopenharmony_ci * Drops all bindings registered in @cbs. No device binding actions are 140362306a36Sopenharmony_ci * performed. 140462306a36Sopenharmony_ci */ 140562306a36Sopenharmony_civoid vmw_binding_state_reset(struct vmw_ctx_binding_state *cbs) 140662306a36Sopenharmony_ci{ 140762306a36Sopenharmony_ci struct vmw_ctx_bindinfo *entry, *next; 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci list_for_each_entry_safe(entry, next, &cbs->list, ctx_list) 141062306a36Sopenharmony_ci vmw_binding_drop(entry); 141162306a36Sopenharmony_ci} 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci/** 141462306a36Sopenharmony_ci * vmw_binding_dirtying - Return whether a binding type is dirtying its resource 141562306a36Sopenharmony_ci * @binding_type: The binding type 141662306a36Sopenharmony_ci * 141762306a36Sopenharmony_ci * Each time a resource is put on the validation list as the result of a 141862306a36Sopenharmony_ci * context binding referencing it, we need to determine whether that resource 141962306a36Sopenharmony_ci * will be dirtied (written to by the GPU) as a result of the corresponding 142062306a36Sopenharmony_ci * GPU operation. Currently rendertarget-, depth-stencil-, stream-output-target 142162306a36Sopenharmony_ci * and unordered access view bindings are capable of dirtying its resource. 142262306a36Sopenharmony_ci * 142362306a36Sopenharmony_ci * Return: Whether the binding type dirties the resource its binding points to. 142462306a36Sopenharmony_ci */ 142562306a36Sopenharmony_ciu32 vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type) 142662306a36Sopenharmony_ci{ 142762306a36Sopenharmony_ci static u32 is_binding_dirtying[vmw_ctx_binding_max] = { 142862306a36Sopenharmony_ci [vmw_ctx_binding_rt] = VMW_RES_DIRTY_SET, 142962306a36Sopenharmony_ci [vmw_ctx_binding_dx_rt] = VMW_RES_DIRTY_SET, 143062306a36Sopenharmony_ci [vmw_ctx_binding_ds] = VMW_RES_DIRTY_SET, 143162306a36Sopenharmony_ci [vmw_ctx_binding_so_target] = VMW_RES_DIRTY_SET, 143262306a36Sopenharmony_ci [vmw_ctx_binding_uav] = VMW_RES_DIRTY_SET, 143362306a36Sopenharmony_ci [vmw_ctx_binding_cs_uav] = VMW_RES_DIRTY_SET, 143462306a36Sopenharmony_ci }; 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci /* Review this function as new bindings are added. */ 143762306a36Sopenharmony_ci BUILD_BUG_ON(vmw_ctx_binding_max != 14); 143862306a36Sopenharmony_ci return is_binding_dirtying[binding_type]; 143962306a36Sopenharmony_ci} 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci/* 144262306a36Sopenharmony_ci * This function is unused at run-time, and only used to hold various build 144362306a36Sopenharmony_ci * asserts important for code optimization assumptions. 144462306a36Sopenharmony_ci */ 144562306a36Sopenharmony_cistatic void vmw_binding_build_asserts(void) 144662306a36Sopenharmony_ci{ 144762306a36Sopenharmony_ci BUILD_BUG_ON(SVGA3D_NUM_SHADERTYPE_DX10 != 3); 144862306a36Sopenharmony_ci BUILD_BUG_ON(SVGA3D_DX_MAX_RENDER_TARGETS > SVGA3D_RT_MAX); 144962306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(uint32) != sizeof(u32)); 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci /* 145262306a36Sopenharmony_ci * struct vmw_ctx_binding_state::bind_cmd_buffer is used for various 145362306a36Sopenharmony_ci * view id arrays. 145462306a36Sopenharmony_ci */ 145562306a36Sopenharmony_ci BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_RT_MAX); 145662306a36Sopenharmony_ci BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_SRVIEWS); 145762306a36Sopenharmony_ci BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_CONSTBUFFERS); 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_ci /* 146062306a36Sopenharmony_ci * struct vmw_ctx_binding_state::bind_cmd_buffer is used for 146162306a36Sopenharmony_ci * u32 view ids, SVGA3dSoTargets and SVGA3dVertexBuffers 146262306a36Sopenharmony_ci */ 146362306a36Sopenharmony_ci BUILD_BUG_ON(SVGA3D_DX_MAX_SOTARGETS*sizeof(SVGA3dSoTarget) > 146462306a36Sopenharmony_ci VMW_MAX_VIEW_BINDINGS*sizeof(u32)); 146562306a36Sopenharmony_ci BUILD_BUG_ON(SVGA3D_DX_MAX_VERTEXBUFFERS*sizeof(SVGA3dVertexBuffer) > 146662306a36Sopenharmony_ci VMW_MAX_VIEW_BINDINGS*sizeof(u32)); 146762306a36Sopenharmony_ci} 1468