summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-06-06 15:47:36 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-06-06 15:47:36 +0000
commitfe135f2472e4a598976860f3f40f85b898fd5cc0 (patch)
tree03a76d6c1a07f7485350a15ee63e2818de20d9ad /Graphics/GraphicsEngineVulkan
parentImprovements to resource liftime management in Vulkan (diff)
downloadDiligentCore-fe135f2472e4a598976860f3f40f85b898fd5cc0.tar.gz
DiligentCore-fe135f2472e4a598976860f3f40f85b898fd5cc0.zip
Added ResourceReleaseQueue class
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h22
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp96
2 files changed, 13 insertions, 105 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
index bda52b94..8998b187 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
@@ -43,6 +43,7 @@
#include "VulkanUtilities/VulkanUploadHeap.h"
#include "FramebufferCache.h"
#include "CommandPoolManager.h"
+#include "ResourceReleaseQueue.h"
/// Namespace for the Direct3D11 implementation of the graphics engine
namespace Diligent
@@ -103,7 +104,10 @@ public:
void ExecuteAndDisposeTransientCmdBuff(VkCommandBuffer vkCmdBuff, VulkanUtilities::CommandPoolWrapper&& CmdPool);
template<typename ObjectType>
- void SafeReleaseVkObject(ObjectType&& Object);
+ void SafeReleaseVkObject(ObjectType&& Object)
+ {
+ m_ReleaseQueue.SafeReleaseResource(std::move(Object), m_NextCmdBuffNumber);
+ }
void FinishFrame(bool ReleaseAllResources);
virtual void FinishFrame()override final { FinishFrame(false); }
@@ -137,7 +141,6 @@ public:
private:
virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat )override final;
void ProcessReleaseQueue(Uint64 CompletedFenceValue);
- void DiscardStaleVkObjects(Uint64 CmdBuffNumber, Uint64 FenceValue);
// Submits command buffer for execution to the command queue
// Returns the submitted command buffer number and the fence value that has been set to signal by GPU
@@ -185,20 +188,6 @@ private:
// Resource X can
// be released
-
- std::mutex m_ReleaseQueueMutex;
-
- class StaleVulkanObjectBase
- {
- public:
- virtual ~StaleVulkanObjectBase() = 0 {}
- };
-
- using ReleaseQueueElemType = std::pair<Uint64, std::unique_ptr<StaleVulkanObjectBase> >;
- std::deque< ReleaseQueueElemType, STDAllocatorRawMem<ReleaseQueueElemType> > m_VkObjReleaseQueue;
-
- std::mutex m_StaleObjectsMutex;
- std::deque< ReleaseQueueElemType, STDAllocatorRawMem<ReleaseQueueElemType> > m_StaleVkObjects;
FramebufferCache m_FramebufferCache;
// [0] - Main descriptor pool
@@ -214,6 +203,7 @@ private:
CommandPoolManager m_TransientCmdPoolMgr;
VulkanUtilities::VulkanMemoryManager m_MemoryMgr;
+ ResourceReleaseQueue<> m_ReleaseQueue;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index e46254ec..bde9dc2e 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -32,8 +32,8 @@
#include "BufferVkImpl.h"
#include "ShaderResourceBindingVkImpl.h"
#include "DeviceContextVkImpl.h"
-
#include "EngineMemory.h"
+
namespace Diligent
{
@@ -56,13 +56,12 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters *pRefCounters,
/*m_CmdListManager(this),
m_ContextPool(STD_ALLOCATOR_RAW_MEM(ContextPoolElemType, GetRawAllocator(), "Allocator for vector<unique_ptr<CommandContext>>")),
m_AvailableContexts(STD_ALLOCATOR_RAW_MEM(CommandContext*, GetRawAllocator(), "Allocator for vector<CommandContext*>")),*/
- m_VkObjReleaseQueue(STD_ALLOCATOR_RAW_MEM(ReleaseQueueElemType, GetRawAllocator(), "Allocator for queue<ReleaseQueueElemType>")),
- m_StaleVkObjects(STD_ALLOCATOR_RAW_MEM(ReleaseQueueElemType, GetRawAllocator(), "Allocator for queue<ReleaseQueueElemType>")),
m_DescriptorPools(STD_ALLOCATOR_RAW_MEM(DescriptorPoolManager, GetRawAllocator(), "Allocator for vector<DescriptorPoolManager>")),
m_UploadHeaps(STD_ALLOCATOR_RAW_MEM(VulkanUtilities::VulkanUploadHeap, GetRawAllocator(), "Allocator for vector<VulkanUploadHeap>")),
m_FramebufferCache(*this),
m_TransientCmdPoolMgr(*m_LogicalVkDevice, pCmdQueue->GetQueueFamilyIndex(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT),
- m_MemoryMgr("Global resource memory manager", *m_LogicalVkDevice, *m_PhysicalDevice, GetRawAllocator(), CreationAttribs.DeviceLocalMemoryPageSize, CreationAttribs.HostVisibleMemoryPageSize, CreationAttribs.DeviceLocalMemoryReserveSize, CreationAttribs.HostVisibleMemoryReserveSize)
+ m_MemoryMgr("Global resource memory manager", *m_LogicalVkDevice, *m_PhysicalDevice, GetRawAllocator(), CreationAttribs.DeviceLocalMemoryPageSize, CreationAttribs.HostVisibleMemoryPageSize, CreationAttribs.DeviceLocalMemoryReserveSize, CreationAttribs.HostVisibleMemoryReserveSize),
+ m_ReleaseQueue(GetRawAllocator())
{
m_DeviceCaps.DevType = DeviceType::Vulkan;
m_DeviceCaps.MajorVersion = 1;
@@ -142,9 +141,6 @@ RenderDeviceVkImpl::~RenderDeviceVkImpl()
m_ContextPool.clear();
#endif
- VERIFY(m_StaleVkObjects.empty(), "Not all stale objects were destroyed");
- VERIFY(m_VkObjReleaseQueue.empty(), "Release queue is not empty");
-
m_TransientCmdPoolMgr.DestroyPools(m_pCommandQueue->GetCompletedFenceValue());
//if(m_PhysicalDevice)
@@ -265,7 +261,7 @@ void RenderDeviceVkImpl::ExecuteCommandBuffer(const VkSubmitInfo &SubmitInfo, De
// As long as resources used by deferred contexts are not released until the command list
// is executed through immediate context, this stategy always works.
- DiscardStaleVkObjects(SubmittedCmdBuffNumber, SubmittedFenceValue);
+ m_ReleaseQueue.DiscardStaleResources(SubmittedCmdBuffNumber, SubmittedFenceValue);
auto CompletedFenceValue = GetCompletedFenceValue();
ProcessReleaseQueue(CompletedFenceValue);
m_MemoryMgr.ShrinkMemory();
@@ -310,7 +306,7 @@ void RenderDeviceVkImpl::IdleGPU(bool ReleaseStaleObjects)
// This is necessary to release outstanding references to the
// swap chain buffers when it is resized in the middle of the frame.
// Since GPU has been idled, it it is safe to do so
- DiscardStaleVkObjects(CmdBuffNumber, FenceValue);
+ m_ReleaseQueue.DiscardStaleResources(CmdBuffNumber, FenceValue);
// FenceValue has now been signaled by the GPU since we waited for it
auto CompletedFenceValue = FenceValue;
ProcessReleaseQueue(CompletedFenceValue);
@@ -408,95 +404,17 @@ void RenderDeviceVkImpl::FinishFrame(bool ReleaseAllResources)
// Discard all remaining objects. This is important to do if there were
// no command lists submitted during the frame
- DiscardStaleVkObjects(CmdBuffNumber, NextFenceValue);
+ m_ReleaseQueue.DiscardStaleResources(CmdBuffNumber, NextFenceValue);
ProcessReleaseQueue(CompletedFenceValue);
m_MemoryMgr.ShrinkMemory();
Atomics::AtomicIncrement(m_FrameNumber);
}
-template<typename ObjectType>
-void RenderDeviceVkImpl::SafeReleaseVkObject(ObjectType&& vkObject)
-{
- class StaleVulkanObject : public RenderDeviceVkImpl::StaleVulkanObjectBase
- {
- public:
- StaleVulkanObject(ObjectType&& Object) :
- m_VkObject(std::move(Object))
- {}
-
- StaleVulkanObject (const StaleVulkanObject&) = delete;
- StaleVulkanObject (StaleVulkanObject&&) = delete;
- StaleVulkanObject& operator = (const StaleVulkanObject&) = delete;
- StaleVulkanObject& operator = (StaleVulkanObject&&) = delete;
-
- private:
- ObjectType m_VkObject;
- };
-
- // When Vk object is released, it is first moved into the
- // stale objects list. The list is moved into a release queue
- // after the next command list is executed.
- std::lock_guard<std::mutex> LockGuard(m_StaleObjectsMutex);
- m_StaleVkObjects.emplace_back(m_NextCmdBuffNumber, new StaleVulkanObject{std::move(vkObject)} );
-}
-
-#define INSTANTIATE_SAFE_RELEASE_VK_OBJECT(Type) template void RenderDeviceVkImpl::SafeReleaseVkObject<Type>(Type &&Object)
-
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::BufferWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::BufferViewWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::ImageWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::ImageViewWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::SamplerWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::DeviceMemoryWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::RenderPassWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::PipelineWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::ShaderModuleWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::PipelineLayoutWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::FramebufferWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::DescriptorPoolWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::DescriptorSetLayoutWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::SemaphoreWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::CommandPoolWrapper);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::VulkanMemoryAllocation);
-INSTANTIATE_SAFE_RELEASE_VK_OBJECT(VulkanUtilities::VulkanUploadAllocation);
-
-#undef INSTANTIATE_SAFE_RELEASE_VK_OBJECT
-
-void RenderDeviceVkImpl::DiscardStaleVkObjects(Uint64 CmdBuffNumber, Uint64 FenceValue)
-{
- // Only discard these stale objects that were released before CmdBuffNumber
- // was executed
- std::lock_guard<std::mutex> StaleObjectsLock(m_StaleObjectsMutex);
- std::lock_guard<std::mutex> ReleaseQueueLock(m_ReleaseQueueMutex);
- while (!m_StaleVkObjects.empty() )
- {
- auto &FirstStaleObj = m_StaleVkObjects.front();
- if (FirstStaleObj.first <= CmdBuffNumber)
- {
- m_VkObjReleaseQueue.emplace_back(FenceValue, std::move(FirstStaleObj.second));
- m_StaleVkObjects.pop_front();
- }
- else
- break;
- }
-}
void RenderDeviceVkImpl::ProcessReleaseQueue(Uint64 CompletedFenceValue)
{
- {
- std::lock_guard<std::mutex> LockGuard(m_ReleaseQueueMutex);
-
- // Release all objects whose associated fence value is at most CompletedFenceValue
- while (!m_VkObjReleaseQueue.empty())
- {
- auto &FirstObj = m_VkObjReleaseQueue.front();
- if (FirstObj.first <= CompletedFenceValue)
- m_VkObjReleaseQueue.pop_front();
- else
- break;
- }
- }
+ m_ReleaseQueue.Purge(CompletedFenceValue);
{
// This is OK if other thread disposes descriptor heap allocation at this time