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