xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/svga/svga_state_rss.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 "pipe/p_defines.h"
9 #include "util/u_bitmask.h"
10 #include "util/format/u_format.h"
11 #include "util/u_inlines.h"
12 #include "util/u_memory.h"
13 #include "util/u_math.h"
14 #include "util/u_memory.h"
15 
16 #include "svga_context.h"
17 #include "svga_screen.h"
18 #include "svga_state.h"
19 #include "svga_cmd.h"
20 #include "svga_format.h"
21 #include "svga_shader.h"
22 
23 
24 struct rs_queue {
25    unsigned rs_count;
26    SVGA3dRenderState rs[SVGA3D_RS_MAX];
27 };
28 
29 
30 #define EMIT_RS(svga, value, token)                       \
31 do {                                                            \
32    STATIC_ASSERT(SVGA3D_RS_##token < ARRAY_SIZE(svga->state.hw_draw.rs)); \
33    if (svga->state.hw_draw.rs[SVGA3D_RS_##token] != value) {    \
34       svga_queue_rs(&queue, SVGA3D_RS_##token, value);          \
35       svga->state.hw_draw.rs[SVGA3D_RS_##token] = value;        \
36    }                                                            \
37 } while (0)
38 
39 #define EMIT_RS_FLOAT(svga, fvalue, token)                \
40 do {                                                            \
41    unsigned value = fui(fvalue);                                \
42    STATIC_ASSERT(SVGA3D_RS_##token < ARRAY_SIZE(svga->state.hw_draw.rs)); \
43    if (svga->state.hw_draw.rs[SVGA3D_RS_##token] != value) {    \
44       svga_queue_rs(&queue, SVGA3D_RS_##token, value);          \
45       svga->state.hw_draw.rs[SVGA3D_RS_##token] = value;        \
46    }                                                            \
47 } while (0)
48 
49 
50 static inline void
svga_queue_rs(struct rs_queue * q,unsigned rss,unsigned value)51 svga_queue_rs(struct rs_queue *q, unsigned rss, unsigned value)
52 {
53    assert(q->rs_count < ARRAY_SIZE(q->rs));
54    q->rs[q->rs_count].state = rss;
55    q->rs[q->rs_count].uintValue = value;
56    q->rs_count++;
57 }
58 
59 
60 static unsigned
translate_fill_mode(unsigned fill)61 translate_fill_mode(unsigned fill)
62 {
63    switch (fill) {
64    case PIPE_POLYGON_MODE_POINT:
65       return SVGA3D_FILLMODE_POINT;
66    case PIPE_POLYGON_MODE_LINE:
67       return SVGA3D_FILLMODE_LINE;
68    case PIPE_POLYGON_MODE_FILL:
69       return SVGA3D_FILLMODE_FILL;
70    default:
71       assert(!"Bad fill mode");
72       return SVGA3D_FILLMODE_FILL;
73    }
74 }
75 
76 
77 /* Compare old and new render states and emit differences between them
78  * to hardware.  Simplest implementation would be to emit the whole of
79  * the "to" state.
80  */
81 static enum pipe_error
emit_rss_vgpu9(struct svga_context * svga,uint64_t dirty)82 emit_rss_vgpu9(struct svga_context *svga, uint64_t dirty)
83 {
84    struct svga_screen *screen = svga_screen(svga->pipe.screen);
85    struct rs_queue queue;
86    float point_size_min;
87 
88    queue.rs_count = 0;
89 
90    if (dirty & (SVGA_NEW_BLEND | SVGA_NEW_BLEND_COLOR)) {
91       const struct svga_blend_state *curr = svga->curr.blend;
92 
93       EMIT_RS(svga, curr->rt[0].writemask, COLORWRITEENABLE);
94       EMIT_RS(svga, curr->rt[0].blend_enable, BLENDENABLE);
95 
96       if (curr->rt[0].blend_enable) {
97          EMIT_RS(svga, curr->rt[0].srcblend, SRCBLEND);
98          EMIT_RS(svga, curr->rt[0].dstblend, DSTBLEND);
99          EMIT_RS(svga, curr->rt[0].blendeq, BLENDEQUATION);
100 
101          EMIT_RS(svga, curr->rt[0].separate_alpha_blend_enable,
102                   SEPARATEALPHABLENDENABLE);
103 
104          if (curr->rt[0].separate_alpha_blend_enable) {
105             EMIT_RS(svga, curr->rt[0].srcblend_alpha, SRCBLENDALPHA);
106             EMIT_RS(svga, curr->rt[0].dstblend_alpha, DSTBLENDALPHA);
107             EMIT_RS(svga, curr->rt[0].blendeq_alpha, BLENDEQUATIONALPHA);
108          }
109       }
110    }
111 
112    if (dirty & SVGA_NEW_BLEND_COLOR) {
113       uint32 color;
114       uint32 r = float_to_ubyte(svga->curr.blend_color.color[0]);
115       uint32 g = float_to_ubyte(svga->curr.blend_color.color[1]);
116       uint32 b = float_to_ubyte(svga->curr.blend_color.color[2]);
117       uint32 a = float_to_ubyte(svga->curr.blend_color.color[3]);
118 
119       color = (a << 24) | (r << 16) | (g << 8) | b;
120 
121       EMIT_RS(svga, color, BLENDCOLOR);
122    }
123 
124    if (dirty & (SVGA_NEW_DEPTH_STENCIL_ALPHA | SVGA_NEW_RAST)) {
125       const struct svga_depth_stencil_state *curr = svga->curr.depth;
126       const struct svga_rasterizer_state *rast = svga->curr.rast;
127 
128       if (!curr->stencil[0].enabled) {
129          /* Stencil disabled
130           */
131          EMIT_RS(svga, false, STENCILENABLE);
132          EMIT_RS(svga, false, STENCILENABLE2SIDED);
133       }
134       else if (curr->stencil[0].enabled && !curr->stencil[1].enabled) {
135          /* Regular stencil
136           */
137          EMIT_RS(svga, true, STENCILENABLE);
138          EMIT_RS(svga, false, STENCILENABLE2SIDED);
139 
140          EMIT_RS(svga, curr->stencil[0].func,  STENCILFUNC);
141          EMIT_RS(svga, curr->stencil[0].fail,  STENCILFAIL);
142          EMIT_RS(svga, curr->stencil[0].zfail, STENCILZFAIL);
143          EMIT_RS(svga, curr->stencil[0].pass,  STENCILPASS);
144 
145          EMIT_RS(svga, curr->stencil_mask, STENCILMASK);
146          EMIT_RS(svga, curr->stencil_writemask, STENCILWRITEMASK);
147       }
148       else {
149          int cw, ccw;
150 
151          /* Hardware frontwinding is always CW, so if ours is also CW,
152           * then our definition of front face agrees with hardware.
153           * Otherwise need to flip.
154           */
155          if (rast->templ.front_ccw) {
156             ccw = 0;
157             cw = 1;
158          }
159          else {
160             ccw = 1;
161             cw = 0;
162          }
163 
164          /* Twoside stencil
165           */
166          EMIT_RS(svga, true, STENCILENABLE);
167          EMIT_RS(svga, true, STENCILENABLE2SIDED);
168 
169          EMIT_RS(svga, curr->stencil[cw].func,  STENCILFUNC);
170          EMIT_RS(svga, curr->stencil[cw].fail,  STENCILFAIL);
171          EMIT_RS(svga, curr->stencil[cw].zfail, STENCILZFAIL);
172          EMIT_RS(svga, curr->stencil[cw].pass,  STENCILPASS);
173 
174          EMIT_RS(svga, curr->stencil[ccw].func,  CCWSTENCILFUNC);
175          EMIT_RS(svga, curr->stencil[ccw].fail,  CCWSTENCILFAIL);
176          EMIT_RS(svga, curr->stencil[ccw].zfail, CCWSTENCILZFAIL);
177          EMIT_RS(svga, curr->stencil[ccw].pass,  CCWSTENCILPASS);
178 
179          EMIT_RS(svga, curr->stencil_mask, STENCILMASK);
180          EMIT_RS(svga, curr->stencil_writemask, STENCILWRITEMASK);
181       }
182 
183       EMIT_RS(svga, curr->zenable, ZENABLE);
184       if (curr->zenable) {
185          EMIT_RS(svga, curr->zfunc, ZFUNC);
186          EMIT_RS(svga, curr->zwriteenable, ZWRITEENABLE);
187       }
188 
189       EMIT_RS(svga, curr->alphatestenable, ALPHATESTENABLE);
190       if (curr->alphatestenable) {
191          EMIT_RS(svga, curr->alphafunc, ALPHAFUNC);
192          EMIT_RS_FLOAT(svga, curr->alpharef, ALPHAREF);
193       }
194    }
195 
196    if (dirty & SVGA_NEW_STENCIL_REF) {
197       EMIT_RS(svga, svga->curr.stencil_ref.ref_value[0], STENCILREF);
198    }
199 
200    if (dirty & (SVGA_NEW_RAST | SVGA_NEW_NEED_PIPELINE)) {
201       const struct svga_rasterizer_state *curr = svga->curr.rast;
202       unsigned cullmode = curr->cullmode;
203 
204       /* Shademode: still need to rearrange index list to move
205        * flat-shading PV first vertex.
206        */
207       EMIT_RS(svga, curr->shademode, SHADEMODE);
208 
209       EMIT_RS(svga, translate_fill_mode(curr->hw_fillmode), FILLMODE);
210 
211       /* Don't do culling while the software pipeline is active.  It
212        * does it for us, and additionally introduces potentially
213        * back-facing triangles.
214        */
215       if (svga->state.sw.need_pipeline)
216          cullmode = SVGA3D_FACE_NONE;
217 
218       point_size_min = util_get_min_point_size(&curr->templ);
219 
220       EMIT_RS(svga, cullmode, CULLMODE);
221       EMIT_RS(svga, curr->scissortestenable, SCISSORTESTENABLE);
222       EMIT_RS(svga, curr->multisampleantialias, MULTISAMPLEANTIALIAS);
223       EMIT_RS(svga, curr->lastpixel, LASTPIXEL);
224       EMIT_RS_FLOAT(svga, curr->pointsize, POINTSIZE);
225       EMIT_RS_FLOAT(svga, point_size_min, POINTSIZEMIN);
226       EMIT_RS_FLOAT(svga, screen->maxPointSize, POINTSIZEMAX);
227       EMIT_RS(svga, curr->pointsprite, POINTSPRITEENABLE);
228 
229       /* Emit line state, when the device understands it */
230       if (screen->haveLineStipple)
231          EMIT_RS(svga, curr->linepattern, LINEPATTERN);
232       if (screen->haveLineSmooth)
233          EMIT_RS(svga, curr->antialiasedlineenable, ANTIALIASEDLINEENABLE);
234       if (screen->maxLineWidth > 1.0F)
235          EMIT_RS_FLOAT(svga, curr->linewidth, LINEWIDTH);
236    }
237 
238    if (dirty & (SVGA_NEW_RAST |
239                 SVGA_NEW_FRAME_BUFFER |
240                 SVGA_NEW_NEED_PIPELINE)) {
241       const struct svga_rasterizer_state *curr = svga->curr.rast;
242       float slope = 0.0;
243       float bias  = 0.0;
244 
245       /* Need to modify depth bias according to bound depthbuffer
246        * format.  Don't do hardware depthbias while the software
247        * pipeline is active.
248        */
249       if (!svga->state.sw.need_pipeline &&
250           svga->curr.framebuffer.zsbuf)
251       {
252          slope = curr->slopescaledepthbias;
253          bias  = svga->curr.depthscale * curr->depthbias;
254       }
255 
256       EMIT_RS_FLOAT(svga, slope, SLOPESCALEDEPTHBIAS);
257       EMIT_RS_FLOAT(svga, bias, DEPTHBIAS);
258    }
259 
260    if (dirty & SVGA_NEW_FRAME_BUFFER) {
261       /* XXX: we only look at the first color buffer's sRGB state */
262       float gamma = 1.0f;
263       if (svga->curr.framebuffer.cbufs[0] &&
264           util_format_is_srgb(svga->curr.framebuffer.cbufs[0]->format)) {
265          gamma = 2.2f;
266       }
267       EMIT_RS_FLOAT(svga, gamma, OUTPUTGAMMA);
268    }
269 
270    if (dirty & SVGA_NEW_RAST) {
271       /* bitmask of the enabled clip planes */
272       unsigned enabled = svga->curr.rast->templ.clip_plane_enable;
273       EMIT_RS(svga, enabled, CLIPPLANEENABLE);
274    }
275 
276    if (queue.rs_count) {
277       SVGA3dRenderState *rs;
278 
279       if (SVGA3D_BeginSetRenderState(svga->swc, &rs, queue.rs_count)
280           != PIPE_OK) {
281          /* XXX: need to poison cached hardware state on failure to ensure
282           * dirty state gets re-emitted.  Fix this by re-instating partial
283           * FIFOCommit command and only updating cached hw state once the
284           * initial allocation has succeeded.
285           */
286          memset(svga->state.hw_draw.rs, 0xcd, sizeof(svga->state.hw_draw.rs));
287 
288          return PIPE_ERROR_OUT_OF_MEMORY;
289       }
290 
291       memcpy(rs, queue.rs, queue.rs_count * sizeof queue.rs[0]);
292 
293       SVGA_FIFOCommitAll(svga->swc);
294    }
295 
296    return PIPE_OK;
297 }
298 
299 
300 /** Returns a non-culling rasterizer state object to be used with
301  *  point sprite.
302  */
303 static struct svga_rasterizer_state *
get_no_cull_rasterizer_state(struct svga_context * svga)304 get_no_cull_rasterizer_state(struct svga_context *svga)
305 {
306    struct svga_rasterizer_state *r = svga->curr.rast;
307 
308    if (!r->no_cull_rasterizer) {
309       struct pipe_rasterizer_state rast;
310 
311       memset(&rast, 0, sizeof(rast));
312       rast.flatshade = 1;
313       rast.front_ccw = 1;
314       rast.point_smooth = r->templ.point_smooth;
315 
316       /* All rasterizer states have the same half_pixel_center,
317        * bottom_edge_rule and clip_halfz values since they are
318        * constant for a context. If we ever implement
319        * GL_ARB_clip_control, the clip_halfz field would have to be observed.
320        */
321       rast.half_pixel_center = r->templ.half_pixel_center;
322       rast.bottom_edge_rule = r->templ.bottom_edge_rule;
323       rast.clip_halfz = r->templ.clip_halfz;
324 
325       r->no_cull_rasterizer =
326                svga->pipe.create_rasterizer_state(&svga->pipe, &rast);
327    }
328    return r->no_cull_rasterizer;
329 }
330 
331 
332 /** Returns a depth stencil state object with depth and stencil test disabled.
333  */
334 static struct svga_depth_stencil_state *
get_no_depth_stencil_test_state(struct svga_context * svga)335 get_no_depth_stencil_test_state(struct svga_context *svga)
336 {
337    if (!svga->depthstencil_disable) {
338       struct pipe_depth_stencil_alpha_state ds = {{{0}}};
339       svga->depthstencil_disable =
340          svga->pipe.create_depth_stencil_alpha_state(&svga->pipe, &ds);
341    }
342    return svga->depthstencil_disable;
343 }
344 
345 
346 /**
347  * A helper function to create an alternate svga rasterizer state object to use
348  * forcedSampleCount to support multisampled framebuffer without attachments.
349  */
350 static SVGA3dRasterizerStateId
get_alt_rasterizer_state_id(struct svga_context * svga,struct svga_rasterizer_state * rast,unsigned samples)351 get_alt_rasterizer_state_id(struct svga_context *svga,
352                             struct svga_rasterizer_state *rast,
353                             unsigned samples)
354 {
355    assert(samples <= SVGA_MAX_FRAMEBUFFER_DEFAULT_SAMPLES);
356    assert(samples >= 0);
357 
358    if (samples <= 1)
359       return rast->id;
360 
361    if (rast->altRastIds[samples] == SVGA3D_INVALID_ID) {
362       rast->altRastIds[samples] = svga_define_rasterizer_object(svga, rast, samples);
363    }
364 
365    return rast->altRastIds[samples];
366 }
367 
368 
369 static enum pipe_error
emit_rss_vgpu10(struct svga_context * svga,uint64_t dirty)370 emit_rss_vgpu10(struct svga_context *svga, uint64_t dirty)
371 {
372    enum pipe_error ret = PIPE_OK;
373 
374    svga_hwtnl_flush_retry(svga);
375 
376    if (dirty & (SVGA_NEW_BLEND | SVGA_NEW_BLEND_COLOR)) {
377       const struct svga_blend_state *curr;
378       float blend_factor[4];
379 
380       if (svga_has_any_integer_cbufs(svga)) {
381          /* Blending is not supported in integer-valued render targets. */
382          curr = svga->noop_blend;
383          blend_factor[0] =
384          blend_factor[1] =
385          blend_factor[2] =
386          blend_factor[3] = 0;
387       }
388       else {
389          curr = svga->curr.blend;
390 
391          if (curr->blend_color_alpha) {
392             blend_factor[0] =
393             blend_factor[1] =
394             blend_factor[2] =
395             blend_factor[3] = svga->curr.blend_color.color[3];
396          }
397          else {
398             blend_factor[0] = svga->curr.blend_color.color[0];
399             blend_factor[1] = svga->curr.blend_color.color[1];
400             blend_factor[2] = svga->curr.blend_color.color[2];
401             blend_factor[3] = svga->curr.blend_color.color[3];
402          }
403       }
404 
405       /* Set/bind the blend state object */
406       if (svga->state.hw_draw.blend_id != curr->id ||
407           svga->state.hw_draw.blend_factor[0] != blend_factor[0] ||
408           svga->state.hw_draw.blend_factor[1] != blend_factor[1] ||
409           svga->state.hw_draw.blend_factor[2] != blend_factor[2] ||
410           svga->state.hw_draw.blend_factor[3] != blend_factor[3] ||
411           svga->state.hw_draw.blend_sample_mask != svga->curr.sample_mask) {
412          ret = SVGA3D_vgpu10_SetBlendState(svga->swc, curr->id,
413                                            blend_factor,
414                                            svga->curr.sample_mask);
415          if (ret != PIPE_OK)
416             return ret;
417 
418          svga->state.hw_draw.blend_id = curr->id;
419          svga->state.hw_draw.blend_factor[0] = blend_factor[0];
420          svga->state.hw_draw.blend_factor[1] = blend_factor[1];
421          svga->state.hw_draw.blend_factor[2] = blend_factor[2];
422          svga->state.hw_draw.blend_factor[3] = blend_factor[3];
423          svga->state.hw_draw.blend_sample_mask = svga->curr.sample_mask;
424       }
425    }
426 
427    if (svga->disable_rasterizer) {
428       if (!svga->state.hw_draw.rasterizer_discard) {
429          struct svga_depth_stencil_state *ds;
430 
431          /* If rasterization is to be disabled, disable depth and stencil
432           * testing as well.
433           */
434          ds = get_no_depth_stencil_test_state(svga);
435          if (ds->id != svga->state.hw_draw.depth_stencil_id) {
436             ret = SVGA3D_vgpu10_SetDepthStencilState(svga->swc, ds->id, 0);
437             if (ret != PIPE_OK)
438                return ret;
439 
440             svga->state.hw_draw.depth_stencil_id = ds->id;
441             svga->state.hw_draw.stencil_ref = 0;
442          }
443          svga->state.hw_draw.rasterizer_discard = true;
444       }
445    } else {
446       if ((dirty & (SVGA_NEW_DEPTH_STENCIL_ALPHA | SVGA_NEW_STENCIL_REF)) ||
447           svga->state.hw_draw.rasterizer_discard) {
448          const struct svga_depth_stencil_state *curr = svga->curr.depth;
449          unsigned curr_ref = svga->curr.stencil_ref.ref_value[0];
450 
451          if (curr->id != svga->state.hw_draw.depth_stencil_id ||
452              curr_ref != svga->state.hw_draw.stencil_ref) {
453             /* Set/bind the depth/stencil state object */
454             ret = SVGA3D_vgpu10_SetDepthStencilState(svga->swc, curr->id,
455                                                      curr_ref);
456             if (ret != PIPE_OK)
457                return ret;
458 
459             svga->state.hw_draw.depth_stencil_id = curr->id;
460             svga->state.hw_draw.stencil_ref = curr_ref;
461          }
462       }
463 
464       if (dirty & (SVGA_NEW_REDUCED_PRIMITIVE | SVGA_NEW_RAST |
465                    SVGA_NEW_FRAME_BUFFER)) {
466          struct svga_rasterizer_state *rast = svga->curr.rast;
467 
468          if (svga->curr.reduced_prim == MESA_PRIM_POINTS &&
469              svga->curr.gs && svga->curr.gs->wide_point) {
470 
471             /* If we are drawing a point sprite, we will need to
472              * bind a non-culling rasterizer state object
473              */
474             rast = get_no_cull_rasterizer_state(svga);
475          }
476 
477          int rastId = rast->id;
478 
479          /* In the case of no-attachment framebuffer, the sample count will be
480           * specified in forcedSampleCount in the RasterizerState_v2 object.
481           */
482          if ((svga->curr.framebuffer.nr_cbufs == 0) &&
483              (svga->curr.framebuffer.zsbuf == NULL)) {
484             rastId =
485                get_alt_rasterizer_state_id(svga, rast,
486                                            svga->curr.framebuffer.samples);
487 
488             if (rastId == SVGA3D_INVALID_ID)
489                return PIPE_ERROR;
490          }
491 
492          if (svga->state.hw_draw.rasterizer_id != rastId) {
493             /* Set/bind the rasterizer state object */
494             ret = SVGA3D_vgpu10_SetRasterizerState(svga->swc, rastId);
495             if (ret != PIPE_OK)
496                return ret;
497             svga->state.hw_draw.rasterizer_id = rastId;
498          }
499       }
500       svga->state.hw_draw.rasterizer_discard = false;
501    }
502    return PIPE_OK;
503 }
504 
505 
506 static enum pipe_error
emit_rss(struct svga_context * svga,uint64_t dirty)507 emit_rss(struct svga_context *svga, uint64_t dirty)
508 {
509    if (svga_have_vgpu10(svga)) {
510       return emit_rss_vgpu10(svga, dirty);
511    }
512    else {
513       return emit_rss_vgpu9(svga, dirty);
514    }
515 }
516 
517 
518 struct svga_tracked_state svga_hw_rss =
519 {
520    "hw rss state",
521 
522    (SVGA_NEW_BLEND |
523     SVGA_NEW_BLEND_COLOR |
524     SVGA_NEW_DEPTH_STENCIL_ALPHA |
525     SVGA_NEW_STENCIL_REF |
526     SVGA_NEW_RAST |
527     SVGA_NEW_FRAME_BUFFER |
528     SVGA_NEW_NEED_PIPELINE |
529     SVGA_NEW_FS |
530     SVGA_NEW_REDUCED_PRIMITIVE),
531 
532    emit_rss
533 };
534