From fbfb99cbc395cd9c002a592cf46a7282221e9499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Pi=C3=B1eiro?= Date: Mon, 8 Apr 2024 14:11:20 +0200 Subject: [PATCH] v3dv: ez_state/incompatible_ez_test could be recomputed at cmd_buffer As the values depends on several values that can be dynamic too. Note that the current approach of this commit is keeping this info duplicated on the pipeline and the cmd_buffer. The alternative would be to just track it at the cmd_buffer, like we did recently with z_updates_enable, but getting the values for ez_state/incompatible_ez were more complex, so this commit still computes it when the pipeline is created, and uses it as default value. This is debatable though, and the alternative would be to just keep ez_state/incompatible_ez_state at the command buffer. Reviewed-by: Iago Toral Quiroga Part-of: --- src/broadcom/vulkan/v3dv_pipeline.c | 50 +++++++++++++++----------- src/broadcom/vulkan/v3dv_private.h | 18 ++++++++++ src/broadcom/vulkan/v3dvx_cmd_buffer.c | 41 +++++++++++++++------ 3 files changed, 78 insertions(+), 31 deletions(-) diff --git a/src/broadcom/vulkan/v3dv_pipeline.c b/src/broadcom/vulkan/v3dv_pipeline.c index ba46aae5974..44b6b259dff 100644 --- a/src/broadcom/vulkan/v3dv_pipeline.c +++ b/src/broadcom/vulkan/v3dv_pipeline.c @@ -2646,10 +2646,10 @@ compute_vpm_config(struct v3dv_pipeline *pipeline) } static bool -stencil_op_is_no_op(const VkStencilOpState *stencil) +stencil_op_is_no_op(struct vk_stencil_test_face_state *stencil) { - return stencil->depthFailOp == VK_STENCIL_OP_KEEP && - stencil->compareOp == VK_COMPARE_OP_ALWAYS; + return stencil->op.depth_fail == VK_STENCIL_OP_KEEP && + stencil->op.compare == VK_COMPARE_OP_ALWAYS; } static void @@ -2672,39 +2672,45 @@ enable_depth_bias(struct v3dv_pipeline *pipeline, pipeline->depth_bias.enabled = true; } -static void -pipeline_set_ez_state(struct v3dv_pipeline *pipeline, - const VkPipelineDepthStencilStateCreateInfo *ds_info) +/* Computes the ez_state based on a given vk_dynamic_graphics_state. Note + * that the parameter dyn doesn't need to be pipeline->dynamic_graphics_state, + * as this method can be used by the cmd_buffer too. + */ +void +v3dv_compute_ez_state(struct vk_dynamic_graphics_state *dyn, + struct v3dv_pipeline *pipeline, + enum v3dv_ez_state *ez_state, + bool *incompatible_ez_test) { - if (!ds_info || !ds_info->depthTestEnable) { - pipeline->ez_state = V3D_EZ_DISABLED; + if (!dyn->ds.depth.test_enable) { + *ez_state = V3D_EZ_DISABLED; return; } - switch (ds_info->depthCompareOp) { + switch (dyn->ds.depth.compare_op) { case VK_COMPARE_OP_LESS: case VK_COMPARE_OP_LESS_OR_EQUAL: - pipeline->ez_state = V3D_EZ_LT_LE; + *ez_state = V3D_EZ_LT_LE; break; case VK_COMPARE_OP_GREATER: case VK_COMPARE_OP_GREATER_OR_EQUAL: - pipeline->ez_state = V3D_EZ_GT_GE; + *ez_state = V3D_EZ_GT_GE; break; case VK_COMPARE_OP_NEVER: case VK_COMPARE_OP_EQUAL: - pipeline->ez_state = V3D_EZ_UNDECIDED; + *ez_state = V3D_EZ_UNDECIDED; break; default: - pipeline->ez_state = V3D_EZ_DISABLED; - pipeline->incompatible_ez_test = true; + *ez_state = V3D_EZ_DISABLED; + *incompatible_ez_test = true; break; } /* If stencil is enabled and is not a no-op, we need to disable EZ */ - if (ds_info->stencilTestEnable && - (!stencil_op_is_no_op(&ds_info->front) || - !stencil_op_is_no_op(&ds_info->back))) { - pipeline->ez_state = V3D_EZ_DISABLED; + if (dyn->ds.stencil.test_enable && + (!stencil_op_is_no_op(&dyn->ds.stencil.front) || + !stencil_op_is_no_op(&dyn->ds.stencil.back))) { + *ez_state = V3D_EZ_DISABLED; } /* If the FS writes Z, then it may update against the chosen EZ direction */ @@ -2712,10 +2718,11 @@ pipeline_set_ez_state(struct v3dv_pipeline *pipeline, 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; + *ez_state = V3D_EZ_DISABLED; } } + static void pipeline_set_sample_mask(struct v3dv_pipeline *pipeline, const VkPipelineMultisampleStateCreateInfo *ms_info) @@ -3001,7 +3008,10 @@ pipeline_init(struct v3dv_pipeline *pipeline, } /* This must be done after the pipeline has been compiled */ - pipeline_set_ez_state(pipeline, ds_info); + v3dv_compute_ez_state(&pipeline->dynamic_graphics_state, + pipeline, + &pipeline->ez_state, + &pipeline->incompatible_ez_test); return result; } diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index c5813d67521..d54b1f3cff9 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -1606,6 +1606,17 @@ struct v3dv_cmd_buffer_state { /* This is dynamic state since VK_EXT_extended_dynamic_state. */ bool z_updates_enable; + + /* ez_state can be dynamic since VK_EXT_extended_dynamic_state so we need + * to keep track of it in the cmd_buffer state + */ + enum v3dv_ez_state ez_state; + + /* incompatible_ez_test can be dynamic since VK_EXT_extended_dynamic_state + * so we need to keep track of it in the cmd_buffer state + */ + bool incompatible_ez_test; + }; void @@ -2687,6 +2698,13 @@ float v3dv_get_aa_line_width(struct v3dv_pipeline *pipeline, struct v3dv_cmd_buffer *buffer); + +void +v3dv_compute_ez_state(struct vk_dynamic_graphics_state *dyn, + struct v3dv_pipeline *pipeline, + enum v3dv_ez_state *ez_state, + bool *incompatible_ez_test); + #if DETECT_OS_ANDROID VkResult v3dv_gralloc_to_drm_explicit_layout(struct u_gralloc *gralloc, diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c index 7394b0b297b..4d3edaa8636 100644 --- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c @@ -1784,14 +1784,32 @@ v3dX(cmd_buffer_emit_varyings_state)(struct v3dv_cmd_buffer *cmd_buffer) } #if V3D_VERSION == 42 -/* Updates job early Z state tracking. Returns False if EZ must be disabled - * for the current draw call. +/* Updates cmd_buffer, and their 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) +cmd_buffer_update_ez_state(struct v3dv_cmd_buffer *cmd_buffer, + struct v3dv_pipeline *pipeline) { + struct vk_dynamic_graphics_state *dyn = &cmd_buffer->vk.dynamic_graphics_state; + /* Update first cmd_buffer ez_state tracking. If possible we reuse the + * values from the pipeline + */ + if (!BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_OP) && + !BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE) && + !BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_DEPTH_TEST_ENABLE) && + !BITSET_TEST(dyn->set, MESA_VK_DYNAMIC_DS_DEPTH_COMPARE_OP)) { + cmd_buffer->state.ez_state = pipeline->ez_state; + cmd_buffer->state.incompatible_ez_test = + pipeline->incompatible_ez_test; + } else { + v3dv_compute_ez_state(dyn, pipeline, + &cmd_buffer->state.ez_state, + &cmd_buffer->state.incompatible_ez_test); + } + + struct v3dv_job *job = cmd_buffer->state.job; + assert(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 @@ -1818,7 +1836,7 @@ job_update_ez_state(struct v3dv_job *job, /* 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). + * pipeline/cmd_buffer state). */ if (!job->decided_global_ez_enable) { job->decided_global_ez_enable = true; @@ -1884,11 +1902,12 @@ 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. + * calls using the CFG_BITS packet based on the bound pipeline state, or + * cmd_buffer state if some stencil/depth flags were dynamic. */ bool disable_ez = false; bool incompatible_test = false; - switch (pipeline->ez_state) { + switch (cmd_buffer->state.ez_state) { case V3D_EZ_UNDECIDED: /* If the pipeline didn't pick a direction but didn't disable, then go * along with the current EZ state. This allows EZ optimization for Z @@ -1902,7 +1921,7 @@ job_update_ez_state(struct v3dv_job *job, * direction if we've decided on one. */ if (job->ez_state == V3D_EZ_UNDECIDED) { - job->ez_state = pipeline->ez_state; + job->ez_state = cmd_buffer->state.ez_state; } else if (job->ez_state != pipeline->ez_state) { disable_ez = true; incompatible_test = true; @@ -1911,7 +1930,7 @@ job_update_ez_state(struct v3dv_job *job, case V3D_EZ_DISABLED: disable_ez = true; - incompatible_test = pipeline->incompatible_ez_test; + incompatible_test = cmd_buffer->state.incompatible_ez_test; break; } @@ -1964,7 +1983,7 @@ v3dX(cmd_buffer_emit_configuration_bits)(struct v3dv_cmd_buffer *cmd_buffer) cmd_buffer->state.z_updates_enable = config.z_updates_enable; #if V3D_VERSION == 42 - bool enable_ez = job_update_ez_state(job, pipeline, cmd_buffer); + bool enable_ez = cmd_buffer_update_ez_state(cmd_buffer, pipeline); config.early_z_enable = enable_ez; config.early_z_updates_enable = config.early_z_enable && cmd_buffer->state.z_updates_enable;