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
60403fef50SDeepak Rawat #define VMW_BINDING_SO_T_BIT   2
61d80efd5cSThomas Hellstrom #define VMW_BINDING_VB_BIT     3
625e8ec0d9SDeepak Rawat #define VMW_BINDING_UAV_BIT    4
635e8ec0d9SDeepak Rawat #define VMW_BINDING_CS_UAV_BIT 5
645e8ec0d9SDeepak Rawat #define VMW_BINDING_NUM_BITS   6
65d80efd5cSThomas Hellstrom 
66d80efd5cSThomas Hellstrom #define VMW_BINDING_PS_SR_BIT  0
67d80efd5cSThomas Hellstrom 
68d80efd5cSThomas Hellstrom /**
69d80efd5cSThomas Hellstrom  * struct vmw_ctx_binding_state - per context binding state
70d80efd5cSThomas Hellstrom  *
71d80efd5cSThomas Hellstrom  * @dev_priv: Pointer to device private structure.
72d80efd5cSThomas Hellstrom  * @list: linked list of individual active bindings.
73d80efd5cSThomas Hellstrom  * @render_targets: Render target bindings.
74d80efd5cSThomas Hellstrom  * @texture_units: Texture units bindings.
75d80efd5cSThomas Hellstrom  * @ds_view: Depth-stencil view binding.
76d80efd5cSThomas Hellstrom  * @so_targets: StreamOutput target bindings.
77d80efd5cSThomas Hellstrom  * @vertex_buffers: Vertex buffer bindings.
78d80efd5cSThomas Hellstrom  * @index_buffer: Index buffer binding.
79d80efd5cSThomas Hellstrom  * @per_shader: Per shader-type bindings.
805e8ec0d9SDeepak Rawat  * @ua_views: UAV bindings.
81e8bead9cSDeepak Rawat  * @so_state: StreamOutput bindings.
82d80efd5cSThomas Hellstrom  * @dirty: Bitmap tracking per binding-type changes that have not yet
83d80efd5cSThomas Hellstrom  * been emitted to the device.
84d80efd5cSThomas Hellstrom  * @dirty_vb: Bitmap tracking individual vertex buffer binding changes that
85d80efd5cSThomas Hellstrom  * have not yet been emitted to the device.
86d80efd5cSThomas Hellstrom  * @bind_cmd_buffer: Scratch space used to construct binding commands.
87d80efd5cSThomas Hellstrom  * @bind_cmd_count: Number of binding command data entries in @bind_cmd_buffer
88d80efd5cSThomas Hellstrom  * @bind_first_slot: Used together with @bind_cmd_buffer to indicate the
89d80efd5cSThomas Hellstrom  * device binding slot of the first command data entry in @bind_cmd_buffer.
90d80efd5cSThomas Hellstrom  *
91d80efd5cSThomas Hellstrom  * Note that this structure also provides storage space for the individual
92d80efd5cSThomas Hellstrom  * struct vmw_ctx_binding objects, so that no dynamic allocation is needed
93d80efd5cSThomas Hellstrom  * for individual bindings.
94d80efd5cSThomas Hellstrom  *
95d80efd5cSThomas Hellstrom  */
96d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state {
97d80efd5cSThomas Hellstrom 	struct vmw_private *dev_priv;
98d80efd5cSThomas Hellstrom 	struct list_head list;
99d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_view render_targets[SVGA3D_RT_MAX];
100d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_tex texture_units[SVGA3D_NUM_TEXTURE_UNITS];
101d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_view ds_view;
102403fef50SDeepak Rawat 	struct vmw_ctx_bindinfo_so_target so_targets[SVGA3D_DX_MAX_SOTARGETS];
103d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_vb vertex_buffers[SVGA3D_DX_MAX_VERTEXBUFFERS];
104d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_ib index_buffer;
105d2e90ab3SDeepak Rawat 	struct vmw_dx_shader_bindings per_shader[SVGA3D_NUM_SHADERTYPE];
1065e8ec0d9SDeepak Rawat 	struct vmw_ctx_bindinfo_uav ua_views[VMW_MAX_UAV_BIND_TYPE];
107e8bead9cSDeepak Rawat 	struct vmw_ctx_bindinfo_so so_state;
108d80efd5cSThomas Hellstrom 
109d80efd5cSThomas Hellstrom 	unsigned long dirty;
110d80efd5cSThomas Hellstrom 	DECLARE_BITMAP(dirty_vb, SVGA3D_DX_MAX_VERTEXBUFFERS);
111d80efd5cSThomas Hellstrom 
112d80efd5cSThomas Hellstrom 	u32 bind_cmd_buffer[VMW_MAX_VIEW_BINDINGS];
113d80efd5cSThomas Hellstrom 	u32 bind_cmd_count;
114d80efd5cSThomas Hellstrom 	u32 bind_first_slot;
115d80efd5cSThomas Hellstrom };
116d80efd5cSThomas Hellstrom 
117d80efd5cSThomas Hellstrom static int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind);
118d80efd5cSThomas Hellstrom static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi,
119d80efd5cSThomas Hellstrom 					   bool rebind);
120d80efd5cSThomas Hellstrom static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi, bool rebind);
121d80efd5cSThomas Hellstrom static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind);
122d80efd5cSThomas Hellstrom static int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind);
123d80efd5cSThomas Hellstrom static int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind);
124403fef50SDeepak Rawat static int vmw_binding_scrub_so_target(struct vmw_ctx_bindinfo *bi, bool rebind);
125d80efd5cSThomas Hellstrom static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs);
126d80efd5cSThomas Hellstrom static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi,
127d80efd5cSThomas Hellstrom 				       bool rebind);
128d80efd5cSThomas Hellstrom static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind);
129d80efd5cSThomas Hellstrom static int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind);
1305e8ec0d9SDeepak Rawat static int vmw_binding_scrub_uav(struct vmw_ctx_bindinfo *bi, bool rebind);
1315e8ec0d9SDeepak Rawat static int vmw_binding_scrub_cs_uav(struct vmw_ctx_bindinfo *bi, bool rebind);
132e8bead9cSDeepak Rawat static int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind);
1335e8ec0d9SDeepak Rawat 
134d80efd5cSThomas Hellstrom static void vmw_binding_build_asserts(void) __attribute__ ((unused));
135d80efd5cSThomas Hellstrom 
136d80efd5cSThomas Hellstrom typedef int (*vmw_scrub_func)(struct vmw_ctx_bindinfo *, bool);
137d80efd5cSThomas Hellstrom 
138d80efd5cSThomas Hellstrom /**
139d80efd5cSThomas Hellstrom  * struct vmw_binding_info - Per binding type information for the binding
140d80efd5cSThomas Hellstrom  * manager
141d80efd5cSThomas Hellstrom  *
142d80efd5cSThomas Hellstrom  * @size: The size of the struct binding derived from a struct vmw_ctx_bindinfo.
143d80efd5cSThomas Hellstrom  * @offsets: array[shader_slot] of offsets to the array[slot]
144d80efd5cSThomas Hellstrom  * of struct bindings for the binding type.
145d80efd5cSThomas Hellstrom  * @scrub_func: Pointer to the scrub function for this binding type.
146d80efd5cSThomas Hellstrom  *
147d80efd5cSThomas Hellstrom  * Holds static information to help optimize the binding manager and avoid
148d80efd5cSThomas Hellstrom  * an excessive amount of switch statements.
149d80efd5cSThomas Hellstrom  */
150d80efd5cSThomas Hellstrom struct vmw_binding_info {
151d80efd5cSThomas Hellstrom 	size_t size;
152d80efd5cSThomas Hellstrom 	const size_t *offsets;
153d80efd5cSThomas Hellstrom 	vmw_scrub_func scrub_func;
154d80efd5cSThomas Hellstrom };
155d80efd5cSThomas Hellstrom 
156d80efd5cSThomas Hellstrom /*
157d80efd5cSThomas Hellstrom  * A number of static variables that help determine the scrub func and the
158d80efd5cSThomas Hellstrom  * location of the struct vmw_ctx_bindinfo slots for each binding type.
159d80efd5cSThomas Hellstrom  */
160d80efd5cSThomas Hellstrom static const size_t vmw_binding_shader_offsets[] = {
161d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, per_shader[0].shader),
162d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, per_shader[1].shader),
163d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, per_shader[2].shader),
164d2e90ab3SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, per_shader[3].shader),
165d2e90ab3SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, per_shader[4].shader),
166d2e90ab3SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, per_shader[5].shader),
167d80efd5cSThomas Hellstrom };
168d80efd5cSThomas Hellstrom static const size_t vmw_binding_rt_offsets[] = {
169d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, render_targets),
170d80efd5cSThomas Hellstrom };
171d80efd5cSThomas Hellstrom static const size_t vmw_binding_tex_offsets[] = {
172d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, texture_units),
173d80efd5cSThomas Hellstrom };
174d80efd5cSThomas Hellstrom static const size_t vmw_binding_cb_offsets[] = {
175d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, per_shader[0].const_buffers),
176d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, per_shader[1].const_buffers),
177d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, per_shader[2].const_buffers),
178d2e90ab3SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, per_shader[3].const_buffers),
179d2e90ab3SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, per_shader[4].const_buffers),
180d2e90ab3SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, per_shader[5].const_buffers),
181d80efd5cSThomas Hellstrom };
182d80efd5cSThomas Hellstrom static const size_t vmw_binding_dx_ds_offsets[] = {
183d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, ds_view),
184d80efd5cSThomas Hellstrom };
185d80efd5cSThomas Hellstrom static const size_t vmw_binding_sr_offsets[] = {
186d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, per_shader[0].shader_res),
187d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, per_shader[1].shader_res),
188d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, per_shader[2].shader_res),
189d2e90ab3SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, per_shader[3].shader_res),
190d2e90ab3SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, per_shader[4].shader_res),
191d2e90ab3SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, per_shader[5].shader_res),
192d80efd5cSThomas Hellstrom };
193403fef50SDeepak Rawat static const size_t vmw_binding_so_target_offsets[] = {
194d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, so_targets),
195d80efd5cSThomas Hellstrom };
196d80efd5cSThomas Hellstrom static const size_t vmw_binding_vb_offsets[] = {
197d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, vertex_buffers),
198d80efd5cSThomas Hellstrom };
199d80efd5cSThomas Hellstrom static const size_t vmw_binding_ib_offsets[] = {
200d80efd5cSThomas Hellstrom 	offsetof(struct vmw_ctx_binding_state, index_buffer),
201d80efd5cSThomas Hellstrom };
2025e8ec0d9SDeepak Rawat static const size_t vmw_binding_uav_offsets[] = {
2035e8ec0d9SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, ua_views[0].views),
2045e8ec0d9SDeepak Rawat };
2055e8ec0d9SDeepak Rawat static const size_t vmw_binding_cs_uav_offsets[] = {
2065e8ec0d9SDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, ua_views[1].views),
2075e8ec0d9SDeepak Rawat };
208e8bead9cSDeepak Rawat static const size_t vmw_binding_so_offsets[] = {
209e8bead9cSDeepak Rawat 	offsetof(struct vmw_ctx_binding_state, so_state),
210e8bead9cSDeepak Rawat };
211d80efd5cSThomas Hellstrom 
212d80efd5cSThomas Hellstrom static const struct vmw_binding_info vmw_binding_infos[] = {
213d80efd5cSThomas Hellstrom 	[vmw_ctx_binding_shader] = {
214d80efd5cSThomas Hellstrom 		.size = sizeof(struct vmw_ctx_bindinfo_shader),
215d80efd5cSThomas Hellstrom 		.offsets = vmw_binding_shader_offsets,
216d80efd5cSThomas Hellstrom 		.scrub_func = vmw_binding_scrub_shader},
217d80efd5cSThomas Hellstrom 	[vmw_ctx_binding_rt] = {
218d80efd5cSThomas Hellstrom 		.size = sizeof(struct vmw_ctx_bindinfo_view),
219d80efd5cSThomas Hellstrom 		.offsets = vmw_binding_rt_offsets,
220d80efd5cSThomas Hellstrom 		.scrub_func = vmw_binding_scrub_render_target},
221d80efd5cSThomas Hellstrom 	[vmw_ctx_binding_tex] = {
222d80efd5cSThomas Hellstrom 		.size = sizeof(struct vmw_ctx_bindinfo_tex),
223d80efd5cSThomas Hellstrom 		.offsets = vmw_binding_tex_offsets,
224d80efd5cSThomas Hellstrom 		.scrub_func = vmw_binding_scrub_texture},
225d80efd5cSThomas Hellstrom 	[vmw_ctx_binding_cb] = {
226d80efd5cSThomas Hellstrom 		.size = sizeof(struct vmw_ctx_bindinfo_cb),
227d80efd5cSThomas Hellstrom 		.offsets = vmw_binding_cb_offsets,
228d80efd5cSThomas Hellstrom 		.scrub_func = vmw_binding_scrub_cb},
229d80efd5cSThomas Hellstrom 	[vmw_ctx_binding_dx_shader] = {
230d80efd5cSThomas Hellstrom 		.size = sizeof(struct vmw_ctx_bindinfo_shader),
231d80efd5cSThomas Hellstrom 		.offsets = vmw_binding_shader_offsets,
232d80efd5cSThomas Hellstrom 		.scrub_func = vmw_binding_scrub_dx_shader},
233d80efd5cSThomas Hellstrom 	[vmw_ctx_binding_dx_rt] = {
234d80efd5cSThomas Hellstrom 		.size = sizeof(struct vmw_ctx_bindinfo_view),
235d80efd5cSThomas Hellstrom 		.offsets = vmw_binding_rt_offsets,
236d80efd5cSThomas Hellstrom 		.scrub_func = vmw_binding_scrub_dx_rt},
237d80efd5cSThomas Hellstrom 	[vmw_ctx_binding_sr] = {
238d80efd5cSThomas Hellstrom 		.size = sizeof(struct vmw_ctx_bindinfo_view),
239d80efd5cSThomas Hellstrom 		.offsets = vmw_binding_sr_offsets,
240d80efd5cSThomas Hellstrom 		.scrub_func = vmw_binding_scrub_sr},
241d80efd5cSThomas Hellstrom 	[vmw_ctx_binding_ds] = {
242d80efd5cSThomas Hellstrom 		.size = sizeof(struct vmw_ctx_bindinfo_view),
243d80efd5cSThomas Hellstrom 		.offsets = vmw_binding_dx_ds_offsets,
244d80efd5cSThomas Hellstrom 		.scrub_func = vmw_binding_scrub_dx_rt},
245403fef50SDeepak Rawat 	[vmw_ctx_binding_so_target] = {
246403fef50SDeepak Rawat 		.size = sizeof(struct vmw_ctx_bindinfo_so_target),
247403fef50SDeepak Rawat 		.offsets = vmw_binding_so_target_offsets,
248403fef50SDeepak Rawat 		.scrub_func = vmw_binding_scrub_so_target},
249d80efd5cSThomas Hellstrom 	[vmw_ctx_binding_vb] = {
250d80efd5cSThomas Hellstrom 		.size = sizeof(struct vmw_ctx_bindinfo_vb),
251d80efd5cSThomas Hellstrom 		.offsets = vmw_binding_vb_offsets,
252d80efd5cSThomas Hellstrom 		.scrub_func = vmw_binding_scrub_vb},
253d80efd5cSThomas Hellstrom 	[vmw_ctx_binding_ib] = {
254d80efd5cSThomas Hellstrom 		.size = sizeof(struct vmw_ctx_bindinfo_ib),
255d80efd5cSThomas Hellstrom 		.offsets = vmw_binding_ib_offsets,
256d80efd5cSThomas Hellstrom 		.scrub_func = vmw_binding_scrub_ib},
2575e8ec0d9SDeepak Rawat 	[vmw_ctx_binding_uav] = {
2585e8ec0d9SDeepak Rawat 		.size = sizeof(struct vmw_ctx_bindinfo_view),
2595e8ec0d9SDeepak Rawat 		.offsets = vmw_binding_uav_offsets,
2605e8ec0d9SDeepak Rawat 		.scrub_func = vmw_binding_scrub_uav},
2615e8ec0d9SDeepak Rawat 	[vmw_ctx_binding_cs_uav] = {
2625e8ec0d9SDeepak Rawat 		.size = sizeof(struct vmw_ctx_bindinfo_view),
2635e8ec0d9SDeepak Rawat 		.offsets = vmw_binding_cs_uav_offsets,
2645e8ec0d9SDeepak Rawat 		.scrub_func = vmw_binding_scrub_cs_uav},
265e8bead9cSDeepak Rawat 	[vmw_ctx_binding_so] = {
266e8bead9cSDeepak Rawat 		.size = sizeof(struct vmw_ctx_bindinfo_so),
267e8bead9cSDeepak Rawat 		.offsets = vmw_binding_so_offsets,
268e8bead9cSDeepak Rawat 		.scrub_func = vmw_binding_scrub_so},
269d80efd5cSThomas Hellstrom };
270d80efd5cSThomas Hellstrom 
271d80efd5cSThomas Hellstrom /**
272d80efd5cSThomas Hellstrom  * vmw_cbs_context - Return a pointer to the context resource of a
273d80efd5cSThomas Hellstrom  * context binding state tracker.
274d80efd5cSThomas Hellstrom  *
275d80efd5cSThomas Hellstrom  * @cbs: The context binding state tracker.
276d80efd5cSThomas Hellstrom  *
277d80efd5cSThomas Hellstrom  * Provided there are any active bindings, this function will return an
278d80efd5cSThomas Hellstrom  * unreferenced pointer to the context resource that owns the context
279d80efd5cSThomas Hellstrom  * binding state tracker. If there are no active bindings, this function
280d80efd5cSThomas Hellstrom  * will return NULL. Note that the caller must somehow ensure that a reference
281d80efd5cSThomas Hellstrom  * is held on the context resource prior to calling this function.
282d80efd5cSThomas Hellstrom  */
283d80efd5cSThomas Hellstrom static const struct vmw_resource *
vmw_cbs_context(const struct vmw_ctx_binding_state * cbs)284d80efd5cSThomas Hellstrom vmw_cbs_context(const struct vmw_ctx_binding_state *cbs)
285d80efd5cSThomas Hellstrom {
286d80efd5cSThomas Hellstrom 	if (list_empty(&cbs->list))
287d80efd5cSThomas Hellstrom 		return NULL;
288d80efd5cSThomas Hellstrom 
289d80efd5cSThomas Hellstrom 	return list_first_entry(&cbs->list, struct vmw_ctx_bindinfo,
290d80efd5cSThomas Hellstrom 				ctx_list)->ctx;
291d80efd5cSThomas Hellstrom }
292d80efd5cSThomas Hellstrom 
293d80efd5cSThomas Hellstrom /**
294d80efd5cSThomas Hellstrom  * vmw_binding_loc - determine the struct vmw_ctx_bindinfo slot location.
295d80efd5cSThomas Hellstrom  *
296d80efd5cSThomas Hellstrom  * @cbs: Pointer to a struct vmw_ctx_binding state which holds the slot.
297d80efd5cSThomas Hellstrom  * @bt: The binding type.
298d80efd5cSThomas Hellstrom  * @shader_slot: The shader slot of the binding. If none, then set to 0.
299d80efd5cSThomas Hellstrom  * @slot: The slot of the binding.
300d80efd5cSThomas Hellstrom  */
301d80efd5cSThomas Hellstrom static struct vmw_ctx_bindinfo *
vmw_binding_loc(struct vmw_ctx_binding_state * cbs,enum vmw_ctx_binding_type bt,u32 shader_slot,u32 slot)302d80efd5cSThomas Hellstrom vmw_binding_loc(struct vmw_ctx_binding_state *cbs,
303d80efd5cSThomas Hellstrom 		enum vmw_ctx_binding_type bt, u32 shader_slot, u32 slot)
304d80efd5cSThomas Hellstrom {
305d80efd5cSThomas Hellstrom 	const struct vmw_binding_info *b = &vmw_binding_infos[bt];
306d80efd5cSThomas Hellstrom 	size_t offset = b->offsets[shader_slot] + b->size*slot;
307d80efd5cSThomas Hellstrom 
308d80efd5cSThomas Hellstrom 	return (struct vmw_ctx_bindinfo *)((u8 *) cbs + offset);
309d80efd5cSThomas Hellstrom }
310d80efd5cSThomas Hellstrom 
311d80efd5cSThomas Hellstrom /**
312d80efd5cSThomas Hellstrom  * vmw_binding_drop: Stop tracking a context binding
313d80efd5cSThomas Hellstrom  *
314d80efd5cSThomas Hellstrom  * @bi: Pointer to binding tracker storage.
315d80efd5cSThomas Hellstrom  *
316d80efd5cSThomas Hellstrom  * Stops tracking a context binding, and re-initializes its storage.
317d80efd5cSThomas Hellstrom  * Typically used when the context binding is replaced with a binding to
318d80efd5cSThomas Hellstrom  * another (or the same, for that matter) resource.
319d80efd5cSThomas Hellstrom  */
vmw_binding_drop(struct vmw_ctx_bindinfo * bi)320d80efd5cSThomas Hellstrom static void vmw_binding_drop(struct vmw_ctx_bindinfo *bi)
321d80efd5cSThomas Hellstrom {
322d80efd5cSThomas Hellstrom 	list_del(&bi->ctx_list);
323d80efd5cSThomas Hellstrom 	if (!list_empty(&bi->res_list))
324d80efd5cSThomas Hellstrom 		list_del(&bi->res_list);
325d80efd5cSThomas Hellstrom 	bi->ctx = NULL;
326d80efd5cSThomas Hellstrom }
327d80efd5cSThomas Hellstrom 
328d80efd5cSThomas Hellstrom /**
329d80efd5cSThomas Hellstrom  * vmw_binding_add: Start tracking a context binding
330d80efd5cSThomas Hellstrom  *
331d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context binding state tracker.
332d80efd5cSThomas Hellstrom  * @bi: Information about the binding to track.
333e8fb41acSLee Jones  * @shader_slot: The shader slot of the binding.
334e8fb41acSLee Jones  * @slot: The slot of the binding.
335d80efd5cSThomas Hellstrom  *
336d80efd5cSThomas Hellstrom  * Starts tracking the binding in the context binding
337d80efd5cSThomas Hellstrom  * state structure @cbs.
338d80efd5cSThomas Hellstrom  */
vmw_binding_add(struct vmw_ctx_binding_state * cbs,const struct vmw_ctx_bindinfo * bi,u32 shader_slot,u32 slot)339d80efd5cSThomas Hellstrom void vmw_binding_add(struct vmw_ctx_binding_state *cbs,
340d80efd5cSThomas Hellstrom 		    const struct vmw_ctx_bindinfo *bi,
341d80efd5cSThomas Hellstrom 		    u32 shader_slot, u32 slot)
342d80efd5cSThomas Hellstrom {
343d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo *loc =
344d80efd5cSThomas Hellstrom 		vmw_binding_loc(cbs, bi->bt, shader_slot, slot);
345d80efd5cSThomas Hellstrom 	const struct vmw_binding_info *b = &vmw_binding_infos[bi->bt];
346d80efd5cSThomas Hellstrom 
347d80efd5cSThomas Hellstrom 	if (loc->ctx != NULL)
348d80efd5cSThomas Hellstrom 		vmw_binding_drop(loc);
349d80efd5cSThomas Hellstrom 
350d80efd5cSThomas Hellstrom 	memcpy(loc, bi, b->size);
351d80efd5cSThomas Hellstrom 	loc->scrubbed = false;
352d80efd5cSThomas Hellstrom 	list_add(&loc->ctx_list, &cbs->list);
353d80efd5cSThomas Hellstrom 	INIT_LIST_HEAD(&loc->res_list);
354d80efd5cSThomas Hellstrom }
355d80efd5cSThomas Hellstrom 
356d80efd5cSThomas Hellstrom /**
357*bf625870SRoland Scheidegger  * vmw_binding_cb_offset_update: Update the offset of a cb binding
358*bf625870SRoland Scheidegger  *
359*bf625870SRoland Scheidegger  * @cbs: Pointer to the context binding state tracker.
360*bf625870SRoland Scheidegger  * @shader_slot: The shader slot of the binding.
361*bf625870SRoland Scheidegger  * @slot: The slot of the binding.
362*bf625870SRoland Scheidegger  * @offsetInBytes: The new offset of the binding.
363*bf625870SRoland Scheidegger  *
364*bf625870SRoland Scheidegger  * Updates the offset of an existing cb binding in the context binding
365*bf625870SRoland Scheidegger  * state structure @cbs.
366*bf625870SRoland Scheidegger  */
vmw_binding_cb_offset_update(struct vmw_ctx_binding_state * cbs,u32 shader_slot,u32 slot,u32 offsetInBytes)367*bf625870SRoland Scheidegger void vmw_binding_cb_offset_update(struct vmw_ctx_binding_state *cbs,
368*bf625870SRoland Scheidegger 				  u32 shader_slot, u32 slot, u32 offsetInBytes)
369*bf625870SRoland Scheidegger {
370*bf625870SRoland Scheidegger 	struct vmw_ctx_bindinfo *loc =
371*bf625870SRoland Scheidegger 		vmw_binding_loc(cbs, vmw_ctx_binding_cb, shader_slot, slot);
372*bf625870SRoland Scheidegger 	struct vmw_ctx_bindinfo_cb *loc_cb =
373*bf625870SRoland Scheidegger 		(struct vmw_ctx_bindinfo_cb *)((u8 *) loc);
374*bf625870SRoland Scheidegger 	loc_cb->offset = offsetInBytes;
375*bf625870SRoland Scheidegger }
376*bf625870SRoland Scheidegger 
377*bf625870SRoland Scheidegger /**
3785e8ec0d9SDeepak Rawat  * vmw_binding_add_uav_index - Add UAV index for tracking.
3795e8ec0d9SDeepak Rawat  * @cbs: Pointer to the context binding state tracker.
3805e8ec0d9SDeepak Rawat  * @slot: UAV type to which bind this index.
3815e8ec0d9SDeepak Rawat  * @index: The splice index to track.
3825e8ec0d9SDeepak Rawat  */
vmw_binding_add_uav_index(struct vmw_ctx_binding_state * cbs,uint32 slot,uint32 index)3835e8ec0d9SDeepak Rawat void vmw_binding_add_uav_index(struct vmw_ctx_binding_state *cbs, uint32 slot,
3845e8ec0d9SDeepak Rawat 			       uint32 index)
3855e8ec0d9SDeepak Rawat {
3865e8ec0d9SDeepak Rawat 	cbs->ua_views[slot].index = index;
3875e8ec0d9SDeepak Rawat }
3885e8ec0d9SDeepak Rawat 
3895e8ec0d9SDeepak Rawat /**
390d80efd5cSThomas Hellstrom  * vmw_binding_transfer: Transfer a context binding tracking entry.
391d80efd5cSThomas Hellstrom  *
392d80efd5cSThomas Hellstrom  * @cbs: Pointer to the persistent context binding state tracker.
393e8fb41acSLee Jones  * @from: Staged binding info built during execbuf
394d80efd5cSThomas Hellstrom  * @bi: Information about the binding to track.
395d80efd5cSThomas Hellstrom  *
396d80efd5cSThomas Hellstrom  */
vmw_binding_transfer(struct vmw_ctx_binding_state * cbs,const struct vmw_ctx_binding_state * from,const struct vmw_ctx_bindinfo * bi)397d80efd5cSThomas Hellstrom static void vmw_binding_transfer(struct vmw_ctx_binding_state *cbs,
398d80efd5cSThomas Hellstrom 				 const struct vmw_ctx_binding_state *from,
399d80efd5cSThomas Hellstrom 				 const struct vmw_ctx_bindinfo *bi)
400d80efd5cSThomas Hellstrom {
401d80efd5cSThomas Hellstrom 	size_t offset = (unsigned long)bi - (unsigned long)from;
402d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo *loc = (struct vmw_ctx_bindinfo *)
403d80efd5cSThomas Hellstrom 		((unsigned long) cbs + offset);
404d80efd5cSThomas Hellstrom 
405d80efd5cSThomas Hellstrom 	if (loc->ctx != NULL) {
406d80efd5cSThomas Hellstrom 		WARN_ON(bi->scrubbed);
407d80efd5cSThomas Hellstrom 
408d80efd5cSThomas Hellstrom 		vmw_binding_drop(loc);
409d80efd5cSThomas Hellstrom 	}
410d80efd5cSThomas Hellstrom 
411d80efd5cSThomas Hellstrom 	if (bi->res != NULL) {
412d80efd5cSThomas Hellstrom 		memcpy(loc, bi, vmw_binding_infos[bi->bt].size);
413d80efd5cSThomas Hellstrom 		list_add_tail(&loc->ctx_list, &cbs->list);
414d80efd5cSThomas Hellstrom 		list_add_tail(&loc->res_list, &loc->res->binding_head);
415d80efd5cSThomas Hellstrom 	}
416d80efd5cSThomas Hellstrom }
417d80efd5cSThomas Hellstrom 
418d80efd5cSThomas Hellstrom /**
419d80efd5cSThomas Hellstrom  * vmw_binding_state_kill - Kill all bindings associated with a
420d80efd5cSThomas Hellstrom  * struct vmw_ctx_binding state structure, and re-initialize the structure.
421d80efd5cSThomas Hellstrom  *
422d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context binding state tracker.
423d80efd5cSThomas Hellstrom  *
424d80efd5cSThomas Hellstrom  * Emits commands to scrub all bindings associated with the
425d80efd5cSThomas Hellstrom  * context binding state tracker. Then re-initializes the whole structure.
426d80efd5cSThomas Hellstrom  */
vmw_binding_state_kill(struct vmw_ctx_binding_state * cbs)427d80efd5cSThomas Hellstrom void vmw_binding_state_kill(struct vmw_ctx_binding_state *cbs)
428d80efd5cSThomas Hellstrom {
429d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo *entry, *next;
430d80efd5cSThomas Hellstrom 
431d80efd5cSThomas Hellstrom 	vmw_binding_state_scrub(cbs);
432d80efd5cSThomas Hellstrom 	list_for_each_entry_safe(entry, next, &cbs->list, ctx_list)
433d80efd5cSThomas Hellstrom 		vmw_binding_drop(entry);
434d80efd5cSThomas Hellstrom }
435d80efd5cSThomas Hellstrom 
436d80efd5cSThomas Hellstrom /**
437d80efd5cSThomas Hellstrom  * vmw_binding_state_scrub - Scrub all bindings associated with a
438d80efd5cSThomas Hellstrom  * struct vmw_ctx_binding state structure.
439d80efd5cSThomas Hellstrom  *
440d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context binding state tracker.
441d80efd5cSThomas Hellstrom  *
442d80efd5cSThomas Hellstrom  * Emits commands to scrub all bindings associated with the
443d80efd5cSThomas Hellstrom  * context binding state tracker.
444d80efd5cSThomas Hellstrom  */
vmw_binding_state_scrub(struct vmw_ctx_binding_state * cbs)445d80efd5cSThomas Hellstrom void vmw_binding_state_scrub(struct vmw_ctx_binding_state *cbs)
446d80efd5cSThomas Hellstrom {
447d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo *entry;
448d80efd5cSThomas Hellstrom 
449d80efd5cSThomas Hellstrom 	list_for_each_entry(entry, &cbs->list, ctx_list) {
450d80efd5cSThomas Hellstrom 		if (!entry->scrubbed) {
451d80efd5cSThomas Hellstrom 			(void) vmw_binding_infos[entry->bt].scrub_func
452d80efd5cSThomas Hellstrom 				(entry, false);
453d80efd5cSThomas Hellstrom 			entry->scrubbed = true;
454d80efd5cSThomas Hellstrom 		}
455d80efd5cSThomas Hellstrom 	}
456d80efd5cSThomas Hellstrom 
457d80efd5cSThomas Hellstrom 	(void) vmw_binding_emit_dirty(cbs);
458d80efd5cSThomas Hellstrom }
459d80efd5cSThomas Hellstrom 
460d80efd5cSThomas Hellstrom /**
461d80efd5cSThomas Hellstrom  * vmw_binding_res_list_kill - Kill all bindings on a
462d80efd5cSThomas Hellstrom  * resource binding list
463d80efd5cSThomas Hellstrom  *
464d80efd5cSThomas Hellstrom  * @head: list head of resource binding list
465d80efd5cSThomas Hellstrom  *
466d80efd5cSThomas Hellstrom  * Kills all bindings associated with a specific resource. Typically
467d80efd5cSThomas Hellstrom  * called before the resource is destroyed.
468d80efd5cSThomas Hellstrom  */
vmw_binding_res_list_kill(struct list_head * head)469d80efd5cSThomas Hellstrom void vmw_binding_res_list_kill(struct list_head *head)
470d80efd5cSThomas Hellstrom {
471d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo *entry, *next;
472d80efd5cSThomas Hellstrom 
473d80efd5cSThomas Hellstrom 	vmw_binding_res_list_scrub(head);
474d80efd5cSThomas Hellstrom 	list_for_each_entry_safe(entry, next, head, res_list)
475d80efd5cSThomas Hellstrom 		vmw_binding_drop(entry);
476d80efd5cSThomas Hellstrom }
477d80efd5cSThomas Hellstrom 
478d80efd5cSThomas Hellstrom /**
479d80efd5cSThomas Hellstrom  * vmw_binding_res_list_scrub - Scrub all bindings on a
480d80efd5cSThomas Hellstrom  * resource binding list
481d80efd5cSThomas Hellstrom  *
482d80efd5cSThomas Hellstrom  * @head: list head of resource binding list
483d80efd5cSThomas Hellstrom  *
484d80efd5cSThomas Hellstrom  * Scrub all bindings associated with a specific resource. Typically
485d80efd5cSThomas Hellstrom  * called before the resource is evicted.
486d80efd5cSThomas Hellstrom  */
vmw_binding_res_list_scrub(struct list_head * head)487d80efd5cSThomas Hellstrom void vmw_binding_res_list_scrub(struct list_head *head)
488d80efd5cSThomas Hellstrom {
489d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo *entry;
490d80efd5cSThomas Hellstrom 
491d80efd5cSThomas Hellstrom 	list_for_each_entry(entry, head, res_list) {
492d80efd5cSThomas Hellstrom 		if (!entry->scrubbed) {
493d80efd5cSThomas Hellstrom 			(void) vmw_binding_infos[entry->bt].scrub_func
494d80efd5cSThomas Hellstrom 				(entry, false);
495d80efd5cSThomas Hellstrom 			entry->scrubbed = true;
496d80efd5cSThomas Hellstrom 		}
497d80efd5cSThomas Hellstrom 	}
498d80efd5cSThomas Hellstrom 
499d80efd5cSThomas Hellstrom 	list_for_each_entry(entry, head, res_list) {
500d80efd5cSThomas Hellstrom 		struct vmw_ctx_binding_state *cbs =
501d80efd5cSThomas Hellstrom 			vmw_context_binding_state(entry->ctx);
502d80efd5cSThomas Hellstrom 
503d80efd5cSThomas Hellstrom 		(void) vmw_binding_emit_dirty(cbs);
504d80efd5cSThomas Hellstrom 	}
505d80efd5cSThomas Hellstrom }
506d80efd5cSThomas Hellstrom 
507d80efd5cSThomas Hellstrom 
508d80efd5cSThomas Hellstrom /**
509d80efd5cSThomas Hellstrom  * vmw_binding_state_commit - Commit staged binding info
510d80efd5cSThomas Hellstrom  *
511e8fb41acSLee Jones  * @to:   Staged binding info area to copy into to.
512d80efd5cSThomas Hellstrom  * @from: Staged binding info built during execbuf.
513d80efd5cSThomas Hellstrom  *
514d80efd5cSThomas Hellstrom  * Transfers binding info from a temporary structure
515d80efd5cSThomas Hellstrom  * (typically used by execbuf) to the persistent
516d80efd5cSThomas Hellstrom  * structure in the context. This can be done once commands have been
517d80efd5cSThomas Hellstrom  * submitted to hardware
518d80efd5cSThomas Hellstrom  */
vmw_binding_state_commit(struct vmw_ctx_binding_state * to,struct vmw_ctx_binding_state * from)519d80efd5cSThomas Hellstrom void vmw_binding_state_commit(struct vmw_ctx_binding_state *to,
520d80efd5cSThomas Hellstrom 			      struct vmw_ctx_binding_state *from)
521d80efd5cSThomas Hellstrom {
522d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo *entry, *next;
523d80efd5cSThomas Hellstrom 
524d80efd5cSThomas Hellstrom 	list_for_each_entry_safe(entry, next, &from->list, ctx_list) {
525d80efd5cSThomas Hellstrom 		vmw_binding_transfer(to, from, entry);
526d80efd5cSThomas Hellstrom 		vmw_binding_drop(entry);
527d80efd5cSThomas Hellstrom 	}
5285e8ec0d9SDeepak Rawat 
5295e8ec0d9SDeepak Rawat 	/* Also transfer uav splice indices */
5305e8ec0d9SDeepak Rawat 	to->ua_views[0].index = from->ua_views[0].index;
5315e8ec0d9SDeepak Rawat 	to->ua_views[1].index = from->ua_views[1].index;
532d80efd5cSThomas Hellstrom }
533d80efd5cSThomas Hellstrom 
534d80efd5cSThomas Hellstrom /**
535d80efd5cSThomas Hellstrom  * vmw_binding_rebind_all - Rebind all scrubbed bindings of a context
536d80efd5cSThomas Hellstrom  *
537e8fb41acSLee Jones  * @cbs: Pointer to the context binding state tracker.
538d80efd5cSThomas Hellstrom  *
539d80efd5cSThomas Hellstrom  * Walks through the context binding list and rebinds all scrubbed
540d80efd5cSThomas Hellstrom  * resources.
541d80efd5cSThomas Hellstrom  */
vmw_binding_rebind_all(struct vmw_ctx_binding_state * cbs)542d80efd5cSThomas Hellstrom int vmw_binding_rebind_all(struct vmw_ctx_binding_state *cbs)
543d80efd5cSThomas Hellstrom {
544d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo *entry;
545d80efd5cSThomas Hellstrom 	int ret;
546d80efd5cSThomas Hellstrom 
547d80efd5cSThomas Hellstrom 	list_for_each_entry(entry, &cbs->list, ctx_list) {
548d80efd5cSThomas Hellstrom 		if (likely(!entry->scrubbed))
549d80efd5cSThomas Hellstrom 			continue;
550d80efd5cSThomas Hellstrom 
551d80efd5cSThomas Hellstrom 		if ((entry->res == NULL || entry->res->id ==
552d80efd5cSThomas Hellstrom 			    SVGA3D_INVALID_ID))
553d80efd5cSThomas Hellstrom 			continue;
554d80efd5cSThomas Hellstrom 
555d80efd5cSThomas Hellstrom 		ret = vmw_binding_infos[entry->bt].scrub_func(entry, true);
556d80efd5cSThomas Hellstrom 		if (unlikely(ret != 0))
557d80efd5cSThomas Hellstrom 			return ret;
558d80efd5cSThomas Hellstrom 
559d80efd5cSThomas Hellstrom 		entry->scrubbed = false;
560d80efd5cSThomas Hellstrom 	}
561d80efd5cSThomas Hellstrom 
562d80efd5cSThomas Hellstrom 	return vmw_binding_emit_dirty(cbs);
563d80efd5cSThomas Hellstrom }
564d80efd5cSThomas Hellstrom 
565d80efd5cSThomas Hellstrom /**
566d80efd5cSThomas Hellstrom  * vmw_binding_scrub_shader - scrub a shader binding from a context.
567d80efd5cSThomas Hellstrom  *
568d80efd5cSThomas Hellstrom  * @bi: single binding information.
569d80efd5cSThomas Hellstrom  * @rebind: Whether to issue a bind instead of scrub command.
570d80efd5cSThomas Hellstrom  */
vmw_binding_scrub_shader(struct vmw_ctx_bindinfo * bi,bool rebind)571d80efd5cSThomas Hellstrom static int vmw_binding_scrub_shader(struct vmw_ctx_bindinfo *bi, bool rebind)
572d80efd5cSThomas Hellstrom {
573d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_shader *binding =
574d80efd5cSThomas Hellstrom 		container_of(bi, typeof(*binding), bi);
575d80efd5cSThomas Hellstrom 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
576d80efd5cSThomas Hellstrom 	struct {
577d80efd5cSThomas Hellstrom 		SVGA3dCmdHeader header;
578d80efd5cSThomas Hellstrom 		SVGA3dCmdSetShader body;
579d80efd5cSThomas Hellstrom 	} *cmd;
580d80efd5cSThomas Hellstrom 
5818426ed9cSZack Rusin 	cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
58211c45419SDeepak Rawat 	if (unlikely(cmd == NULL))
583d80efd5cSThomas Hellstrom 		return -ENOMEM;
584d80efd5cSThomas Hellstrom 
585d80efd5cSThomas Hellstrom 	cmd->header.id = SVGA_3D_CMD_SET_SHADER;
586d80efd5cSThomas Hellstrom 	cmd->header.size = sizeof(cmd->body);
587d80efd5cSThomas Hellstrom 	cmd->body.cid = bi->ctx->id;
588d80efd5cSThomas Hellstrom 	cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN;
589d80efd5cSThomas Hellstrom 	cmd->body.shid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
5908426ed9cSZack Rusin 	vmw_cmd_commit(dev_priv, sizeof(*cmd));
591d80efd5cSThomas Hellstrom 
592d80efd5cSThomas Hellstrom 	return 0;
593d80efd5cSThomas Hellstrom }
594d80efd5cSThomas Hellstrom 
595d80efd5cSThomas Hellstrom /**
596d80efd5cSThomas Hellstrom  * vmw_binding_scrub_render_target - scrub a render target binding
597d80efd5cSThomas Hellstrom  * from a context.
598d80efd5cSThomas Hellstrom  *
599d80efd5cSThomas Hellstrom  * @bi: single binding information.
600d80efd5cSThomas Hellstrom  * @rebind: Whether to issue a bind instead of scrub command.
601d80efd5cSThomas Hellstrom  */
vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo * bi,bool rebind)602d80efd5cSThomas Hellstrom static int vmw_binding_scrub_render_target(struct vmw_ctx_bindinfo *bi,
603d80efd5cSThomas Hellstrom 					   bool rebind)
604d80efd5cSThomas Hellstrom {
605d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_view *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 		SVGA3dCmdSetRenderTarget body;
611d80efd5cSThomas Hellstrom 	} *cmd;
612d80efd5cSThomas Hellstrom 
6138426ed9cSZack Rusin 	cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
61411c45419SDeepak Rawat 	if (unlikely(cmd == NULL))
615d80efd5cSThomas Hellstrom 		return -ENOMEM;
616d80efd5cSThomas Hellstrom 
617d80efd5cSThomas Hellstrom 	cmd->header.id = SVGA_3D_CMD_SETRENDERTARGET;
618d80efd5cSThomas Hellstrom 	cmd->header.size = sizeof(cmd->body);
619d80efd5cSThomas Hellstrom 	cmd->body.cid = bi->ctx->id;
620d80efd5cSThomas Hellstrom 	cmd->body.type = binding->slot;
621d80efd5cSThomas Hellstrom 	cmd->body.target.sid = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
622d80efd5cSThomas Hellstrom 	cmd->body.target.face = 0;
623d80efd5cSThomas Hellstrom 	cmd->body.target.mipmap = 0;
6248426ed9cSZack Rusin 	vmw_cmd_commit(dev_priv, sizeof(*cmd));
625d80efd5cSThomas Hellstrom 
626d80efd5cSThomas Hellstrom 	return 0;
627d80efd5cSThomas Hellstrom }
628d80efd5cSThomas Hellstrom 
629d80efd5cSThomas Hellstrom /**
630d80efd5cSThomas Hellstrom  * vmw_binding_scrub_texture - scrub a texture binding from a context.
631d80efd5cSThomas Hellstrom  *
632d80efd5cSThomas Hellstrom  * @bi: single binding information.
633d80efd5cSThomas Hellstrom  * @rebind: Whether to issue a bind instead of scrub command.
634d80efd5cSThomas Hellstrom  *
635d80efd5cSThomas Hellstrom  * TODO: Possibly complement this function with a function that takes
636d80efd5cSThomas Hellstrom  * a list of texture bindings and combines them to a single command.
637d80efd5cSThomas Hellstrom  */
vmw_binding_scrub_texture(struct vmw_ctx_bindinfo * bi,bool rebind)638d80efd5cSThomas Hellstrom static int vmw_binding_scrub_texture(struct vmw_ctx_bindinfo *bi,
639d80efd5cSThomas Hellstrom 				     bool rebind)
640d80efd5cSThomas Hellstrom {
641d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_tex *binding =
642d80efd5cSThomas Hellstrom 		container_of(bi, typeof(*binding), bi);
643d80efd5cSThomas Hellstrom 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
644d80efd5cSThomas Hellstrom 	struct {
645d80efd5cSThomas Hellstrom 		SVGA3dCmdHeader header;
646d80efd5cSThomas Hellstrom 		struct {
647d80efd5cSThomas Hellstrom 			SVGA3dCmdSetTextureState c;
648d80efd5cSThomas Hellstrom 			SVGA3dTextureState s1;
649d80efd5cSThomas Hellstrom 		} body;
650d80efd5cSThomas Hellstrom 	} *cmd;
651d80efd5cSThomas Hellstrom 
6528426ed9cSZack Rusin 	cmd = VMW_CMD_RESERVE(dev_priv, sizeof(*cmd));
65311c45419SDeepak Rawat 	if (unlikely(cmd == NULL))
654d80efd5cSThomas Hellstrom 		return -ENOMEM;
655d80efd5cSThomas Hellstrom 
656d80efd5cSThomas Hellstrom 	cmd->header.id = SVGA_3D_CMD_SETTEXTURESTATE;
657d80efd5cSThomas Hellstrom 	cmd->header.size = sizeof(cmd->body);
658d80efd5cSThomas Hellstrom 	cmd->body.c.cid = bi->ctx->id;
659d80efd5cSThomas Hellstrom 	cmd->body.s1.stage = binding->texture_stage;
660d80efd5cSThomas Hellstrom 	cmd->body.s1.name = SVGA3D_TS_BIND_TEXTURE;
661d80efd5cSThomas Hellstrom 	cmd->body.s1.value = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
6628426ed9cSZack Rusin 	vmw_cmd_commit(dev_priv, sizeof(*cmd));
663d80efd5cSThomas Hellstrom 
664d80efd5cSThomas Hellstrom 	return 0;
665d80efd5cSThomas Hellstrom }
666d80efd5cSThomas Hellstrom 
667d80efd5cSThomas Hellstrom /**
668d80efd5cSThomas Hellstrom  * vmw_binding_scrub_dx_shader - scrub a dx shader binding from a context.
669d80efd5cSThomas Hellstrom  *
670d80efd5cSThomas Hellstrom  * @bi: single binding information.
671d80efd5cSThomas Hellstrom  * @rebind: Whether to issue a bind instead of scrub command.
672d80efd5cSThomas Hellstrom  */
vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo * bi,bool rebind)673d80efd5cSThomas Hellstrom static int vmw_binding_scrub_dx_shader(struct vmw_ctx_bindinfo *bi, bool rebind)
674d80efd5cSThomas Hellstrom {
675d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_shader *binding =
676d80efd5cSThomas Hellstrom 		container_of(bi, typeof(*binding), bi);
677d80efd5cSThomas Hellstrom 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
678d80efd5cSThomas Hellstrom 	struct {
679d80efd5cSThomas Hellstrom 		SVGA3dCmdHeader header;
680d80efd5cSThomas Hellstrom 		SVGA3dCmdDXSetShader body;
681d80efd5cSThomas Hellstrom 	} *cmd;
682d80efd5cSThomas Hellstrom 
6838426ed9cSZack Rusin 	cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), bi->ctx->id);
68411c45419SDeepak Rawat 	if (unlikely(cmd == NULL))
685d80efd5cSThomas Hellstrom 		return -ENOMEM;
68611c45419SDeepak Rawat 
687d80efd5cSThomas Hellstrom 	cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER;
688d80efd5cSThomas Hellstrom 	cmd->header.size = sizeof(cmd->body);
689d80efd5cSThomas Hellstrom 	cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN;
690d80efd5cSThomas Hellstrom 	cmd->body.shaderId = ((rebind) ? bi->res->id : SVGA3D_INVALID_ID);
6918426ed9cSZack Rusin 	vmw_cmd_commit(dev_priv, sizeof(*cmd));
692d80efd5cSThomas Hellstrom 
693d80efd5cSThomas Hellstrom 	return 0;
694d80efd5cSThomas Hellstrom }
695d80efd5cSThomas Hellstrom 
696d80efd5cSThomas Hellstrom /**
697d80efd5cSThomas Hellstrom  * vmw_binding_scrub_cb - scrub a constant buffer binding from a context.
698d80efd5cSThomas Hellstrom  *
699d80efd5cSThomas Hellstrom  * @bi: single binding information.
700d80efd5cSThomas Hellstrom  * @rebind: Whether to issue a bind instead of scrub command.
701d80efd5cSThomas Hellstrom  */
vmw_binding_scrub_cb(struct vmw_ctx_bindinfo * bi,bool rebind)702d80efd5cSThomas Hellstrom static int vmw_binding_scrub_cb(struct vmw_ctx_bindinfo *bi, bool rebind)
703d80efd5cSThomas Hellstrom {
704d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_cb *binding =
705d80efd5cSThomas Hellstrom 		container_of(bi, typeof(*binding), bi);
706d80efd5cSThomas Hellstrom 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
707d80efd5cSThomas Hellstrom 	struct {
708d80efd5cSThomas Hellstrom 		SVGA3dCmdHeader header;
709d80efd5cSThomas Hellstrom 		SVGA3dCmdDXSetSingleConstantBuffer body;
710d80efd5cSThomas Hellstrom 	} *cmd;
711d80efd5cSThomas Hellstrom 
7128426ed9cSZack Rusin 	cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), bi->ctx->id);
71311c45419SDeepak Rawat 	if (unlikely(cmd == NULL))
714d80efd5cSThomas Hellstrom 		return -ENOMEM;
715d80efd5cSThomas Hellstrom 
716d80efd5cSThomas Hellstrom 	cmd->header.id = SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER;
717d80efd5cSThomas Hellstrom 	cmd->header.size = sizeof(cmd->body);
718d80efd5cSThomas Hellstrom 	cmd->body.slot = binding->slot;
719d80efd5cSThomas Hellstrom 	cmd->body.type = binding->shader_slot + SVGA3D_SHADERTYPE_MIN;
720d80efd5cSThomas Hellstrom 	if (rebind) {
721d80efd5cSThomas Hellstrom 		cmd->body.offsetInBytes = binding->offset;
722d80efd5cSThomas Hellstrom 		cmd->body.sizeInBytes = binding->size;
723d80efd5cSThomas Hellstrom 		cmd->body.sid = bi->res->id;
724d80efd5cSThomas Hellstrom 	} else {
725d80efd5cSThomas Hellstrom 		cmd->body.offsetInBytes = 0;
726d80efd5cSThomas Hellstrom 		cmd->body.sizeInBytes = 0;
727d80efd5cSThomas Hellstrom 		cmd->body.sid = SVGA3D_INVALID_ID;
728d80efd5cSThomas Hellstrom 	}
7298426ed9cSZack Rusin 	vmw_cmd_commit(dev_priv, sizeof(*cmd));
730d80efd5cSThomas Hellstrom 
731d80efd5cSThomas Hellstrom 	return 0;
732d80efd5cSThomas Hellstrom }
733d80efd5cSThomas Hellstrom 
734d80efd5cSThomas Hellstrom /**
735d80efd5cSThomas Hellstrom  * vmw_collect_view_ids - Build view id data for a view binding command
736d80efd5cSThomas Hellstrom  * without checking which bindings actually need to be emitted
737d80efd5cSThomas Hellstrom  *
738d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
73974231041SZack Rusin  * @biv: Pointer to where the binding info array is stored in @cbs
740d80efd5cSThomas Hellstrom  * @max_num: Maximum number of entries in the @bi array.
741d80efd5cSThomas Hellstrom  *
742d80efd5cSThomas Hellstrom  * Scans the @bi array for bindings and builds a buffer of view id data.
743d80efd5cSThomas Hellstrom  * Stops at the first non-existing binding in the @bi array.
744d80efd5cSThomas Hellstrom  * On output, @cbs->bind_cmd_count contains the number of bindings to be
745d80efd5cSThomas Hellstrom  * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer
746d80efd5cSThomas Hellstrom  * contains the command data.
747d80efd5cSThomas Hellstrom  */
vmw_collect_view_ids(struct vmw_ctx_binding_state * cbs,const struct vmw_ctx_bindinfo_view * biv,u32 max_num)748d80efd5cSThomas Hellstrom static void vmw_collect_view_ids(struct vmw_ctx_binding_state *cbs,
74974231041SZack Rusin 				 const struct vmw_ctx_bindinfo_view *biv,
750d80efd5cSThomas Hellstrom 				 u32 max_num)
751d80efd5cSThomas Hellstrom {
752d80efd5cSThomas Hellstrom 	unsigned long i;
753d80efd5cSThomas Hellstrom 
754d80efd5cSThomas Hellstrom 	cbs->bind_cmd_count = 0;
755d80efd5cSThomas Hellstrom 	cbs->bind_first_slot = 0;
756d80efd5cSThomas Hellstrom 
757d80efd5cSThomas Hellstrom 	for (i = 0; i < max_num; ++i, ++biv) {
758d80efd5cSThomas Hellstrom 		if (!biv->bi.ctx)
759d80efd5cSThomas Hellstrom 			break;
760d80efd5cSThomas Hellstrom 
761d80efd5cSThomas Hellstrom 		cbs->bind_cmd_buffer[cbs->bind_cmd_count++] =
762d80efd5cSThomas Hellstrom 			((biv->bi.scrubbed) ?
763d80efd5cSThomas Hellstrom 			 SVGA3D_INVALID_ID : biv->bi.res->id);
764d80efd5cSThomas Hellstrom 	}
765d80efd5cSThomas Hellstrom }
766d80efd5cSThomas Hellstrom 
767d80efd5cSThomas Hellstrom /**
768d80efd5cSThomas Hellstrom  * vmw_collect_dirty_view_ids - Build view id data for a view binding command
769d80efd5cSThomas Hellstrom  *
770d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
771d80efd5cSThomas Hellstrom  * @bi: Pointer to where the binding info array is stored in @cbs
772d80efd5cSThomas Hellstrom  * @dirty: Bitmap indicating which bindings need to be emitted.
773d80efd5cSThomas Hellstrom  * @max_num: Maximum number of entries in the @bi array.
774d80efd5cSThomas Hellstrom  *
775d80efd5cSThomas Hellstrom  * Scans the @bi array for bindings that need to be emitted and
776d80efd5cSThomas Hellstrom  * builds a buffer of view id data.
777d80efd5cSThomas Hellstrom  * On output, @cbs->bind_cmd_count contains the number of bindings to be
778d80efd5cSThomas Hellstrom  * emitted, @cbs->bind_first_slot indicates the index of the first emitted
779d80efd5cSThomas Hellstrom  * binding, and @cbs->bind_cmd_buffer contains the command data.
780d80efd5cSThomas Hellstrom  */
vmw_collect_dirty_view_ids(struct vmw_ctx_binding_state * cbs,const struct vmw_ctx_bindinfo * bi,unsigned long * dirty,u32 max_num)781d80efd5cSThomas Hellstrom static void vmw_collect_dirty_view_ids(struct vmw_ctx_binding_state *cbs,
782d80efd5cSThomas Hellstrom 				       const struct vmw_ctx_bindinfo *bi,
783d80efd5cSThomas Hellstrom 				       unsigned long *dirty,
784d80efd5cSThomas Hellstrom 				       u32 max_num)
785d80efd5cSThomas Hellstrom {
786d80efd5cSThomas Hellstrom 	const struct vmw_ctx_bindinfo_view *biv =
787d80efd5cSThomas Hellstrom 		container_of(bi, struct vmw_ctx_bindinfo_view, bi);
788d80efd5cSThomas Hellstrom 	unsigned long i, next_bit;
789d80efd5cSThomas Hellstrom 
790d80efd5cSThomas Hellstrom 	cbs->bind_cmd_count = 0;
791d80efd5cSThomas Hellstrom 	i = find_first_bit(dirty, max_num);
792d80efd5cSThomas Hellstrom 	next_bit = i;
793d80efd5cSThomas Hellstrom 	cbs->bind_first_slot = i;
794d80efd5cSThomas Hellstrom 
795d80efd5cSThomas Hellstrom 	biv += i;
796d80efd5cSThomas Hellstrom 	for (; i < max_num; ++i, ++biv) {
797d80efd5cSThomas Hellstrom 		cbs->bind_cmd_buffer[cbs->bind_cmd_count++] =
798d80efd5cSThomas Hellstrom 			((!biv->bi.ctx || biv->bi.scrubbed) ?
799d80efd5cSThomas Hellstrom 			 SVGA3D_INVALID_ID : biv->bi.res->id);
800d80efd5cSThomas Hellstrom 
801d80efd5cSThomas Hellstrom 		if (next_bit == i) {
802d80efd5cSThomas Hellstrom 			next_bit = find_next_bit(dirty, max_num, i + 1);
803d80efd5cSThomas Hellstrom 			if (next_bit >= max_num)
804d80efd5cSThomas Hellstrom 				break;
805d80efd5cSThomas Hellstrom 		}
806d80efd5cSThomas Hellstrom 	}
807d80efd5cSThomas Hellstrom }
808d80efd5cSThomas Hellstrom 
809d80efd5cSThomas Hellstrom /**
8102cd80dbdSZack Rusin  * vmw_emit_set_sr - Issue delayed DX shader resource binding commands
811d80efd5cSThomas Hellstrom  *
812d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
813e8fb41acSLee Jones  * @shader_slot: The shader slot of the binding.
814d80efd5cSThomas Hellstrom  */
vmw_emit_set_sr(struct vmw_ctx_binding_state * cbs,int shader_slot)815d80efd5cSThomas Hellstrom static int vmw_emit_set_sr(struct vmw_ctx_binding_state *cbs,
816d80efd5cSThomas Hellstrom 			   int shader_slot)
817d80efd5cSThomas Hellstrom {
818d80efd5cSThomas Hellstrom 	const struct vmw_ctx_bindinfo *loc =
819d80efd5cSThomas Hellstrom 		&cbs->per_shader[shader_slot].shader_res[0].bi;
820d80efd5cSThomas Hellstrom 	struct {
821d80efd5cSThomas Hellstrom 		SVGA3dCmdHeader header;
822d80efd5cSThomas Hellstrom 		SVGA3dCmdDXSetShaderResources body;
823d80efd5cSThomas Hellstrom 	} *cmd;
824d80efd5cSThomas Hellstrom 	size_t cmd_size, view_id_size;
825d80efd5cSThomas Hellstrom 	const struct vmw_resource *ctx = vmw_cbs_context(cbs);
826d80efd5cSThomas Hellstrom 
827d80efd5cSThomas Hellstrom 	vmw_collect_dirty_view_ids(cbs, loc,
828d80efd5cSThomas Hellstrom 				   cbs->per_shader[shader_slot].dirty_sr,
829d80efd5cSThomas Hellstrom 				   SVGA3D_DX_MAX_SRVIEWS);
830d80efd5cSThomas Hellstrom 	if (cbs->bind_cmd_count == 0)
831d80efd5cSThomas Hellstrom 		return 0;
832d80efd5cSThomas Hellstrom 
833d80efd5cSThomas Hellstrom 	view_id_size = cbs->bind_cmd_count*sizeof(uint32);
834d80efd5cSThomas Hellstrom 	cmd_size = sizeof(*cmd) + view_id_size;
8358426ed9cSZack Rusin 	cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id);
83611c45419SDeepak Rawat 	if (unlikely(cmd == NULL))
837d80efd5cSThomas Hellstrom 		return -ENOMEM;
838d80efd5cSThomas Hellstrom 
839d80efd5cSThomas Hellstrom 	cmd->header.id = SVGA_3D_CMD_DX_SET_SHADER_RESOURCES;
840d80efd5cSThomas Hellstrom 	cmd->header.size = sizeof(cmd->body) + view_id_size;
841d80efd5cSThomas Hellstrom 	cmd->body.type = shader_slot + SVGA3D_SHADERTYPE_MIN;
842d80efd5cSThomas Hellstrom 	cmd->body.startView = cbs->bind_first_slot;
843d80efd5cSThomas Hellstrom 
844d80efd5cSThomas Hellstrom 	memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size);
845d80efd5cSThomas Hellstrom 
8468426ed9cSZack Rusin 	vmw_cmd_commit(ctx->dev_priv, cmd_size);
847d80efd5cSThomas Hellstrom 	bitmap_clear(cbs->per_shader[shader_slot].dirty_sr,
848d80efd5cSThomas Hellstrom 		     cbs->bind_first_slot, cbs->bind_cmd_count);
849d80efd5cSThomas Hellstrom 
850d80efd5cSThomas Hellstrom 	return 0;
851d80efd5cSThomas Hellstrom }
852d80efd5cSThomas Hellstrom 
853d80efd5cSThomas Hellstrom /**
8542cd80dbdSZack Rusin  * vmw_emit_set_rt - Issue delayed DX rendertarget binding commands
855d80efd5cSThomas Hellstrom  *
856d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
857d80efd5cSThomas Hellstrom  */
vmw_emit_set_rt(struct vmw_ctx_binding_state * cbs)858d80efd5cSThomas Hellstrom static int vmw_emit_set_rt(struct vmw_ctx_binding_state *cbs)
859d80efd5cSThomas Hellstrom {
86074231041SZack Rusin 	const struct vmw_ctx_bindinfo_view *loc = &cbs->render_targets[0];
861d80efd5cSThomas Hellstrom 	struct {
862d80efd5cSThomas Hellstrom 		SVGA3dCmdHeader header;
863d80efd5cSThomas Hellstrom 		SVGA3dCmdDXSetRenderTargets body;
864d80efd5cSThomas Hellstrom 	} *cmd;
865d80efd5cSThomas Hellstrom 	size_t cmd_size, view_id_size;
866d80efd5cSThomas Hellstrom 	const struct vmw_resource *ctx = vmw_cbs_context(cbs);
867d80efd5cSThomas Hellstrom 
868ebc9ac7cSZack Rusin 	vmw_collect_view_ids(cbs, loc, SVGA3D_DX_MAX_RENDER_TARGETS);
869d80efd5cSThomas Hellstrom 	view_id_size = cbs->bind_cmd_count*sizeof(uint32);
870d80efd5cSThomas Hellstrom 	cmd_size = sizeof(*cmd) + view_id_size;
8718426ed9cSZack Rusin 	cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id);
87211c45419SDeepak Rawat 	if (unlikely(cmd == NULL))
873d80efd5cSThomas Hellstrom 		return -ENOMEM;
874d80efd5cSThomas Hellstrom 
875d80efd5cSThomas Hellstrom 	cmd->header.id = SVGA_3D_CMD_DX_SET_RENDERTARGETS;
876d80efd5cSThomas Hellstrom 	cmd->header.size = sizeof(cmd->body) + view_id_size;
877d80efd5cSThomas Hellstrom 
878d80efd5cSThomas Hellstrom 	if (cbs->ds_view.bi.ctx && !cbs->ds_view.bi.scrubbed)
879d80efd5cSThomas Hellstrom 		cmd->body.depthStencilViewId = cbs->ds_view.bi.res->id;
880d80efd5cSThomas Hellstrom 	else
881d80efd5cSThomas Hellstrom 		cmd->body.depthStencilViewId = SVGA3D_INVALID_ID;
882d80efd5cSThomas Hellstrom 
883d80efd5cSThomas Hellstrom 	memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size);
884d80efd5cSThomas Hellstrom 
8858426ed9cSZack Rusin 	vmw_cmd_commit(ctx->dev_priv, cmd_size);
886d80efd5cSThomas Hellstrom 
887d80efd5cSThomas Hellstrom 	return 0;
888d80efd5cSThomas Hellstrom 
889d80efd5cSThomas Hellstrom }
890d80efd5cSThomas Hellstrom 
891d80efd5cSThomas Hellstrom /**
892d80efd5cSThomas Hellstrom  * vmw_collect_so_targets - Build SVGA3dSoTarget data for a binding command
893d80efd5cSThomas Hellstrom  * without checking which bindings actually need to be emitted
894d80efd5cSThomas Hellstrom  *
895d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
89674231041SZack Rusin  * @biso: Pointer to where the binding info array is stored in @cbs
897d80efd5cSThomas Hellstrom  * @max_num: Maximum number of entries in the @bi array.
898d80efd5cSThomas Hellstrom  *
899d80efd5cSThomas Hellstrom  * Scans the @bi array for bindings and builds a buffer of SVGA3dSoTarget data.
900d80efd5cSThomas Hellstrom  * Stops at the first non-existing binding in the @bi array.
901d80efd5cSThomas Hellstrom  * On output, @cbs->bind_cmd_count contains the number of bindings to be
902d80efd5cSThomas Hellstrom  * emitted, @cbs->bind_first_slot is set to zero, and @cbs->bind_cmd_buffer
903d80efd5cSThomas Hellstrom  * contains the command data.
904d80efd5cSThomas Hellstrom  */
vmw_collect_so_targets(struct vmw_ctx_binding_state * cbs,const struct vmw_ctx_bindinfo_so_target * biso,u32 max_num)905d80efd5cSThomas Hellstrom static void vmw_collect_so_targets(struct vmw_ctx_binding_state *cbs,
90674231041SZack Rusin 				   const struct vmw_ctx_bindinfo_so_target *biso,
907d80efd5cSThomas Hellstrom 				   u32 max_num)
908d80efd5cSThomas Hellstrom {
909d80efd5cSThomas Hellstrom 	unsigned long i;
910d80efd5cSThomas Hellstrom 	SVGA3dSoTarget *so_buffer = (SVGA3dSoTarget *) cbs->bind_cmd_buffer;
911d80efd5cSThomas Hellstrom 
912d80efd5cSThomas Hellstrom 	cbs->bind_cmd_count = 0;
913d80efd5cSThomas Hellstrom 	cbs->bind_first_slot = 0;
914d80efd5cSThomas Hellstrom 
915d80efd5cSThomas Hellstrom 	for (i = 0; i < max_num; ++i, ++biso, ++so_buffer,
916d80efd5cSThomas Hellstrom 		    ++cbs->bind_cmd_count) {
917d80efd5cSThomas Hellstrom 		if (!biso->bi.ctx)
918d80efd5cSThomas Hellstrom 			break;
919d80efd5cSThomas Hellstrom 
920d80efd5cSThomas Hellstrom 		if (!biso->bi.scrubbed) {
921d80efd5cSThomas Hellstrom 			so_buffer->sid = biso->bi.res->id;
922d80efd5cSThomas Hellstrom 			so_buffer->offset = biso->offset;
923d80efd5cSThomas Hellstrom 			so_buffer->sizeInBytes = biso->size;
924d80efd5cSThomas Hellstrom 		} else {
925d80efd5cSThomas Hellstrom 			so_buffer->sid = SVGA3D_INVALID_ID;
926d80efd5cSThomas Hellstrom 			so_buffer->offset = 0;
927d80efd5cSThomas Hellstrom 			so_buffer->sizeInBytes = 0;
928d80efd5cSThomas Hellstrom 		}
929d80efd5cSThomas Hellstrom 	}
930d80efd5cSThomas Hellstrom }
931d80efd5cSThomas Hellstrom 
932d80efd5cSThomas Hellstrom /**
933403fef50SDeepak Rawat  * vmw_emit_set_so_target - Issue delayed streamout binding commands
934d80efd5cSThomas Hellstrom  *
935d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
936d80efd5cSThomas Hellstrom  */
vmw_emit_set_so_target(struct vmw_ctx_binding_state * cbs)937403fef50SDeepak Rawat static int vmw_emit_set_so_target(struct vmw_ctx_binding_state *cbs)
938d80efd5cSThomas Hellstrom {
93974231041SZack Rusin 	const struct vmw_ctx_bindinfo_so_target *loc = &cbs->so_targets[0];
940d80efd5cSThomas Hellstrom 	struct {
941d80efd5cSThomas Hellstrom 		SVGA3dCmdHeader header;
942d80efd5cSThomas Hellstrom 		SVGA3dCmdDXSetSOTargets body;
943d80efd5cSThomas Hellstrom 	} *cmd;
944d80efd5cSThomas Hellstrom 	size_t cmd_size, so_target_size;
945d80efd5cSThomas Hellstrom 	const struct vmw_resource *ctx = vmw_cbs_context(cbs);
946d80efd5cSThomas Hellstrom 
947d80efd5cSThomas Hellstrom 	vmw_collect_so_targets(cbs, loc, SVGA3D_DX_MAX_SOTARGETS);
948d80efd5cSThomas Hellstrom 	if (cbs->bind_cmd_count == 0)
949d80efd5cSThomas Hellstrom 		return 0;
950d80efd5cSThomas Hellstrom 
951d80efd5cSThomas Hellstrom 	so_target_size = cbs->bind_cmd_count*sizeof(SVGA3dSoTarget);
952d80efd5cSThomas Hellstrom 	cmd_size = sizeof(*cmd) + so_target_size;
9538426ed9cSZack Rusin 	cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id);
95411c45419SDeepak Rawat 	if (unlikely(cmd == NULL))
955d80efd5cSThomas Hellstrom 		return -ENOMEM;
956d80efd5cSThomas Hellstrom 
957d80efd5cSThomas Hellstrom 	cmd->header.id = SVGA_3D_CMD_DX_SET_SOTARGETS;
958d80efd5cSThomas Hellstrom 	cmd->header.size = sizeof(cmd->body) + so_target_size;
959d80efd5cSThomas Hellstrom 	memcpy(&cmd[1], cbs->bind_cmd_buffer, so_target_size);
960d80efd5cSThomas Hellstrom 
9618426ed9cSZack Rusin 	vmw_cmd_commit(ctx->dev_priv, cmd_size);
962d80efd5cSThomas Hellstrom 
963d80efd5cSThomas Hellstrom 	return 0;
964d80efd5cSThomas Hellstrom 
965d80efd5cSThomas Hellstrom }
966d80efd5cSThomas Hellstrom 
967d80efd5cSThomas Hellstrom /**
968d80efd5cSThomas Hellstrom  * vmw_binding_emit_dirty_ps - Issue delayed per shader binding commands
969d80efd5cSThomas Hellstrom  *
970d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
971d80efd5cSThomas Hellstrom  *
972d80efd5cSThomas Hellstrom  */
vmw_binding_emit_dirty_ps(struct vmw_ctx_binding_state * cbs)973d80efd5cSThomas Hellstrom static int vmw_binding_emit_dirty_ps(struct vmw_ctx_binding_state *cbs)
974d80efd5cSThomas Hellstrom {
975d80efd5cSThomas Hellstrom 	struct vmw_dx_shader_bindings *sb = &cbs->per_shader[0];
976d80efd5cSThomas Hellstrom 	u32 i;
977d80efd5cSThomas Hellstrom 	int ret;
978d80efd5cSThomas Hellstrom 
979d80efd5cSThomas Hellstrom 	for (i = 0; i < SVGA3D_NUM_SHADERTYPE_DX10; ++i, ++sb) {
980d80efd5cSThomas Hellstrom 		if (!test_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty))
981d80efd5cSThomas Hellstrom 			continue;
982d80efd5cSThomas Hellstrom 
983d80efd5cSThomas Hellstrom 		ret = vmw_emit_set_sr(cbs, i);
984d80efd5cSThomas Hellstrom 		if (ret)
985d80efd5cSThomas Hellstrom 			break;
986d80efd5cSThomas Hellstrom 
987d80efd5cSThomas Hellstrom 		__clear_bit(VMW_BINDING_PS_SR_BIT, &sb->dirty);
988d80efd5cSThomas Hellstrom 	}
989d80efd5cSThomas Hellstrom 
990d80efd5cSThomas Hellstrom 	return 0;
991d80efd5cSThomas Hellstrom }
992d80efd5cSThomas Hellstrom 
993d80efd5cSThomas Hellstrom /**
994d80efd5cSThomas Hellstrom  * vmw_collect_dirty_vbs - Build SVGA3dVertexBuffer data for a
995d80efd5cSThomas Hellstrom  * SVGA3dCmdDXSetVertexBuffers command
996d80efd5cSThomas Hellstrom  *
997d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
998d80efd5cSThomas Hellstrom  * @bi: Pointer to where the binding info array is stored in @cbs
999d80efd5cSThomas Hellstrom  * @dirty: Bitmap indicating which bindings need to be emitted.
1000d80efd5cSThomas Hellstrom  * @max_num: Maximum number of entries in the @bi array.
1001d80efd5cSThomas Hellstrom  *
1002d80efd5cSThomas Hellstrom  * Scans the @bi array for bindings that need to be emitted and
1003d80efd5cSThomas Hellstrom  * builds a buffer of SVGA3dVertexBuffer data.
1004d80efd5cSThomas Hellstrom  * On output, @cbs->bind_cmd_count contains the number of bindings to be
1005d80efd5cSThomas Hellstrom  * emitted, @cbs->bind_first_slot indicates the index of the first emitted
1006d80efd5cSThomas Hellstrom  * binding, and @cbs->bind_cmd_buffer contains the command data.
1007d80efd5cSThomas Hellstrom  */
vmw_collect_dirty_vbs(struct vmw_ctx_binding_state * cbs,const struct vmw_ctx_bindinfo * bi,unsigned long * dirty,u32 max_num)1008d80efd5cSThomas Hellstrom static void vmw_collect_dirty_vbs(struct vmw_ctx_binding_state *cbs,
1009d80efd5cSThomas Hellstrom 				  const struct vmw_ctx_bindinfo *bi,
1010d80efd5cSThomas Hellstrom 				  unsigned long *dirty,
1011d80efd5cSThomas Hellstrom 				  u32 max_num)
1012d80efd5cSThomas Hellstrom {
1013d80efd5cSThomas Hellstrom 	const struct vmw_ctx_bindinfo_vb *biv =
1014d80efd5cSThomas Hellstrom 		container_of(bi, struct vmw_ctx_bindinfo_vb, bi);
1015d80efd5cSThomas Hellstrom 	unsigned long i, next_bit;
1016d80efd5cSThomas Hellstrom 	SVGA3dVertexBuffer *vbs = (SVGA3dVertexBuffer *) &cbs->bind_cmd_buffer;
1017d80efd5cSThomas Hellstrom 
1018d80efd5cSThomas Hellstrom 	cbs->bind_cmd_count = 0;
1019d80efd5cSThomas Hellstrom 	i = find_first_bit(dirty, max_num);
1020d80efd5cSThomas Hellstrom 	next_bit = i;
1021d80efd5cSThomas Hellstrom 	cbs->bind_first_slot = i;
1022d80efd5cSThomas Hellstrom 
1023d80efd5cSThomas Hellstrom 	biv += i;
1024d80efd5cSThomas Hellstrom 	for (; i < max_num; ++i, ++biv, ++vbs) {
1025d80efd5cSThomas Hellstrom 		if (!biv->bi.ctx || biv->bi.scrubbed) {
1026d80efd5cSThomas Hellstrom 			vbs->sid = SVGA3D_INVALID_ID;
1027d80efd5cSThomas Hellstrom 			vbs->stride = 0;
1028d80efd5cSThomas Hellstrom 			vbs->offset = 0;
1029d80efd5cSThomas Hellstrom 		} else {
1030d80efd5cSThomas Hellstrom 			vbs->sid = biv->bi.res->id;
1031d80efd5cSThomas Hellstrom 			vbs->stride = biv->stride;
1032d80efd5cSThomas Hellstrom 			vbs->offset = biv->offset;
1033d80efd5cSThomas Hellstrom 		}
1034d80efd5cSThomas Hellstrom 		cbs->bind_cmd_count++;
1035d80efd5cSThomas Hellstrom 		if (next_bit == i) {
1036d80efd5cSThomas Hellstrom 			next_bit = find_next_bit(dirty, max_num, i + 1);
1037d80efd5cSThomas Hellstrom 			if (next_bit >= max_num)
1038d80efd5cSThomas Hellstrom 				break;
1039d80efd5cSThomas Hellstrom 		}
1040d80efd5cSThomas Hellstrom 	}
1041d80efd5cSThomas Hellstrom }
1042d80efd5cSThomas Hellstrom 
1043d80efd5cSThomas Hellstrom /**
10442cd80dbdSZack Rusin  * vmw_emit_set_vb - Issue delayed vertex buffer binding commands
1045d80efd5cSThomas Hellstrom  *
1046d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
1047d80efd5cSThomas Hellstrom  *
1048d80efd5cSThomas Hellstrom  */
vmw_emit_set_vb(struct vmw_ctx_binding_state * cbs)1049d80efd5cSThomas Hellstrom static int vmw_emit_set_vb(struct vmw_ctx_binding_state *cbs)
1050d80efd5cSThomas Hellstrom {
1051d80efd5cSThomas Hellstrom 	const struct vmw_ctx_bindinfo *loc =
1052d80efd5cSThomas Hellstrom 		&cbs->vertex_buffers[0].bi;
1053d80efd5cSThomas Hellstrom 	struct {
1054d80efd5cSThomas Hellstrom 		SVGA3dCmdHeader header;
1055d80efd5cSThomas Hellstrom 		SVGA3dCmdDXSetVertexBuffers body;
1056d80efd5cSThomas Hellstrom 	} *cmd;
1057d80efd5cSThomas Hellstrom 	size_t cmd_size, set_vb_size;
1058d80efd5cSThomas Hellstrom 	const struct vmw_resource *ctx = vmw_cbs_context(cbs);
1059d80efd5cSThomas Hellstrom 
1060d80efd5cSThomas Hellstrom 	vmw_collect_dirty_vbs(cbs, loc, cbs->dirty_vb,
1061d80efd5cSThomas Hellstrom 			     SVGA3D_DX_MAX_VERTEXBUFFERS);
1062d80efd5cSThomas Hellstrom 	if (cbs->bind_cmd_count == 0)
1063d80efd5cSThomas Hellstrom 		return 0;
1064d80efd5cSThomas Hellstrom 
1065d80efd5cSThomas Hellstrom 	set_vb_size = cbs->bind_cmd_count*sizeof(SVGA3dVertexBuffer);
1066d80efd5cSThomas Hellstrom 	cmd_size = sizeof(*cmd) + set_vb_size;
10678426ed9cSZack Rusin 	cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id);
106811c45419SDeepak Rawat 	if (unlikely(cmd == NULL))
1069d80efd5cSThomas Hellstrom 		return -ENOMEM;
1070d80efd5cSThomas Hellstrom 
1071d80efd5cSThomas Hellstrom 	cmd->header.id = SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS;
1072d80efd5cSThomas Hellstrom 	cmd->header.size = sizeof(cmd->body) + set_vb_size;
1073d80efd5cSThomas Hellstrom 	cmd->body.startBuffer = cbs->bind_first_slot;
1074d80efd5cSThomas Hellstrom 
1075d80efd5cSThomas Hellstrom 	memcpy(&cmd[1], cbs->bind_cmd_buffer, set_vb_size);
1076d80efd5cSThomas Hellstrom 
10778426ed9cSZack Rusin 	vmw_cmd_commit(ctx->dev_priv, cmd_size);
1078d80efd5cSThomas Hellstrom 	bitmap_clear(cbs->dirty_vb,
1079d80efd5cSThomas Hellstrom 		     cbs->bind_first_slot, cbs->bind_cmd_count);
1080d80efd5cSThomas Hellstrom 
1081d80efd5cSThomas Hellstrom 	return 0;
1082d80efd5cSThomas Hellstrom }
1083d80efd5cSThomas Hellstrom 
vmw_emit_set_uav(struct vmw_ctx_binding_state * cbs)10845e8ec0d9SDeepak Rawat static int vmw_emit_set_uav(struct vmw_ctx_binding_state *cbs)
10855e8ec0d9SDeepak Rawat {
108674231041SZack Rusin 	const struct vmw_ctx_bindinfo_view *loc = &cbs->ua_views[0].views[0];
10875e8ec0d9SDeepak Rawat 	struct {
10885e8ec0d9SDeepak Rawat 		SVGA3dCmdHeader header;
10895e8ec0d9SDeepak Rawat 		SVGA3dCmdDXSetUAViews body;
10905e8ec0d9SDeepak Rawat 	} *cmd;
10915e8ec0d9SDeepak Rawat 	size_t cmd_size, view_id_size;
10925e8ec0d9SDeepak Rawat 	const struct vmw_resource *ctx = vmw_cbs_context(cbs);
10935e8ec0d9SDeepak Rawat 
10944fb9326bSZack Rusin 	vmw_collect_view_ids(cbs, loc, vmw_max_num_uavs(cbs->dev_priv));
10955e8ec0d9SDeepak Rawat 	view_id_size = cbs->bind_cmd_count*sizeof(uint32);
10965e8ec0d9SDeepak Rawat 	cmd_size = sizeof(*cmd) + view_id_size;
10978426ed9cSZack Rusin 	cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id);
10985e8ec0d9SDeepak Rawat 	if (!cmd)
10995e8ec0d9SDeepak Rawat 		return -ENOMEM;
11005e8ec0d9SDeepak Rawat 
11015e8ec0d9SDeepak Rawat 	cmd->header.id = SVGA_3D_CMD_DX_SET_UA_VIEWS;
11025e8ec0d9SDeepak Rawat 	cmd->header.size = sizeof(cmd->body) + view_id_size;
11035e8ec0d9SDeepak Rawat 
11045e8ec0d9SDeepak Rawat 	/* Splice index is specified user-space   */
11055e8ec0d9SDeepak Rawat 	cmd->body.uavSpliceIndex = cbs->ua_views[0].index;
11065e8ec0d9SDeepak Rawat 
11075e8ec0d9SDeepak Rawat 	memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size);
11085e8ec0d9SDeepak Rawat 
11098426ed9cSZack Rusin 	vmw_cmd_commit(ctx->dev_priv, cmd_size);
11105e8ec0d9SDeepak Rawat 
11115e8ec0d9SDeepak Rawat 	return 0;
11125e8ec0d9SDeepak Rawat }
11135e8ec0d9SDeepak Rawat 
vmw_emit_set_cs_uav(struct vmw_ctx_binding_state * cbs)11145e8ec0d9SDeepak Rawat static int vmw_emit_set_cs_uav(struct vmw_ctx_binding_state *cbs)
11155e8ec0d9SDeepak Rawat {
111674231041SZack Rusin 	const struct vmw_ctx_bindinfo_view *loc = &cbs->ua_views[1].views[0];
11175e8ec0d9SDeepak Rawat 	struct {
11185e8ec0d9SDeepak Rawat 		SVGA3dCmdHeader header;
11195e8ec0d9SDeepak Rawat 		SVGA3dCmdDXSetCSUAViews body;
11205e8ec0d9SDeepak Rawat 	} *cmd;
11215e8ec0d9SDeepak Rawat 	size_t cmd_size, view_id_size;
11225e8ec0d9SDeepak Rawat 	const struct vmw_resource *ctx = vmw_cbs_context(cbs);
11235e8ec0d9SDeepak Rawat 
11244fb9326bSZack Rusin 	vmw_collect_view_ids(cbs, loc, vmw_max_num_uavs(cbs->dev_priv));
11255e8ec0d9SDeepak Rawat 	view_id_size = cbs->bind_cmd_count*sizeof(uint32);
11265e8ec0d9SDeepak Rawat 	cmd_size = sizeof(*cmd) + view_id_size;
11278426ed9cSZack Rusin 	cmd = VMW_CMD_CTX_RESERVE(ctx->dev_priv, cmd_size, ctx->id);
11285e8ec0d9SDeepak Rawat 	if (!cmd)
11295e8ec0d9SDeepak Rawat 		return -ENOMEM;
11305e8ec0d9SDeepak Rawat 
11315e8ec0d9SDeepak Rawat 	cmd->header.id = SVGA_3D_CMD_DX_SET_CS_UA_VIEWS;
11325e8ec0d9SDeepak Rawat 	cmd->header.size = sizeof(cmd->body) + view_id_size;
11335e8ec0d9SDeepak Rawat 
11345e8ec0d9SDeepak Rawat 	/* Start index is specified user-space */
11355e8ec0d9SDeepak Rawat 	cmd->body.startIndex = cbs->ua_views[1].index;
11365e8ec0d9SDeepak Rawat 
11375e8ec0d9SDeepak Rawat 	memcpy(&cmd[1], cbs->bind_cmd_buffer, view_id_size);
11385e8ec0d9SDeepak Rawat 
11398426ed9cSZack Rusin 	vmw_cmd_commit(ctx->dev_priv, cmd_size);
11405e8ec0d9SDeepak Rawat 
11415e8ec0d9SDeepak Rawat 	return 0;
11425e8ec0d9SDeepak Rawat }
11435e8ec0d9SDeepak Rawat 
1144d80efd5cSThomas Hellstrom /**
1145d80efd5cSThomas Hellstrom  * vmw_binding_emit_dirty - Issue delayed binding commands
1146d80efd5cSThomas Hellstrom  *
1147d80efd5cSThomas Hellstrom  * @cbs: Pointer to the context's struct vmw_ctx_binding_state
1148d80efd5cSThomas Hellstrom  *
1149d80efd5cSThomas Hellstrom  * This function issues the delayed binding commands that arise from
1150d80efd5cSThomas Hellstrom  * previous scrub / unscrub calls. These binding commands are typically
1151d80efd5cSThomas Hellstrom  * commands that batch a number of bindings and therefore it makes sense
1152d80efd5cSThomas Hellstrom  * to delay them.
1153d80efd5cSThomas Hellstrom  */
vmw_binding_emit_dirty(struct vmw_ctx_binding_state * cbs)1154d80efd5cSThomas Hellstrom static int vmw_binding_emit_dirty(struct vmw_ctx_binding_state *cbs)
1155d80efd5cSThomas Hellstrom {
1156d80efd5cSThomas Hellstrom 	int ret = 0;
1157d80efd5cSThomas Hellstrom 	unsigned long hit = 0;
1158d80efd5cSThomas Hellstrom 
1159d80efd5cSThomas Hellstrom 	while ((hit = find_next_bit(&cbs->dirty, VMW_BINDING_NUM_BITS, hit))
1160d80efd5cSThomas Hellstrom 	      < VMW_BINDING_NUM_BITS) {
1161d80efd5cSThomas Hellstrom 
1162d80efd5cSThomas Hellstrom 		switch (hit) {
1163d80efd5cSThomas Hellstrom 		case VMW_BINDING_RT_BIT:
1164d80efd5cSThomas Hellstrom 			ret = vmw_emit_set_rt(cbs);
1165d80efd5cSThomas Hellstrom 			break;
1166d80efd5cSThomas Hellstrom 		case VMW_BINDING_PS_BIT:
1167d80efd5cSThomas Hellstrom 			ret = vmw_binding_emit_dirty_ps(cbs);
1168d80efd5cSThomas Hellstrom 			break;
1169403fef50SDeepak Rawat 		case VMW_BINDING_SO_T_BIT:
1170403fef50SDeepak Rawat 			ret = vmw_emit_set_so_target(cbs);
1171d80efd5cSThomas Hellstrom 			break;
1172d80efd5cSThomas Hellstrom 		case VMW_BINDING_VB_BIT:
1173d80efd5cSThomas Hellstrom 			ret = vmw_emit_set_vb(cbs);
1174d80efd5cSThomas Hellstrom 			break;
11755e8ec0d9SDeepak Rawat 		case VMW_BINDING_UAV_BIT:
11765e8ec0d9SDeepak Rawat 			ret = vmw_emit_set_uav(cbs);
11775e8ec0d9SDeepak Rawat 			break;
11785e8ec0d9SDeepak Rawat 		case VMW_BINDING_CS_UAV_BIT:
11795e8ec0d9SDeepak Rawat 			ret = vmw_emit_set_cs_uav(cbs);
11805e8ec0d9SDeepak Rawat 			break;
1181d80efd5cSThomas Hellstrom 		default:
1182d80efd5cSThomas Hellstrom 			BUG();
1183d80efd5cSThomas Hellstrom 		}
1184d80efd5cSThomas Hellstrom 		if (ret)
1185d80efd5cSThomas Hellstrom 			return ret;
1186d80efd5cSThomas Hellstrom 
1187d80efd5cSThomas Hellstrom 		__clear_bit(hit, &cbs->dirty);
1188d80efd5cSThomas Hellstrom 		hit++;
1189d80efd5cSThomas Hellstrom 	}
1190d80efd5cSThomas Hellstrom 
1191d80efd5cSThomas Hellstrom 	return 0;
1192d80efd5cSThomas Hellstrom }
1193d80efd5cSThomas Hellstrom 
1194d80efd5cSThomas Hellstrom /**
1195d80efd5cSThomas Hellstrom  * vmw_binding_scrub_sr - Schedule a dx shaderresource binding
1196d80efd5cSThomas Hellstrom  * scrub from a context
1197d80efd5cSThomas Hellstrom  *
1198d80efd5cSThomas Hellstrom  * @bi: single binding information.
1199d80efd5cSThomas Hellstrom  * @rebind: Whether to issue a bind instead of scrub command.
1200d80efd5cSThomas Hellstrom  */
vmw_binding_scrub_sr(struct vmw_ctx_bindinfo * bi,bool rebind)1201d80efd5cSThomas Hellstrom static int vmw_binding_scrub_sr(struct vmw_ctx_bindinfo *bi, bool rebind)
1202d80efd5cSThomas Hellstrom {
1203d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_view *biv =
1204d80efd5cSThomas Hellstrom 		container_of(bi, struct vmw_ctx_bindinfo_view, bi);
1205d80efd5cSThomas Hellstrom 	struct vmw_ctx_binding_state *cbs =
1206d80efd5cSThomas Hellstrom 		vmw_context_binding_state(bi->ctx);
1207d80efd5cSThomas Hellstrom 
1208d80efd5cSThomas Hellstrom 	__set_bit(biv->slot, cbs->per_shader[biv->shader_slot].dirty_sr);
1209d80efd5cSThomas Hellstrom 	__set_bit(VMW_BINDING_PS_SR_BIT,
1210d80efd5cSThomas Hellstrom 		  &cbs->per_shader[biv->shader_slot].dirty);
1211d80efd5cSThomas Hellstrom 	__set_bit(VMW_BINDING_PS_BIT, &cbs->dirty);
1212d80efd5cSThomas Hellstrom 
1213d80efd5cSThomas Hellstrom 	return 0;
1214d80efd5cSThomas Hellstrom }
1215d80efd5cSThomas Hellstrom 
1216d80efd5cSThomas Hellstrom /**
1217d80efd5cSThomas Hellstrom  * vmw_binding_scrub_dx_rt - Schedule a dx rendertarget binding
1218d80efd5cSThomas Hellstrom  * scrub from a context
1219d80efd5cSThomas Hellstrom  *
1220d80efd5cSThomas Hellstrom  * @bi: single binding information.
1221d80efd5cSThomas Hellstrom  * @rebind: Whether to issue a bind instead of scrub command.
1222d80efd5cSThomas Hellstrom  */
vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo * bi,bool rebind)1223d80efd5cSThomas Hellstrom static int vmw_binding_scrub_dx_rt(struct vmw_ctx_bindinfo *bi, bool rebind)
1224d80efd5cSThomas Hellstrom {
1225d80efd5cSThomas Hellstrom 	struct vmw_ctx_binding_state *cbs =
1226d80efd5cSThomas Hellstrom 		vmw_context_binding_state(bi->ctx);
1227d80efd5cSThomas Hellstrom 
1228d80efd5cSThomas Hellstrom 	__set_bit(VMW_BINDING_RT_BIT, &cbs->dirty);
1229d80efd5cSThomas Hellstrom 
1230d80efd5cSThomas Hellstrom 	return 0;
1231d80efd5cSThomas Hellstrom }
1232d80efd5cSThomas Hellstrom 
1233d80efd5cSThomas Hellstrom /**
1234403fef50SDeepak Rawat  * vmw_binding_scrub_so_target - Schedule a dx streamoutput buffer binding
1235d80efd5cSThomas Hellstrom  * scrub from a context
1236d80efd5cSThomas Hellstrom  *
1237d80efd5cSThomas Hellstrom  * @bi: single binding information.
1238d80efd5cSThomas Hellstrom  * @rebind: Whether to issue a bind instead of scrub command.
1239d80efd5cSThomas Hellstrom  */
vmw_binding_scrub_so_target(struct vmw_ctx_bindinfo * bi,bool rebind)1240403fef50SDeepak Rawat static int vmw_binding_scrub_so_target(struct vmw_ctx_bindinfo *bi, bool rebind)
1241d80efd5cSThomas Hellstrom {
1242d80efd5cSThomas Hellstrom 	struct vmw_ctx_binding_state *cbs =
1243d80efd5cSThomas Hellstrom 		vmw_context_binding_state(bi->ctx);
1244d80efd5cSThomas Hellstrom 
1245403fef50SDeepak Rawat 	__set_bit(VMW_BINDING_SO_T_BIT, &cbs->dirty);
1246d80efd5cSThomas Hellstrom 
1247d80efd5cSThomas Hellstrom 	return 0;
1248d80efd5cSThomas Hellstrom }
1249d80efd5cSThomas Hellstrom 
1250d80efd5cSThomas Hellstrom /**
1251d80efd5cSThomas Hellstrom  * vmw_binding_scrub_vb - Schedule a dx vertex buffer binding
1252d80efd5cSThomas Hellstrom  * scrub from a context
1253d80efd5cSThomas Hellstrom  *
1254d80efd5cSThomas Hellstrom  * @bi: single binding information.
1255d80efd5cSThomas Hellstrom  * @rebind: Whether to issue a bind instead of scrub command.
1256d80efd5cSThomas Hellstrom  */
vmw_binding_scrub_vb(struct vmw_ctx_bindinfo * bi,bool rebind)1257d80efd5cSThomas Hellstrom static int vmw_binding_scrub_vb(struct vmw_ctx_bindinfo *bi, bool rebind)
1258d80efd5cSThomas Hellstrom {
1259d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_vb *bivb =
1260d80efd5cSThomas Hellstrom 		container_of(bi, struct vmw_ctx_bindinfo_vb, bi);
1261d80efd5cSThomas Hellstrom 	struct vmw_ctx_binding_state *cbs =
1262d80efd5cSThomas Hellstrom 		vmw_context_binding_state(bi->ctx);
1263d80efd5cSThomas Hellstrom 
1264d80efd5cSThomas Hellstrom 	__set_bit(bivb->slot, cbs->dirty_vb);
1265d80efd5cSThomas Hellstrom 	__set_bit(VMW_BINDING_VB_BIT, &cbs->dirty);
1266d80efd5cSThomas Hellstrom 
1267d80efd5cSThomas Hellstrom 	return 0;
1268d80efd5cSThomas Hellstrom }
1269d80efd5cSThomas Hellstrom 
1270d80efd5cSThomas Hellstrom /**
1271d80efd5cSThomas Hellstrom  * vmw_binding_scrub_ib - scrub a dx index buffer binding from a context
1272d80efd5cSThomas Hellstrom  *
1273d80efd5cSThomas Hellstrom  * @bi: single binding information.
1274d80efd5cSThomas Hellstrom  * @rebind: Whether to issue a bind instead of scrub command.
1275d80efd5cSThomas Hellstrom  */
vmw_binding_scrub_ib(struct vmw_ctx_bindinfo * bi,bool rebind)1276d80efd5cSThomas Hellstrom static int vmw_binding_scrub_ib(struct vmw_ctx_bindinfo *bi, bool rebind)
1277d80efd5cSThomas Hellstrom {
1278d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo_ib *binding =
1279d80efd5cSThomas Hellstrom 		container_of(bi, typeof(*binding), bi);
1280d80efd5cSThomas Hellstrom 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
1281d80efd5cSThomas Hellstrom 	struct {
1282d80efd5cSThomas Hellstrom 		SVGA3dCmdHeader header;
1283d80efd5cSThomas Hellstrom 		SVGA3dCmdDXSetIndexBuffer body;
1284d80efd5cSThomas Hellstrom 	} *cmd;
1285d80efd5cSThomas Hellstrom 
12868426ed9cSZack Rusin 	cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), bi->ctx->id);
128711c45419SDeepak Rawat 	if (unlikely(cmd == NULL))
1288d80efd5cSThomas Hellstrom 		return -ENOMEM;
128911c45419SDeepak Rawat 
1290d80efd5cSThomas Hellstrom 	cmd->header.id = SVGA_3D_CMD_DX_SET_INDEX_BUFFER;
1291d80efd5cSThomas Hellstrom 	cmd->header.size = sizeof(cmd->body);
1292d80efd5cSThomas Hellstrom 	if (rebind) {
1293d80efd5cSThomas Hellstrom 		cmd->body.sid = bi->res->id;
1294d80efd5cSThomas Hellstrom 		cmd->body.format = binding->format;
1295d80efd5cSThomas Hellstrom 		cmd->body.offset = binding->offset;
1296d80efd5cSThomas Hellstrom 	} else {
1297d80efd5cSThomas Hellstrom 		cmd->body.sid = SVGA3D_INVALID_ID;
1298d80efd5cSThomas Hellstrom 		cmd->body.format = 0;
1299d80efd5cSThomas Hellstrom 		cmd->body.offset = 0;
1300d80efd5cSThomas Hellstrom 	}
1301d80efd5cSThomas Hellstrom 
13028426ed9cSZack Rusin 	vmw_cmd_commit(dev_priv, sizeof(*cmd));
1303d80efd5cSThomas Hellstrom 
1304d80efd5cSThomas Hellstrom 	return 0;
1305d80efd5cSThomas Hellstrom }
1306d80efd5cSThomas Hellstrom 
vmw_binding_scrub_uav(struct vmw_ctx_bindinfo * bi,bool rebind)13075e8ec0d9SDeepak Rawat static int vmw_binding_scrub_uav(struct vmw_ctx_bindinfo *bi, bool rebind)
13085e8ec0d9SDeepak Rawat {
13095e8ec0d9SDeepak Rawat 	struct vmw_ctx_binding_state *cbs = vmw_context_binding_state(bi->ctx);
13105e8ec0d9SDeepak Rawat 
13115e8ec0d9SDeepak Rawat 	__set_bit(VMW_BINDING_UAV_BIT, &cbs->dirty);
13125e8ec0d9SDeepak Rawat 	return 0;
13135e8ec0d9SDeepak Rawat }
13145e8ec0d9SDeepak Rawat 
vmw_binding_scrub_cs_uav(struct vmw_ctx_bindinfo * bi,bool rebind)13155e8ec0d9SDeepak Rawat static int vmw_binding_scrub_cs_uav(struct vmw_ctx_bindinfo *bi, bool rebind)
13165e8ec0d9SDeepak Rawat {
13175e8ec0d9SDeepak Rawat 	struct vmw_ctx_binding_state *cbs = vmw_context_binding_state(bi->ctx);
13185e8ec0d9SDeepak Rawat 
13195e8ec0d9SDeepak Rawat 	__set_bit(VMW_BINDING_CS_UAV_BIT, &cbs->dirty);
13205e8ec0d9SDeepak Rawat 	return 0;
13215e8ec0d9SDeepak Rawat }
13225e8ec0d9SDeepak Rawat 
1323d80efd5cSThomas Hellstrom /**
1324e8bead9cSDeepak Rawat  * vmw_binding_scrub_so - Scrub a streamoutput binding from context.
1325e8bead9cSDeepak Rawat  * @bi: Single binding information.
1326e8bead9cSDeepak Rawat  * @rebind: Whether to issue a bind instead of scrub command.
1327e8bead9cSDeepak Rawat  */
vmw_binding_scrub_so(struct vmw_ctx_bindinfo * bi,bool rebind)1328e8bead9cSDeepak Rawat static int vmw_binding_scrub_so(struct vmw_ctx_bindinfo *bi, bool rebind)
1329e8bead9cSDeepak Rawat {
1330e8bead9cSDeepak Rawat 	struct vmw_ctx_bindinfo_so *binding =
1331e8bead9cSDeepak Rawat 		container_of(bi, typeof(*binding), bi);
1332e8bead9cSDeepak Rawat 	struct vmw_private *dev_priv = bi->ctx->dev_priv;
1333e8bead9cSDeepak Rawat 	struct {
1334e8bead9cSDeepak Rawat 		SVGA3dCmdHeader header;
1335e8bead9cSDeepak Rawat 		SVGA3dCmdDXSetStreamOutput body;
1336e8bead9cSDeepak Rawat 	} *cmd;
1337e8bead9cSDeepak Rawat 
13388426ed9cSZack Rusin 	cmd = VMW_CMD_CTX_RESERVE(dev_priv, sizeof(*cmd), bi->ctx->id);
1339e8bead9cSDeepak Rawat 	if (!cmd)
1340e8bead9cSDeepak Rawat 		return -ENOMEM;
1341e8bead9cSDeepak Rawat 
1342e8bead9cSDeepak Rawat 	cmd->header.id = SVGA_3D_CMD_DX_SET_STREAMOUTPUT;
1343e8bead9cSDeepak Rawat 	cmd->header.size = sizeof(cmd->body);
1344e8bead9cSDeepak Rawat 	cmd->body.soid = rebind ? bi->res->id : SVGA3D_INVALID_ID;
13458426ed9cSZack Rusin 	vmw_cmd_commit(dev_priv, sizeof(*cmd));
1346e8bead9cSDeepak Rawat 
1347e8bead9cSDeepak Rawat 	return 0;
1348e8bead9cSDeepak Rawat }
1349e8bead9cSDeepak Rawat 
1350e8bead9cSDeepak Rawat /**
13518aadeb8aSZack Rusin  * vmw_binding_state_alloc - Allocate a struct vmw_ctx_binding_state.
1352d80efd5cSThomas Hellstrom  *
1353d80efd5cSThomas Hellstrom  * @dev_priv: Pointer to a device private structure.
1354d80efd5cSThomas Hellstrom  *
1355d80efd5cSThomas Hellstrom  * Returns a pointer to a newly allocated struct or an error pointer on error.
1356d80efd5cSThomas Hellstrom  */
1357d80efd5cSThomas Hellstrom struct vmw_ctx_binding_state *
vmw_binding_state_alloc(struct vmw_private * dev_priv)1358d80efd5cSThomas Hellstrom vmw_binding_state_alloc(struct vmw_private *dev_priv)
1359d80efd5cSThomas Hellstrom {
1360d80efd5cSThomas Hellstrom 	struct vmw_ctx_binding_state *cbs;
1361d80efd5cSThomas Hellstrom 
1362d80efd5cSThomas Hellstrom 	cbs = vzalloc(sizeof(*cbs));
1363d80efd5cSThomas Hellstrom 	if (!cbs) {
1364d80efd5cSThomas Hellstrom 		return ERR_PTR(-ENOMEM);
1365d80efd5cSThomas Hellstrom 	}
1366d80efd5cSThomas Hellstrom 
1367d80efd5cSThomas Hellstrom 	cbs->dev_priv = dev_priv;
1368d80efd5cSThomas Hellstrom 	INIT_LIST_HEAD(&cbs->list);
1369d80efd5cSThomas Hellstrom 
1370d80efd5cSThomas Hellstrom 	return cbs;
1371d80efd5cSThomas Hellstrom }
1372d80efd5cSThomas Hellstrom 
1373d80efd5cSThomas Hellstrom /**
13748aadeb8aSZack Rusin  * vmw_binding_state_free - Free a struct vmw_ctx_binding_state.
1375d80efd5cSThomas Hellstrom  *
1376d80efd5cSThomas Hellstrom  * @cbs: Pointer to the struct vmw_ctx_binding_state to be freed.
1377d80efd5cSThomas Hellstrom  */
vmw_binding_state_free(struct vmw_ctx_binding_state * cbs)1378d80efd5cSThomas Hellstrom void vmw_binding_state_free(struct vmw_ctx_binding_state *cbs)
1379d80efd5cSThomas Hellstrom {
1380d80efd5cSThomas Hellstrom 	vfree(cbs);
1381d80efd5cSThomas Hellstrom }
1382d80efd5cSThomas Hellstrom 
1383d80efd5cSThomas Hellstrom /**
1384d80efd5cSThomas Hellstrom  * vmw_binding_state_list - Get the binding list of a
1385d80efd5cSThomas Hellstrom  * struct vmw_ctx_binding_state
1386d80efd5cSThomas Hellstrom  *
1387d80efd5cSThomas Hellstrom  * @cbs: Pointer to the struct vmw_ctx_binding_state
1388d80efd5cSThomas Hellstrom  *
1389d80efd5cSThomas Hellstrom  * Returns the binding list which can be used to traverse through the bindings
1390d80efd5cSThomas Hellstrom  * and access the resource information of all bindings.
1391d80efd5cSThomas Hellstrom  */
vmw_binding_state_list(struct vmw_ctx_binding_state * cbs)1392d80efd5cSThomas Hellstrom struct list_head *vmw_binding_state_list(struct vmw_ctx_binding_state *cbs)
1393d80efd5cSThomas Hellstrom {
1394d80efd5cSThomas Hellstrom 	return &cbs->list;
1395d80efd5cSThomas Hellstrom }
1396d80efd5cSThomas Hellstrom 
1397d80efd5cSThomas Hellstrom /**
13982cd80dbdSZack Rusin  * vmw_binding_state_reset - clear a struct vmw_ctx_binding_state
1399d80efd5cSThomas Hellstrom  *
1400d80efd5cSThomas Hellstrom  * @cbs: Pointer to the struct vmw_ctx_binding_state to be cleared
1401d80efd5cSThomas Hellstrom  *
1402d80efd5cSThomas Hellstrom  * Drops all bindings registered in @cbs. No device binding actions are
1403d80efd5cSThomas Hellstrom  * performed.
1404d80efd5cSThomas Hellstrom  */
vmw_binding_state_reset(struct vmw_ctx_binding_state * cbs)1405d80efd5cSThomas Hellstrom void vmw_binding_state_reset(struct vmw_ctx_binding_state *cbs)
1406d80efd5cSThomas Hellstrom {
1407d80efd5cSThomas Hellstrom 	struct vmw_ctx_bindinfo *entry, *next;
1408d80efd5cSThomas Hellstrom 
1409d80efd5cSThomas Hellstrom 	list_for_each_entry_safe(entry, next, &cbs->list, ctx_list)
1410d80efd5cSThomas Hellstrom 		vmw_binding_drop(entry);
1411d80efd5cSThomas Hellstrom }
1412d80efd5cSThomas Hellstrom 
1413a9f58c45SThomas Hellstrom /**
1414a9f58c45SThomas Hellstrom  * vmw_binding_dirtying - Return whether a binding type is dirtying its resource
1415a9f58c45SThomas Hellstrom  * @binding_type: The binding type
1416a9f58c45SThomas Hellstrom  *
1417a9f58c45SThomas Hellstrom  * Each time a resource is put on the validation list as the result of a
1418a9f58c45SThomas Hellstrom  * context binding referencing it, we need to determine whether that resource
1419a9f58c45SThomas Hellstrom  * will be dirtied (written to by the GPU) as a result of the corresponding
14205e8ec0d9SDeepak Rawat  * GPU operation. Currently rendertarget-, depth-stencil-, stream-output-target
14215e8ec0d9SDeepak Rawat  * and unordered access view bindings are capable of dirtying its resource.
1422a9f58c45SThomas Hellstrom  *
1423a9f58c45SThomas Hellstrom  * Return: Whether the binding type dirties the resource its binding points to.
1424a9f58c45SThomas Hellstrom  */
vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type)1425a9f58c45SThomas Hellstrom u32 vmw_binding_dirtying(enum vmw_ctx_binding_type binding_type)
1426a9f58c45SThomas Hellstrom {
1427a9f58c45SThomas Hellstrom 	static u32 is_binding_dirtying[vmw_ctx_binding_max] = {
1428a9f58c45SThomas Hellstrom 		[vmw_ctx_binding_rt] = VMW_RES_DIRTY_SET,
1429a9f58c45SThomas Hellstrom 		[vmw_ctx_binding_dx_rt] = VMW_RES_DIRTY_SET,
1430a9f58c45SThomas Hellstrom 		[vmw_ctx_binding_ds] = VMW_RES_DIRTY_SET,
1431403fef50SDeepak Rawat 		[vmw_ctx_binding_so_target] = VMW_RES_DIRTY_SET,
14325e8ec0d9SDeepak Rawat 		[vmw_ctx_binding_uav] = VMW_RES_DIRTY_SET,
14335e8ec0d9SDeepak Rawat 		[vmw_ctx_binding_cs_uav] = VMW_RES_DIRTY_SET,
1434a9f58c45SThomas Hellstrom 	};
1435a9f58c45SThomas Hellstrom 
1436a9f58c45SThomas Hellstrom 	/* Review this function as new bindings are added. */
1437e8bead9cSDeepak Rawat 	BUILD_BUG_ON(vmw_ctx_binding_max != 14);
1438a9f58c45SThomas Hellstrom 	return is_binding_dirtying[binding_type];
1439a9f58c45SThomas Hellstrom }
1440a9f58c45SThomas Hellstrom 
1441d80efd5cSThomas Hellstrom /*
1442d80efd5cSThomas Hellstrom  * This function is unused at run-time, and only used to hold various build
1443d80efd5cSThomas Hellstrom  * asserts important for code optimization assumptions.
1444d80efd5cSThomas Hellstrom  */
vmw_binding_build_asserts(void)1445d80efd5cSThomas Hellstrom static void vmw_binding_build_asserts(void)
1446d80efd5cSThomas Hellstrom {
1447d80efd5cSThomas Hellstrom 	BUILD_BUG_ON(SVGA3D_NUM_SHADERTYPE_DX10 != 3);
1448ebc9ac7cSZack Rusin 	BUILD_BUG_ON(SVGA3D_DX_MAX_RENDER_TARGETS > SVGA3D_RT_MAX);
1449d80efd5cSThomas Hellstrom 	BUILD_BUG_ON(sizeof(uint32) != sizeof(u32));
1450d80efd5cSThomas Hellstrom 
1451d80efd5cSThomas Hellstrom 	/*
1452d80efd5cSThomas Hellstrom 	 * struct vmw_ctx_binding_state::bind_cmd_buffer is used for various
1453d80efd5cSThomas Hellstrom 	 * view id arrays.
1454d80efd5cSThomas Hellstrom 	 */
1455d80efd5cSThomas Hellstrom 	BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_RT_MAX);
1456d80efd5cSThomas Hellstrom 	BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_SRVIEWS);
1457d80efd5cSThomas Hellstrom 	BUILD_BUG_ON(VMW_MAX_VIEW_BINDINGS < SVGA3D_DX_MAX_CONSTBUFFERS);
1458d80efd5cSThomas Hellstrom 
1459d80efd5cSThomas Hellstrom 	/*
1460d80efd5cSThomas Hellstrom 	 * struct vmw_ctx_binding_state::bind_cmd_buffer is used for
1461d80efd5cSThomas Hellstrom 	 * u32 view ids, SVGA3dSoTargets and SVGA3dVertexBuffers
1462d80efd5cSThomas Hellstrom 	 */
1463d80efd5cSThomas Hellstrom 	BUILD_BUG_ON(SVGA3D_DX_MAX_SOTARGETS*sizeof(SVGA3dSoTarget) >
1464d80efd5cSThomas Hellstrom 		     VMW_MAX_VIEW_BINDINGS*sizeof(u32));
1465d80efd5cSThomas Hellstrom 	BUILD_BUG_ON(SVGA3D_DX_MAX_VERTEXBUFFERS*sizeof(SVGA3dVertexBuffer) >
1466d80efd5cSThomas Hellstrom 		     VMW_MAX_VIEW_BINDINGS*sizeof(u32));
1467d80efd5cSThomas Hellstrom }
1468