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