From 34df1b4a167b980f2807125a9a557fe6968cba41 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sat, 4 Jul 2026 22:03:22 -0400 Subject: [PATCH] [vulkan] Another approach for queries reset --- .../renderer_vulkan/vk_query_cache.cpp | 38 ++++++++++++++++--- src/video_core/vulkan_common/vulkan_device.h | 6 ++- .../vulkan_common/vulkan_wrapper.cpp | 1 + src/video_core/vulkan_common/vulkan_wrapper.h | 5 +++ 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index ea8c971080..935f8b79fb 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -41,8 +41,8 @@ class SamplesQueryBank : public VideoCommon::BankBase { public: static constexpr size_t BANK_SIZE = 256; static constexpr size_t QUERY_SIZE = 8; - explicit SamplesQueryBank(const Device& device_, size_t index_) - : BankBase(BANK_SIZE), device{device_}, index{index_} { + explicit SamplesQueryBank(const Device& device_, Scheduler& scheduler_, size_t index_) + : BankBase(BANK_SIZE), device{device_}, scheduler{scheduler_}, index{index_} { const auto& dev = device.GetLogical(); query_pool = dev.CreateQueryPool({ .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, @@ -60,12 +60,28 @@ public: void Reset() override { ASSERT(references == 0); VideoCommon::BankBase::Reset(); - const auto& dev = device.GetLogical(); - dev.ResetQueryPool(*query_pool, 0, BANK_SIZE); + if (device.IsHostQueryResetSupported()) { + const auto& dev = device.GetLogical(); + dev.ResetQueryPool(*query_pool, 0, BANK_SIZE); + } else { + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([pool = *query_pool](vk::CommandBuffer cmdbuf) { + cmdbuf.ResetQueryPool(pool, 0, BANK_SIZE); + }); + } host_results.fill(0ULL); next_bank = 0; } + void AddReference(size_t how_many = 1) { + BankBase::AddReference(how_many); + last_used_tick = scheduler.CurrentTick(); + } + + [[nodiscard]] bool IsDead() const { + return BankBase::IsDead() && scheduler.IsFree(last_used_tick); + } + void Sync(size_t start, size_t size) { const auto& dev = device.GetLogical(); const VkResult query_result = dev.GetQueryResults( @@ -98,9 +114,11 @@ public: private: const Device& device; + Scheduler& scheduler; const size_t index; vk::QueryPool query_pool; std::array host_results; + u64 last_used_tick{}; }; using BaseStreamer = VideoCommon::SimpleStreamer; @@ -431,7 +449,7 @@ private: void ReserveBank() { current_bank_id = bank_pool.ReserveBank([this](std::deque& queue, size_t index) { - queue.emplace_back(device, index); + queue.emplace_back(device, scheduler, index); }); if (current_bank) { current_bank->next_bank = current_bank_id + 1; @@ -620,6 +638,15 @@ public: VideoCommon::BankBase::Reset(); } + void AddReference(size_t how_many = 1) { + BankBase::AddReference(how_many); + last_used_tick = scheduler.CurrentTick(); + } + + [[nodiscard]] bool IsDead() const { + return BankBase::IsDead() && scheduler.IsFree(last_used_tick); + } + void Sync(StagingBufferRef& stagging_buffer, size_t extra_offset, size_t start, size_t size) { scheduler.RequestOutsideRenderPassOperationContext(); scheduler.Record([this, dst_buffer = stagging_buffer.buffer, extra_offset, start, @@ -645,6 +672,7 @@ private: Scheduler& scheduler; const size_t index; vk::Buffer buffer; + u64 last_used_tick{}; }; class PrimitivesSucceededStreamer; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 5b6c3da57d..cf039768fd 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -523,7 +523,6 @@ FN_MAX_LIMIT_LIST } /// Returns true if the device supports VK_EXT_shader_stencil_export. - /// Note: Most Mali/NVIDIA drivers don't support this. Use hardware blits as fallback. bool IsExtShaderStencilExportSupported() const { return extensions.shader_stencil_export; } @@ -560,6 +559,11 @@ FN_MAX_LIMIT_LIST return extensions.subgroup_size_control; } + /// Returns true if vkResetQueryPool (host-side query reset) is supported. + bool IsHostQueryResetSupported() const { + return features.host_query_reset.hostQueryReset != VK_FALSE; + } + /// Returns true if the device supports VK_EXT_transform_feedback. bool IsExtTransformFeedbackSupported() const { return extensions.transform_feedback; diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 6f35e0b0c3..e5d5e93426 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -165,6 +165,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkCmdSetColorWriteEnableEXT); X(vkCmdSetColorBlendEnableEXT); X(vkCmdSetColorBlendEquationEXT); + X(vkCmdResetQueryPool); X(vkCmdResolveImage); X(vkCreateBuffer); X(vkCreateBufferView); diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 5c68ef9d25..691390f002 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -241,6 +241,7 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2{}; PFN_vkCmdPushConstants vkCmdPushConstants{}; PFN_vkCmdPushDescriptorSetWithTemplateKHR vkCmdPushDescriptorSetWithTemplateKHR{}; + PFN_vkCmdResetQueryPool vkCmdResetQueryPool{}; PFN_vkCmdResolveImage vkCmdResolveImage{}; PFN_vkCmdSetBlendConstants vkCmdSetBlendConstants{}; PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT{}; @@ -1191,6 +1192,10 @@ public: dld->vkCmdEndQuery(handle, query_pool, query); } + void ResetQueryPool(VkQueryPool query_pool, u32 first, u32 count) const noexcept { + dld->vkCmdResetQueryPool(handle, query_pool, first, count); + } + void BindDescriptorSets(VkPipelineBindPoint bind_point, VkPipelineLayout layout, u32 first, Span sets, Span dynamic_offsets) const noexcept { dld->vkCmdBindDescriptorSets(handle, bind_point, layout, first, sets.size(), sets.data(),