From 8f5d433840209e6380ffef6a9a2ba0f59675d2de Mon Sep 17 00:00:00 2001 From: Danylo Piliaiev Date: Fri, 16 May 2025 12:14:42 +0200 Subject: [PATCH] tu: Occlusion query counting should happen after FS that kills "EARLY_Z + discard" would yield incorrect occlusion query result, since Vulkan expects occlusion query to happen after fragment shader. See Vulkan spec "29. Fragment Operations". Also see https://gitlab.khronos.org/Tracker/vk-gl-cts/-/issues/5713 Signed-off-by: Danylo Piliaiev Part-of: --- src/freedreno/vulkan/tu_cmd_buffer.cc | 10 ++++++++++ src/freedreno/vulkan/tu_cmd_buffer.h | 2 ++ src/freedreno/vulkan/tu_query_pool.cc | 3 +++ 3 files changed, 15 insertions(+) diff --git a/src/freedreno/vulkan/tu_cmd_buffer.cc b/src/freedreno/vulkan/tu_cmd_buffer.cc index e2ba0e0f783..c66d11cb08f 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.cc +++ b/src/freedreno/vulkan/tu_cmd_buffer.cc @@ -3277,6 +3277,9 @@ tu_BeginCommandBuffer(VkCommandBuffer commandBuffer, cmd_buffer->inherited_pipeline_statistics = pBeginInfo->pInheritanceInfo->pipelineStatistics; + cmd_buffer->state.occlusion_query_may_be_running = + pBeginInfo->pInheritanceInfo->occlusionQueryEnable; + vk_foreach_struct_const(ext, pBeginInfo->pInheritanceInfo) { switch (ext->sType) { case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT: { @@ -6271,6 +6274,13 @@ tu6_build_depth_plane_z_mode(struct tu_cmd_buffer *cmd, struct tu_cs *cs) zmode = A6XX_EARLY_Z_LATE_Z; } + /* "EARLY_Z + discard" would yield incorrect occlusion query result, + * since Vulkan expects occlusion query to happen after fragment shader. + */ + if (zmode == A6XX_EARLY_Z && fs_kill_fragments && + cmd->state.occlusion_query_may_be_running) + zmode = A6XX_EARLY_Z_LATE_Z; + if (zmode == A6XX_EARLY_Z_LATE_Z && (cmd->state.stencil_written_on_depth_fail || fs->fs.per_samp || !vk_format_has_depth(depth_format) || !ds_test_enable)) { diff --git a/src/freedreno/vulkan/tu_cmd_buffer.h b/src/freedreno/vulkan/tu_cmd_buffer.h index cde022f9d37..e8d1c87609d 100644 --- a/src/freedreno/vulkan/tu_cmd_buffer.h +++ b/src/freedreno/vulkan/tu_cmd_buffer.h @@ -544,6 +544,8 @@ struct tu_cmd_state bool prim_generated_query_running_before_rp; + bool occlusion_query_may_be_running; + enum tu_suspend_resume_state suspend_resume; bool suspending, resuming; diff --git a/src/freedreno/vulkan/tu_query_pool.cc b/src/freedreno/vulkan/tu_query_pool.cc index 264fc9ae3bb..4f9c5663625 100644 --- a/src/freedreno/vulkan/tu_query_pool.cc +++ b/src/freedreno/vulkan/tu_query_pool.cc @@ -1040,6 +1040,7 @@ emit_begin_occlusion_query(struct tu_cmd_buffer *cmdbuf, * sample counts in slot->result to compute the query result. */ struct tu_cs *cs = cmdbuf->state.pass ? &cmdbuf->draw_cs : &cmdbuf->cs; + cmdbuf->state.occlusion_query_may_be_running = true; uint64_t begin_iova = occlusion_query_iova(pool, query, begin); @@ -1507,6 +1508,8 @@ emit_end_occlusion_query(struct tu_cmd_buffer *cmdbuf, tu_cs_emit_pkt7(epilogue_cs, CP_MEM_WRITE, 4); tu_cs_emit_qw(epilogue_cs, available_iova); tu_cs_emit_qw(epilogue_cs, 0x1); + + cmdbuf->state.occlusion_query_may_be_running = false; } /* PRIMITIVE_CTRS is used for two distinct queries: