etnaviv: rework ZSA into a derived state

The ZSA state is not fully self contained, as other states (mostly
shader using discard or writing depth information) have an influence
on whether we can use early Z test/write.

Rework the ZSA state into a derived state that gets updated whenever
a new ZSA or SHADER state is bound. This way we can automatically
enable/disable early Z as needed.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7396>
This commit is contained in:
Lucas Stach 2020-11-01 16:53:19 +01:00
parent 3c7fc95f4f
commit b29fe26d43
6 changed files with 84 additions and 33 deletions

View File

@ -431,8 +431,7 @@ etna_emit_state(struct etna_context *ctx)
}
if (unlikely(dirty & (ETNA_DIRTY_ZSA | ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_SHADER))) {
/*01400*/ EMIT_STATE(PE_DEPTH_CONFIG, (etna_zsa_state(ctx->zsa)->PE_DEPTH_CONFIG |
ctx->framebuffer.PE_DEPTH_CONFIG) &
ctx->shader_state.PE_DEPTH_CONFIG);
ctx->framebuffer.PE_DEPTH_CONFIG));
}
if (unlikely(dirty & (ETNA_DIRTY_VIEWPORT))) {
/*01404*/ EMIT_STATE(PE_DEPTH_NEAR, ctx->viewport.PE_DEPTH_NEAR);

View File

@ -245,7 +245,6 @@ struct compiled_shader_state {
uint32_t PS_TEMP_REGISTER_CONTROL;
uint32_t PS_TEMP_REGISTER_CONTROL_MSAA; /* Adds a temporary if needed to make space for extra input */
uint32_t PS_START_PC;
uint32_t PE_DEPTH_CONFIG;
uint32_t GL_VARYING_TOTAL_COMPONENTS;
uint32_t GL_VARYING_NUM_COMPONENTS[2];
uint32_t GL_VARYING_COMPONENT_USE[2];
@ -257,6 +256,8 @@ struct compiled_shader_state {
uint32_t *PS_INST_MEM;
struct etna_reloc PS_INST_ADDR;
struct etna_reloc VS_INST_ADDR;
unsigned writes_z:1;
unsigned uses_discard:1;
};
/* Helpers to assist creating and setting bitarrays (eg, for varyings).

View File

@ -251,8 +251,8 @@ etna_link_shaders(struct etna_context *ctx, struct compiled_shader_state *cs,
VIVS_GL_HALTI5_SH_SPECIALS_PS_PCOORD_IN((link.pcoord_varying_comp_ofs != -1) ?
link.pcoord_varying_comp_ofs : 0x7f);
/* mask out early Z bit when frag depth is written */
cs->PE_DEPTH_CONFIG = ~COND(fs->ps_depth_out_reg >= 0, VIVS_PE_DEPTH_CONFIG_EARLY_Z);
cs->writes_z = fs->ps_depth_out_reg >= 0;
cs->uses_discard = fs->uses_discard;
/* reference instruction memory */
cs->vs_inst_mem_size = vs->code_size;

View File

@ -39,6 +39,7 @@
#include "etnaviv_surface.h"
#include "etnaviv_translate.h"
#include "etnaviv_util.h"
#include "etnaviv_zsa.h"
#include "util/u_framebuffer.h"
#include "util/u_helpers.h"
#include "util/u_inlines.h"
@ -675,6 +676,71 @@ etna_update_clipping(struct etna_context *ctx)
return true;
}
static bool
etna_update_zsa(struct etna_context *ctx)
{
struct compiled_shader_state *shader_state = &ctx->shader_state;
struct pipe_depth_stencil_alpha_state *zsa_state = ctx->zsa;
struct etna_zsa_state *zsa = etna_zsa_state(zsa_state);
struct etna_screen *screen = ctx->screen;
uint32_t new_pe_depth, new_ra_depth;
bool late_z_write = false, early_z_write = false,
late_z_test = false, early_z_test = false;
if (zsa->z_write_enabled) {
if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH) &&
!VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z) &&
!zsa->stencil_enabled &&
!zsa_state->alpha.enabled &&
!shader_state->writes_z &&
!shader_state->uses_discard)
early_z_write = true;
else
late_z_write = true;
}
if (zsa->z_test_enabled) {
if (!VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z) &&
!zsa->stencil_modified &&
!shader_state->writes_z)
early_z_test = true;
else
late_z_test = true;
}
new_pe_depth = VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(zsa->z_test_enabled ?
/* compare funcs have 1 to 1 mapping */
zsa_state->depth.func : PIPE_FUNC_ALWAYS) |
COND(zsa->z_write_enabled, VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE) |
COND(early_z_test, VIVS_PE_DEPTH_CONFIG_EARLY_Z) |
COND(!late_z_write && !late_z_test && !zsa->stencil_enabled,
VIVS_PE_DEPTH_CONFIG_DISABLE_ZS);
/* blob sets this to 0x40000031 on GC7000, seems to make no difference,
* but keep it in mind if depth behaves strangely. */
new_ra_depth = 0x0000030 |
COND(early_z_test, VIVS_RA_EARLY_DEPTH_TEST_ENABLE);
if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH)) {
if (!early_z_write)
new_ra_depth |= VIVS_RA_EARLY_DEPTH_WRITE_DISABLE;
/* The new early hierarchical test seems to only work properly if depth
* is also written from the early stage.
*/
if (late_z_test || (early_z_test && late_z_write))
new_ra_depth |= VIVS_RA_EARLY_DEPTH_HDEPTH_DISABLE;
}
if (new_pe_depth != zsa->PE_DEPTH_CONFIG ||
new_ra_depth != zsa->RA_DEPTH_CONFIG)
ctx->dirty |= ETNA_DIRTY_ZSA;
zsa->PE_DEPTH_CONFIG = new_pe_depth;
zsa->RA_DEPTH_CONFIG = new_ra_depth;
return true;
}
struct etna_state_updater {
bool (*update)(struct etna_context *ctx);
uint32_t dirty;
@ -699,6 +765,9 @@ static const struct etna_state_updater etna_state_updates[] = {
{
etna_update_clipping, ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER |
ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT,
},
{
etna_update_zsa, ETNA_DIRTY_ZSA | ETNA_DIRTY_SHADER,
}
};

View File

@ -47,11 +47,10 @@ etna_zsa_state_create(struct pipe_context *pctx,
cs->base = *so;
cs->z_test_enabled = so->depth.enabled && so->depth.func != PIPE_FUNC_ALWAYS;
cs->z_write_enabled = so->depth.enabled && so->depth.writemask;
/* XXX does stencil[0] / stencil[1] order depend on rs->front_ccw? */
bool early_z = !VIV_FEATURE(ctx->screen, chipFeatures, NO_EARLY_Z);
bool disable_zs =
(!so->depth.enabled || so->depth.func == PIPE_FUNC_ALWAYS) &&
!so->depth.writemask;
/* Set operations to KEEP if write mask is 0.
* When we don't do this, the depth buffer is written for the entire primitive
@ -73,27 +72,21 @@ etna_zsa_state_create(struct pipe_context *pctx,
if (so->stencil[0].enabled) {
if (so->stencil[0].func != PIPE_FUNC_ALWAYS ||
(so->stencil[1].enabled && so->stencil[1].func != PIPE_FUNC_ALWAYS))
disable_zs = false;
cs->stencil_enabled = 1;
if (so->stencil[0].fail_op != PIPE_STENCIL_OP_KEEP ||
so->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP ||
so->stencil[0].zpass_op != PIPE_STENCIL_OP_KEEP) {
disable_zs = early_z = false;
cs->stencil_modified = 1;
} else if (so->stencil[1].enabled) {
if (so->stencil[1].fail_op != PIPE_STENCIL_OP_KEEP ||
so->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP ||
so->stencil[1].zpass_op != PIPE_STENCIL_OP_KEEP) {
disable_zs = early_z = false;
cs->stencil_modified = 1;
}
}
}
/* Disable early z reject when no depth test is enabled.
* This avoids having to sample depth even though we know it's going to
* succeed. */
if (so->depth.enabled == false || so->depth.func == PIPE_FUNC_ALWAYS)
early_z = false;
/* calculate extra_reference value */
uint32_t extra_reference = 0;
@ -103,15 +96,6 @@ etna_zsa_state_create(struct pipe_context *pctx,
cs->PE_STENCIL_CONFIG_EXT =
VIVS_PE_STENCIL_CONFIG_EXT_EXTRA_ALPHA_REF(extra_reference);
/* compare funcs have 1 to 1 mapping */
cs->PE_DEPTH_CONFIG =
VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(so->depth.enabled ? so->depth.func
: PIPE_FUNC_ALWAYS) |
COND(so->depth.writemask, VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE) |
COND(early_z, VIVS_PE_DEPTH_CONFIG_EARLY_Z) |
/* this bit changed meaning with HALTI5: */
COND((disable_zs && screen->specs.halti < 5) || ((early_z || disable_zs) && VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH)), VIVS_PE_DEPTH_CONFIG_DISABLE_ZS);
cs->PE_ALPHA_OP =
COND(so->alpha.enabled, VIVS_PE_ALPHA_OP_ALPHA_TEST) |
VIVS_PE_ALPHA_OP_ALPHA_FUNC(so->alpha.func) |
@ -138,12 +122,6 @@ etna_zsa_state_create(struct pipe_context *pctx,
VIVS_PE_STENCIL_CONFIG_EXT2_WRITE_MASK_BACK(stencil_back->writemask);
}
/* blob sets this to 0x40000031 on GC7000, seems to make no difference,
* but keep it in mind if depth behaves strangely. */
cs->RA_DEPTH_CONFIG = 0x00000031;
if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH) && !disable_zs && !early_z)
cs->RA_DEPTH_CONFIG |= 0x11000000;
/* XXX does alpha/stencil test affect PE_COLOR_FORMAT_OVERWRITE? */
return cs;
}

View File

@ -40,6 +40,10 @@ struct etna_zsa_state {
uint32_t PE_STENCIL_CONFIG_EXT;
uint32_t PE_STENCIL_CONFIG_EXT2[2];
uint32_t RA_DEPTH_CONFIG;
unsigned z_test_enabled:1;
unsigned z_write_enabled:1;
unsigned stencil_enabled:1;
unsigned stencil_modified:1;
};