From d760a995e3cb1725c87c6f1b62867a1205a8f2fc Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 25 Jan 2021 12:00:56 +0100 Subject: [PATCH] panfrost: Hook up indirect draw support Signed-off-by: Boris Brezillon Reviewed-by: Alyssa Rosenzweig Part-of: --- src/gallium/drivers/panfrost/pan_cmdstream.c | 9 +- src/gallium/drivers/panfrost/pan_context.c | 133 ++++++++++++++++++- src/gallium/drivers/panfrost/pan_job.h | 4 + src/gallium/drivers/panfrost/pan_screen.c | 5 + 4 files changed, 147 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c index 815f5c1b5ab..1e8462e5e4d 100644 --- a/src/gallium/drivers/panfrost/pan_cmdstream.c +++ b/src/gallium/drivers/panfrost/pan_cmdstream.c @@ -2237,11 +2237,14 @@ panfrost_emit_vertex_tiler_jobs(struct panfrost_batch *batch, unsigned vertex = panfrost_add_job(&batch->pool, &batch->scoreboard, MALI_JOB_TYPE_VERTEX, false, false, - 0, 0, vertex_job, false); + ctx->indirect_draw ? + batch->indirect_draw_job_id : 0, + 0, vertex_job, false); if (ctx->rasterizer->base.rasterizer_discard) return; - panfrost_add_job(&batch->pool, &batch->scoreboard, MALI_JOB_TYPE_TILER, - false, false, vertex, 0, tiler_job, false); + panfrost_add_job(&batch->pool, &batch->scoreboard, + MALI_JOB_TYPE_TILER, false, false, + vertex, 0, tiler_job, false); } diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c index 34eb5b58874..11e32c86b45 100644 --- a/src/gallium/drivers/panfrost/pan_context.c +++ b/src/gallium/drivers/panfrost/pan_context.c @@ -52,6 +52,7 @@ #include "midgard_pack.h" #include "pan_screen.h" #include "pan_cmdstream.h" +#include "pan_indirect_draw.h" #include "pan_util.h" #include "decode.h" #include "util/pan_lower_framebuffer.h" @@ -596,7 +597,137 @@ panfrost_indirect_draw(struct panfrost_context *ctx, return; } - assert(0); + /* Indirect draw count and multi-draw not supported. */ + assert(indirect->draw_count == 1 && !indirect->indirect_draw_count); + + /* TODO: update statistics (see panfrost_statistics_record()) */ + /* TODO: Increment transform feedback offsets */ + assert(ctx->streamout.num_targets == 0); + + struct panfrost_device *dev = pan_device(ctx->base.screen); + + assert(ctx->draw_modes & (1 << info->mode)); + ctx->active_prim = info->mode; + ctx->indirect_draw = true; + + struct panfrost_batch *batch = panfrost_get_batch_for_fbo(ctx); + + /* Don't add too many jobs to a single batch */ + if (batch->scoreboard.job_index + (indirect->draw_count * 3) > 10000) + batch = panfrost_get_fresh_batch_for_fbo(ctx); + + panfrost_batch_set_requirements(batch); + + mali_ptr shared_mem = panfrost_batch_reserve_framebuffer(batch); + + struct panfrost_ptr tiler = + panfrost_pool_alloc_aligned(&batch->pool, + pan_is_bifrost(dev) ? + MALI_BIFROST_TILER_JOB_LENGTH : + MALI_MIDGARD_TILER_JOB_LENGTH, + 64); + struct panfrost_ptr vertex = + panfrost_pool_alloc_aligned(&batch->pool, + MALI_COMPUTE_JOB_LENGTH, + 64); + + struct panfrost_shader_state *vs = + panfrost_get_shader_state(ctx, PIPE_SHADER_VERTEX); + + struct panfrost_bo *index_buf = NULL; + + if (info->index_size) { + assert(!info->has_user_indices); + index_buf = pan_resource(info->index.resource)->bo; + panfrost_batch_add_bo(batch, + index_buf, + PAN_BO_ACCESS_SHARED | PAN_BO_ACCESS_READ | + PAN_BO_ACCESS_VERTEX_TILER); + } + + mali_ptr varyings = 0, vs_vary = 0, fs_vary = 0, pos = 0, psiz = 0; + unsigned varying_buf_count; + + /* We want to create templates, set all count fields to 0 to reflect + * that. + */ + ctx->instance_count = ctx->vertex_count = ctx->padded_count = 0; + ctx->offset_start = 0; + + panfrost_emit_varying_descriptor(batch, 0, + &vs_vary, &fs_vary, &varyings, + &varying_buf_count, &pos, &psiz); + + mali_ptr attribs, attrib_bufs; + attribs = panfrost_emit_vertex_data(batch, &attrib_bufs); + + /* Zero-ed invocation, the compute job will update it. */ + static struct mali_invocation_packed invocation; + + /* Fire off the draw itself */ + panfrost_draw_emit_vertex(batch, info, &invocation, shared_mem, + vs_vary, varyings, attribs, attrib_bufs, + vertex.cpu); + panfrost_draw_emit_tiler(batch, info, NULL, &invocation, shared_mem, + index_buf ? index_buf->ptr.gpu : 0, + fs_vary, varyings, pos, psiz, tiler.cpu); + + /* Add the varying heap BO to the batch if we're allocating varyings. */ + if (varyings) { + panfrost_batch_add_bo(batch, + dev->indirect_draw_shaders.varying_heap, + PAN_BO_ACCESS_SHARED | PAN_BO_ACCESS_RW | + PAN_BO_ACCESS_VERTEX_TILER); + } + + assert(indirect->buffer); + + struct panfrost_resource *draw_buf = pan_resource(indirect->buffer); + + /* Don't count images: those attributes don't need to be patched. */ + unsigned attrib_count = + vs->info.attribute_count - + util_bitcount(ctx->image_mask[PIPE_SHADER_VERTEX]); + + panfrost_batch_add_bo(batch, draw_buf->bo, + PAN_BO_ACCESS_SHARED | PAN_BO_ACCESS_READ | + PAN_BO_ACCESS_VERTEX_TILER); + + struct pan_indirect_draw_info draw_info = { + .last_indirect_draw = batch->indirect_draw_job_id, + .draw_buf = draw_buf->bo->ptr.gpu + indirect->offset, + .index_buf = index_buf ? index_buf->ptr.gpu : 0, + .vertex_job = vertex.gpu, + .tiler_job = tiler.gpu, + .attrib_bufs = attrib_bufs, + .attribs = attribs, + .attrib_count = attrib_count, + .varying_bufs = varyings, + .index_size = info->index_size, + }; + + if (panfrost_writes_point_size(ctx)) + draw_info.flags |= PAN_INDIRECT_DRAW_UPDATE_PRIM_SIZE; + + if (vs->info.vs.writes_point_size) + draw_info.flags |= PAN_INDIRECT_DRAW_HAS_PSIZ; + + + if (info->primitive_restart) { + draw_info.restart_index = info->restart_index; + draw_info.flags |= PAN_INDIRECT_DRAW_PRIMITIVE_RESTART; + } + + batch->indirect_draw_job_id = + panfrost_emit_indirect_draw(&batch->pool, + &batch->scoreboard, + &draw_info, + &batch->indirect_draw_ctx); + + panfrost_emit_vertex_tiler_jobs(batch, &vertex, &tiler); + + /* Adjust the batch stack size based on the new shader stack sizes. */ + panfrost_batch_adjust_stack_size(batch); } static void diff --git a/src/gallium/drivers/panfrost/pan_job.h b/src/gallium/drivers/panfrost/pan_job.h index 0b316d9c15b..088a3af2d64 100644 --- a/src/gallium/drivers/panfrost/pan_job.h +++ b/src/gallium/drivers/panfrost/pan_job.h @@ -125,6 +125,10 @@ struct panfrost_batch { /* Batch dependencies */ struct util_dynarray dependencies; + + /* Indirect draw data */ + struct panfrost_ptr indirect_draw_ctx; + unsigned indirect_draw_job_id; }; /* Functions for managing the above */ diff --git a/src/gallium/drivers/panfrost/pan_screen.c b/src/gallium/drivers/panfrost/pan_screen.c index 7d754d4c3e5..43ed6f6d0fe 100644 --- a/src/gallium/drivers/panfrost/pan_screen.c +++ b/src/gallium/drivers/panfrost/pan_screen.c @@ -301,6 +301,9 @@ panfrost_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_SHAREABLE_SHADERS: return 0; + case PIPE_CAP_DRAW_INDIRECT: + return is_deqp; + default: return u_pipe_screen_get_param_defaults(screen, param); } @@ -686,6 +689,7 @@ panfrost_destroy_screen(struct pipe_screen *pscreen) { struct panfrost_device *dev = pan_device(pscreen); + panfrost_cleanup_indirect_draw_shaders(dev); pan_blend_shaders_cleanup(dev); if (dev->ro) @@ -860,6 +864,7 @@ panfrost_create_screen(int fd, struct renderonly *ro) panfrost_resource_screen_init(&screen->base); panfrost_init_blit_shaders(dev); pan_blend_shaders_init(dev); + panfrost_init_indirect_draw_shaders(dev); return &screen->base; }