Mesa (master): turnip: add LRZ early-z support

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Apr 20 10:23:46 UTC 2021


Module: Mesa
Branch: master
Commit: b2a60c157e4d6cc62c55d8fe8777f7cbd548a722
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=b2a60c157e4d6cc62c55d8fe8777f7cbd548a722

Author: Samuel Iglesias Gonsálvez <siglesias at igalia.com>
Date:   Thu Feb  4 16:50:12 2021 +0100

turnip: add LRZ early-z support

Imported the logic from Freedreno driver.

Signed-off-by: Samuel Iglesias Gonsálvez <siglesias at igalia.com>
Reviewed-by: Eric Anholt <eric at anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7186>

---

 src/freedreno/vulkan/tu_cmd_buffer.c | 96 ++++++++++++++++++++++++++++++++++--
 src/freedreno/vulkan/tu_pipeline.c   | 34 ++++++-------
 src/freedreno/vulkan/tu_private.h    |  5 ++
 3 files changed, 114 insertions(+), 21 deletions(-)

diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c
index 85182464a11..1841fd3b80d 100644
--- a/src/freedreno/vulkan/tu_cmd_buffer.c
+++ b/src/freedreno/vulkan/tu_cmd_buffer.c
@@ -3517,6 +3517,91 @@ tu6_build_lrz(struct tu_cmd_buffer *cmd)
    return ds;
 }
 
