From 3b871856d1ef9fbe901ac73cddf80a93f5c682bc Mon Sep 17 00:00:00 2001 From: antonino Date: Tue, 20 Aug 2024 22:40:12 -0400 Subject: [PATCH] panfrost: refactor draw logic to support native draw indirect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the draw logic into multiple methods depending on whether the draw is single direct, multiple direct or indirect. Indirect draws are emulated for now by reading back the indirect buffer info, but we can implement optimized version later for JM and CSF. Signed-off-by: Antonino Maniscalco Reviewed-by: Boris Brezillon Reviewed-by: Louis-Francis Ratté-Boulianne Reviewed-by: Mary Guillemard Part-of: --- src/gallium/drivers/panfrost/pan_cmdstream.c | 115 +++++++++++++++---- src/gallium/drivers/panfrost/pan_cmdstream.h | 1 + src/gallium/drivers/panfrost/pan_csf.c | 9 ++ src/gallium/drivers/panfrost/pan_csf.h | 4 + src/gallium/drivers/panfrost/pan_jm.c | 9 ++ src/gallium/drivers/panfrost/pan_jm.h | 4 + 6 files changed, 119 insertions(+), 23 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 29e11ab2ce0..e650b39dc2b 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -2912,9 +2912,10 @@ panfrost_draw_get_vertex_count(struct panfrost_batch *batch, } static void -panfrost_direct_draw(struct panfrost_batch *batch, - const struct pipe_draw_info *info, unsigned drawid_offset, - const struct pipe_draw_start_count_bias *draw) +panfrost_single_draw_direct(struct panfrost_batch *batch, + const struct pipe_draw_info *info, + unsigned drawid_offset, + const struct pipe_draw_start_count_bias *draw) { if (!draw->count || !info->instance_count) return; @@ -2995,29 +2996,12 @@ panfrost_compatible_batch_state(struct panfrost_batch *batch, return pan_tristate_set(&batch->first_provoking_vertex, first); } -static void -panfrost_draw_vbo(struct pipe_context *pipe, 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) +static struct panfrost_batch * +prepare_draw(struct pipe_context *pipe, const struct pipe_draw_info *info) { struct panfrost_context *ctx = pan_context(pipe); struct panfrost_device *dev = pan_device(pipe->screen); - if (!panfrost_render_condition_check(ctx)) - return; - - ctx->draw_calls++; - - /* Emulate indirect draws on JM */ - if (indirect && indirect->buffer) { - assert(num_draws == 1); - util_draw_indirect(pipe, info, drawid_offset, indirect); - perf_debug(ctx, "Emulating indirect draw on the CPU"); - return; - } - /* Do some common setup */ struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx); @@ -3053,11 +3037,74 @@ panfrost_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, /* Conservatively assume draw parameters always change */ ctx->dirty |= PAN_DIRTY_PARAMS | PAN_DIRTY_DRAWID; + return batch; +} + +static void +panfrost_draw_indirect(struct pipe_context *pipe, + const struct pipe_draw_info *info, + unsigned drawid_offset, + const struct pipe_draw_indirect_info *indirect) +{ + struct panfrost_context *ctx = pan_context(pipe); + + if (!PAN_GPU_SUPPORTS_DRAW_INDIRECT || ctx->active_queries || + ctx->streamout.num_targets) { + util_draw_indirect(pipe, info, drawid_offset, indirect); + perf_debug(ctx, "Emulating indirect draw on the CPU"); + return; + } + + struct panfrost_batch *batch = prepare_draw(pipe, info); + struct pipe_draw_info tmp_info = *info; + + panfrost_batch_read_rsrc(batch, pan_resource(indirect->buffer), + PIPE_SHADER_VERTEX); + + panfrost_update_active_prim(ctx, &tmp_info); + + ctx->drawid = drawid_offset; + + batch->indices = 0; + if (info->index_size) { + struct panfrost_resource *index_buffer = + pan_resource(info->index.resource); + panfrost_batch_read_rsrc(batch, index_buffer, PIPE_SHADER_VERTEX); + batch->indices = index_buffer->image.data.base; + } + + panfrost_update_state_3d(batch); + panfrost_update_shader_state(batch, PIPE_SHADER_VERTEX); + panfrost_update_shader_state(batch, PIPE_SHADER_FRAGMENT); + panfrost_clean_state_3d(ctx); + + /* Increment transform feedback offsets */ + panfrost_update_streamout_offsets(ctx); + + /* Any side effects must be handled by the XFB shader, so we only need + * to run vertex shaders if we need rasterization. + */ + if (panfrost_batch_skip_rasterization(batch)) + return; + + JOBX(launch_draw_indirect)(batch, &tmp_info, drawid_offset, indirect); + batch->draw_count++; +} + +static void +panfrost_multi_draw_direct(struct pipe_context *pipe, + const struct pipe_draw_info *info, + unsigned drawid_offset, + const struct pipe_draw_start_count_bias *draws, + unsigned num_draws) +{ + struct panfrost_context *ctx = pan_context(pipe); + struct panfrost_batch *batch = prepare_draw(pipe, info); struct pipe_draw_info tmp_info = *info; unsigned drawid = drawid_offset; for (unsigned i = 0; i < num_draws; i++) { - panfrost_direct_draw(batch, &tmp_info, drawid, &draws[i]); + panfrost_single_draw_direct(batch, &tmp_info, drawid, &draws[i]); if (tmp_info.increment_draw_id) { ctx->dirty |= PAN_DIRTY_DRAWID; @@ -3066,6 +3113,28 @@ panfrost_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, } } +static void +panfrost_draw_vbo(struct pipe_context *pipe, 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) +{ + struct panfrost_context *ctx = pan_context(pipe); + + if (!panfrost_render_condition_check(ctx)) + return; + + ctx->draw_calls++; + + if (indirect && indirect->buffer) { + assert(num_draws == 1); + panfrost_draw_indirect(pipe, info, drawid_offset, indirect); + } else { + panfrost_multi_draw_direct(pipe, info, drawid_offset, draws, num_draws); + } +} + /* Launch grid is the compute equivalent of draw_vbo, so in this routine, we * construct the COMPUTE job and some of its payload. */ diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.h b/src/gallium/drivers/panfrost/pan_cmdstream.h index 608c503dfe1..09d3481d8ff 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.h +++ b/src/gallium/drivers/panfrost/pan_cmdstream.h @@ -41,6 +41,7 @@ #include "util/u_prim.h" #define PAN_GPU_SUPPORTS_DISPATCH_INDIRECT (PAN_ARCH == 7 || PAN_ARCH >= 10) +#define PAN_GPU_SUPPORTS_DRAW_INDIRECT 0 struct panfrost_rasterizer { struct pipe_rasterizer_state base; diff --git a/src/gallium/drivers/panfrost/pan_csf.c b/src/gallium/drivers/panfrost/pan_csf.c index 4354384eba1..bd5191b32df 100644 --- a/src/gallium/drivers/panfrost/pan_csf.c +++ b/src/gallium/drivers/panfrost/pan_csf.c @@ -942,6 +942,15 @@ GENX(csf_launch_draw)(struct panfrost_batch *batch, cs_shader_res_sel(2, 2, 2, 0), cs_undef()); } +void +GENX(csf_launch_draw_indirect)(struct panfrost_batch *batch, + const struct pipe_draw_info *info, + unsigned drawid_offset, + const struct pipe_draw_indirect_info *indirect) +{ + unreachable("draw indirect not implemented yet for CSF"); +} + #define POSITION_FIFO_SIZE (64 * 1024) int diff --git a/src/gallium/drivers/panfrost/pan_csf.h b/src/gallium/drivers/panfrost/pan_csf.h index e429770d672..21398ce29fd 100644 --- a/src/gallium/drivers/panfrost/pan_csf.h +++ b/src/gallium/drivers/panfrost/pan_csf.h @@ -91,6 +91,10 @@ void GENX(csf_launch_draw)(struct panfrost_batch *batch, unsigned drawid_offset, const struct pipe_draw_start_count_bias *draw, unsigned vertex_count); +void GENX(csf_launch_draw_indirect)(struct panfrost_batch *batch, + const struct pipe_draw_info *info, + unsigned drawid_offset, + const struct pipe_draw_indirect_info *indirect); #endif /* PAN_ARCH >= 10 */ diff --git a/src/gallium/drivers/panfrost/pan_jm.c b/src/gallium/drivers/panfrost/pan_jm.c index 46155ff61e5..ff246e92812 100644 --- a/src/gallium/drivers/panfrost/pan_jm.c +++ b/src/gallium/drivers/panfrost/pan_jm.c @@ -969,3 +969,12 @@ GENX(jm_launch_draw)(struct panfrost_batch *batch, } #endif } + +void +GENX(jm_launch_draw_indirect)(struct panfrost_batch *batch, + const struct pipe_draw_info *info, + unsigned drawid_offset, + const struct pipe_draw_indirect_info *indirect) +{ + unreachable("draw indirect not implemented for jm"); +} diff --git a/src/gallium/drivers/panfrost/pan_jm.h b/src/gallium/drivers/panfrost/pan_jm.h index ae4bb69249e..5c594446452 100644 --- a/src/gallium/drivers/panfrost/pan_jm.h +++ b/src/gallium/drivers/panfrost/pan_jm.h @@ -84,6 +84,10 @@ void GENX(jm_launch_draw)(struct panfrost_batch *batch, unsigned drawid_offset, const struct pipe_draw_start_count_bias *draw, unsigned vertex_count); +void GENX(jm_launch_draw_indirect)(struct panfrost_batch *batch, + const struct pipe_draw_info *info, + unsigned drawid_offset, + const struct pipe_draw_indirect_info *indirect); #endif /* PAN_ARCH < 10 */