From 35fc1595b378ce093f126312d00e86e59ab3bc52 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 11 Feb 2023 08:06:38 -0800 Subject: [PATCH] freedreno/a6xx: Pre-compute PROG related LRZ state 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 Part-of: --- src/freedreno/registers/adreno/a6xx.xml | 2 ++ .../drivers/freedreno/a6xx/fd6_context.h | 17 ++++++++----- src/gallium/drivers/freedreno/a6xx/fd6_emit.c | 24 +++++++------------ .../drivers/freedreno/a6xx/fd6_program.c | 21 ++++++++++++++++ .../drivers/freedreno/a6xx/fd6_program.h | 5 ++++ 5 files changed, 47 insertions(+), 22 deletions(-) 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 *