+static bool
+tu6_writes_depth(struct tu_cmd_buffer *cmd, bool depth_test_enable)
+{
+   bool depth_write_enable =
+      cmd->state.rb_depth_cntl & A6XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE;
+
+   VkCompareOp depth_compare_op =
+      (cmd->state.rb_depth_cntl & A6XX_RB_DEPTH_CNTL_ZFUNC__MASK) >> A6XX_RB_DEPTH_CNTL_ZFUNC__SHIFT;
+
+   bool depth_compare_op_writes = depth_compare_op != VK_COMPARE_OP_NEVER;
+
+   return depth_test_enable && depth_write_enable && depth_compare_op_writes;
+}
+
+static bool
+tu6_writes_stencil(struct tu_cmd_buffer *cmd)
+{
+   bool stencil_test_enable =
+      cmd->state.rb_stencil_cntl & A6XX_RB_STENCIL_CONTROL_STENCIL_ENABLE;
+
+   bool stencil_front_writemask =
+      (cmd->state.pipeline->dynamic_state_mask & BIT(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK)) ?
+      (cmd->state.dynamic_stencil_wrmask & 0xff) :
+      (cmd->state.pipeline->stencil_wrmask & 0xff);
+
+   bool stencil_back_writemask =
+      (cmd->state.pipeline->dynamic_state_mask & BIT(VK_DYNAMIC_STATE_STENCIL_WRITE_MASK)) ?
+      ((cmd->state.dynamic_stencil_wrmask & 0xff00) >> 8) :
+      (cmd->state.pipeline->stencil_wrmask & 0xff00) >> 8;
+
+   VkStencilOp front_fail_op =
+      (cmd->state.rb_stencil_cntl & A6XX_RB_STENCIL_CONTROL_FAIL__MASK) >> A6XX_RB_STENCIL_CONTROL_FAIL__SHIFT;
+   VkStencilOp front_pass_op =
+      (cmd->state.rb_stencil_cntl & A6XX_RB_STENCIL_CONTROL_ZPASS__MASK) >> A6XX_RB_STENCIL_CONTROL_ZPASS__SHIFT;
+   VkStencilOp front_depth_fail_op =
+      (cmd->state.rb_stencil_cntl & A6XX_RB_STENCIL_CONTROL_ZFAIL__MASK) >> A6XX_RB_STENCIL_CONTROL_ZFAIL__SHIFT;
+   VkStencilOp back_fail_op =
+      (cmd->state.rb_stencil_cntl & A6XX_RB_STENCIL_CONTROL_FAIL_BF__MASK) >> A6XX_RB_STENCIL_CONTROL_FAIL_BF__SHIFT;
+   VkStencilOp back_pass_op =
+      (cmd->state.rb_stencil_cntl & A6XX_RB_STENCIL_CONTROL_ZPASS_BF__MASK) >> A6XX_RB_STENCIL_CONTROL_ZPASS_BF__SHIFT;
+   VkStencilOp back_depth_fail_op =
+      (cmd->state.rb_stencil_cntl & A6XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK) >> A6XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT;
+
+   bool stencil_front_op_writes =
+      front_pass_op != VK_STENCIL_OP_KEEP &&
+      front_fail_op != VK_STENCIL_OP_KEEP &&
+      front_depth_fail_op != VK_STENCIL_OP_KEEP;
+
+   bool stencil_back_op_writes =
+      back_pass_op != VK_STENCIL_OP_KEEP &&
+      back_fail_op != VK_STENCIL_OP_KEEP &&
+      back_depth_fail_op != VK_STENCIL_OP_KEEP;
+
+   return stencil_test_enable &&
+      ((stencil_front_writemask && stencil_front_op_writes) ||
+       (stencil_back_writemask && stencil_back_op_writes));
+}
+
+static struct tu_draw_state
+tu6_build_depth_plane_z_mode(struct tu_cmd_buffer *cmd)
+{
+   struct tu_cs cs;
+   struct tu_draw_state ds = tu_cs_draw_state(&cmd->sub_cs, &cs, 4);
+
+   enum a6xx_ztest_mode zmode = A6XX_EARLY_Z;
+   bool depth_test_enable = cmd->state.rb_depth_cntl & A6XX_RB_DEPTH_CNTL_Z_ENABLE;
+   bool depth_write = tu6_writes_depth(cmd, depth_test_enable);
+   bool stencil_write = tu6_writes_stencil(cmd);
+
+   if (cmd->state.pipeline->lrz.fs_has_kill &&
+       (depth_write || stencil_write)) {
+      zmode = cmd->state.lrz.valid ? A6XX_EARLY_LRZ_LATE_Z : A6XX_LATE_Z;
+   }
+
+   if (cmd->state.pipeline->lrz.force_late_z || !depth_test_enable)
+      zmode = A6XX_LATE_Z;
+
+   tu_cs_emit_pkt4(&cs, REG_A6XX_GRAS_SU_DEPTH_PLANE_CNTL, 1);
+   tu_cs_emit(&cs, A6XX_GRAS_SU_DEPTH_PLANE_CNTL_Z_MODE(zmode));
+
+   tu_cs_emit_pkt4(&cs, REG_A6XX_RB_DEPTH_PLANE_CNTL, 1);
+   tu_cs_emit(&cs, A6XX_RB_DEPTH_PLANE_CNTL_Z_MODE(zmode));
+   return ds;
+}
+
 static VkResult
 tu6_draw_common(struct tu_cmd_buffer *cmd,
                 struct tu_cs *cs,
@@ -3533,8 +3618,10 @@ tu6_draw_common(struct tu_cmd_buffer *cmd,
 
    tu_emit_cache_flush_renderpass(cmd, cs);
 
-   if (dirty_lrz)
+   if (dirty_lrz) {
       cmd->state.lrz.state = tu6_build_lrz(cmd);
+      cmd->state.depth_plane_state = tu6_build_depth_plane_z_mode(cmd);
+   }
 
    tu_cs_emit_regs(cs, A6XX_PC_PRIMITIVE_CNTL_0(
          .primitive_restart =
@@ -3623,6 +3710,7 @@ tu6_draw_common(struct tu_cmd_buffer *cmd,
       tu_cs_emit_draw_state(cs, TU_DRAW_STATE_VB, cmd->state.vertex_buffers);
       tu_cs_emit_draw_state(cs, TU_DRAW_STATE_VS_PARAMS, cmd->state.vs_params);
       tu_cs_emit_draw_state(cs, TU_DRAW_STATE_LRZ, cmd->state.lrz.state);
+      tu_cs_emit_draw_state(cs, TU_DRAW_STATE_DEPTH_PLANE, cmd->state.depth_plane_state);
 
       for (uint32_t i = 0; i < ARRAY_SIZE(cmd->state.dynamic_state); i++) {
          tu_cs_emit_draw_state(cs, TU_DRAW_STATE_DYNAMIC + i,
@@ -3640,7 +3728,7 @@ tu6_draw_common(struct tu_cmd_buffer *cmd,
          ((cmd->state.dirty & TU_CMD_DIRTY_SHADER_CONSTS) ? 2 : 0) +
          ((cmd->state.dirty & TU_CMD_DIRTY_DESC_SETS_LOAD) ? 1 : 0) +
          ((cmd->state.dirty & TU_CMD_DIRTY_VERTEX_BUFFERS) ? 1 : 0) +
-         (dirty_lrz ? 1 : 0) +
+         (dirty_lrz ? 2 : 0) +
          1; /* vs_params */
 
       if ((cmd->state.dirty & TU_CMD_DIRTY_VB_STRIDE) &&
@@ -3669,8 +3757,10 @@ tu6_draw_common(struct tu_cmd_buffer *cmd,
       }
       tu_cs_emit_draw_state(cs, TU_DRAW_STATE_VS_PARAMS, cmd->state.vs_params);
 
-      if (dirty_lrz)
+      if (dirty_lrz) {
          tu_cs_emit_draw_state(cs, TU_DRAW_STATE_LRZ, cmd->state.lrz.state);
+         tu_cs_emit_draw_state(cs, TU_DRAW_STATE_DEPTH_PLANE, cmd->state.depth_plane_state);
+      }
    }
 
    tu_cs_sanity_check(cs);
diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c
index 2c4a9521f45..e866f8d7e00 100644
--- a/src/freedreno/vulkan/tu_pipeline.c
+++ b/src/freedreno/vulkan/tu_pipeline.c
@@ -1371,7 +1371,8 @@ tu6_emit_fs_outputs(struct tu_cs *cs,
                     const struct ir3_shader_variant *fs,
                     uint32_t mrt_count, bool dual_src_blend,
                     uint32_t render_components,
-                    bool no_earlyz)
+                    bool no_earlyz,
+                    struct tu_pipeline *pipeline)
 {
    uint32_t smask_regid, posz_regid, stencilref_regid;
 
@@ -1417,20 +1418,14 @@ tu6_emit_fs_outputs(struct tu_cs *cs,
    tu_cs_emit_regs(cs,
                    A6XX_RB_RENDER_COMPONENTS(.dword = render_components));
 
-   enum a6xx_ztest_mode zmode;
+   if (pipeline) {
+      pipeline->lrz.fs_has_kill = fs->has_kill;
 
-   if ((fs->shader && !fs->shader->nir->info.fs.early_fragment_tests) &&
-       (fs->no_earlyz || fs->has_kill || fs->writes_pos || fs->writes_stencilref || no_earlyz || fs->writes_smask)) {
-      zmode = A6XX_LATE_Z;
-   } else {
-      zmode = A6XX_EARLY_Z;
+      if ((fs->shader && !fs->shader->nir->info.fs.early_fragment_tests) &&
+          (fs->no_earlyz || fs->has_kill || fs->writes_pos || fs->writes_stencilref || no_earlyz || fs->writes_smask)) {
+         pipeline->lrz.force_late_z = true;
+      }
    }
-
-   tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_SU_DEPTH_PLANE_CNTL, 1);
-   tu_cs_emit(cs, A6XX_GRAS_SU_DEPTH_PLANE_CNTL_Z_MODE(zmode));
-
-   tu_cs_emit_pkt4(cs, REG_A6XX_RB_DEPTH_PLANE_CNTL, 1);
-   tu_cs_emit(cs, A6XX_RB_DEPTH_PLANE_CNTL_Z_MODE(zmode));
 }
 
 static void
@@ -1498,7 +1493,8 @@ tu6_emit_geom_tess_consts(struct tu_cs *cs,
 static void
 tu6_emit_program(struct tu_cs *cs,
                  struct tu_pipeline_builder *builder,
-                 bool binning_pass)
+                 bool binning_pass,
+                 struct tu_pipeline *pipeline)
 {
    const struct ir3_shader_variant *vs = builder->variants[MESA_SHADER_VERTEX];
    const struct ir3_shader_variant *bs = builder->binning_variant;
@@ -1592,7 +1588,8 @@ tu6_emit_program(struct tu_cs *cs,
       tu6_emit_fs_outputs(cs, fs, mrt_count,
                           builder->use_dual_src_blend,
                           render_components,
-                          no_earlyz);
+                          no_earlyz,
+                          pipeline);
    } else {
       /* TODO: check if these can be skipped if fs is disabled */
       struct ir3_shader_variant dummy_variant = {};
@@ -1600,7 +1597,8 @@ tu6_emit_program(struct tu_cs *cs,
       tu6_emit_fs_outputs(cs, &dummy_variant, mrt_count,
                           builder->use_dual_src_blend,
                           render_components,
-                          no_earlyz);
+                          no_earlyz,
+                          NULL);
    }
 
    if (gs || hs) {
@@ -2421,11 +2419,11 @@ tu_pipeline_builder_parse_shader_stages(struct tu_pipeline_builder *builder,
 {
    struct tu_cs prog_cs;
    tu_cs_begin_sub_stream(&pipeline->cs, 512, &prog_cs);
-   tu6_emit_program(&prog_cs, builder, false);
+   tu6_emit_program(&prog_cs, builder, false, pipeline);
    pipeline->program.state = tu_cs_end_draw_state(&pipeline->cs, &prog_cs);
 
    tu_cs_begin_sub_stream(&pipeline->cs, 512, &prog_cs);
-   tu6_emit_program(&prog_cs, builder, true);
+   tu6_emit_program(&prog_cs, builder, true, pipeline);
    pipeline->program.binning_state = tu_cs_end_draw_state(&pipeline->cs, &prog_cs);
 
    VkShaderStageFlags stages = 0;
diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h
index d2a46ec9861..99e2f1f63e2 100644
--- a/src/freedreno/vulkan/tu_private.h
+++ b/src/freedreno/vulkan/tu_private.h
@@ -487,6 +487,7 @@ enum tu_draw_state_group_id
    TU_DRAW_STATE_INPUT_ATTACHMENTS_GMEM,
    TU_DRAW_STATE_INPUT_ATTACHMENTS_SYSMEM,
    TU_DRAW_STATE_LRZ,
+   TU_DRAW_STATE_DEPTH_PLANE,
 
    /* dynamic state related draw states */
    TU_DRAW_STATE_DYNAMIC,
@@ -849,6 +850,8 @@ enum tu_lrz_direction {
 struct tu_lrz_pipeline
 {
    uint32_t force_disable_mask;
+   bool fs_has_kill;
+   bool force_late_z;
 };
 
 struct tu_lrz_state
@@ -931,6 +934,8 @@ struct tu_cmd_state
    bool predication_active;
 
    struct tu_lrz_state lrz;
+
+   struct tu_draw_state depth_plane_state;
 };
 
 struct tu_cmd_pool



More information about the mesa-commit mailing list