diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-08-27 19:33:45 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-08-27 19:33:45 +0000 |
| commit | 49be75e82241dbd5aa8959dcc4d3ba39a8a7a28c (patch) | |
| tree | e6a8c4e19da3cf57bbafeb09740f1ba9aa64dae7 /Graphics/GraphicsEngineVulkan | |
| parent | Implemented duration query in D3D12 (diff) | |
| download | DiligentCore-49be75e82241dbd5aa8959dcc4d3ba39a8a7a28c.tar.gz DiligentCore-49be75e82241dbd5aa8959dcc4d3ba39a8a7a28c.zip | |
Implemented duration queries in Vulkan
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
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; |
