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:
parent
3c7fc95f4f
commit
b29fe26d43
|
@ -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);
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue