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