diff --git a/src/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h index 6e084cc079..865e707f21 100644 --- a/src/video_core/query_cache/query_cache.h +++ b/src/video_core/query_cache/query_cache.h @@ -27,7 +27,7 @@ #include "video_core/query_cache/query_cache_base.h" #include "video_core/query_cache/query_stream.h" #include "video_core/query_cache/types.h" - +namespace Vulkan { class Scheduler; } namespace VideoCommon { using Maxwell = Tegra::Engines::Maxwell3D; @@ -222,6 +222,12 @@ void QueryCacheBase::CounterReset(QueryType counter_type) { streamer->ResetCounter(); } +// Called at frame start to batch vkCmdResetQueryPool outside render passes. +template +void QueryCacheBase::FramePrologueResets(Vulkan::Scheduler& scheduler) { + impl->runtime.FramePrologueResets(scheduler); +} + template void QueryCacheBase::BindToChannel(s32 id) { VideoCommon::ChannelSetupCaches::BindToChannel(id); diff --git a/src/video_core/query_cache/query_cache_base.h b/src/video_core/query_cache/query_cache_base.h index 00c25c8d63..3eddd5a7f2 100644 --- a/src/video_core/query_cache/query_cache_base.h +++ b/src/video_core/query_cache/query_cache_base.h @@ -21,7 +21,9 @@ namespace VideoCore { class RasterizerInterface; } - +namespace Vulkan { + class Scheduler; +} namespace Tegra { class GPU; } @@ -53,7 +55,7 @@ public: RuntimeType& runtime_); ~QueryCacheBase(); - + void FramePrologueResets(Vulkan::Scheduler& scheduler); void InvalidateRegion(VAddr addr, std::size_t size) { IterateCache(addr, size, [this](QueryLocation location) { InvalidateQuery(location); }); diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index d6ecc2b65c..3ce69c3908 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -156,7 +156,7 @@ public: ReserveHostQuery(); - // Ensure outside render pass + /* Ensure outside render pass scheduler.RequestOutsideRenderPassOperationContext(); // Reset query pool outside render pass @@ -167,7 +167,7 @@ public: // Manually restart the render pass (required for vkCmdClearAttachments, etc.) scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); - + */ // Begin query inside the newly started render pass scheduler.Record([query_pool = current_query_pool, query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { @@ -402,6 +402,13 @@ public: } } + VkQueryPool GetOrCreateCurrentPoolForPrologue() { + if (!current_bank || current_bank->IsClosed()) { + ReserveBank(); + } + return current_query_pool; + } + private: template void ApplyBankOp(VideoCommon::HostQueryBase* query, Func&& func) { @@ -1305,6 +1312,19 @@ void QueryCacheRuntime::ResumeHostConditionalRendering() { impl->is_hcr_running = true; } +void QueryCacheRuntime::FramePrologueResets(Scheduler& scheduler) { + // Reset the occlusion queries we plan to use this frame in one go. + // Ensure this is recorded OUTSIDE any render pass. + const VkQueryPool pool = impl->sample_streamer.GetOrCreateCurrentPoolForPrologue(); + scheduler.RequestOutsideRenderPassOperationContext(); + scheduler.Record([pool](vk::CommandBuffer cmdbuf) { + // Reset the whole bank so subsequent BeginQuery calls don't need per-slot resets. + cmdbuf.ResetQueryPool(pool, + /*first*/ 0, + /*count*/ SamplesQueryBank::BANK_SIZE); + }); +} + void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::LookupData object, bool is_equal) { { diff --git a/src/video_core/renderer_vulkan/vk_query_cache.h b/src/video_core/renderer_vulkan/vk_query_cache.h index b8dae9bc2d..05e270e5f1 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.h +++ b/src/video_core/renderer_vulkan/vk_query_cache.h @@ -20,7 +20,7 @@ namespace Vulkan { class Device; class Scheduler; class StagingBufferPool; - +class Scheduler; struct QueryCacheRuntimeImpl; class QueryCacheRuntime { @@ -33,7 +33,7 @@ public: ComputePassDescriptorQueue& compute_pass_descriptor_queue, DescriptorPool& descriptor_pool, TextureCache& texture_cache_); ~QueryCacheRuntime(); - + void FramePrologueResets(Scheduler& scheduler); template void SyncValues(std::span values, VkBuffer base_src_buffer = nullptr); diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 530d161dfe..7560852f97 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -257,6 +257,11 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se void Scheduler::AllocateNewContext() { // Enable counters once again. These are disabled when a command buffer is finished. + // Record per frame query resets outside any render pass, before the first draw. + if (query_cache) { + query_cache->FramePrologueResets(*this); + } + } void Scheduler::InvalidateState() {