mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-25 02:40:46 +02:00
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.
This commit is contained in:
parent
262208eb3c
commit
1bf466270d
5 changed files with 111 additions and 21 deletions
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -326,6 +326,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)
|
||||
{
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue