xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/svga/svga_state.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright (c) 2008-2024 Broadcom. All Rights Reserved.
3  * The term “Broadcom” refers to Broadcom Inc.
4  * and/or its subsidiaries.
5  * SPDX-License-Identifier: MIT
6  */
7 
8 #include "util/u_bitmask.h"
9 #include "util/u_debug.h"
10 #include "pipe/p_defines.h"
11 #include "util/u_memory.h"
12 #include "draw/draw_context.h"
13 
14 #include "svga_context.h"
15 #include "svga_screen.h"
16 #include "svga_state.h"
17 #include "svga_draw.h"
18 #include "svga_cmd.h"
19 #include "svga_hw_reg.h"
20 
21 /* This is just enough to decide whether we need to use the draw
22  * module (swtnl) or not.
23  */
24 static const struct svga_tracked_state *need_swtnl_state[] =
25 {
26    &svga_update_need_swvfetch,
27    &svga_update_need_pipeline,
28    &svga_update_need_swtnl,
29    NULL
30 };
31 
32 
33 /* Atoms to update hardware state prior to emitting a clear or draw
34  * packet.
35  */
36 static const struct svga_tracked_state *hw_clear_state[] =
37 {
38    &svga_hw_scissor,
39    &svga_hw_viewport,
40    &svga_hw_framebuffer,
41    NULL
42 };
43 
44 
45 /**
46  * Atoms to update hardware state prior to emitting a draw packet
47  * for VGPU9 device.
48  */
49 static const struct svga_tracked_state *hw_draw_state_vgpu9[] =
50 {
51    &svga_hw_fs,
52    &svga_hw_vs,
53    &svga_hw_rss,
54    &svga_hw_tss,
55    &svga_hw_tss_binding,
56    &svga_hw_clip_planes,
57    &svga_hw_vdecl,
58    &svga_hw_fs_constants,
59    &svga_hw_vs_constants,
60    NULL
61 };
62 
63 
64 /**
65  * Atoms to update hardware state prior to emitting a draw packet
66  * for VGPU10 device.
67  * Geometry Shader is new to VGPU10.
68  * TSS and TSS bindings are replaced by sampler and sampler bindings.
69  */
70 static const struct svga_tracked_state *hw_draw_state_vgpu10[] =
71 {
72    &svga_need_tgsi_transform,
73    &svga_hw_fs,
74    &svga_hw_gs,
75    &svga_hw_vs,
76    &svga_hw_rss,
77    &svga_hw_sampler,
78    &svga_hw_sampler_bindings,
79    &svga_hw_clip_planes,
80    &svga_hw_vdecl,
81    &svga_hw_fs_constants,
82    &svga_hw_fs_constbufs,
83    &svga_hw_gs_constants,
84    &svga_hw_gs_constbufs,
85    &svga_hw_vs_constants,
86    &svga_hw_vs_constbufs,
87    NULL
88 };
89 
90 
91 /**
92  * Atoms to update hardware state prior to emitting a draw packet
93  * for SM5 device.
94  * TCS and TES Shaders are new to SM5 device.
95  */
96 static const struct svga_tracked_state *hw_draw_state_sm5[] =
97 {
98    &svga_need_tgsi_transform,
99    &svga_hw_fs,
100    &svga_hw_gs,
101    &svga_hw_tes,
102    &svga_hw_tcs,
103    &svga_hw_vs,
104    &svga_hw_rss,
105    &svga_hw_sampler,
106    &svga_hw_sampler_bindings,
107    &svga_hw_clip_planes,
108    &svga_hw_vdecl,
109    &svga_hw_fs_constants,
110    &svga_hw_fs_constbufs,
111    &svga_hw_gs_constants,
112    &svga_hw_gs_constbufs,
113    &svga_hw_tes_constants,
114    &svga_hw_tes_constbufs,
115    &svga_hw_tcs_constants,
116    &svga_hw_tcs_constbufs,
117    &svga_hw_vs_constants,
118    &svga_hw_vs_constbufs,
119    NULL
120 };
121 
122 
123 /**
124  * Atoms to update hardware state prior to emitting a draw packet
125  * for GL43 device which includes uav update.
126  */
127 static const struct svga_tracked_state *hw_draw_state_gl43[] =
128 {
129    &svga_need_tgsi_transform,
130    &svga_need_rawbuf_srv,
131    &svga_hw_uav,
132    &svga_hw_fs,
133    &svga_hw_gs,
134    &svga_hw_tes,
135    &svga_hw_tcs,
136    &svga_hw_vs,
137    &svga_hw_rss,
138    &svga_hw_sampler,
139    &svga_hw_sampler_bindings,
140    &svga_hw_clip_planes,
141    &svga_hw_vdecl,
142    &svga_hw_fs_constants,
143    &svga_hw_fs_constbufs,
144    &svga_hw_gs_constants,
145    &svga_hw_gs_constbufs,
146    &svga_hw_tes_constants,
147    &svga_hw_tes_constbufs,
148    &svga_hw_tcs_constants,
149    &svga_hw_tcs_constbufs,
150    &svga_hw_vs_constants,
151    &svga_hw_vs_constbufs,
152    NULL
153 };
154 
155 
156 static const struct svga_tracked_state *swtnl_draw_state[] =
157 {
158    &svga_update_swtnl_draw,
159    &svga_update_swtnl_vdecl,
160    NULL
161 };
162 
163 
164 /* Flattens the graph of state dependencies.  Could swap the positions
165  * of hw_clear_state and need_swtnl_state without breaking anything.
166  */
167 static const struct svga_tracked_state **state_levels[] =
168 {
169    need_swtnl_state,
170    hw_clear_state,
171    NULL,              /* hw_draw_state, to be set to the right version */
172    swtnl_draw_state
173 };
174 
175 
176 static uint64_t
check_state(uint64_t a,uint64_t b)177 check_state(uint64_t a, uint64_t b)
178 {
179    return (a & b);
180 }
181 
182 static void
accumulate_state(uint64_t * a,uint64_t b)183 accumulate_state(uint64_t *a, uint64_t b)
184 {
185    *a |= b;
186 }
187 
188 
189 static void
xor_states(uint64_t * result,uint64_t a,uint64_t b)190 xor_states(uint64_t *result, uint64_t a, uint64_t b)
191 {
192    *result = a ^ b;
193 }
194 
195 
196 static enum pipe_error
update_state(struct svga_context * svga,const struct svga_tracked_state * atoms[],uint64_t * state)197 update_state(struct svga_context *svga,
198              const struct svga_tracked_state *atoms[],
199              uint64_t *state)
200 {
201 #if MESA_DEBUG
202    bool debug = true;
203 #else
204    bool debug = false;
205 #endif
206    enum pipe_error ret = PIPE_OK;
207    unsigned i;
208 
209    ret = svga_hwtnl_flush( svga->hwtnl );
210    if (ret != PIPE_OK)
211       return ret;
212 
213    if (debug) {
214       /* Debug version which enforces various sanity checks on the
215        * state flags which are generated and checked to help ensure
216        * state atoms are ordered correctly in the list.
217        */
218       uint64_t examined, prev;
219 
220       examined = 0;
221       prev = *state;
222 
223       for (i = 0; atoms[i] != NULL; i++) {
224          uint64_t generated;
225 
226          assert(atoms[i]->dirty);
227          assert(atoms[i]->update);
228 
229          if (check_state(*state, atoms[i]->dirty)) {
230             if (0)
231                debug_printf("update: %s\n", atoms[i]->name);
232             ret = atoms[i]->update( svga, *state );
233             if (ret != PIPE_OK)
234                return ret;
235          }
236 
237          /* generated = (prev ^ state)
238           * if (examined & generated)
239           *     fail;
240           */
241          xor_states(&generated, prev, *state);
242          if (check_state(examined, generated)) {
243             debug_printf("state atom %s generated state already examined\n",
244                          atoms[i]->name);
245             assert(0);
246          }
247 
248          prev = *state;
249          accumulate_state(&examined, atoms[i]->dirty);
250       }
251    }
252    else {
253       for (i = 0; atoms[i] != NULL; i++) {
254          if (check_state(*state, atoms[i]->dirty)) {
255             ret = atoms[i]->update( svga, *state );
256             if (ret != PIPE_OK)
257                return ret;
258          }
259       }
260    }
261 
262    return PIPE_OK;
263 }
264 
265 
266 enum pipe_error
svga_update_state(struct svga_context * svga,unsigned max_level)267 svga_update_state(struct svga_context *svga, unsigned max_level)
268 {
269    struct svga_screen *screen = svga_screen(svga->pipe.screen);
270    enum pipe_error ret = PIPE_OK;
271    unsigned i;
272 
273    SVGA_STATS_TIME_PUSH(screen->sws, SVGA_STATS_TIME_UPDATESTATE);
274 
275    /* Check for updates to bound textures.  This can't be done in an
276     * atom as there is no flag which could provoke this test, and we
277     * cannot create one.
278     */
279    if (svga->state.texture_timestamp != screen->texture_timestamp) {
280       svga->state.texture_timestamp = screen->texture_timestamp;
281       svga->dirty |= SVGA_NEW_TEXTURE;
282    }
283 
284    for (i = 0; i <= max_level; i++) {
285       svga->dirty |= svga->state.dirty[i];
286 
287       if (svga->dirty) {
288          ret = update_state( svga,
289                              state_levels[i],
290                              &svga->dirty );
291          if (ret != PIPE_OK)
292             goto done;
293 
294          svga->state.dirty[i] = 0;
295       }
296    }
297 
298    for (; i < SVGA_STATE_MAX; i++)
299       svga->state.dirty[i] |= svga->dirty;
300 
301    svga->dirty = 0;
302 
303    svga->hud.num_validations++;
304 
305 done:
306    SVGA_STATS_TIME_POP(screen->sws);
307    return ret;
308 }
309 
310 
311 /**
312  * Update state.  If the first attempt fails, flush the command buffer
313  * and retry.
314  * \return  true if success, false if second attempt fails.
315  */
316 bool
svga_update_state_retry(struct svga_context * svga,unsigned max_level)317 svga_update_state_retry(struct svga_context *svga, unsigned max_level)
318 {
319    enum pipe_error ret;
320 
321    SVGA_RETRY_OOM(svga, ret, svga_update_state( svga, max_level ));
322 
323    return ret == PIPE_OK;
324 }
325 
326 
327 #define EMIT_RS(_rs, _count, _name, _value)     \
328 do {                                            \
329    _rs[_count].state = _name;                   \
330    _rs[_count].uintValue = _value;              \
331    _count++;                                    \
332 } while (0)
333 
334 
335 /* Setup any hardware state which will be constant through the life of
336  * a context.
337  */
338 enum pipe_error
svga_emit_initial_state(struct svga_context * svga)339 svga_emit_initial_state(struct svga_context *svga)
340 {
341    if (svga_have_vgpu10(svga)) {
342       SVGA3dRasterizerStateId id = util_bitmask_add(svga->rast_object_id_bm);
343       enum pipe_error ret;
344 
345       /* XXX preliminary code */
346       ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc,
347                                              id,
348                                              SVGA3D_FILLMODE_FILL,
349                                              SVGA3D_CULL_NONE,
350                                              1, /* frontCounterClockwise */
351                                              0, /* depthBias */
352                                              0.0f, /* depthBiasClamp */
353                                              0.0f, /* slopeScaledDepthBiasClamp */
354                                              0, /* depthClampEnable */
355                                              0, /* scissorEnable */
356                                              0, /* multisampleEnable */
357                                              0, /* aalineEnable */
358                                              1.0f, /* lineWidth */
359                                              0, /* lineStippleEnable */
360                                              0, /* lineStippleFactor */
361                                              0, /* lineStipplePattern */
362                                              0); /* provokingVertexLast */
363 
364 
365       assert(ret == PIPE_OK);
366 
367       ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, id);
368       return ret;
369    }
370    else {
371       SVGA3dRenderState *rs;
372       unsigned count = 0;
373       const unsigned COUNT = 2;
374       enum pipe_error ret;
375 
376       ret = SVGA3D_BeginSetRenderState( svga->swc, &rs, COUNT );
377       if (ret != PIPE_OK)
378          return ret;
379 
380       /* Always use D3D style coordinate space as this is the only one
381        * which is implemented on all backends.
382        */
383       EMIT_RS(rs, count, SVGA3D_RS_COORDINATETYPE,
384               SVGA3D_COORDINATE_LEFTHANDED );
385       EMIT_RS(rs, count, SVGA3D_RS_FRONTWINDING, SVGA3D_FRONTWINDING_CW );
386 
387       assert( COUNT == count );
388       SVGA_FIFOCommitAll( svga->swc );
389 
390       return PIPE_OK;
391    }
392 }
393 
394 
395 void
svga_init_tracked_state(struct svga_context * svga)396 svga_init_tracked_state(struct svga_context *svga)
397 {
398    /* Set the hw_draw_state atom list to the one for the particular gpu version.
399     */
400    state_levels[2] =
401       svga_have_gl43(svga) ? hw_draw_state_gl43 :
402          (svga_have_sm5(svga) ? hw_draw_state_sm5 :
403             ((svga_have_vgpu10(svga) ? hw_draw_state_vgpu10 :
404                                        hw_draw_state_vgpu9)));
405 }
406 
407 
408 static const struct svga_tracked_state *compute_state[] =
409 {
410    &svga_hw_cs_uav,
411    &svga_hw_cs_sampler,
412    &svga_hw_cs_sampler_bindings,
413    &svga_hw_cs,
414    &svga_hw_cs_constants,
415    &svga_hw_cs_constbufs,
416    NULL
417 };
418 
419 /**
420  * Update compute state.
421  * If the first attempt fails, flush the command buffer and retry.
422  * \return  true if success, false if second attempt fails.
423  */
424 bool
svga_update_compute_state(struct svga_context * svga)425 svga_update_compute_state(struct svga_context *svga)
426 {
427    enum pipe_error ret = PIPE_OK;
428    uint64_t compute_dirty = svga->dirty;
429 
430    if (compute_dirty) {
431       SVGA_RETRY_OOM(svga, ret, update_state(svga, compute_state,
432                                              &compute_dirty));
433 
434       /* Set the dirty flag to the remaining dirty bits which are
435        * not processed in the compute pipeline.
436        */
437       svga->dirty = compute_dirty;
438    }
439 
440    return ret == PIPE_OK;
441 }
442