From 18ca5ed7b68bb55344adf2b16720565a3c7fd5b4 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 5 Jan 2020 22:05:08 -0800 Subject: Vulkan backend: resetting queries before first use as required by spec --- .../include/DeviceContextVkImpl.h | 6 ++-- .../GraphicsEngineVulkan/include/QueryManagerVk.h | 7 +++-- .../src/DeviceContextVkImpl.cpp | 17 +++++++---- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 34 ++++++++++++++-------- .../GraphicsEngineVulkan/src/QueryManagerVk.cpp | 19 +++++++++--- Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp | 19 +++++++----- 6 files changed, 67 insertions(+), 35 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h index f7939c08..d561a37d 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h @@ -319,7 +319,7 @@ public: Int64 GetContextFrameNumber() const { return m_ContextFrameNumber; } GenerateMipsVkHelper& GetGenerateMipsHelper() { return *m_GenerateMipsHelper; } - QueryManagerVk& GetQueryManager() { return m_QueryMgr; } + QueryManagerVk* GetQueryManager() { return m_QueryMgr.get(); } private: void TransitionRenderTargets(RESOURCE_STATE_TRANSITION_MODE StateTransitionMode); @@ -472,8 +472,8 @@ private: // In Vulkan we can't bind null vertex buffer, so we have to create a dummy VB RefCntAutoPtr m_DummyVB; - QueryManagerVk m_QueryMgr; - Int32 m_ActiveQueriesCounter = 0; + std::unique_ptr m_QueryMgr; + Int32 m_ActiveQueriesCounter = 0; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/QueryManagerVk.h b/Graphics/GraphicsEngineVulkan/include/QueryManagerVk.h index 6df7b82c..c713837c 100644 --- a/Graphics/GraphicsEngineVulkan/include/QueryManagerVk.h +++ b/Graphics/GraphicsEngineVulkan/include/QueryManagerVk.h @@ -41,12 +41,13 @@ namespace Diligent { +class RenderDeviceVkImpl; + class QueryManagerVk { public: - QueryManagerVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, - const VulkanUtilities::VulkanPhysicalDevice& PhysicalDevice, - const Uint32 QueryHeapSizes[]); + QueryManagerVk(RenderDeviceVkImpl* RenderDeviceVk, + const Uint32 QueryHeapSizes[]); ~QueryManagerVk(); // clang-format off diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 3bdc41a1..5af8012f 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -96,10 +96,14 @@ DeviceContextVkImpl::DeviceContextVkImpl(IReferenceCounters* p pDeviceVkImpl->GetDynamicDescriptorPool(), GetContextObjectName("Dynamic descriptor set allocator", bIsDeferred, ContextId), }, - m_GenerateMipsHelper{std::move(GenerateMipsHelper)}, - m_QueryMgr{pDeviceVkImpl->GetLogicalDevice(), pDeviceVkImpl->GetPhysicalDevice(), EngineCI.QueryPoolSizes} + m_GenerateMipsHelper{std::move(GenerateMipsHelper)} // clang-format on { + if (!m_bIsDeferred) + { + m_QueryMgr.reset(new QueryManagerVk{pDeviceVkImpl, EngineCI.QueryPoolSizes}); + } + m_GenerateMipsHelper->CreateSRB(&m_GenerateMipsSRB); BufferDesc DummyVBDesc; @@ -880,7 +884,10 @@ void DeviceContextVkImpl::Flush() auto vkCmdBuff = m_CommandBuffer.GetVkCmdBuffer(); if (vkCmdBuff != VK_NULL_HANDLE) { - m_QueryMgr.ResetStaleQueries(m_CommandBuffer); + if (m_QueryMgr) + { + m_QueryMgr->ResetStaleQueries(m_CommandBuffer); + } if (m_State.NumCommands != 0) { @@ -2036,7 +2043,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(m_QueryMgr->GetQueryPool(QueryType), 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 @@ -2053,7 +2060,7 @@ void DeviceContextVkImpl::EndQuery(IQuery* pQuery) auto* pQueryVkImpl = ValidatedCast(pQuery); const auto QueryType = pQueryVkImpl->GetDesc().Type; - auto vkQueryPool = m_QueryMgr.GetQueryPool(QueryType); + auto vkQueryPool = m_QueryMgr->GetQueryPool(QueryType); auto Idx = pQueryVkImpl->GetQueryPoolIndex(); EnsureVkCmdBuffer(); diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 676d8ca3..6c457ce2 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -76,6 +76,9 @@ public: const SwapChainDesc& SwapChainDesc, void* pNativeWndHandle, ISwapChain** ppSwapChain) override final; + +private: + std::function OnRenderDeviceCreated = nullptr; }; /// Creates render device and device contexts for Vulkan backend @@ -211,21 +214,25 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E auto vkPhysicalDevice = PhysicalDevice->GetVkDeviceHandle(); auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(vkPhysicalDevice, DeviceCreateInfo, vkAllocator); - RefCntAutoPtr pCmdQueueVk; - auto& RawMemAllocator = GetRawAllocator(); - pCmdQueueVk = NEW_RC_OBJ(RawMemAllocator, "CommandQueueVk instance", CommandQueueVkImpl)(LogicalDevice, QueueInfo.queueFamilyIndex); + auto& RawMemAllocator = GetRawAllocator(); - std::array CommandQueues = {{pCmdQueueVk}}; - AttachToVulkanDevice(Instance, std::move(PhysicalDevice), LogicalDevice, CommandQueues.size(), CommandQueues.data(), EngineCI, ppDevice, ppContexts); + RefCntAutoPtr pCmdQueueVk{ + NEW_RC_OBJ(RawMemAllocator, "CommandQueueVk instance", CommandQueueVkImpl)(LogicalDevice, QueueInfo.queueFamilyIndex)}; - FenceDesc Desc; - Desc.Name = "Command queue fence"; - // Render device owns command queue that in turn owns the fence, so it is an internal device object - bool IsDeviceInternal = true; - auto* pRenderDeviceVk = ValidatedCast(*ppDevice); + OnRenderDeviceCreated = [&](RenderDeviceVkImpl* pRenderDeviceVk) // + { + FenceDesc Desc; + Desc.Name = "Command queue internal fence"; + // Render device owns command queue that in turn owns the fence, so it is an internal device object + constexpr bool IsDeviceInternal = true; - RefCntAutoPtr pFenceVk(NEW_RC_OBJ(RawMemAllocator, "FenceVkImpl instance", FenceVkImpl)(pRenderDeviceVk, Desc, IsDeviceInternal)); - pCmdQueueVk->SetFence(std::move(pFenceVk)); + RefCntAutoPtr pFenceVk{ + NEW_RC_OBJ(RawMemAllocator, "FenceVkImpl instance", FenceVkImpl)(pRenderDeviceVk, Desc, IsDeviceInternal)}; + pCmdQueueVk->SetFence(std::move(pFenceVk)); + }; + + std::array CommandQueues = {{pCmdQueueVk}}; + AttachToVulkanDevice(Instance, std::move(PhysicalDevice), LogicalDevice, CommandQueues.size(), CommandQueues.data(), EngineCI, ppDevice, ppContexts); } catch (std::runtime_error&) { @@ -275,6 +282,9 @@ void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptrQueryInterface(IID_RenderDevice, reinterpret_cast(ppDevice)); + if (OnRenderDeviceCreated != nullptr) + OnRenderDeviceCreated(pRenderDeviceVk); + std::shared_ptr GenerateMipsHelper(new GenerateMipsVkHelper(*pRenderDeviceVk)); RefCntAutoPtr pImmediateCtxVk(NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, false, EngineCI, 0, 0, GenerateMipsHelper)); diff --git a/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp b/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp index 33231272..a3d0b92b 100644 --- a/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/QueryManagerVk.cpp @@ -34,14 +34,19 @@ namespace Diligent { -QueryManagerVk::QueryManagerVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, - const VulkanUtilities::VulkanPhysicalDevice& PhysicalDevice, - const Uint32 QueryHeapSizes[]) +QueryManagerVk::QueryManagerVk(RenderDeviceVkImpl* pRenderDeviceVk, + const Uint32 QueryHeapSizes[]) { + const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); + const auto& PhysicalDevice = pRenderDeviceVk->GetPhysicalDevice(); + auto timestampPeriod = PhysicalDevice.GetProperties().limits.timestampPeriod; m_CounterFrequency = static_cast(1000000000.0 / timestampPeriod); - //Uint32 ResolveBufferOffset = 0; + VulkanUtilities::CommandPoolWrapper CmdPool; + VkCommandBuffer vkCmdBuff; + pRenderDeviceVk->AllocateTransientCmdPool(CmdPool, vkCmdBuff, "Transient command pool to reset queries before first use"); + for (Uint32 QueryType = QUERY_TYPE_UNDEFINED + 1; QueryType < QUERY_TYPE_NUM_TYPES; ++QueryType) { // clang-format off @@ -105,12 +110,18 @@ QueryManagerVk::QueryManagerVk(const VulkanUtilities::VulkanLogicalDevice& Logi HeapInfo.vkQueryPool = LogicalDevice.CreateQueryPool(QueryPoolCI, "QueryManagerVk: query pool"); + // Queries must be reset before first use. + vkCmdResetQueryPool(vkCmdBuff, HeapInfo.vkQueryPool, 0, QueryPoolCI.queryCount); + HeapInfo.AvailableQueries.resize(HeapInfo.PoolSize); for (Uint32 i = 0; i < HeapInfo.PoolSize; ++i) { HeapInfo.AvailableQueries[i] = i; } } + + Uint32 QueueIndex = 0; + pRenderDeviceVk->ExecuteAndDisposeTransientCmdBuff(QueueIndex, vkCmdBuff, std::move(CmdPool)); } QueryManagerVk::~QueryManagerVk() diff --git a/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp index 716efa99..f1f670d6 100644 --- a/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/QueryVkImpl.cpp @@ -53,18 +53,20 @@ QueryVkImpl::QueryVkImpl(IReferenceCounters* pRefCounters, QueryVkImpl::~QueryVkImpl() { - auto& QueryMgr = m_pContext.RawPtr()->GetQueryManager(); - QueryMgr.DiscardQuery(m_Desc.Type, m_QueryPoolIndex); + auto* pQueryMgr = m_pContext.RawPtr()->GetQueryManager(); + VERIFY_EXPR(pQueryMgr != nullptr); + pQueryMgr->DiscardQuery(m_Desc.Type, m_QueryPoolIndex); } bool QueryVkImpl::AllocateQuery() { - auto& QueryMgr = m_pContext.RawPtr()->GetQueryManager(); + auto* pQueryMgr = m_pContext.RawPtr()->GetQueryManager(); + VERIFY_EXPR(pQueryMgr != nullptr); if (m_QueryPoolIndex != QueryManagerVk::InvalidIndex) { - QueryMgr.DiscardQuery(m_Desc.Type, m_QueryPoolIndex); + pQueryMgr->DiscardQuery(m_Desc.Type, m_QueryPoolIndex); } - m_QueryPoolIndex = QueryMgr.AllocateQuery(m_Desc.Type); + m_QueryPoolIndex = pQueryMgr->AllocateQuery(m_Desc.Type); if (m_QueryPoolIndex == QueryManagerVk::InvalidIndex) { LOG_ERROR_MESSAGE("Failed to allocate Vulkan query for type ", GetQueryTypeString(m_Desc.Type), @@ -112,9 +114,10 @@ bool QueryVkImpl::GetData(void* pData, Uint32 DataSize) auto CompletedFenceValue = m_pDevice->GetCompletedFenceValue(CmdQueueId); if (CompletedFenceValue >= m_QueryEndFenceValue) { - auto& QueryMgr = m_pContext.RawPtr()->GetQueryManager(); + auto* pQueryMgr = m_pContext.RawPtr()->GetQueryManager(); + VERIFY_EXPR(pQueryMgr != nullptr); const auto& LogicalDevice = m_pDevice->GetLogicalDevice(); - auto vkQueryPool = QueryMgr.GetQueryPool(m_Desc.Type); + auto vkQueryPool = pQueryMgr->GetQueryPool(m_Desc.Type); switch (m_Desc.Type) { @@ -162,7 +165,7 @@ bool QueryVkImpl::GetData(void* pData, Uint32 DataSize) auto& QueryData = *reinterpret_cast(pData); QueryData.Counter = Results[0]; - QueryData.Frequency = QueryMgr.GetCounterFrequency(); + QueryData.Frequency = pQueryMgr->GetCounterFrequency(); } break; -- cgit v1.2.3