xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/freedreno/a4xx/fd4_draw.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2014 Rob Clark <[email protected]>
3  * SPDX-License-Identifier: MIT
4  *
5  * Authors:
6  *    Rob Clark <[email protected]>
7  */
8 
9 #include "pipe/p_state.h"
10 #include "util/u_memory.h"
11 #include "util/u_prim.h"
12 #include "util/u_string.h"
13 
14 #include "freedreno_resource.h"
15 #include "freedreno_state.h"
16 
17 #include "fd4_context.h"
18 #include "fd4_draw.h"
19 #include "fd4_emit.h"
20 #include "fd4_format.h"
21 #include "fd4_program.h"
22 #include "fd4_zsa.h"
23 
24 static void
draw_impl(struct fd_context * ctx,struct fd_ringbuffer * ring,struct fd4_emit * emit,unsigned index_offset)25 draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring,
26           struct fd4_emit *emit, unsigned index_offset) assert_dt
27 {
28    const struct pipe_draw_info *info = emit->info;
29    enum pc_di_primtype primtype = ctx->screen->primtypes[info->mode];
30 
31    fd4_emit_state(ctx, ring, emit);
32 
33    if (emit->dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE))
34       fd4_emit_vertex_bufs(ring, emit);
35 
36    OUT_PKT0(ring, REG_A4XX_VFD_INDEX_OFFSET, 2);
37    OUT_RING(ring, info->index_size ? emit->draw->index_bias
38                                    : emit->draw->start); /* VFD_INDEX_OFFSET */
39    OUT_RING(ring, info->start_instance);                 /* ??? UNKNOWN_2209 */
40 
41    OUT_PKT0(ring, REG_A4XX_PC_RESTART_INDEX, 1);
42    OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */
43                      info->restart_index
44                                           : 0xffffffff);
45 
46    /* points + psize -> spritelist: */
47    if (ctx->rasterizer->point_size_per_vertex &&
48        fd4_emit_get_vp(emit)->writes_psize && (info->mode == MESA_PRIM_POINTS))
49       primtype = DI_PT_POINTLIST_PSIZE;
50 
51    fd4_draw_emit(ctx->batch, ring, primtype,
52                  emit->binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY, info,
53                  emit->indirect, emit->draw, index_offset);
54 }
55 
56 static bool
fd4_draw_vbo(struct fd_context * ctx,const struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draw,unsigned index_offset)57 fd4_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info,
58              unsigned drawid_offset,
59              const struct pipe_draw_indirect_info *indirect,
60              const struct pipe_draw_start_count_bias *draw,
61              unsigned index_offset) in_dt
62 {
63    struct fd4_context *fd4_ctx = fd4_context(ctx);
64    struct fd4_emit emit = {
65       .debug = &ctx->debug,
66       .vtx = &ctx->vtx,
67       .info = info,
68       .drawid_offset = drawid_offset,
69       .indirect = indirect,
70       .draw = draw,
71       .key = {
72          .vs = ctx->prog.vs,
73          .fs = ctx->prog.fs,
74          .key = {
75             .rasterflat = ctx->rasterizer->flatshade,
76             .ucp_enables = ctx->rasterizer->clip_plane_enable,
77             .has_per_samp = fd4_ctx->fastc_srgb || fd4_ctx->vastc_srgb,
78             .vastc_srgb = fd4_ctx->vastc_srgb,
79             .fastc_srgb = fd4_ctx->fastc_srgb,
80          },
81       },
82       .rasterflat = ctx->rasterizer->flatshade,
83       .sprite_coord_enable = ctx->rasterizer->sprite_coord_enable,
84       .sprite_coord_mode = ctx->rasterizer->sprite_coord_mode,
85    };
86 
87    /* Check if we actually need the tg4 workarounds */
88    if (ir3_get_shader_info(emit.key.vs)->uses_texture_gather) {
89       emit.key.key.has_per_samp = true;
90       memcpy(emit.key.key.vsampler_swizzles, fd4_ctx->vsampler_swizzles,
91             sizeof(emit.key.key.vsampler_swizzles));
92    }
93    if (ir3_get_shader_info(emit.key.fs)->uses_texture_gather) {
94       emit.key.key.has_per_samp = true;
95       memcpy(emit.key.key.fsampler_swizzles, fd4_ctx->fsampler_swizzles,
96             sizeof(emit.key.key.fsampler_swizzles));
97    }
98 
99    if (info->mode != MESA_PRIM_COUNT && !indirect && !info->primitive_restart &&
100        !u_trim_pipe_prim(info->mode, (unsigned *)&draw->count))
101       return false;
102 
103    ir3_fixup_shader_state(&ctx->base, &emit.key.key);
104 
105    enum fd_dirty_3d_state dirty = ctx->dirty;
106 
107    emit.prog = fd4_program_state(
108       ir3_cache_lookup(ctx->shader_cache, &emit.key, &ctx->debug));
109 
110    /* bail if compile failed: */
111    if (!emit.prog)
112       return false;
113 
114    fd_blend_tracking(ctx);
115 
116    const struct ir3_shader_variant *vp = fd4_emit_get_vp(&emit);
117    const struct ir3_shader_variant *fp = fd4_emit_get_fp(&emit);
118 
119    ir3_update_max_tf_vtx(ctx, vp);
120 
121    /* do regular pass first: */
122 
123    if (unlikely(ctx->stats_users > 0)) {
124       ctx->stats.vs_regs += ir3_shader_halfregs(vp);
125       ctx->stats.fs_regs += ir3_shader_halfregs(fp);
126    }
127 
128    emit.binning_pass = false;
129    emit.dirty = dirty;
130 
131    struct fd_ringbuffer *ring = ctx->batch->draw;
132 
133    if (ctx->rasterizer->rasterizer_discard) {
134       fd_wfi(ctx->batch, ring);
135       OUT_PKT3(ring, CP_REG_RMW, 3);
136       OUT_RING(ring, REG_A4XX_RB_RENDER_CONTROL);
137       OUT_RING(ring, ~A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE);
138       OUT_RING(ring, A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE);
139    }
140 
141    draw_impl(ctx, ctx->batch->draw, &emit, index_offset);
142 
143    if (ctx->rasterizer->rasterizer_discard) {
144       fd_wfi(ctx->batch, ring);
145       OUT_PKT3(ring, CP_REG_RMW, 3);
146       OUT_RING(ring, REG_A4XX_RB_RENDER_CONTROL);
147       OUT_RING(ring, ~A4XX_RB_RENDER_CONTROL_DISABLE_COLOR_PIPE);
148       OUT_RING(ring, 0);
149    }
150 
151    /* and now binning pass: */
152    emit.binning_pass = true;
153    emit.dirty = dirty & ~(FD_DIRTY_BLEND);
154    emit.vs = NULL; /* we changed key so need to refetch vs */
155    emit.fs = NULL;
156    draw_impl(ctx, ctx->batch->binning, &emit, index_offset);
157 
158    fd_context_all_clean(ctx);
159 
160    return true;
161 }
162 
163 static void
fd4_draw_vbos(struct fd_context * ctx,const struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_indirect_info * indirect,const struct pipe_draw_start_count_bias * draws,unsigned num_draws,unsigned index_offset)164 fd4_draw_vbos(struct fd_context *ctx, const struct pipe_draw_info *info,
165               unsigned drawid_offset,
166               const struct pipe_draw_indirect_info *indirect,
167               const struct pipe_draw_start_count_bias *draws,
168               unsigned num_draws,
169               unsigned index_offset)
170    assert_dt
171 {
172    for (unsigned i = 0; i < num_draws; i++)
173       fd4_draw_vbo(ctx, info, drawid_offset, indirect, &draws[i], index_offset);
174 }
175 
176 void
fd4_draw_init(struct pipe_context * pctx)177 fd4_draw_init(struct pipe_context *pctx) disable_thread_safety_analysis
178 {
179    struct fd_context *ctx = fd_context(pctx);
180    ctx->draw_vbos = fd4_draw_vbos;
181 }
182