Commit b29fe26d authored by Lucas Stach's avatar Lucas Stach
Browse files

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's avatarLucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner's avatarChristian Gmeiner <christian.gmeiner@gmail.com>
Part-of: <mesa/mesa!7396>
parent 3c7fc95f
...@@ -431,8 +431,7 @@ etna_emit_state(struct etna_context *ctx) ...@@ -431,8 +431,7 @@ etna_emit_state(struct etna_context *ctx)
} }
if (unlikely(dirty & (ETNA_DIRTY_ZSA | ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_SHADER))) { 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 | /*01400*/ EMIT_STATE(PE_DEPTH_CONFIG, (etna_zsa_state(ctx->zsa)->PE_DEPTH_CONFIG |
ctx->framebuffer.PE_DEPTH_CONFIG) & ctx->framebuffer.PE_DEPTH_CONFIG));
ctx->shader_state.PE_DEPTH_CONFIG);
} }
if (unlikely(dirty & (ETNA_DIRTY_VIEWPORT))) { if (unlikely(dirty & (ETNA_DIRTY_VIEWPORT))) {
/*01404*/ EMIT_STATE(PE_DEPTH_NEAR, ctx->viewport.PE_DEPTH_NEAR); /*01404*/ EMIT_STATE(PE_DEPTH_NEAR, ctx->viewport.PE_DEPTH_NEAR);
......
...@@ -245,7 +245,6 @@ struct compiled_shader_state { ...@@ -245,7 +245,6 @@ struct compiled_shader_state {
uint32_t PS_TEMP_REGISTER_CONTROL; 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_TEMP_REGISTER_CONTROL_MSAA; /* Adds a temporary if needed to make space for extra input */
uint32_t PS_START_PC; uint32_t PS_START_PC;
uint32_t PE_DEPTH_CONFIG;
uint32_t GL_VARYING_TOTAL_COMPONENTS; uint32_t GL_VARYING_TOTAL_COMPONENTS;
uint32_t GL_VARYING_NUM_COMPONENTS[2]; uint32_t GL_VARYING_NUM_COMPONENTS[2];
uint32_t GL_VARYING_COMPONENT_USE[2]; uint32_t GL_VARYING_COMPONENT_USE[2];
...@@ -257,6 +256,8 @@ struct compiled_shader_state { ...@@ -257,6 +256,8 @@ struct compiled_shader_state {
uint32_t *PS_INST_MEM; uint32_t *PS_INST_MEM;
struct etna_reloc PS_INST_ADDR; struct etna_reloc PS_INST_ADDR;
struct etna_reloc VS_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). /* 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, ...@@ -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) ? VIVS_GL_HALTI5_SH_SPECIALS_PS_PCOORD_IN((link.pcoord_varying_comp_ofs != -1) ?
link.pcoord_varying_comp_ofs : 0x7f); link.pcoord_varying_comp_ofs : 0x7f);
/* mask out early Z bit when frag depth is written */ cs->writes_z = fs->ps_depth_out_reg >= 0;
cs->PE_DEPTH_CONFIG = ~COND(fs->ps_depth_out_reg >= 0, VIVS_PE_DEPTH_CONFIG_EARLY_Z); cs->uses_discard = fs->uses_discard;
/* reference instruction memory */ /* reference instruction memory */
cs->vs_inst_mem_size = vs->code_size; cs->vs_inst_mem_size = vs->code_size;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "etnaviv_surface.h" #include "etnaviv_surface.h"
#include "etnaviv_translate.h" #include "etnaviv_translate.h"
#include "etnaviv_util.h" #include "etnaviv_util.h"
#include "etnaviv_zsa.h"
#include "util/u_framebuffer.h" #include "util/u_framebuffer.h"
#include "util/u_helpers.h" #include "util/u_helpers.h"
#include "util/u_inlines.h" #include "util/u_inlines.h"
...@@ -675,6 +676,71 @@ etna_update_clipping(struct etna_context *ctx) ...@@ -675,6 +676,71 @@ etna_update_clipping(struct etna_context *ctx)
return true; 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 { struct etna_state_updater {
bool (*update)(struct etna_context *ctx); bool (*update)(struct etna_context *ctx);
uint32_t dirty; uint32_t dirty;
...@@ -699,6 +765,9 @@ static const struct etna_state_updater etna_state_updates[] = { ...@@ -699,6 +765,9 @@ static const struct etna_state_updater etna_state_updates[] = {
{ {
etna_update_clipping, ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER | etna_update_clipping, ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER |
ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT, 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, ...@@ -47,11 +47,10 @@ etna_zsa_state_create(struct pipe_context *pctx,
cs->base = *so; 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? */ /* 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. /* Set operations to KEEP if write mask is 0.
* When we don't do this, the depth buffer is written for the entire primitive * 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, ...@@ -73,27 +72,21 @@ etna_zsa_state_create(struct pipe_context *pctx,
if (so->stencil[0].enabled) { if (so->stencil[0].enabled) {
if (so->stencil[0].func != PIPE_FUNC_ALWAYS || if (so->stencil[0].func != PIPE_FUNC_ALWAYS ||
(so->stencil[1].enabled && so->stencil[1].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 || if (so->stencil[0].fail_op != PIPE_STENCIL_OP_KEEP ||
so->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP || so->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP ||
so->stencil[0].zpass_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) { } else if (so->stencil[1].enabled) {
if (so->stencil[1].fail_op != PIPE_STENCIL_OP_KEEP || if (so->stencil[1].fail_op != PIPE_STENCIL_OP_KEEP ||
so->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP || so->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP ||
so->stencil[1].zpass_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 */ /* calculate extra_reference value */
uint32_t extra_reference = 0; uint32_t extra_reference = 0;
...@@ -103,15 +96,6 @@ etna_zsa_state_create(struct pipe_context *pctx, ...@@ -103,15 +96,6 @@ etna_zsa_state_create(struct pipe_context *pctx,
cs->PE_STENCIL_CONFIG_EXT = cs->PE_STENCIL_CONFIG_EXT =
VIVS_PE_STENCIL_CONFIG_EXT_EXTRA_ALPHA_REF(extra_reference); 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 = cs->PE_ALPHA_OP =
COND(so->alpha.enabled, VIVS_PE_ALPHA_OP_ALPHA_TEST) | COND(so->alpha.enabled, VIVS_PE_ALPHA_OP_ALPHA_TEST) |
VIVS_PE_ALPHA_OP_ALPHA_FUNC(so->alpha.func) | VIVS_PE_ALPHA_OP_ALPHA_FUNC(so->alpha.func) |
...@@ -138,12 +122,6 @@ etna_zsa_state_create(struct pipe_context *pctx, ...@@ -138,12 +122,6 @@ etna_zsa_state_create(struct pipe_context *pctx,
VIVS_PE_STENCIL_CONFIG_EXT2_WRITE_MASK_BACK(stencil_back->writemask); 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? */ /* XXX does alpha/stencil test affect PE_COLOR_FORMAT_OVERWRITE? */
return cs; return cs;
} }
...@@ -40,6 +40,10 @@ struct etna_zsa_state { ...@@ -40,6 +40,10 @@ struct etna_zsa_state {
uint32_t PE_STENCIL_CONFIG_EXT; uint32_t PE_STENCIL_CONFIG_EXT;
uint32_t PE_STENCIL_CONFIG_EXT2[2]; uint32_t PE_STENCIL_CONFIG_EXT2[2];
uint32_t RA_DEPTH_CONFIG; uint32_t RA_DEPTH_CONFIG;
unsigned z_test_enabled:1;
unsigned z_write_enabled:1;
unsigned stencil_enabled:1;
unsigned stencil_modified:1;
}; };
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment