summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-08-27 19:33:45 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-08-27 19:33:45 +0000
commit49be75e82241dbd5aa8959dcc4d3ba39a8a7a28c (patch)
treee6a8c4e19da3cf57bbafeb09740f1ba9aa64dae7 /Graphics/GraphicsEngineVulkan
parentImplemented duration query in D3D12 (diff)
downloadDiligentCore-49be75e82241dbd5aa8959dcc4d3ba39a8a7a28c.tar.gz
DiligentCore-49be75e82241dbd5aa8959dcc4d3ba39a8a7a28c.zip
Implemented duration queries in Vulkan
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/QueryVkImpl.hpp14
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp13
-rw-r--r--Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp114
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp1
4 files changed, 98 insertions, 44 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/QueryVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/QueryVkImpl.hpp
index a2814172..11bacb61 100644
--- a/Graphics/GraphicsEngineVulkan/include/QueryVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/QueryVkImpl.hpp
@@ -30,6 +30,8 @@
/// \file
/// Declaration of Diligent::QueryVkImpl class
+#include <array>
+
#include "QueryVk.h"
#include "QueryBase.hpp"
#include "RenderDeviceVkImpl.hpp"
@@ -60,19 +62,21 @@ public:
/// Implementation of IQuery::Invalidate().
virtual void DILIGENT_CALL_TYPE Invalidate() override final;
- Uint32 GetQueryPoolIndex() const
+ Uint32 GetQueryPoolIndex(Uint32 QueryId) const
{
- return m_QueryPoolIndex;
+ VERIFY_EXPR(QueryId == 0 || m_Desc.Type == QUERY_TYPE_DURATION && QueryId == 1);
+ return m_QueryPoolIndex[QueryId];
}
bool OnEndQuery(IDeviceContext* pContext);
bool OnBeginQuery(IDeviceContext* pContext);
private:
- bool AllocateQuery();
- void DiscardQuery();
+ bool AllocateQueries();
+ void DiscardQueries();
+
+ std::array<Uint32, 2> m_QueryPoolIndex = {QueryManagerVk::InvalidIndex, QueryManagerVk::InvalidIndex};
- Uint32 m_QueryPoolIndex = QueryManagerVk::InvalidIndex;
Uint64 m_QueryEndFenceValue = 0;
};
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index f9328d0a..ccc804ad 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -2165,13 +2165,18 @@ void DeviceContextVkImpl::BeginQuery(IQuery* pQuery)
auto* pQueryVkImpl = ValidatedCast<QueryVkImpl>(pQuery);
const auto QueryType = pQueryVkImpl->GetDesc().Type;
- auto Idx = pQueryVkImpl->GetQueryPoolIndex();
+ auto vkQueryPool = m_QueryMgr->GetQueryPool(QueryType);
+ auto Idx = pQueryVkImpl->GetQueryPoolIndex(0);
EnsureVkCmdBuffer();
if (QueryType == QUERY_TYPE_TIMESTAMP)
{
LOG_ERROR_MESSAGE("BeginQuery() is disabled for timestamp queries");
}
+ else if (QueryType == QUERY_TYPE_DURATION)
+ {
+ m_CommandBuffer.WriteTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, vkQueryPool, Idx);
+ }
else
{
const auto& CmdBuffState = m_CommandBuffer.GetState();
@@ -2187,7 +2192,7 @@ void DeviceContextVkImpl::BeginQuery(IQuery* pQuery)
// both begin and end outside of a render pass instance (i.e. contain entire render pass instances). (17.2)
++m_ActiveQueriesCounter;
- m_CommandBuffer.BeginQuery(m_QueryMgr->GetQueryPool(QueryType),
+ m_CommandBuffer.BeginQuery(vkQueryPool,
Idx,
// If flags does not contain VK_QUERY_CONTROL_PRECISE_BIT an implementation
// may generate any non-zero result value for the query if the count of
@@ -2205,10 +2210,10 @@ void DeviceContextVkImpl::EndQuery(IQuery* pQuery)
auto* pQueryVkImpl = ValidatedCast<QueryVkImpl>(pQuery);
const auto QueryType = pQueryVkImpl->GetDesc().Type;
auto vkQueryPool = m_QueryMgr->GetQueryPool(QueryType);
- auto Idx = pQueryVkImpl->GetQueryPoolIndex();
+ auto Idx = pQueryVkImpl->GetQueryPoolIndex(QueryType == QUERY_TYPE_DURATION ? 1 : 0);
EnsureVkCmdBuffer();
- if (QueryType == QUERY_TYPE_TIMESTAMP)
+ if (QueryType == QUERY_TYPE_TIMESTAMP || QueryType == QUERY_TYPE_DURATION)
{
m_CommandBuffer.WriteTimestamp(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, vkQueryPool, Idx);
}
diff --git a/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp
index b4464d50..381ee631 100644
--- a/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp
@@ -53,47 +53,49 @@ QueryVkImpl::QueryVkImpl(IReferenceCounters* pRefCounters,
QueryVkImpl::~QueryVkImpl()
{
- if (m_QueryPoolIndex != QueryManagerVk::InvalidIndex)
- {
- VERIFY(m_pContext != nullptr, "Device context is not initialized");
- auto* pQueryMgr = m_pContext.RawPtr<DeviceContextVkImpl>()->GetQueryManager();
- VERIFY_EXPR(pQueryMgr != nullptr);
- pQueryMgr->DiscardQuery(m_Desc.Type, m_QueryPoolIndex);
- }
+ DiscardQueries();
}
-void QueryVkImpl::DiscardQuery()
+void QueryVkImpl::DiscardQueries()
{
- if (m_QueryPoolIndex != QueryManagerVk::InvalidIndex)
+ for (auto& QueryPoolIdx : m_QueryPoolIndex)
{
- VERIFY_EXPR(m_pContext);
- auto* pQueryMgr = m_pContext.RawPtr<DeviceContextVkImpl>()->GetQueryManager();
- VERIFY_EXPR(pQueryMgr != nullptr);
- pQueryMgr->DiscardQuery(m_Desc.Type, m_QueryPoolIndex);
- m_QueryPoolIndex = QueryManagerVk::InvalidIndex;
+ if (QueryPoolIdx != QueryManagerVk::InvalidIndex)
+ {
+ VERIFY_EXPR(m_pContext);
+ auto* pQueryMgr = m_pContext.RawPtr<DeviceContextVkImpl>()->GetQueryManager();
+ VERIFY_EXPR(pQueryMgr != nullptr);
+ pQueryMgr->DiscardQuery(m_Desc.Type, QueryPoolIdx);
+ QueryPoolIdx = QueryManagerVk::InvalidIndex;
+ }
}
}
void QueryVkImpl::Invalidate()
{
- DiscardQuery();
+ DiscardQueries();
TQueryBase::Invalidate();
}
-bool QueryVkImpl::AllocateQuery()
+bool QueryVkImpl::AllocateQueries()
{
- DiscardQuery();
+ DiscardQueries();
VERIFY_EXPR(m_pContext);
auto* pQueryMgr = m_pContext.RawPtr<DeviceContextVkImpl>()->GetQueryManager();
VERIFY_EXPR(pQueryMgr != nullptr);
- VERIFY_EXPR(m_QueryPoolIndex == QueryManagerVk::InvalidIndex);
-
- m_QueryPoolIndex = pQueryMgr->AllocateQuery(m_Desc.Type);
- if (m_QueryPoolIndex == QueryManagerVk::InvalidIndex)
+ for (Uint32 i = 0; i < (m_Desc.Type == QUERY_TYPE_DURATION ? Uint32{2} : Uint32{1}); ++i)
{
- LOG_ERROR_MESSAGE("Failed to allocate Vulkan query for type ", GetQueryTypeString(m_Desc.Type),
- ". Increase the query pool size in EngineVkCreateInfo.");
- return false;
+ auto& QueryPoolIdx = m_QueryPoolIndex[i];
+ VERIFY_EXPR(QueryPoolIdx == QueryManagerVk::InvalidIndex);
+
+ QueryPoolIdx = pQueryMgr->AllocateQuery(m_Desc.Type);
+ if (QueryPoolIdx == QueryManagerVk::InvalidIndex)
+ {
+ LOG_ERROR_MESSAGE("Failed to allocate Vulkan query for type ", GetQueryTypeString(m_Desc.Type),
+ ". Increase the query pool size in EngineVkCreateInfo.");
+ DiscardQueries();
+ return false;
+ }
}
return true;
@@ -104,7 +106,7 @@ bool QueryVkImpl::OnBeginQuery(IDeviceContext* pContext)
if (!TQueryBase::OnBeginQuery(pContext))
return false;
- return AllocateQuery();
+ return AllocateQueries();
}
bool QueryVkImpl::OnEndQuery(IDeviceContext* pContext)
@@ -114,11 +116,11 @@ bool QueryVkImpl::OnEndQuery(IDeviceContext* pContext)
if (m_Desc.Type == QUERY_TYPE_TIMESTAMP)
{
- if (!AllocateQuery())
+ if (!AllocateQueries())
return false;
}
- if (m_QueryPoolIndex == QueryManagerVk::InvalidIndex)
+ if (m_QueryPoolIndex[0] == QueryManagerVk::InvalidIndex || (m_Desc.Type == QUERY_TYPE_DURATION && m_QueryPoolIndex[1] == QueryManagerVk::InvalidIndex))
{
LOG_ERROR_MESSAGE("Query '", m_Desc.Name, "' is invalid: Vulkan query allocation failed");
return false;
@@ -146,7 +148,7 @@ bool QueryVkImpl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate)
{
case QUERY_TYPE_OCCLUSION:
{
- uint64_t Results[2];
+ std::array<uint64_t, 2> Results = {};
// If VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set, the final integer value written for each query
// is non-zero if the query's status was available or zero if the status was unavailable.
@@ -158,7 +160,9 @@ bool QueryVkImpl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate)
// command executes on a queue. Applications can use fences or events to ensure that a query has
// already been reset before checking for its results or availability status. Otherwise, a stale
// value could be returned from a previous use of the query.
- auto res = LogicalDevice.GetQueryPoolResults(vkQueryPool, m_QueryPoolIndex, 1, sizeof(Results), Results, 0, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
+ auto res = LogicalDevice.GetQueryPoolResults(vkQueryPool, m_QueryPoolIndex[0], 1,
+ sizeof(Results[0]) * Results.size(), Results.data(), 0,
+ VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
DataAvailable = (res == VK_SUCCESS && Results[1] != 0);
if (DataAvailable && pData != nullptr)
@@ -171,8 +175,11 @@ bool QueryVkImpl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate)
case QUERY_TYPE_BINARY_OCCLUSION:
{
- uint64_t Results[2];
- auto res = LogicalDevice.GetQueryPoolResults(vkQueryPool, m_QueryPoolIndex, 1, sizeof(Results), Results, 0, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
+ std::array<uint64_t, 2> Results = {};
+
+ auto res = LogicalDevice.GetQueryPoolResults(vkQueryPool, m_QueryPoolIndex[0], 1,
+ sizeof(Results[0]) * Results.size(), Results.data(), 0,
+ VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
DataAvailable = (res == VK_SUCCESS && Results[1] != 0);
if (DataAvailable && pData != nullptr)
@@ -185,8 +192,11 @@ bool QueryVkImpl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate)
case QUERY_TYPE_TIMESTAMP:
{
- uint64_t Results[2];
- auto res = LogicalDevice.GetQueryPoolResults(vkQueryPool, m_QueryPoolIndex, 1, sizeof(Results), Results, 0, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
+ std::array<uint64_t, 2> Results = {};
+
+ auto res = LogicalDevice.GetQueryPoolResults(vkQueryPool, m_QueryPoolIndex[0], 1,
+ sizeof(Results[0]) * Results.size(), Results.data(), 0,
+ VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
DataAvailable = (res == VK_SUCCESS && Results[1] != 0);
if (DataAvailable && pData != nullptr)
@@ -204,8 +214,11 @@ bool QueryVkImpl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate)
// pipelineStatistics when the pool is created, and the statistics values are written in bit
// order starting from the least significant bit. (17.2)
- Uint64 Results[12];
- auto res = LogicalDevice.GetQueryPoolResults(vkQueryPool, m_QueryPoolIndex, 1, sizeof(Results), Results, 0, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
+ std::array<Uint64, 12> Results;
+
+ auto res = LogicalDevice.GetQueryPoolResults(vkQueryPool, m_QueryPoolIndex[0], 1,
+ sizeof(Results[0]) * Results.size(), Results.data(), 0,
+ VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
DataAvailable = (res == VK_SUCCESS);
if (DataAvailable && pData != nullptr)
@@ -241,6 +254,37 @@ bool QueryVkImpl::GetData(void* pData, Uint32 DataSize, bool AutoInvalidate)
}
break;
+
+ case QUERY_TYPE_DURATION:
+ {
+ uint64_t StartCounter = 0;
+ uint64_t EndCounter = 0;
+
+ DataAvailable = true;
+ for (Uint32 i = 0; i < 2; ++i)
+ {
+ std::array<uint64_t, 2> Results = {};
+
+ auto res = LogicalDevice.GetQueryPoolResults(vkQueryPool, m_QueryPoolIndex[i], 1,
+ sizeof(Results[0]) * Results.size(), Results.data(), 0,
+ VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
+
+ if (res != VK_SUCCESS || Results[1] == 0)
+ DataAvailable = false;
+
+ (i == 0 ? StartCounter : EndCounter) = Results[0];
+ }
+
+ if (DataAvailable && pData != nullptr)
+ {
+ auto& QueryData = *reinterpret_cast<QueryDataTimestamp*>(pData);
+ VERIFY_EXPR(EndCounter >= StartCounter);
+ QueryData.Counter = EndCounter - StartCounter;
+ QueryData.Frequency = pQueryMgr->GetCounterFrequency();
+ }
+ }
+ break;
+
default:
UNEXPECTED("Unexpected query type");
}
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index 18814e06..c278d0ed 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -172,6 +172,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
Features.OcclusionQueries = vkDeviceFeatures.occlusionQueryPrecise != VK_FALSE;
Features.BinaryOcclusionQueries = True;
Features.TimestampQueries = True;
+ Features.DurationQueries = True;
Features.PipelineStatisticsQueries = vkDeviceFeatures.pipelineStatisticsQuery != VK_FALSE;
Features.DepthBiasClamp = vkDeviceFeatures.depthBiasClamp != VK_FALSE;
Features.DepthClamp = vkDeviceFeatures.depthClamp != VK_FALSE;