From bf74d58f219503947449bb2785414d6a9ea99b8b Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 17 Sep 2021 12:22:30 -0700 Subject: [PATCH] freedreno/a6xx: Pre-bake SO-disable stateobj No need to re-create this every time we transition from stream-out enabled to disabled. Creation of streamout_disable_stateobj is deferred until we create a program state using streamout to avoid creating it unnecessarily and because fd6_prog_init() is called before ctx->pipe is created. (Changing that ordering is complicated by the fact that u_blitter copies pctx->bind_fs_state(), and friends.) Signed-off-by: Rob Clark Part-of: --- .../drivers/freedreno/a6xx/fd6_context.c | 3 ++ .../drivers/freedreno/a6xx/fd6_context.h | 3 ++ src/gallium/drivers/freedreno/a6xx/fd6_emit.c | 26 ++------------- .../drivers/freedreno/a6xx/fd6_program.c | 32 +++++++++++++++++++ 4 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.c b/src/gallium/drivers/freedreno/a6xx/fd6_context.c index 3bafe3c7e5a..56b6fe42e1b 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_context.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.c @@ -51,6 +51,9 @@ fd6_context_destroy(struct pipe_context *pctx) in_dt u_upload_destroy(fd6_ctx->border_color_uploader); pipe_resource_reference(&fd6_ctx->border_color_buf, NULL); + if (fd6_ctx->streamout_disable_stateobj) + fd_ringbuffer_del(fd6_ctx->streamout_disable_stateobj); + fd_context_destroy(pctx); if (fd6_ctx->vsc_draw_strm) diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.h b/src/gallium/drivers/freedreno/a6xx/fd6_context.h index 1487e74b725..122642e4e88 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_context.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.h @@ -70,6 +70,9 @@ struct fd6_context { struct u_upload_mgr *border_color_uploader; struct pipe_resource *border_color_buf; + /* pre-backed stateobj for stream-out disable: */ + struct fd_ringbuffer *streamout_disable_stateobj; + /* storage for ctx->last.key: */ struct ir3_shader_key last_key; diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c index 583f840cf83..95cdfa81258 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c @@ -909,32 +909,12 @@ fd6_emit_streamout(struct fd_ringbuffer *ring, struct fd6_emit *emit) assert_dt if (emit->streamout_mask) { fd6_emit_add_group(emit, prog->streamout_stateobj, FD6_GROUP_SO, ENABLE_ALL); - } else { + } else if (ctx->last.streamout_mask != 0) { /* If we transition from a draw with streamout to one without, turn * off streamout. */ - if (ctx->last.streamout_mask != 0) { - unsigned sizedw = 4; - - if (ctx->screen->info->a6xx.tess_use_shared) - sizedw += 2; - - struct fd_ringbuffer *obj = fd_submit_new_ringbuffer( - emit->ctx->batch->submit, (1 + sizedw) * 4, FD_RINGBUFFER_STREAMING); - - OUT_PKT7(obj, CP_CONTEXT_REG_BUNCH, sizedw); - OUT_RING(obj, REG_A6XX_VPC_SO_CNTL); - OUT_RING(obj, 0); - OUT_RING(obj, REG_A6XX_VPC_SO_STREAM_CNTL); - OUT_RING(obj, 0); - - if (ctx->screen->info->a6xx.tess_use_shared) { - OUT_RING(ring, REG_A6XX_PC_SO_STREAM_CNTL); - OUT_RING(ring, 0); - } - - fd6_emit_take_group(emit, obj, FD6_GROUP_SO, ENABLE_ALL); - } + fd6_emit_add_group(emit, fd6_context(ctx)->streamout_disable_stateobj, + FD6_GROUP_SO, ENABLE_ALL); } /* Make sure that any use of our TFB outputs (indirect draw source or shader diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_program.c b/src/gallium/drivers/freedreno/a6xx/fd6_program.c index 13e8d1d3b2b..e1dae440f1a 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_program.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_program.c @@ -152,6 +152,35 @@ fd6_emit_shader(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RELOC(ring, so->bo, 0, 0, 0); } +/** + * Build a pre-baked state-obj to disable SO, so that we aren't dynamically + * building this at draw time whenever we transition from SO enabled->disabled + */ +static void +setup_stream_out_disable(struct fd_context *ctx) +{ + unsigned sizedw = 4; + + if (ctx->screen->info->a6xx.tess_use_shared) + sizedw += 2; + + struct fd_ringbuffer *ring = + fd_ringbuffer_new_object(ctx->pipe, (1 + sizedw) * 4); + + OUT_PKT7(ring, CP_CONTEXT_REG_BUNCH, sizedw); + OUT_RING(ring, REG_A6XX_VPC_SO_CNTL); + OUT_RING(ring, 0); + OUT_RING(ring, REG_A6XX_VPC_SO_STREAM_CNTL); + OUT_RING(ring, 0); + + if (ctx->screen->info->a6xx.tess_use_shared) { + OUT_RING(ring, REG_A6XX_PC_SO_STREAM_CNTL); + OUT_RING(ring, 0); + } + + fd6_context(ctx)->streamout_disable_stateobj = ring; +} + static void setup_stream_out(struct fd_context *ctx, struct fd6_program_state *state, const struct ir3_shader_variant *v, @@ -568,6 +597,9 @@ setup_stateobj(struct fd_ringbuffer *ring, struct fd_context *ctx, */ if (do_streamout && !binning_pass) { setup_stream_out(ctx, state, last_shader, &l); + + if (!fd6_context(ctx)->streamout_disable_stateobj) + setup_stream_out_disable(ctx); } debug_assert(l.cnt <= 32);