freedreno/a6xx: Pre-compute PROG related LRZ state
authorRob Clark <robdclark@chromium.org>
Sat, 11 Feb 2023 16:06:38 +0000 (08:06 -0800)
committerMarge Bot <emma+marge@anholt.net>
Thu, 16 Feb 2023 19:57:13 +0000 (19:57 +0000)
PROG state mostly just disables various LRZ related flags, which can
be handled as a simple mask.  The exception is ztest mode, which is
either overriden by PROG state, or we use the all 1's value (which
isn't valid from hw standpoint) to signal that it needs to be computed
at draw time, which fortunately fits in with the bitmask approach.

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

src/freedreno/registers/adreno/a6xx.xml
src/gallium/drivers/freedreno/a6xx/fd6_context.h
src/gallium/drivers/freedreno/a6xx/fd6_emit.c
src/gallium/drivers/freedreno/a6xx/fd6_program.c
src/gallium/drivers/freedreno/a6xx/fd6_program.h

index 20ea4b6..9f801a2 100644 (file)
@@ -954,6 +954,8 @@ to upconvert to 32b float internally?
                know will definitely not be visible.
        </doc>
        <value value="0x2" name="A6XX_EARLY_LRZ_LATE_Z"/>
+       <doc>Not a real hw value, used internally by mesa</doc>
+       <value value="0x3" name="A6XX_INVALID_ZTEST"/>
 </enum>
 
 <domain name="A6XX" width="32">
index cb264ca..93d6766 100644 (file)
 #include "a6xx.xml.h"
 
 struct fd6_lrz_state {
-   bool enable : 1;
-   bool write : 1;
-   bool test : 1;
-   enum fd_lrz_direction direction : 2;
-
-   /* this comes from the fs program state, rather than zsa: */
-   enum a6xx_ztest_mode z_mode : 2;
+   union {
+      struct {
+         bool enable : 1;
+         bool write : 1;
+         bool test : 1;
+         enum fd_lrz_direction direction : 2;
+
+         /* this comes from the fs program state, rather than zsa: */
+         enum a6xx_ztest_mode z_mode : 2;
+      };
+      uint32_t val : 7;
+   };
 };
 
 /**
index 689d3b8..98ed531 100644 (file)
@@ -107,16 +107,15 @@ build_vbo_state(struct fd6_emit *emit) assert_dt
 static enum a6xx_ztest_mode
 compute_ztest_mode(struct fd6_emit *emit, bool lrz_valid) assert_dt
 {
+   if (emit->prog->lrz_mask.z_mode != A6XX_INVALID_ZTEST)
+      return emit->prog->lrz_mask.z_mode;
+
    struct fd_context *ctx = emit->ctx;
    struct pipe_framebuffer_state *pfb = &ctx->batch->framebuffer;
    struct fd6_zsa_stateobj *zsa = fd6_zsa_stateobj(ctx->zsa);
    const struct ir3_shader_variant *fs = emit->fs;
 
-   if (fs->fs.early_fragment_tests)
-      return A6XX_EARLY_Z;
-
-   if (fs->no_earlyz || fs->writes_pos || !zsa->base.depth_enabled ||
-       fs->writes_stencilref) {
+   if (!zsa->base.depth_enabled) {
       return A6XX_LATE_Z;
    } else if ((fs->has_kill || zsa->alpha_test) &&
               (zsa->writes_zs || !pfb->zsbuf)) {
@@ -142,7 +141,6 @@ compute_lrz_state(struct fd6_emit *emit) assert_dt
 {
    struct fd_context *ctx = emit->ctx;
    struct pipe_framebuffer_state *pfb = &ctx->batch->framebuffer;
-   const struct ir3_shader_variant *fs = emit->fs;
    struct fd6_lrz_state lrz;
 
    if (!pfb->zsbuf) {
@@ -158,9 +156,10 @@ compute_lrz_state(struct fd6_emit *emit) assert_dt
 
    lrz = zsa->lrz;
 
+   lrz.val &= emit->prog->lrz_mask.val;
+
    /* normalize lrz state: */
-   if (reads_dest || fs->writes_pos || fs->no_earlyz || fs->has_kill ||
-       blend->base.alpha_to_coverage) {
+   if (reads_dest || blend->base.alpha_to_coverage) {
       lrz.write = false;
    }
 
@@ -222,12 +221,6 @@ compute_lrz_state(struct fd6_emit *emit) assert_dt
       memset(&lrz, 0, sizeof(lrz));
    }
 
-   if (fs->no_earlyz || fs->writes_pos) {
-      lrz.enable = false;
-      lrz.write = false;
-      lrz.test = false;
-   }
-
    lrz.z_mode = compute_ztest_mode(emit, rsc->lrz_valid);
 
    /* Once we start writing to the real depth buffer, we lock in the
@@ -255,8 +248,7 @@ build_lrz(struct fd6_emit *emit) assert_dt
    struct fd6_lrz_state lrz = compute_lrz_state(emit);
 
    /* If the LRZ state has not changed, we can skip the emit: */
-   if (!ctx->last.dirty &&
-       !memcmp(&fd6_ctx->last.lrz, &lrz, sizeof(lrz)))
+   if (!ctx->last.dirty && (fd6_ctx->last.lrz.val == lrz.val))
       return NULL;
 
    fd6_ctx->last.lrz = lrz;
index db718bd..765c719 100644 (file)
@@ -1366,6 +1366,27 @@ fd6_program_create(void *data, struct ir3_shader_variant *bs,
 
    state->num_driver_params = num_dp;
 
+   state->lrz_mask.val = ~0;
+
+   if (fs->has_kill) {
+      state->lrz_mask.write = false;
+   }
+
+   if (fs->no_earlyz || fs->writes_pos) {
+      state->lrz_mask.enable = false;
+      state->lrz_mask.write = false;
+      state->lrz_mask.test = false;
+   }
+
+   if (fs->fs.early_fragment_tests) {
+      state->lrz_mask.z_mode = A6XX_EARLY_Z;
+   } else if (fs->no_earlyz || fs->writes_pos || fs->writes_stencilref) {
+      state->lrz_mask.z_mode = A6XX_LATE_Z;
+   } else {
+      /* Wildcard indicates that we need to figure out at draw time: */
+      state->lrz_mask.z_mode = A6XX_INVALID_ZTEST;
+   }
+
    return &state->base;
 }
 
index 09150c2..2acdd0e 100644 (file)
@@ -75,6 +75,11 @@ struct fd6_program_state {
     * calculate it up-front.
     */
    uint32_t user_consts_cmdstream_size;
+
+   /**
+    * The FS contribution to LRZ state
+    */
+   struct fd6_lrz_state lrz_mask;
 };
 
 static inline struct fd6_program_state *