summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2018-03-23 16:18:02 -0700
committerEric Anholt <[email protected]>2018-03-26 17:46:19 -0700
commit1bf466270d416643e8fcacd6b790e53660303059 (patch)
tree3ae25f7ebdd170df7afd3aa1ac4d2e82022673ce
parent262208eb3c2c53a1fd807bc76b12088f6ce2c56d (diff)
broadcom/vc5: Fix EZ disabling and allow using GT/GE direction as well.
Once we've disabled EZ for some draws, we need to not use EZ on future draws. Implementing that made implementing the GT/GE direction trivial. Fixes KHR-GLES3.shaders.fragdepth.compare.no_write on V3D 4.1 simulation.
-rw-r--r--src/gallium/drivers/vc5/vc5_context.h20
-rw-r--r--src/gallium/drivers/vc5/vc5_draw.c47
-rw-r--r--src/gallium/drivers/vc5/vc5_emit.c9
-rw-r--r--src/gallium/drivers/vc5/vc5_rcl.c16
-rw-r--r--src/gallium/drivers/vc5/vc5_state.c40
5 files changed, 111 insertions, 21 deletions
diff --git a/src/gallium/drivers/vc5/vc5_context.h b/src/gallium/drivers/vc5/vc5_context.h
index f6ed91c27ae..f61c37ba924 100644
--- a/src/gallium/drivers/vc5/vc5_context.h
+++ b/src/gallium/drivers/vc5/vc5_context.h
@@ -199,6 +199,13 @@ struct vc5_job_key {
struct pipe_surface *zsbuf;
};
+enum vc5_ez_state {
+ VC5_EZ_UNDECIDED = 0,
+ VC5_EZ_GT_GE,
+ VC5_EZ_LT_LE,
+ VC5_EZ_DISABLED,
+};
+
/**
* A complete bin/render job.
*
@@ -300,7 +307,16 @@ struct vc5_job {
*/
bool tf_enabled;
- bool uses_early_z;
+ /**
+ * Current EZ state for drawing. Updated at the start of draw after
+ * we've decided on the shader being rendered.
+ */
+ enum vc5_ez_state ez_state;
+ /**
+ * The first EZ state that was used for drawing with a decided EZ
+ * direction (so either UNDECIDED, GT, or LT).
+ */
+ enum vc5_ez_state first_ez_state;
/**
* Number of draw calls (not counting full buffer clears) queued in
@@ -429,7 +445,7 @@ struct vc5_rasterizer_state {
struct vc5_depth_stencil_alpha_state {
struct pipe_depth_stencil_alpha_state base;
- bool early_z_enable;
+ enum vc5_ez_state ez_state;
/** Uniforms for stencil state.
*
diff --git a/src/gallium/drivers/vc5/vc5_draw.c b/src/gallium/drivers/vc5/vc5_draw.c
index 7a409c14d4c..25f4883be2d 100644
--- a/src/gallium/drivers/vc5/vc5_draw.c
+++ b/src/gallium/drivers/vc5/vc5_draw.c
@@ -327,6 +327,49 @@ vc5_tf_statistics_record(struct vc5_context *vc5,
}
static void
+vc5_update_job_ez(struct vc5_context *vc5, struct vc5_job *job)
+{
+ switch (vc5->zsa->ez_state) {
+ case VC5_EZ_UNDECIDED:
+ /* If the Z/S state didn't pick a direction but didn't
+ * disable, then go along with the current EZ state. This
+ * allows EZ optimization for Z func == EQUAL or NEVER.
+ */
+ break;
+
+ case VC5_EZ_LT_LE:
+ case VC5_EZ_GT_GE:
+ /* If the Z/S state picked a direction, then it needs to match
+ * the current direction if we've decided on one.
+ */
+ if (job->ez_state == VC5_EZ_UNDECIDED)
+ job->ez_state = vc5->zsa->ez_state;
+ else if (job->ez_state != vc5->zsa->ez_state)
+ job->ez_state = VC5_EZ_DISABLED;
+ break;
+
+ case VC5_EZ_DISABLED:
+ /* If the current Z/S state disables EZ because of a bad Z
+ * func or stencil operation, then we can't do any more EZ in
+ * this frame.
+ */
+ job->ez_state = VC5_EZ_DISABLED;
+ break;
+ }
+
+ /* If the FS affects the Z of the pixels, then it may update against
+ * the chosen EZ direction (though we could use
+ * ARB_conservative_depth's hints to avoid this)
+ */
+ if (vc5->prog.fs->prog_data.fs->writes_z) {
+ job->ez_state = VC5_EZ_DISABLED;
+ }
+
+ if (job->first_ez_state == VC5_EZ_UNDECIDED)
+ job->first_ez_state = job->ez_state;
+}
+
+static void
vc5_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
{
struct vc5_context *vc5 = vc5_context(pctx);
@@ -384,6 +427,7 @@ vc5_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
vc5_start_draw(vc5);
vc5_update_compiled_shaders(vc5, info->mode);
+ vc5_update_job_ez(vc5, job);
#if V3D_VERSION >= 41
v3d41_emit_state(pctx);
@@ -515,9 +559,6 @@ vc5_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
if (vc5->zsa->base.depth.enabled) {
job->resolve |= PIPE_CLEAR_DEPTH;
rsc->initialized_buffers = PIPE_CLEAR_DEPTH;
-
- if (vc5->zsa->early_z_enable)
- job->uses_early_z = true;
}
if (vc5->zsa->base.stencil[0].enabled) {
diff --git a/src/gallium/drivers/vc5/vc5_emit.c b/src/gallium/drivers/vc5/vc5_emit.c
index d5bf2824d29..71f508c9ee8 100644
--- a/src/gallium/drivers/vc5/vc5_emit.c
+++ b/src/gallium/drivers/vc5/vc5_emit.c
@@ -382,13 +382,16 @@ v3dX(emit_state)(struct pipe_context *pctx)
config.blend_enable = vc5->blend->rt[0].blend_enable;
- config.early_z_updates_enable = true;
+ /* Note: EZ state may update based on the compiled FS,
+ * along with ZSA
+ */
+ config.early_z_updates_enable =
+ (job->ez_state != VC5_EZ_DISABLED);
if (vc5->zsa->base.depth.enabled) {
config.z_updates_enable =
vc5->zsa->base.depth.writemask;
config.early_z_enable =
- (vc5->zsa->early_z_enable &&
- !vc5->prog.fs->prog_data.fs->writes_z);
+ config.early_z_updates_enable;
config.depth_test_function =
vc5->zsa->base.depth.func;
} else {
diff --git a/src/gallium/drivers/vc5/vc5_rcl.c b/src/gallium/drivers/vc5/vc5_rcl.c
index a5efa32e215..8ff1515f883 100644
--- a/src/gallium/drivers/vc5/vc5_rcl.c
+++ b/src/gallium/drivers/vc5/vc5_rcl.c
@@ -481,7 +481,21 @@ v3dX(emit_rcl)(struct vc5_job *job)
/* XXX: Early D/S clear */
- config.early_z_disable = !job->uses_early_z;
+ switch (job->first_ez_state) {
+ case VC5_EZ_UNDECIDED:
+ case VC5_EZ_LT_LE:
+ config.early_z_disable = false;
+ config.early_z_test_and_update_direction =
+ EARLY_Z_DIRECTION_LT_LE;
+ break;
+ case VC5_EZ_GT_GE:
+ config.early_z_disable = false;
+ config.early_z_test_and_update_direction =
+ EARLY_Z_DIRECTION_GT_GE;
+ break;
+ case VC5_EZ_DISABLED:
+ config.early_z_disable = true;
+ }
config.image_width_pixels = job->draw_width;
config.image_height_pixels = job->draw_height;
diff --git a/src/gallium/drivers/vc5/vc5_state.c b/src/gallium/drivers/vc5/vc5_state.c
index 75cd948e4a3..ba2d748ba94 100644
--- a/src/gallium/drivers/vc5/vc5_state.c
+++ b/src/gallium/drivers/vc5/vc5_state.c
@@ -158,19 +158,35 @@ vc5_create_depth_stencil_alpha_state(struct pipe_context *pctx,
so->base = *cso;
if (cso->depth.enabled) {
- /* We only handle early Z in the < direction because otherwise
- * we'd have to runtime guess which direction to set in the
- * render config.
+ switch (cso->depth.func) {
+ case PIPE_FUNC_LESS:
+ case PIPE_FUNC_LEQUAL:
+ so->ez_state = VC5_EZ_LT_LE;
+ break;
+ case PIPE_FUNC_GREATER:
+ case PIPE_FUNC_GEQUAL:
+ so->ez_state = VC5_EZ_GT_GE;
+ break;
+ case PIPE_FUNC_NEVER:
+ case PIPE_FUNC_EQUAL:
+ so->ez_state = VC5_EZ_UNDECIDED;
+ break;
+ default:
+ so->ez_state = VC5_EZ_DISABLED;
+ break;
+ }
+
+ /* If stencil is enabled and it's not a no-op, then it would
+ * break EZ updates.
*/
- so->early_z_enable =
- ((cso->depth.func == PIPE_FUNC_LESS ||
- cso->depth.func == PIPE_FUNC_LEQUAL) &&
- (!cso->stencil[0].enabled ||
- (cso->stencil[0].zfail_op == PIPE_STENCIL_OP_KEEP &&
- cso->stencil[0].func == PIPE_FUNC_ALWAYS &&
- (!cso->stencil[1].enabled ||
- (cso->stencil[1].zfail_op == PIPE_STENCIL_OP_KEEP &&
- cso->stencil[1].func == PIPE_FUNC_ALWAYS)))));
+ if (cso->stencil[0].enabled &&
+ (cso->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP ||
+ cso->stencil[0].func != PIPE_FUNC_ALWAYS ||
+ (cso->stencil[1].enabled &&
+ (cso->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP &&
+ cso->stencil[1].func != PIPE_FUNC_ALWAYS)))) {
+ so->ez_state = VC5_EZ_DISABLED;
+ }
}
const struct pipe_stencil_state *front = &cso->stencil[0];