[VK]Improve query reset before use so that now queries are reset outside render pass and are batched
Some checks failed
eden-license / license-header (pull_request) Failing after 23s

Note to testers, please enable validation layers and see if there are any errors related to queries not being reset before every use, Thanks.
This commit is contained in:
wildcard 2025-08-14 22:00:09 +02:00 committed by crueter
parent e28b0d2590
commit 793ac9a8b1
5 changed files with 40 additions and 7 deletions

View file

@ -27,7 +27,7 @@
#include "video_core/query_cache/query_cache_base.h" #include "video_core/query_cache/query_cache_base.h"
#include "video_core/query_cache/query_stream.h" #include "video_core/query_cache/query_stream.h"
#include "video_core/query_cache/types.h" #include "video_core/query_cache/types.h"
namespace Vulkan { class Scheduler; }
namespace VideoCommon { namespace VideoCommon {
using Maxwell = Tegra::Engines::Maxwell3D; using Maxwell = Tegra::Engines::Maxwell3D;
@ -222,6 +222,12 @@ void QueryCacheBase<Traits>::CounterReset(QueryType counter_type) {
streamer->ResetCounter(); streamer->ResetCounter();
} }
// Called at frame start to batch vkCmdResetQueryPool outside render passes.
template <typename Traits>
void QueryCacheBase<Traits>::FramePrologueResets(Vulkan::Scheduler& scheduler) {
impl->runtime.FramePrologueResets(scheduler);
}
template <typename Traits> template <typename Traits>
void QueryCacheBase<Traits>::BindToChannel(s32 id) { void QueryCacheBase<Traits>::BindToChannel(s32 id) {
VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo>::BindToChannel(id); VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo>::BindToChannel(id);

View file

@ -21,7 +21,9 @@
namespace VideoCore { namespace VideoCore {
class RasterizerInterface; class RasterizerInterface;
} }
namespace Vulkan {
class Scheduler;
}
namespace Tegra { namespace Tegra {
class GPU; class GPU;
} }
@ -53,7 +55,7 @@ public:
RuntimeType& runtime_); RuntimeType& runtime_);
~QueryCacheBase(); ~QueryCacheBase();
void FramePrologueResets(Vulkan::Scheduler& scheduler);
void InvalidateRegion(VAddr addr, std::size_t size) { void InvalidateRegion(VAddr addr, std::size_t size) {
IterateCache<true>(addr, size, IterateCache<true>(addr, size,
[this](QueryLocation location) { InvalidateQuery(location); }); [this](QueryLocation location) { InvalidateQuery(location); });

View file

@ -156,7 +156,7 @@ public:
ReserveHostQuery(); ReserveHostQuery();
// Ensure outside render pass /* Ensure outside render pass
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
// Reset query pool outside render pass // Reset query pool outside render pass
@ -167,7 +167,7 @@ public:
// Manually restart the render pass (required for vkCmdClearAttachments, etc.) // Manually restart the render pass (required for vkCmdClearAttachments, etc.)
scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); scheduler.RequestRenderpass(texture_cache.GetFramebuffer());
*/
// Begin query inside the newly started render pass // Begin query inside the newly started render pass
scheduler.Record([query_pool = current_query_pool, scheduler.Record([query_pool = current_query_pool,
query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { 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: private:
template <typename Func> template <typename Func>
void ApplyBankOp(VideoCommon::HostQueryBase* query, Func&& func) { void ApplyBankOp(VideoCommon::HostQueryBase* query, Func&& func) {
@ -1305,6 +1312,19 @@ void QueryCacheRuntime::ResumeHostConditionalRendering() {
impl->is_hcr_running = true; 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, void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::LookupData object,
bool is_equal) { bool is_equal) {
{ {

View file

@ -20,7 +20,7 @@ namespace Vulkan {
class Device; class Device;
class Scheduler; class Scheduler;
class StagingBufferPool; class StagingBufferPool;
class Scheduler;
struct QueryCacheRuntimeImpl; struct QueryCacheRuntimeImpl;
class QueryCacheRuntime { class QueryCacheRuntime {
@ -33,7 +33,7 @@ public:
ComputePassDescriptorQueue& compute_pass_descriptor_queue, ComputePassDescriptorQueue& compute_pass_descriptor_queue,
DescriptorPool& descriptor_pool, TextureCache& texture_cache_); DescriptorPool& descriptor_pool, TextureCache& texture_cache_);
~QueryCacheRuntime(); ~QueryCacheRuntime();
void FramePrologueResets(Scheduler& scheduler);
template <typename SyncValuesType> template <typename SyncValuesType>
void SyncValues(std::span<SyncValuesType> values, VkBuffer base_src_buffer = nullptr); void SyncValues(std::span<SyncValuesType> values, VkBuffer base_src_buffer = nullptr);

View file

@ -257,6 +257,11 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se
void Scheduler::AllocateNewContext() { void Scheduler::AllocateNewContext() {
// Enable counters once again. These are disabled when a command buffer is finished. // 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() { void Scheduler::InvalidateState() {