From 270e595811ff54e341404c4eca43bb8d23f22944 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 24 Sep 2024 14:33:23 -0700 Subject: [PATCH] freedreno/a6xx: Move static regs to preamble IB We can re-use this for preemption. Signed-off-by: Rob Clark Part-of: --- .../drivers/freedreno/a6xx/fd6_context.cc | 12 ++ .../drivers/freedreno/a6xx/fd6_context.h | 5 + .../drivers/freedreno/a6xx/fd6_emit.cc | 111 ++++++++++-------- src/gallium/drivers/freedreno/a6xx/fd6_emit.h | 3 + .../drivers/freedreno/a6xx/fd6_gmem.cc | 59 ++++++++-- src/gallium/drivers/freedreno/a6xx/fd6_gmem.h | 3 + 6 files changed, 135 insertions(+), 58 deletions(-) diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.cc b/src/gallium/drivers/freedreno/a6xx/fd6_context.cc index 272cc73b727..a68b7fe186d 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_context.cc +++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.cc @@ -44,6 +44,12 @@ fd6_context_destroy(struct pipe_context *pctx) in_dt if (fd6_ctx->sample_locations_disable_stateobj) fd_ringbuffer_del(fd6_ctx->sample_locations_disable_stateobj); + if (fd6_ctx->preamble) + fd_ringbuffer_del(fd6_ctx->preamble); + + if (fd6_ctx->restore) + fd_ringbuffer_del(fd6_ctx->restore); + fd_context_destroy(pctx); if (fd6_ctx->vsc_draw_strm) @@ -311,6 +317,12 @@ fd6_context_create(struct pipe_screen *pscreen, void *priv, fd6_ctx->sample_locations_disable_stateobj = ring; + fd6_ctx->preamble = fd6_build_preemption_preamble(&fd6_ctx->base); + + ring = fd_ringbuffer_new_object(fd6_ctx->base.pipe, 0x1000); + fd6_emit_static_regs(&fd6_ctx->base, ring); + fd6_ctx->restore = ring; + return fd_context_init_tc(pctx, flags); } FD_GENX(fd6_context_create); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.h b/src/gallium/drivers/freedreno/a6xx/fd6_context.h index 76ae4b41460..b3d342a3772 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_context.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.h @@ -92,6 +92,9 @@ struct fd6_context { /* pre-baked stateobj for sample-locations disable: */ struct fd_ringbuffer *sample_locations_disable_stateobj; + /* pre-baked stateobj for preamble: */ + struct fd_ringbuffer *preamble, *restore; + /* storage for ctx->last.key: */ struct ir3_shader_key last_key; @@ -154,6 +157,8 @@ struct fd6_control { uint32_t offset; uint32_t pad[7]; } flush_base[4]; + + uint32_t vsc_state[32]; }; #define control_ptr(fd6_ctx, member) \ diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.cc b/src/gallium/drivers/freedreno/a6xx/fd6_emit.cc index eeb7919b659..18b67287eea 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.cc +++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.cc @@ -856,60 +856,12 @@ fd6_emit_stomp(struct fd_ringbuffer *ring, const uint16_t *regs, size_t count) } } -/* emit setup at begin of new cmdstream buffer (don't rely on previous - * state, there could have been a context switch between ioctls): - */ template void -fd6_emit_restore(struct fd_batch *batch, struct fd_ringbuffer *ring) +fd6_emit_static_regs(struct fd_context *ctx, struct fd_ringbuffer *ring) { - struct fd_context *ctx = batch->ctx; struct fd_screen *screen = ctx->screen; - if (!batch->nondraw) { - trace_start_state_restore(&batch->trace, ring); - } - - if (FD_DBG(STOMP)) { - fd6_emit_stomp(ring, &RP_BLIT_REGS[0], ARRAY_SIZE(RP_BLIT_REGS)); - fd6_emit_stomp(ring, &CMD_REGS[0], ARRAY_SIZE(CMD_REGS)); - } - - OUT_PKT7(ring, CP_SET_MODE, 1); - OUT_RING(ring, 0); - - if (CHIP == A6XX) { - fd6_cache_inv(ctx, ring); - } else { - OUT_PKT7(ring, CP_THREAD_CONTROL, 1); - OUT_RING(ring, CP_THREAD_CONTROL_0_THREAD(CP_SET_THREAD_BR) | - CP_THREAD_CONTROL_0_CONCURRENT_BIN_DISABLE); - - fd6_event_write(ctx, ring, FD_CCU_INVALIDATE_COLOR); - fd6_event_write(ctx, ring, FD_CCU_INVALIDATE_DEPTH); - - OUT_PKT7(ring, CP_EVENT_WRITE, 1); - OUT_RING(ring, UNK_40); - - fd6_event_write(ctx, ring, FD_CACHE_INVALIDATE); - OUT_WFI5(ring); - } - - OUT_REG(ring, - HLSQ_INVALIDATE_CMD(CHIP, - .vs_state = true, .hs_state = true, - .ds_state = true, .gs_state = true, - .fs_state = true, .cs_state = true, - .cs_ibo = true, .gfx_ibo = true, - .cs_shared_const = true, - .gfx_shared_const = true, - .cs_bindless = CHIP == A6XX ? 0x1f : 0xff, - .gfx_bindless = CHIP == A6XX ? 0x1f : 0xff, - ) - ); - - OUT_WFI5(ring); - if (CHIP >= A7XX) { /* On A7XX, RB_CCU_CNTL was broken into two registers, RB_CCU_CNTL which has * static properties that can be set once, this requires a WFI to take effect. @@ -926,8 +878,6 @@ fd6_emit_restore(struct fd_batch *batch, struct fd_ringbuffer *ring) ); } - fd6_emit_ccu_cntl(ring, screen, false); - for (size_t i = 0; i < ARRAY_SIZE(screen->info->a6xx.magic_raw); i++) { auto magic_reg = screen->info->a6xx.magic_raw[i]; if (!magic_reg.reg) @@ -1126,6 +1076,65 @@ fd6_emit_restore(struct fd_batch *batch, struct fd_ringbuffer *ring) if (screen->info->a6xx.has_early_preamble) { WRITE(REG_A6XX_SP_FS_CTRL_REG0, 0); } +} +FD_GENX(fd6_emit_static_regs); + +/* emit setup at begin of new cmdstream buffer (don't rely on previous + * state, there could have been a context switch between ioctls): + */ +template +void +fd6_emit_restore(struct fd_batch *batch, struct fd_ringbuffer *ring) +{ + struct fd_context *ctx = batch->ctx; + struct fd_screen *screen = ctx->screen; + + if (!batch->nondraw) { + trace_start_state_restore(&batch->trace, ring); + } + + if (FD_DBG(STOMP)) { + fd6_emit_stomp(ring, &RP_BLIT_REGS[0], ARRAY_SIZE(RP_BLIT_REGS)); + fd6_emit_stomp(ring, &CMD_REGS[0], ARRAY_SIZE(CMD_REGS)); + } + + OUT_PKT7(ring, CP_SET_MODE, 1); + OUT_RING(ring, 0); + + if (CHIP == A6XX) { + fd6_cache_inv(ctx, ring); + } else { + OUT_PKT7(ring, CP_THREAD_CONTROL, 1); + OUT_RING(ring, CP_THREAD_CONTROL_0_THREAD(CP_SET_THREAD_BR) | + CP_THREAD_CONTROL_0_CONCURRENT_BIN_DISABLE); + + fd6_event_write(ctx, ring, FD_CCU_INVALIDATE_COLOR); + fd6_event_write(ctx, ring, FD_CCU_INVALIDATE_DEPTH); + + OUT_PKT7(ring, CP_EVENT_WRITE, 1); + OUT_RING(ring, UNK_40); + + fd6_event_write(ctx, ring, FD_CACHE_INVALIDATE); + OUT_WFI5(ring); + } + + OUT_REG(ring, + HLSQ_INVALIDATE_CMD(CHIP, + .vs_state = true, .hs_state = true, + .ds_state = true, .gs_state = true, + .fs_state = true, .cs_state = true, + .cs_ibo = true, .gfx_ibo = true, + .cs_shared_const = true, + .gfx_shared_const = true, + .cs_bindless = CHIP == A6XX ? 0x1f : 0xff, + .gfx_bindless = CHIP == A6XX ? 0x1f : 0xff, + ) + ); + + OUT_WFI5(ring); + + fd6_emit_ib(ring, fd6_context(ctx)->restore); + fd6_emit_ccu_cntl(ring, screen, false); if (!batch->nondraw) { trace_end_state_restore(&batch->trace, ring); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.h b/src/gallium/drivers/freedreno/a6xx/fd6_emit.h index 351efccd707..d8b9f5b6359 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.h @@ -384,6 +384,9 @@ void fd6_emit_cs_state(struct fd_context *ctx, struct fd_ringbuffer *ring, template void fd6_emit_ccu_cntl(struct fd_ringbuffer *ring, struct fd_screen *screen, bool gmem); +template +void fd6_emit_static_regs(struct fd_context *ctx, struct fd_ringbuffer *ring); + template void fd6_emit_restore(struct fd_batch *batch, struct fd_ringbuffer *ring); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.cc b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.cc index 91c2c0a37eb..ef878cc9815 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.cc +++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.cc @@ -1068,6 +1068,48 @@ static void prepare_tile_setup(struct fd_batch *batch); template static void prepare_tile_fini(struct fd_batch *batch); +static void +fd7_emit_static_binning_regs(struct fd_ringbuffer *ring) +{ + OUT_REG(ring, A7XX_RB_UNKNOWN_8812(0x0)); + OUT_REG(ring, A7XX_RB_UNKNOWN_8E06(0x0)); + OUT_REG(ring, A7XX_GRAS_UNKNOWN_8007(0x0)); + OUT_REG(ring, A6XX_GRAS_UNKNOWN_8110(0x2)); + OUT_REG(ring, A7XX_RB_UNKNOWN_8E09(0x4)); + OUT_REG(ring, A7XX_RB_BLIT_CLEAR_MODE(.clear_mode = CLEAR_MODE_GMEM)); +} + +template +struct fd_ringbuffer * +fd6_build_preemption_preamble(struct fd_context *ctx) +{ + struct fd_screen *screen = ctx->screen; + struct fd_ringbuffer *ring; + + ring = fd_ringbuffer_new_object(ctx->pipe, 0x1000); + fd6_emit_static_regs(ctx, ring); + fd6_emit_ccu_cntl(ring, screen, false); + + if (CHIP == A6XX) { + OUT_REG(ring, A6XX_PC_POWER_CNTL(screen->info->a6xx.magic.PC_POWER_CNTL)); + OUT_REG(ring, A6XX_VFD_POWER_CNTL(screen->info->a6xx.magic.PC_POWER_CNTL)); + } else if (CHIP >= A7XX) { + fd7_emit_static_binning_regs(ring); + } + + /* TODO use CP_MEM_TO_SCRATCH_MEM on a7xx. The VSC scratch mem should be + * automatically saved, unlike GPU registers, so we wouldn't have to + * manually restore this state. + */ + OUT_PKT7(ring, CP_MEM_TO_REG, 3); + OUT_RING(ring, CP_MEM_TO_REG_0_REG(REG_A6XX_VSC_STATE(0)) | + CP_MEM_TO_REG_0_CNT(32)); + OUT_RELOC(ring, control_ptr(fd6_context(ctx), vsc_state)); + + return ring; +} +FD_GENX(fd6_build_preemption_preamble); + /* before first tile */ template static void @@ -1109,13 +1151,8 @@ fd6_emit_tile_init(struct fd_batch *batch) assert_dt emit_msaa(ring, pfb->samples); patch_fb_read_gmem(batch); - if (CHIP >= A7XX) { - OUT_REG(ring, A7XX_RB_UNKNOWN_8812(0x0)); - OUT_REG(ring, A7XX_RB_UNKNOWN_8E06(0x0)); - OUT_REG(ring, A7XX_GRAS_UNKNOWN_8007(0x0)); - OUT_REG(ring, A6XX_GRAS_UNKNOWN_8110(0x2)); - OUT_REG(ring, A7XX_RB_UNKNOWN_8E09(0x4)); - } + if (CHIP >= A7XX) + fd7_emit_static_binning_regs(ring); if (use_hw_binning(batch)) { /* enable stream-out during binning pass: */ @@ -1156,6 +1193,14 @@ fd6_emit_tile_init(struct fd_batch *batch) assert_dt OUT_PKT7(ring, CP_SKIP_IB2_ENABLE_GLOBAL, 1); OUT_RING(ring, 0x1); + + /* Upload state regs to memory to be restored on skipsaverestore + * preemption. + */ + OUT_PKT7(ring, CP_REG_TO_MEM, 3); + OUT_RING(ring, CP_REG_TO_MEM_0_REG(REG_A6XX_VSC_STATE_REG(0)) | + CP_REG_TO_MEM_0_CNT(32)); + OUT_RELOC(ring, control_ptr(fd6_context(batch->ctx), vsc_state)); } else { /* no binning pass, so enable stream-out for draw pass:: */ OUT_REG(ring, A6XX_VPC_SO_DISABLE(false)); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.h b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.h index aa539c95852..ca735df0edd 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.h @@ -12,6 +12,9 @@ #include "pipe/p_context.h" +template +struct fd_ringbuffer *fd6_build_preemption_preamble(struct fd_context *ctx); + template void fd6_gmem_init(struct pipe_context *pctx);