Fix timer queries reset before use on Vulkan

This commit is contained in:
Wojtek Figat
2024-07-02 00:53:45 +02:00
parent ef129a3135
commit fbc648302d
4 changed files with 25 additions and 33 deletions

View File

@@ -28,7 +28,7 @@
#define VULKAN_RESOURCE_DELETE_SAFE_FRAMES_COUNT 20 #define VULKAN_RESOURCE_DELETE_SAFE_FRAMES_COUNT 20
#define VULKAN_ENABLE_API_DUMP 0 #define VULKAN_ENABLE_API_DUMP 0
#define VULKAN_RESET_QUERY_POOLS 0 #define VULKAN_RESET_QUERY_POOLS 1
#define VULKAN_HASH_POOLS_WITH_LAYOUT_TYPES 1 #define VULKAN_HASH_POOLS_WITH_LAYOUT_TYPES 1
#define VULKAN_USE_DEBUG_LAYER GPU_ENABLE_DIAGNOSTICS #define VULKAN_USE_DEBUG_LAYER GPU_ENABLE_DIAGNOSTICS
#define VULKAN_USE_DEBUG_DATA (GPU_ENABLE_DIAGNOSTICS && COMPILE_WITH_DEV_ENV) #define VULKAN_USE_DEBUG_DATA (GPU_ENABLE_DIAGNOSTICS && COMPILE_WITH_DEV_ENV)

View File

