xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/freedreno/a3xx/fd3_draw.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2013 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/format/u_format.h"
11 #include "util/u_memory.h"
12 #include "util/u_prim.h"
13 #include "util/u_string.h"
14 
15 #include "freedreno_resource.h"
16 #include "freedreno_state.h"
17 
18 #include "fd3_context.h"
19 #include "fd3_draw.h"
20 #include "fd3_emit.h"
21 #include "fd3_format.h"
22 #include "fd3_program.h"
23 #include "fd3_zsa.h"
24 
25 static inline uint32_t
add_sat(uint32_t a,int32_t b)26 add_sat(uint32_t a, int32_t b)
27 {
28    int64_t ret = (uint64_t)a + (int64_t)b;
29    if (ret > ~0U)
30       return ~0U;
31    if (ret < 0)
32       return 0;
33    return (uint32_t)ret;
34 }
35 
36 static void
draw_impl(struct fd_context * ctx,struct fd_ringbuffer * ring,struct fd3_emit * emit,unsigned index_offset)37 draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring,
38           struct fd3_emit *emit, unsigned index_offset) assert_dt
39 {
40    const struct pipe_draw_info *info = emit->info;
41    enum pc_di_primtype primtype = ctx->screen->primtypes[info->mode];
42 
43    fd3_emit_state(ctx, ring, emit);
44 
45    if (emit->dirty & (FD_DIRTY_VTXBUF | FD_DIRTY_VTXSTATE))
46       fd3_emit_vertex_bufs(ring, emit);
47 
48    OUT_PKT0(ring, REG_A3XX_PC_VERTEX_REUSE_BLOCK_CNTL, 1);
49    OUT_RING(ring, 0x0000000b); /* PC_VERTEX_REUSE_BLOCK_CNTL */
50 
51    OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4);
52    OUT_RING(ring, info->index_bounds_valid
53                      ? add_sat(info->min_index,
54                                info->index_size ? emit->draw->index_bias : 0)
55                      : 0); /* VFD_INDEX_MIN */
56    OUT_RING(ring, info->index_bounds_valid
57                      ? add_sat(info->max_index,
58                                info->index_size ? emit->draw->index_bias : 0)
59                      : ~0);              /* VFD_INDEX_MAX */
60    OUT_RING(ring, info->start_instance); /* VFD_INSTANCEID_OFFSET */
61    OUT_RING(ring, info->index_size ? emit->draw->index_bias
62                                    : emit->draw->start); /* VFD_INDEX_OFFSET */
63 
64    OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1);
65    OUT_RING(ring, info->primitive_restart ? /* PC_RESTART_INDEX */
66                      info->restart_index
67                                           : 0xffffffff);
68 
69    /* points + psize -> spritelist: */
70    if (ctx->rasterizer->point_size_per_vertex &&
71        fd3_emit_get_vp(emit)->writes_psize && (info->mode == MESA_PRIM_POINTS))
72       primtype = DI_PT_POINTLIST_PSIZE;
73 
74    fd_draw_emit(ctx->batch, ring, primtype,
75                 emit->binning_pass ? IGNORE_VISIBILITY : USE_VISIBILITY, info,
76                 emit->draw, index_offset);
77 }
78 
79 static bool
fd3_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)80 fd3_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info,
81              unsigned drawid_offset,
82              const struct pipe_draw_indirect_info *indirect,
83              const struct pipe_draw_start_count_bias *draw,
84              unsigned index_offset) in_dt
85 {
86    struct fd3_emit emit = {
87       .debug = &ctx->debug,
88       .vtx = &ctx->vtx,
89       .info = info,
90       .drawid_offset = drawid_offset,
91       .indirect = indirect,
92       .draw = draw,
93       .key = {
94          .vs = ctx->prog.vs,
95          .fs = ctx->prog.fs,
96       },
97       .rasterflat = ctx->rasterizer->flatshade,
98       .sprite_coord_enable = ctx->rasterizer->sprite_coord_enable,
99       .sprite_coord_mode = ctx->rasterizer->sprite_coord_mode,
100    };
101 
102    if (info->mode != MESA_PRIM_COUNT && !indirect && !info->primitive_restart &&
103        !u_trim_pipe_prim(info->mode, (unsigned *)&draw->count))
104       return false;
105 
106    if (fd3_needs_manual_clipping(ir3_get_shader(ctx->prog.vs), ctx->rasterizer))
107       emit.key.key.ucp_enables = ctx->rasterizer->clip_plane_enable;
108 
109    ir3_fixup_shader_state(&ctx->base, &emit.key.key);
110 
111    unsigned dirty = ctx->dirty;
112 
113    emit.prog = fd3_program_state(
114       ir3_cache_lookup(ctx->shader_cache, &emit.key, &ctx->debug));
115 
116    /* bail if compile failed: */
117    if (!emit.prog)
118       return false;
119 
120    fd_blend_tracking(ctx);
121 
122    const struct ir3_shader_variant *vp = fd3_emit_get_vp(&emit);
123    const struct ir3_shader_variant *fp = fd3_emit_get_fp(&emit);
124 
125    ir3_update_max_tf_vtx(ctx, vp);
126 
127    /* do regular pass first: */
128 
129    if (unlikely(ctx->stats_users > 0)) {
130       ctx->stats.vs_regs += ir3_shader_halfregs(vp);
131       ctx->stats.fs_regs += ir3_shader_halfregs(fp);
132    }
133 
134    emit.binning_pass = false;
135    emit.dirty = dirty;
136    draw_impl(ctx, ctx->batch->draw, &emit, index_offset);
137 
138    /* and now binning pass: */
139    emit.binning_pass = true;
140    emit.dirty = dirty & ~(FD_DIRTY_BLEND);
141    emit.vs = NULL; /* we changed key so need to refetch vs */
142    emit.fs = NULL;
143    draw_impl(ctx, ctx->batch->binning, &emit, index_offset);
144 
145    fd_context_all_clean(ctx);
146 
147    ctx->batch->num_vertices += draw->count * info->instance_count;
148 
149    return true;
150 }
151 
152 static void
fd3_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)153 fd3_draw_vbos(struct fd_context *ctx, const struct pipe_draw_info *info,
154               unsigned drawid_offset,
155               const struct pipe_draw_indirect_info *indirect,
156               const struct pipe_draw_start_count_bias *draws,
157               unsigned num_draws,
158               unsigned index_offset)
159    assert_dt
160 {
161    for (unsigned i = 0; i < num_draws; i++)
162       fd3_draw_vbo(ctx, info, drawid_offset, indirect, &draws[i], index_offset);
163 }
164 
165 void
fd3_draw_init(struct pipe_context * pctx)166 fd3_draw_init(struct pipe_context *pctx) disable_thread_safety_analysis
167 {
168    struct fd_context *ctx = fd_context(pctx);
169    ctx->draw_vbos = fd3_draw_vbos;
170 }
171