Add new GPU Query API that is lightweight and supports occlusion queries

This commit is contained in:
Wojtek Figat
2026-01-16 10:40:30 +01:00
parent d2d7a871ce
commit 9ac231c403
31 changed files with 829 additions and 254 deletions

View File

@@ -6,7 +6,7 @@
#include "RenderToolsVulkan.h"
#include "QueueVulkan.h"
#include "GPUContextVulkan.h"
#if VULKAN_USE_QUERIES
#if VULKAN_USE_TIMER_QUERIES
#include "GPUTimerQueryVulkan.h"
#endif
#include "DescriptorSetVulkan.h"
@@ -243,6 +243,7 @@ void CmdBufferPoolVulkan::RefreshFenceStatus(const CmdBufferVulkan* skipCmdBuffe
CmdBufferManagerVulkan::CmdBufferManagerVulkan(GPUDeviceVulkan* device, GPUContextVulkan* context)
: _device(device)
, _context(context)
, _pool(device)
, _queue(context->GetQueue())
, _activeCmdBuffer(nullptr)
@@ -259,12 +260,28 @@ void CmdBufferManagerVulkan::SubmitActiveCmdBuffer(SemaphoreVulkan* signalSemaph
if (_activeCmdBuffer->IsInsideRenderPass())
_activeCmdBuffer->EndRenderPass();
#if VULKAN_USE_QUERIES
// Pause all active queries
for (int32 i = 0; i < _queriesInProgress.Count(); i++)
#if VULKAN_USE_TIMER_QUERIES && GPU_VULKAN_PAUSE_QUERIES
// Pause all active timer queries
auto queries = _activeTimerQueries.Get();
#if GPU_VULKAN_QUERY_NEW
for (int32 i = 0; i < _activeTimerQueries.Count(); i++)
{
_queriesInProgress.Get()[i]->Interrupt(_activeCmdBuffer);
GPUQueryVulkan query;
query.Raw = queries[i];
// End active query to get time from start until submission
auto pool = _device->QueryPools[query.PoolIndex];
vkCmdWriteTimestamp(_activeCmdBuffer->GetHandle(), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, pool->GetHandle(), query.SecondQueryIndex);
pool->MarkQueryAsStarted(query.SecondQueryIndex);
// TODO: somehow handle ending this query properly by stopping split query instead
//_context->EndQuery(query.Raw);
// TODO: reimplement timer queries pause/resume to be more exact?
}
#else
for (int32 i = 0; i < _activeTimerQueries.Count(); i++)
queries->Interrupt(_activeCmdBuffer);
#endif
#endif
_activeCmdBuffer->End();
@@ -317,27 +334,37 @@ void CmdBufferManagerVulkan::PrepareForNewActiveCommandBuffer()
_activeCmdBuffer->Begin();
#if VULKAN_USE_QUERIES
// Resume any paused queries with the new command buffer
for (int32 i = 0; i < _queriesInProgress.Count(); i++)
#if VULKAN_USE_TIMER_QUERIES && GPU_VULKAN_PAUSE_QUERIES
// Resume any paused timer queries with the new command buffer
auto queries = _activeTimerQueries.Get();
#if GPU_VULKAN_QUERY_NEW
for (int32 i = 0; i < _activeTimerQueries.Count(); i++)
{
_queriesInProgress.Get()[i]->Resume(_activeCmdBuffer);
GPUQueryVulkan query;
query.Raw = queries[i];
//_activeTimerQueries.Get()[i]->Resume(_activeCmdBuffer);
}
#else
for (int32 i = 0; i < _activeTimerQueries.Count(); i++)
{
queries->Resume(_activeCmdBuffer);
}
#endif
#endif
}
void CmdBufferManagerVulkan::OnQueryBegin(GPUTimerQueryVulkan* query)
#if GPU_VULKAN_QUERY_NEW && GPU_VULKAN_PAUSE_QUERIES
void CmdBufferManagerVulkan::OnTimerQueryBegin(QueryType query)
{
#if VULKAN_USE_QUERIES
_queriesInProgress.Add(query);
#endif
_activeTimerQueries.Add(query);
}
void CmdBufferManagerVulkan::OnQueryEnd(GPUTimerQueryVulkan* query)
void CmdBufferManagerVulkan::OnTimerQueryEnd(QueryType query)
{
#if VULKAN_USE_QUERIES
_queriesInProgress.Remove(query);
#endif
_activeTimerQueries.Remove(query);
}
#endif
#endif