@@ -594,8 +594,6 @@ RenderPassVulkan::~RenderPassVulkan()
QueryPoolVulkan::QueryPoolVulkan(GPUDeviceVulkan* device, int32 capacity, VkQueryType type) QueryPoolVulkan::QueryPoolVulkan(GPUDeviceVulkan* device, int32 capacity, VkQueryType type)
: _device(device) : _device(device)
, _handle(VK_NULL_HANDLE) , _handle(VK_NULL_HANDLE)
, _count(0)
, _capacity(capacity)
, _type(type) , _type(type)
{ {
VkQueryPoolCreateInfo createInfo; VkQueryPoolCreateInfo createInfo;
@@ -603,9 +601,11 @@ QueryPoolVulkan::QueryPoolVulkan(GPUDeviceVulkan* device, int32 capacity, VkQuer
createInfo.queryType = type; createInfo.queryType = type;
createInfo.queryCount = capacity; createInfo.queryCount = capacity;
VALIDATE_VULKAN_RESULT(vkCreateQueryPool(device->Device, &createInfo, nullptr, &_handle)); VALIDATE_VULKAN_RESULT(vkCreateQueryPool(device->Device, &createInfo, nullptr, &_handle));
#if VULKAN_RESET_QUERY_POOLS #if VULKAN_RESET_QUERY_POOLS
// New queries have to be reset before use
ResetBeforeUse = true;
_resetRanges.Add(Range{ 0, static_cast<uint32>(capacity) }); _resetRanges.Add(Range{ 0, static_cast<uint32>(capacity) });
device->QueriesToReset.Add(this);
#endif #endif
} }
@@ -626,6 +626,7 @@ void QueryPoolVulkan::Reset(CmdBufferVulkan* cmdBuffer)
vkCmdResetQueryPool(cmdBuffer->GetHandle(), _handle, range.Start, range.Count); vkCmdResetQueryPool(cmdBuffer->GetHandle(), _handle, range.Start, range.Count);
} }
_resetRanges.Clear(); _resetRanges.Clear();
ResetBeforeUse = false;
} }
#endif #endif
@@ -640,9 +641,9 @@ BufferedQueryPoolVulkan::BufferedQueryPoolVulkan(GPUDeviceVulkan* device, int32
_readResultsBits.AddZeroed((capacity + 63) / 64); _readResultsBits.AddZeroed((capacity + 63) / 64);
} }
bool BufferedQueryPoolVulkan::AcquireQuery(uint32& resultIndex) bool BufferedQueryPoolVulkan::AcquireQuery(CmdBufferVulkan* cmdBuffer, uint32& resultIndex)
{ {
const uint64 allUsedMask = (uint64)-1; const uint64 allUsedMask = MAX_uint64;
for (int32 wordIndex = _lastBeginIndex / 64; wordIndex < _usedQueryBits.Count(); wordIndex++) for (int32 wordIndex = _lastBeginIndex / 64; wordIndex < _usedQueryBits.Count(); wordIndex++)
{ {
uint64 beginQueryWord = _usedQueryBits[wordIndex]; uint64 beginQueryWord = _usedQueryBits[wordIndex];
@@ -659,10 +660,11 @@ bool BufferedQueryPoolVulkan::AcquireQuery(uint32& resultIndex)
_usedQueryBits[wordIndex] = _usedQueryBits[wordIndex] | bit; _usedQueryBits[wordIndex] = _usedQueryBits[wordIndex] | bit;
_readResultsBits[wordIndex] &= ~bit; _readResultsBits[wordIndex] &= ~bit;
_lastBeginIndex = resultIndex + 1; _lastBeginIndex = resultIndex + 1;
if (ResetBeforeUse)
Reset(cmdBuffer);
return true; return true;
} }
} }
return false; return false;
} }
@@ -675,7 +677,7 @@ void BufferedQueryPoolVulkan::ReleaseQuery(uint32 queryIndex)
if (queryIndex < (uint32)_lastBeginIndex) if (queryIndex < (uint32)_lastBeginIndex)
{ {
// Use the lowest word available // Use the lowest word available
const uint64 allUsedMask = (uint64)-1; const uint64 allUsedMask = MAX_uint64;
const int32 lastQueryWord = _lastBeginIndex / 64; const int32 lastQueryWord = _lastBeginIndex / 64;
if (lastQueryWord < _usedQueryBits.Count() && _usedQueryBits[lastQueryWord] == allUsedMask) if (lastQueryWord < _usedQueryBits.Count() && _usedQueryBits[lastQueryWord] == allUsedMask)
{ {
@@ -736,7 +738,7 @@ bool BufferedQueryPoolVulkan::GetResults(GPUContextVulkan* context, uint32 index
bool BufferedQueryPoolVulkan::HasRoom() const bool BufferedQueryPoolVulkan::HasRoom() const
{ {
const uint64 allUsedMask = (uint64)-1; const uint64 allUsedMask = MAX_uint64;
if (_lastBeginIndex < _usedQueryBits.Count() * 64) if (_lastBeginIndex < _usedQueryBits.Count() * 64)
{ {
ASSERT((_usedQueryBits[_lastBeginIndex / 64] & allUsedMask) != allUsedMask); ASSERT((_usedQueryBits[_lastBeginIndex / 64] & allUsedMask) != allUsedMask);

View File

@@ -259,8 +259,6 @@ protected:
GPUDeviceVulkan* _device; GPUDeviceVulkan* _device;
VkQueryPool _handle; VkQueryPool _handle;
volatile int32 _count;
const uint32 _capacity;
const VkQueryType _type; const VkQueryType _type;
#if VULKAN_RESET_QUERY_POOLS #if VULKAN_RESET_QUERY_POOLS
Array<Range> _resetRanges; Array<Range> _resetRanges;
@@ -277,6 +275,7 @@ public:
} }
#if VULKAN_RESET_QUERY_POOLS #if VULKAN_RESET_QUERY_POOLS
bool ResetBeforeUse;
void Reset(CmdBufferVulkan* cmdBuffer); void Reset(CmdBufferVulkan* cmdBuffer);
#endif #endif
}; };
@@ -294,7 +293,7 @@ private:
public: public:
BufferedQueryPoolVulkan(GPUDeviceVulkan* device, int32 capacity, VkQueryType type); BufferedQueryPoolVulkan(GPUDeviceVulkan* device, int32 capacity, VkQueryType type);
bool AcquireQuery(uint32& resultIndex); bool AcquireQuery(CmdBufferVulkan* cmdBuffer, uint32& resultIndex);
void ReleaseQuery(uint32 queryIndex); void ReleaseQuery(uint32 queryIndex);
void MarkQueryAsStarted(uint32 queryIndex); void MarkQueryAsStarted(uint32 queryIndex);
bool GetResults(GPUContextVulkan* context, uint32 index, uint64& result); bool GetResults(GPUContextVulkan* context, uint32 index, uint64& result);

View File

@@ -60,13 +60,18 @@ void GPUTimerQueryVulkan::WriteTimestamp(CmdBufferVulkan* cmdBuffer, Query& quer
{ {
auto pool = _device->FindAvailableTimestampQueryPool(); auto pool = _device->FindAvailableTimestampQueryPool();
uint32 index; uint32 index;
pool->AcquireQuery(index); if (pool->AcquireQuery(cmdBuffer, index))
{
vkCmdWriteTimestamp(cmdBuffer->GetHandle(), stage, pool->GetHandle(), index); vkCmdWriteTimestamp(cmdBuffer->GetHandle(), stage, pool->GetHandle(), index);
pool->MarkQueryAsStarted(index); pool->MarkQueryAsStarted(index);
query.Pool = pool;
query.Pool = pool; query.Index = index;
query.Index = index; }
else
{
query.Pool = nullptr;
query.Index = 0;
}
} }
bool GPUTimerQueryVulkan::TryGetResult() bool GPUTimerQueryVulkan::TryGetResult()
@@ -104,16 +109,10 @@ bool GPUTimerQueryVulkan::TryGetResult()
for (int32 i = 0; i < _queries.Count(); i++) for (int32 i = 0; i < _queries.Count(); i++)
{ {
auto& e = _queries[i]; auto& e = _queries[i];
if (e.Begin.Pool) if (e.Begin.Pool)
{
e.Begin.Pool->ReleaseQuery(e.Begin.Index); e.Begin.Pool->ReleaseQuery(e.Begin.Index);
}
if (e.End.Pool) if (e.End.Pool)
{
e.End.Pool->ReleaseQuery(e.End.Index); e.End.Pool->ReleaseQuery(e.End.Index);
}
} }
_queries.Clear(); _queries.Clear();
#else #else
@@ -141,16 +140,10 @@ void GPUTimerQueryVulkan::OnReleaseGPU()
for (int32 i = 0; i < _queries.Count(); i++) for (int32 i = 0; i < _queries.Count(); i++)
{ {
auto& e = _queries[i]; auto& e = _queries[i];
if (e.Begin.Pool) if (e.Begin.Pool)
{
e.Begin.Pool->ReleaseQuery(e.Begin.Index); e.Begin.Pool->ReleaseQuery(e.Begin.Index);
}
if (e.End.Pool) if (e.End.Pool)
{
e.End.Pool->ReleaseQuery(e.End.Index); e.End.Pool->ReleaseQuery(e.End.Index);
}
} }
_queries.Clear(); _queries.Clear();
} }
@@ -208,7 +201,6 @@ bool GPUTimerQueryVulkan::HasResult()
return false; return false;
if (_hasResult) if (_hasResult)
return true; return true;
return TryGetResult(); return TryGetResult();
} }
@@ -216,7 +208,6 @@ float GPUTimerQueryVulkan::GetResult()
{ {
if (_hasResult) if (_hasResult)
return _timeDelta; return _timeDelta;
TryGetResult(); TryGetResult();
return _timeDelta; return _timeDelta;
} }