diff --git a/src/broadcom/vulkan/v3dv_pipeline.c b/src/broadcom/vulkan/v3dv_pipeline.c index 63a8efe984d..0a18d095051 100644 --- a/src/broadcom/vulkan/v3dv_pipeline.c +++ b/src/broadcom/vulkan/v3dv_pipeline.c @@ -2882,6 +2882,7 @@ pipeline_set_ez_state(struct v3dv_pipeline *pipeline, break; default: pipeline->ez_state = V3D_EZ_DISABLED; + pipeline->incompatible_ez_test = true; break; } @@ -2891,6 +2892,14 @@ pipeline_set_ez_state(struct v3dv_pipeline *pipeline, !stencil_op_is_no_op(&ds_info->back))) { pipeline->ez_state = V3D_EZ_DISABLED; } + + /* If the FS writes Z, then it may update against the chosen EZ direction */ + struct v3dv_shader_variant *fs_variant = + pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT]; + if (fs_variant && fs_variant->prog_data.fs->writes_z && + !fs_variant->prog_data.fs->writes_z_from_fep) { + pipeline->ez_state = V3D_EZ_DISABLED; + } } static bool @@ -3047,7 +3056,6 @@ pipeline_init(struct v3dv_pipeline *pipeline, rs_info, pv_info, ls_info, ms_info); - pipeline_set_ez_state(pipeline, ds_info); enable_depth_bias(pipeline, rs_info); pipeline_set_sample_mask(pipeline, ms_info); pipeline_set_sample_rate_shading(pipeline, ms_info); @@ -3082,6 +3090,9 @@ pipeline_init(struct v3dv_pipeline *pipeline, pipeline->default_attribute_values = NULL; } + /* This must be done after the pipeline has been compiled */ + pipeline_set_ez_state(pipeline, ds_info); + return result; } diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index a191e9ed19c..3656db97ac5 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -1913,6 +1913,11 @@ struct v3dv_pipeline { enum v3dv_ez_state ez_state; + /* If ez_state is V3D_EZ_DISABLED, if the reason for disabling is that the + * pipeline selects an incompatible depth test function. + */ + bool incompatible_ez_test; + bool msaa; bool sample_rate_shading; uint32_t sample_mask; diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c index 21bf3c4cf9b..ad3e9ba35a9 100644 --- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c @@ -1400,7 +1400,10 @@ v3dX(cmd_buffer_emit_varyings_state)(struct v3dv_cmd_buffer *cmd_buffer) } } -static void +/* Updates job early Z state tracking. Returns False if EZ must be disabled + * for the current draw call. + */ +static bool job_update_ez_state(struct v3dv_job *job, struct v3dv_pipeline *pipeline, struct v3dv_cmd_buffer *cmd_buffer) @@ -1414,9 +1417,15 @@ job_update_ez_state(struct v3dv_job *job, */ if (job->first_ez_state == V3D_EZ_DISABLED) { assert(job->ez_state == V3D_EZ_DISABLED); - return; + return false; } + /* If ez_state is V3D_EZ_DISABLED it means that we have already decided + * that EZ must be disabled for the remaining of the frame. + */ + if (job->ez_state == V3D_EZ_DISABLED) + return false; + /* This is part of the pre draw call handling, so we should be inside a * render pass. */ @@ -1436,7 +1445,7 @@ job_update_ez_state(struct v3dv_job *job, if (subpass->ds_attachment.attachment == VK_ATTACHMENT_UNUSED) { job->first_ez_state = V3D_EZ_DISABLED; job->ez_state = V3D_EZ_DISABLED; - return; + return false; } /* GFXH-1918: the early-z buffer may load incorrect depth values @@ -1465,7 +1474,7 @@ job_update_ez_state(struct v3dv_job *job, "without framebuffer info disables early-z tests.\n"); job->first_ez_state = V3D_EZ_DISABLED; job->ez_state = V3D_EZ_DISABLED; - return; + return false; } if (((fb->width % 2) != 0 || (fb->height % 2) != 0)) { @@ -1473,7 +1482,7 @@ job_update_ez_state(struct v3dv_job *job, "or height disables early-Z tests.\n"); job->first_ez_state = V3D_EZ_DISABLED; job->ez_state = V3D_EZ_DISABLED; - return; + return false; } } } @@ -1481,16 +1490,8 @@ job_update_ez_state(struct v3dv_job *job, /* Otherwise, we can decide to selectively enable or disable EZ for draw * calls using the CFG_BITS packet based on the bound pipeline state. */ - - /* If the FS writes Z, then it may update against the chosen EZ direction */ - struct v3dv_shader_variant *fs_variant = - pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT]; - if (fs_variant->prog_data.fs->writes_z && - !fs_variant->prog_data.fs->writes_z_from_fep) { - job->ez_state = V3D_EZ_DISABLED; - return; - } - + bool disable_ez = false; + bool incompatible_test = false; switch (pipeline->ez_state) { case V3D_EZ_UNDECIDED: /* If the pipeline didn't pick a direction but didn't disable, then go @@ -1504,24 +1505,35 @@ job_update_ez_state(struct v3dv_job *job, /* If the pipeline picked a direction, then it needs to match the current * direction if we've decided on one. */ - if (job->ez_state == V3D_EZ_UNDECIDED) + if (job->ez_state == V3D_EZ_UNDECIDED) { job->ez_state = pipeline->ez_state; - else if (job->ez_state != pipeline->ez_state) - job->ez_state = V3D_EZ_DISABLED; + } else if (job->ez_state != pipeline->ez_state) { + disable_ez = true; + incompatible_test = true; + } break; case V3D_EZ_DISABLED: - /* If the pipeline 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 = V3D_EZ_DISABLED; + disable_ez = true; + incompatible_test = pipeline->incompatible_ez_test; break; } - if (job->first_ez_state == V3D_EZ_UNDECIDED && - job->ez_state != V3D_EZ_DISABLED) { + if (job->first_ez_state == V3D_EZ_UNDECIDED && !disable_ez) { + assert(job->ez_state != V3D_EZ_DISABLED); job->first_ez_state = job->ez_state; } + + /* If we had to disable EZ because of an incompatible test direction and + * and the pipeline writes depth then we need to disable EZ for the rest of + * the frame. + */ + if (incompatible_test && pipeline->z_updates_enable) { + assert(disable_ez); + job->ez_state = V3D_EZ_DISABLED; + } + + return !disable_ez; } void @@ -1533,13 +1545,13 @@ v3dX(cmd_buffer_emit_configuration_bits)(struct v3dv_cmd_buffer *cmd_buffer) struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline; assert(pipeline); - job_update_ez_state(job, pipeline, cmd_buffer); + bool enable_ez = job_update_ez_state(job, pipeline, cmd_buffer); v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(CFG_BITS)); v3dv_return_if_oom(cmd_buffer, NULL); cl_emit_with_prepacked(&job->bcl, CFG_BITS, pipeline->cfg_bits, config) { - config.early_z_enable = job->ez_state != V3D_EZ_DISABLED; + config.early_z_enable = enable_ez; config.early_z_updates_enable = config.early_z_enable && pipeline->z_updates_enable; }