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