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 */