From: Juan A. Suarez Romero Date: Tue, 19 Apr 2022 14:53:20 +0000 (+0200) Subject: v3d: disable early-Z on odd frame dimensions X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f21e396f4c0bb41b4cbaec92b4d81bca69f8299e;p=platform%2Fupstream%2Fmesa.git v3d: disable early-Z on odd frame dimensions The early-Z buffer may load incorrect depth values if the frame has an od width or height. In this case we need to disable early-Z. v3: - Set job->early_zs_clear only for V3D_VERSION >= 40 (Iago) - Check early-Z is disabled if no zsbuf (Iago) v4: - Borrow comments from v3dv around v3d_update_job_ez() (Iago) Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3557 Signed-off-by: Juan A. Suarez Romero Reviewed-by: Iago Toral Quiroga Part-of: --- diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index 5bfe53e..5ba8727 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -471,6 +471,12 @@ struct v3d_job { enum v3d_ez_state first_ez_state; /** + * If we have already decided if we need to disable early Z/S + * completely for this job. + */ + bool decided_global_ez_enable; + + /** * If this job has been configured to use early Z/S clear. */ bool early_zs_clear; diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c index 80842b4..a3bc119 100644 --- a/src/gallium/drivers/v3d/v3dx_draw.c +++ b/src/gallium/drivers/v3d/v3dx_draw.c @@ -852,6 +852,49 @@ v3d_update_primitives_generated_counter(struct v3d_context *v3d, static void v3d_update_job_ez(struct v3d_context *v3d, struct v3d_job *job) { + /* If first_ez_state is V3D_EZ_DISABLED it means that we have already + * determined that we should disable EZ completely for all draw calls + * in this job. This will cause us to disable EZ for the entire job in + * the Tile Rendering Mode RCL packet and when we do that we need to + * make sure we never emit a draw call in the job with EZ enabled in + * the CFG_BITS packet, so ez_state must also be V3D_EZ_DISABLED. + */ + if (job->first_ez_state == V3D_EZ_DISABLED) { + assert(job->ez_state == V3D_EZ_DISABLED); + return; + } + + /* If this is the first time we update EZ state for this job we first + * check if there is anything that requires disabling it completely + * for the entire job (based on state that is not related to the + * current draw call and pipeline state). + */ + if (!job->decided_global_ez_enable) { + job->decided_global_ez_enable = true; + + if (!job->zsbuf) { + job->first_ez_state = V3D_EZ_DISABLED; + job->ez_state = V3D_EZ_DISABLED; + return; + } + + /* GFXH-1918: the early-Z buffer may load incorrect depth + * values if the frame has odd width or height. Disable early-Z + * in this case. + */ + bool needs_depth_load = v3d->zsa && job->zsbuf && + v3d->zsa->base.depth_enabled && + (PIPE_CLEAR_DEPTH & ~job->clear); + if (needs_depth_load && + ((job->draw_width % 2 != 0) || (job->draw_height % 2 != 0))) { + perf_debug("Loading depth buffer for framebuffer with odd width " + "or height disables early-Z tests\n"); + job->first_ez_state = V3D_EZ_DISABLED; + job->ez_state = V3D_EZ_DISABLED; + return; + } + } + switch (v3d->zsa->ez_state) { case V3D_EZ_UNDECIDED: /* If the Z/S state didn't pick a direction but didn't diff --git a/src/gallium/drivers/v3d/v3dx_rcl.c b/src/gallium/drivers/v3d/v3dx_rcl.c index 7c85525..6147d6a 100644 --- a/src/gallium/drivers/v3d/v3dx_rcl.c +++ b/src/gallium/drivers/v3d/v3dx_rcl.c @@ -726,6 +726,31 @@ v3dX(emit_rcl)(struct v3d_job *job) struct v3d_surface *surf = v3d_surface(job->zsbuf); config.internal_depth_type = surf->internal_type; } +#endif /* V3D_VERSION >= 40 */ + + if (job->decided_global_ez_enable) { + switch (job->first_ez_state) { + case V3D_EZ_UNDECIDED: + case V3D_EZ_LT_LE: + config.early_z_disable = false; + config.early_z_test_and_update_direction = + EARLY_Z_DIRECTION_LT_LE; + break; + case V3D_EZ_GT_GE: + config.early_z_disable = false; + config.early_z_test_and_update_direction = + EARLY_Z_DIRECTION_GT_GE; + break; + case V3D_EZ_DISABLED: + config.early_z_disable = true; + } + } else { + assert(job->draw_calls_queued == 0); + config.early_z_disable = true; + } + +#if V3D_VERSION >= 40 + assert(job->zsbuf || config.early_z_disable); job->early_zs_clear = (job->clear & PIPE_CLEAR_DEPTHSTENCIL) && !(job->load & PIPE_CLEAR_DEPTHSTENCIL) && @@ -734,22 +759,6 @@ v3dX(emit_rcl)(struct v3d_job *job) config.early_depth_stencil_clear = job->early_zs_clear; #endif /* V3D_VERSION >= 40 */ - switch (job->first_ez_state) { - case V3D_EZ_UNDECIDED: - case V3D_EZ_LT_LE: - config.early_z_disable = false; - config.early_z_test_and_update_direction = - EARLY_Z_DIRECTION_LT_LE; - break; - case V3D_EZ_GT_GE: - config.early_z_disable = false; - config.early_z_test_and_update_direction = - EARLY_Z_DIRECTION_GT_GE; - break; - case V3D_EZ_DISABLED: - config.early_z_disable = true; - } - config.image_width_pixels = job->draw_width; config.image_height_pixels = job->draw_height;