From e552784e68efd771342fad473a48dc6e1eeb8cee Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 8 Jul 2021 10:28:43 -0700 Subject: [PATCH] freedreno+turnip: Add has_cp_reg_write Newer a6xx devices drop this packet from the sqe firmware, and use direct (pkt4) register writes instead for the few cases that previously used CP_REG_WRITE. The turnip part was adapted from Jonathans patch on !10892 Signed-off-by: Rob Clark Part-of: --- src/freedreno/common/freedreno_dev_info.h | 5 +++++ src/freedreno/common/freedreno_devices.py | 4 ++++ src/freedreno/vulkan/tu_clear_blit.c | 4 ++++ src/freedreno/vulkan/tu_cmd_buffer.c | 10 ++++++++++ src/freedreno/vulkan/tu_pipeline.c | 10 +++++++--- src/gallium/drivers/freedreno/a6xx/fd6_gmem.c | 11 ++++++++--- 6 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/freedreno/common/freedreno_dev_info.h b/src/freedreno/common/freedreno_dev_info.h index b4e4cf7b6c6..eaa64015e58 100644 --- a/src/freedreno/common/freedreno_dev_info.h +++ b/src/freedreno/common/freedreno_dev_info.h @@ -89,6 +89,11 @@ struct fd_dev_info { bool has_sample_locations; + /* The firmware on newer a6xx drops CP_REG_WRITE support as we + * can now use direct register writes for these regs. + */ + bool has_cp_reg_write; + struct { uint32_t RB_UNKNOWN_8E04_blit; uint32_t PC_UNKNOWN_9805; diff --git a/src/freedreno/common/freedreno_devices.py b/src/freedreno/common/freedreno_devices.py index 7e8bd6df89e..eb29fea6fd3 100644 --- a/src/freedreno/common/freedreno_devices.py +++ b/src/freedreno/common/freedreno_devices.py @@ -112,6 +112,10 @@ class A6xxGPUInfo(GPUInfo): self.a6xx.magic.PC_UNKNOWN_9805 = PC_UNKNOWN_9805 self.a6xx.magic.SP_UNKNOWN_A0F8 = SP_UNKNOWN_A0F8 + # Things that earlier gens have and later gens remove, provide + # defaults here and let them be overridden by sub-gen template: + self.a6xx.has_cp_reg_write = True + for name, val in template.items(): setattr(self.a6xx, name, val) diff --git a/src/freedreno/vulkan/tu_clear_blit.c b/src/freedreno/vulkan/tu_clear_blit.c index 5384b9e5bd7..1b2f7e95fc7 100644 --- a/src/freedreno/vulkan/tu_clear_blit.c +++ b/src/freedreno/vulkan/tu_clear_blit.c @@ -482,6 +482,7 @@ r3d_common(struct tu_cmd_buffer *cmd, struct tu_cs *cs, bool blit, uint32_t num_ tu_cs_emit_regs(cs, A6XX_PC_PRIMITIVE_CNTL_0()); tu_cs_emit_regs(cs, A6XX_VFD_CONTROL_0()); + if (cmd->device->physical_device->info->a6xx.has_cp_reg_write) { /* Copy what the blob does here. This will emit an extra 0x3f * CP_EVENT_WRITE when multiview is disabled. I'm not exactly sure what * this is working around yet. @@ -490,6 +491,9 @@ r3d_common(struct tu_cmd_buffer *cmd, struct tu_cs *cs, bool blit, uint32_t num_ tu_cs_emit(cs, CP_REG_WRITE_0_TRACKER(UNK_EVENT_WRITE)); tu_cs_emit(cs, REG_A6XX_PC_MULTIVIEW_CNTL); tu_cs_emit(cs, 0); + } else { + tu_cs_emit_regs(cs, A6XX_PC_MULTIVIEW_CNTL()); + } tu_cs_emit_regs(cs, A6XX_VFD_MULTIVIEW_CNTL()); tu6_emit_vpc(cs, &vs, NULL, NULL, NULL, &fs, 0); diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c index 4ff660dabee..ee69aa6d94c 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.c +++ b/src/freedreno/vulkan/tu_cmd_buffer.c @@ -324,9 +324,13 @@ tu6_emit_render_cntl(struct tu_cmd_buffer *cmd, bool binning) { const struct tu_framebuffer *fb = cmd->state.framebuffer; + /* doesn't RB_RENDER_CNTL set differently for binning pass: */ + bool no_track = !cmd->device->physical_device->info->a6xx.has_cp_reg_write; uint32_t cntl = 0; cntl |= A6XX_RB_RENDER_CNTL_UNK4; if (binning) { + if (no_track) + return; cntl |= A6XX_RB_RENDER_CNTL_BINNING; } else { uint32_t mrts_ubwc_enable = 0; @@ -349,6 +353,12 @@ tu6_emit_render_cntl(struct tu_cmd_buffer *cmd, cntl |= A6XX_RB_RENDER_CNTL_FLAG_DEPTH; } + if (no_track) { + tu_cs_emit_pkt4(cs, REG_A6XX_RB_RENDER_CNTL, 1); + tu_cs_emit(cs, cntl); + return; + } + /* In the !binning case, we need to set RB_RENDER_CNTL in the draw_cs * in order to set it correctly for the different subpasses. However, * that means the packets we're emitting also happen during binning. So diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c index 3e2f51e0db6..a7b495a04f6 100644 --- a/src/freedreno/vulkan/tu_pipeline.c +++ b/src/freedreno/vulkan/tu_pipeline.c @@ -1612,9 +1612,13 @@ tu6_emit_program(struct tu_cs *cs, * CP_EVENT_WRITE when multiview is disabled. I'm not exactly sure what * this is working around yet. */ - tu_cs_emit_pkt7(cs, CP_REG_WRITE, 3); - tu_cs_emit(cs, CP_REG_WRITE_0_TRACKER(UNK_EVENT_WRITE)); - tu_cs_emit(cs, REG_A6XX_PC_MULTIVIEW_CNTL); + if (builder->device->physical_device->info->a6xx.has_cp_reg_write) { + tu_cs_emit_pkt7(cs, CP_REG_WRITE, 3); + tu_cs_emit(cs, CP_REG_WRITE_0_TRACKER(UNK_EVENT_WRITE)); + tu_cs_emit(cs, REG_A6XX_PC_MULTIVIEW_CNTL); + } else { + tu_cs_emit_pkt4(cs, REG_A6XX_PC_MULTIVIEW_CNTL, 1); + } tu_cs_emit(cs, multiview_cntl); tu_cs_emit_pkt4(cs, REG_A6XX_VFD_MULTIVIEW_CNTL, 1); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c index 3e71cdd9ebc..f2cb7e8a7e8 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c @@ -335,6 +335,7 @@ update_render_cntl(struct fd_batch *batch, struct pipe_framebuffer_state *pfb, bool binning) { struct fd_ringbuffer *ring = batch->gmem; + struct fd_screen *screen = batch->ctx->screen; uint32_t cntl = 0; bool depth_ubwc_enable = false; uint32_t mrts_ubwc_enable = 0; @@ -363,9 +364,13 @@ update_render_cntl(struct fd_batch *batch, struct pipe_framebuffer_state *pfb, if (binning) cntl |= A6XX_RB_RENDER_CNTL_BINNING; - OUT_PKT7(ring, CP_REG_WRITE, 3); - OUT_RING(ring, CP_REG_WRITE_0_TRACKER(TRACK_RENDER_CNTL)); - OUT_RING(ring, REG_A6XX_RB_RENDER_CNTL); + if (screen->info->a6xx.has_cp_reg_write) { + OUT_PKT7(ring, CP_REG_WRITE, 3); + OUT_RING(ring, CP_REG_WRITE_0_TRACKER(TRACK_RENDER_CNTL)); + OUT_RING(ring, REG_A6XX_RB_RENDER_CNTL); + } else { + OUT_PKT4(ring, REG_A6XX_RB_RENDER_CNTL, 1); + } OUT_RING(ring, cntl | COND(depth_ubwc_enable, A6XX_RB_RENDER_CNTL_FLAG_DEPTH) | A6XX_RB_RENDER_CNTL_FLAG_MRTS(mrts_ubwc_enable));