freedreno/a6xx: update depth-plane control regs
authorRob Clark <robdclark@chromium.org>
Sun, 31 May 2020 17:46:54 +0000 (10:46 -0700)
committerMarge Bot <eric+marge@anholt.net>
Thu, 4 Jun 2020 02:34:54 +0000 (02:34 +0000)
And document the early-lrz-late-z mode.

Initially I thought this would be two bits to control early-lrz vs
early-z.  But having early-z without early-lrz does not make sense,
and the way the values line up makes an enum fit better.

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5298>

src/freedreno/registers/a6xx.xml
src/freedreno/vulkan/tu_pipeline.c
src/gallium/drivers/freedreno/a6xx/fd6_program.c

index c7b83059eb8cfb3f7c59fda325231632ac86a280..0a0eec3ea07c153ba038df22494099d1237ffa2e 100644 (file)
@@ -891,6 +891,44 @@ to upconvert to 32b float internally?
        <value value="0x0"  name="R2D_RAW"/>
 </enum>
 
+<enum name="a6xx_ztest_mode">
+       <doc>Allow early z-test and early-lrz (if applicable)</doc>
+       <value value="0x0" name="A6XX_EARLY_Z"/>
+       <doc>Disable early z-test and early-lrz test (if applicable)</doc>
+       <value value="0x1" name="A6XX_LATE_Z"/>
+       <doc>
+               A special mode that allows early-lrz test but disables
+               early-z test.  Which might sound a bit funny, since
+               lrz-test happens before z-test.  But as long as a couple
+               conditions are maintained this allows using lrz-test in
+               cases where fragment shader has kill/discard:
+
+               1) Disable lrz-write in cases where it is uncertain during
+                  binning pass that a fragment will pass.  Ie.  if frag
+                  shader has-kill, writes-z, or alpha/stencil test is
+                  enabled.  (For correctness, lrz-write must be disabled
+                  when blend is enabled.)  This is analogous to how a
+                  z-prepass works.
+
+               2) Disable lrz-write and test if a depth-test direction
+                  reversal is detected.  Due to condition (1), the contents
+                  of the lrz buffer are a conservative estimation of the
+                  depth buffer during the draw pass.  Meaning that geometry
+                  that we know for certain will not be visible will not pass
+                  lrz-test.  But geometry which may be (or contributes to
+                  blend) will pass the lrz-test.
+
+               This allows us to keep early-lrz-test in cases where the frag
+               shader does not write-z (ie. we know the z-value before FS)
+               and does not have side-effects (image/ssbo writes, etc), but
+               does have kill/discard.  Which turns out to be a common
+               enough case that it is useful to keep early-lrz test against
+               the conservative lrz buffer to discard fragments that we
+               know will definitely not be visible.
+       </doc>
+       <value value="0x2" name="A6XX_EARLY_LRZ_LATE_Z"/>
+</enum>
+
 <domain name="A6XX" width="32">
        <bitset name="A6XX_RBBM_INT_0_MASK" inline="yes">
                <bitfield name="RBBM_GPU_IDLE" pos="0"/>
@@ -1909,7 +1947,7 @@ to upconvert to 32b float internally?
        <reg32 offset="0x8092" name="GRAS_SU_POINT_SIZE" type="fixed" radix="4"/>
 
        <reg32 offset="0x8094" name="GRAS_SU_DEPTH_PLANE_CNTL">
-               <bitfield name="FRAG_WRITES_Z" pos="0" type="boolean"/>
+               <bitfield name="Z_MODE" low="0" high="1" type="a6xx_ztest_mode"/>
        </reg32>
        <reg32 offset="0x8095" name="GRAS_SU_POLY_OFFSET_SCALE" type="float"/>
        <reg32 offset="0x8096" name="GRAS_SU_POLY_OFFSET_OFFSET" type="float"/>
@@ -2259,7 +2297,7 @@ to upconvert to 32b float internally?
                <bitfield name="SAMPLE_MASK" low="16" high="31"/>
        </reg32>
        <reg32 offset="0x8870" name="RB_DEPTH_PLANE_CNTL">
-               <bitfield name="FRAG_WRITES_Z" pos="0" type="boolean"/>
+               <bitfield name="Z_MODE" low="0" high="1" type="a6xx_ztest_mode"/>
        </reg32>
 
        <reg32 offset="0x8871" name="RB_DEPTH_CNTL">
index debc4811e32417d558b9fe980a204147f7ddd703..5002f9f6f2a2685c420a3a6a16d5c5263a5da733 100644 (file)
@@ -1383,18 +1383,19 @@ tu6_emit_fs_outputs(struct tu_cs *cs,
    tu_cs_emit_regs(cs,
                    A6XX_RB_RENDER_COMPONENTS(.dword = render_components));
 
-   uint32_t gras_su_depth_plane_cntl = 0;
-   uint32_t rb_depth_plane_cntl = 0;
+   enum a6xx_ztest_mode zmode;
+
    if (fs->no_earlyz || fs->has_kill || fs->writes_pos) {
-      gras_su_depth_plane_cntl |= A6XX_GRAS_SU_DEPTH_PLANE_CNTL_FRAG_WRITES_Z;
-      rb_depth_plane_cntl |= A6XX_RB_DEPTH_PLANE_CNTL_FRAG_WRITES_Z;
+      zmode = A6XX_LATE_Z;
+   } else {
+      zmode = A6XX_EARLY_Z;
    }
 
    tu_cs_emit_pkt4(cs, REG_A6XX_GRAS_SU_DEPTH_PLANE_CNTL, 1);
-   tu_cs_emit(cs, gras_su_depth_plane_cntl);
+   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, rb_depth_plane_cntl);
+   tu_cs_emit(cs, A6XX_RB_DEPTH_PLANE_CNTL_Z_MODE(zmode));
 }
 
 static void
index 45a05544e6b3bed1297ea905d295301fe2415e26..dad117688af31420f39b0b3e2843c10135a8b509 100644 (file)
@@ -835,13 +835,19 @@ setup_stateobj(struct fd_ringbuffer *ring, struct fd_screen *screen,
        OUT_RING(ring,
                         COND(primid_passthru, A6XX_VFD_CONTROL_6_PRIMID_PASSTHRU));   /* VFD_CONTROL_6 */
 
-       bool fragz = fs->no_earlyz || fs->has_kill || fs->writes_pos;
+       enum a6xx_ztest_mode zmode;
+
+       if (fs->no_earlyz || fs->has_kill || fs->writes_pos) {
+               zmode = A6XX_LATE_Z;
+       } else {
+               zmode = A6XX_EARLY_Z;
+       }
 
        OUT_PKT4(ring, REG_A6XX_RB_DEPTH_PLANE_CNTL, 1);
-       OUT_RING(ring, COND(fragz, A6XX_RB_DEPTH_PLANE_CNTL_FRAG_WRITES_Z));
+       OUT_RING(ring, A6XX_RB_DEPTH_PLANE_CNTL_Z_MODE(zmode));
 
        OUT_PKT4(ring, REG_A6XX_GRAS_SU_DEPTH_PLANE_CNTL, 1);
-       OUT_RING(ring, COND(fragz, A6XX_GRAS_SU_DEPTH_PLANE_CNTL_FRAG_WRITES_Z));
+       OUT_RING(ring, A6XX_GRAS_SU_DEPTH_PLANE_CNTL_Z_MODE(zmode));
 
        if (!binning_pass)
                fd6_emit_immediates(screen, fs, ring);