diff --git a/src/freedreno/registers/adreno/a6xx.xml b/src/freedreno/registers/adreno/a6xx.xml
index 20ea4b6b162..9f801a20c61 100644
--- a/src/freedreno/registers/adreno/a6xx.xml
+++ b/src/freedreno/registers/adreno/a6xx.xml
@@ -954,6 +954,8 @@ to upconvert to 32b float internally?
know will definitely not be visible.
+ Not a real hw value, used internally by mesa
+
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.h b/src/gallium/drivers/freedreno/a6xx/fd6_context.h
index cb264ca1c0c..93d676661a3 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_context.h
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.h
@@ -39,13 +39,18 @@
#include "a6xx.xml.h"
struct fd6_lrz_state {
- bool enable : 1;
- bool write : 1;
- bool test : 1;
- enum fd_lrz_direction direction : 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;
+ /* this comes from the fs program state, rather than zsa: */
+ enum a6xx_ztest_mode z_mode : 2;
+ };
+ uint32_t val : 7;
+ };
};
/**
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
index 689d3b8ec27..98ed5312b53 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
@@ -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;
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_program.c b/src/gallium/drivers/freedreno/a6xx/fd6_program.c
index db718bdfc54..765c719ebdc 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_program.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_program.c
@@ -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;
}
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_program.h b/src/gallium/drivers/freedreno/a6xx/fd6_program.h
index 09150c2afb8..2acdd0e18cb 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_program.h
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_program.h
@@ -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 *