summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-10-03 14:52:06 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-10-03 14:52:06 +0000
commit588ecd05de0bd124d5210018c06be26838d689cf (patch)
tree3a9eb08a74e5033d6c4df2291867fe62652857ca /Graphics/GraphicsEngineD3D12
parentReworked D3D12DynamicHeap to use release queues (diff)
downloadDiligentCore-588ecd05de0bd124d5210018c06be26838d689cf.tar.gz
DiligentCore-588ecd05de0bd124d5210018c06be26838d689cf.zip
Reworked D3D12 descriptor heaps to rely on device release queues
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/include/CommandContext.h20
-rw-r--r--Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.h10
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h217
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h6
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h13
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/RenderDeviceD3D12.h9
-rw-r--r--Graphics/GraphicsEngineD3D12/src/CommandContext.cpp20
-rw-r--r--Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp10
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp308
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp51
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp72
-rw-r--r--Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp2
12 files changed, 363 insertions, 375 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/CommandContext.h b/Graphics/GraphicsEngineD3D12/include/CommandContext.h
index ac69e906..13fd65eb 100644
--- a/Graphics/GraphicsEngineD3D12/include/CommandContext.h
+++ b/Graphics/GraphicsEngineD3D12/include/CommandContext.h
@@ -59,10 +59,7 @@ class CommandContext
{
public:
- CommandContext( IMemoryAllocator &MemAllocator,
- class CommandListManager& CmdListManager,
- GPUDescriptorHeap GPUDescriptorHeaps[],
- const Uint32 DynamicDescriptorAllocationChunkSize[]);
+ CommandContext( class CommandListManager& CmdListManager);
~CommandContext(void);
@@ -115,7 +112,6 @@ public:
void SetID(const Char* ID) { m_ID = ID; }
ID3D12GraphicsCommandList *GetCommandList(){return m_pCommandList;}
- void DiscardDynamicDescriptors(Uint64 FenceValue);
DescriptorHeapAllocation AllocateDynamicGPUVisibleDescriptor( D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count = 1 );
void InsertUAVBarrier(D3D12ResourceBase& Resource, IDeviceObject &Object, bool FlushImmediate = false);
@@ -128,6 +124,11 @@ public:
}
}
+ void SetDynamicGPUDescriptorAllocators(DynamicSuballocationsManager* Allocators)
+ {
+ m_DynamicGPUDescriptorAllocators = Allocators;
+ }
+
protected:
void TransitionResource(D3D12ResourceBase& Resource, IDeviceObject &Object, D3D12_RESOURCE_STATES NewState, bool FlushImmediate);
void InsertAliasBarrier(D3D12ResourceBase& Before, D3D12ResourceBase& After, IDeviceObject &BeforeObj, IDeviceObject &AfterObj, bool FlushImmediate = false);
@@ -135,9 +136,9 @@ protected:
CComPtr<ID3D12GraphicsCommandList> m_pCommandList;
CComPtr<ID3D12CommandAllocator> m_pCurrentAllocator;
- ID3D12PipelineState* m_pCurPipelineState = nullptr;
+ ID3D12PipelineState* m_pCurPipelineState = nullptr;
ID3D12RootSignature* m_pCurGraphicsRootSignature = nullptr;
- ID3D12RootSignature* m_pCurComputeRootSignature = nullptr;
+ ID3D12RootSignature* m_pCurComputeRootSignature = nullptr;
static constexpr int MaxPendingBarriers = 16;
std::vector<D3D12_RESOURCE_BARRIER, STDAllocatorRawMem<D3D12_RESOURCE_BARRIER> > m_PendingResourceBarriers;
@@ -149,10 +150,7 @@ protected:
ShaderDescriptorHeaps m_BoundDescriptorHeaps;
- // Every context must use its own allocator that maintains individual list of retired descriptor heaps to
- // avoid interference with other command contexts
- // The heaps can only be discarded after the command list is submitted for execution
- DynamicSuballocationsManager m_DynamicGPUDescriptorAllocator[2];
+ DynamicSuballocationsManager* m_DynamicGPUDescriptorAllocators = nullptr;
String m_ID;
diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.h b/Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.h
index a7d54d27..f251d814 100644
--- a/Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.h
+++ b/Graphics/GraphicsEngineD3D12/include/D3D12DynamicHeap.h
@@ -151,9 +151,9 @@ class D3D12DynamicHeap
{
public:
D3D12DynamicHeap(D3D12DynamicMemoryManager& DynamicMemMgr, std::string HeapName, Uint64 PageSize) :
- m_DynamicMemMgr (DynamicMemMgr),
- m_HeapName (std::move(HeapName)),
- m_PageSize (PageSize)
+ m_GlobalDynamicMemMgr (DynamicMemMgr),
+ m_HeapName (std::move(HeapName)),
+ m_PageSize (PageSize)
{}
D3D12DynamicHeap (const D3D12DynamicHeap&) = delete;
@@ -168,8 +168,10 @@ public:
static constexpr Uint64 InvalidOffset = static_cast<Uint64>(-1);
+ size_t GetAllocatedPagesCount() const {return m_AllocatedPages.size();}
+
private:
- D3D12DynamicMemoryManager& m_DynamicMemMgr;
+ D3D12DynamicMemoryManager& m_GlobalDynamicMemMgr;
const std::string m_HeapName;
std::vector<D3D12DynamicPage> m_AllocatedPages;
diff --git a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h
index 859b0cad..a4dfa0e9 100644
--- a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h
+++ b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h
@@ -30,9 +30,10 @@
#include <vector>
#include <queue>
#include <string>
-#include <set>
+#include <unordered_set>
+#include <atomic>
#include "ObjectBase.h"
-#include "VariableSizeGPUAllocationsManager.h"
+#include "VariableSizeAllocationsManager.h"
namespace Diligent
{
@@ -46,7 +47,7 @@ class IDescriptorAllocator
public:
// Allocate Count descriptors
virtual DescriptorHeapAllocation Allocate( uint32_t Count ) = 0;
- virtual void Free(DescriptorHeapAllocation&& Allocation) = 0;
+ virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask) = 0;
virtual Uint32 GetDescriptorSize()const = 0;
};
@@ -63,7 +64,7 @@ class DescriptorHeapAllocation
{
public:
// Creates null allocation
- DescriptorHeapAllocation()noexcept :
+ DescriptorHeapAllocation() noexcept :
m_NumHandles (1), // One null descriptor handle
m_pDescriptorHeap (nullptr),
m_DescriptorSize (0)
@@ -73,7 +74,7 @@ public:
}
// Initializes non-null allocation
- DescriptorHeapAllocation( IDescriptorAllocator* pAllocator,
+ DescriptorHeapAllocation( IDescriptorAllocator& Allocator,
ID3D12DescriptorHeap* pHeap,
D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle,
@@ -81,7 +82,7 @@ public:
Uint16 AllocationManagerId = static_cast<Uint16>(-1) )noexcept :
m_FirstCpuHandle (CpuHandle),
m_FirstGpuHandle (GpuHandle),
- m_pAllocator (pAllocator),
+ m_pAllocator (&Allocator),
m_NumHandles (NHandles),
m_pDescriptorHeap (pHeap),
m_AllocationManagerId (AllocationManagerId)
@@ -94,45 +95,44 @@ public:
// Move constructor (copy is not allowed)
DescriptorHeapAllocation(DescriptorHeapAllocation&& Allocation)noexcept :
- m_FirstCpuHandle (Allocation.m_FirstCpuHandle),
- m_FirstGpuHandle (Allocation.m_FirstGpuHandle),
- m_NumHandles (Allocation.m_NumHandles),
+ m_FirstCpuHandle (std::move(Allocation.m_FirstCpuHandle)),
+ m_FirstGpuHandle (std::move(Allocation.m_FirstGpuHandle)),
+ m_NumHandles (std::move(Allocation.m_NumHandles)),
m_pAllocator (std::move(Allocation.m_pAllocator)),
m_AllocationManagerId (std::move(Allocation.m_AllocationManagerId)),
m_pDescriptorHeap (std::move(Allocation.m_pDescriptorHeap) ),
m_DescriptorSize (std::move(Allocation.m_DescriptorSize) )
{
- Allocation.m_pAllocator = nullptr;
- Allocation.m_FirstCpuHandle.ptr = 0;
- Allocation.m_FirstGpuHandle.ptr = 0;
- Allocation.m_NumHandles = 0;
- Allocation.m_pDescriptorHeap = nullptr;
- Allocation.m_DescriptorSize = 0;
- Allocation.m_AllocationManagerId = static_cast<Uint16>(-1);
+ Allocation.Reset();
}
// Move assignment (assignment is not allowed)
DescriptorHeapAllocation& operator = (DescriptorHeapAllocation&& Allocation)noexcept
{
- m_FirstCpuHandle = Allocation.m_FirstCpuHandle;
- m_FirstGpuHandle = Allocation.m_FirstGpuHandle;
- m_NumHandles = Allocation.m_NumHandles;
+ m_FirstCpuHandle = std::move(Allocation.m_FirstCpuHandle);
+ m_FirstGpuHandle = std::move(Allocation.m_FirstGpuHandle);
+ m_NumHandles = std::move(Allocation.m_NumHandles);
m_pAllocator = std::move(Allocation.m_pAllocator);
m_AllocationManagerId = std::move(Allocation.m_AllocationManagerId);
m_pDescriptorHeap = std::move(Allocation.m_pDescriptorHeap);
m_DescriptorSize = std::move(Allocation.m_DescriptorSize);
- Allocation.m_FirstCpuHandle.ptr = 0;
- Allocation.m_FirstGpuHandle.ptr = 0;
- Allocation.m_NumHandles = 0;
- Allocation.m_pAllocator = nullptr;
- Allocation.m_pDescriptorHeap = nullptr;
- Allocation.m_DescriptorSize = 0;
- Allocation.m_AllocationManagerId = static_cast<Uint16>(-1);
+ Allocation.Reset();
return *this;
}
+ void Reset()
+ {
+ m_FirstCpuHandle.ptr = 0;
+ m_FirstGpuHandle.ptr = 0;
+ m_pAllocator = nullptr;
+ m_pDescriptorHeap = nullptr;
+ m_NumHandles = 0;
+ m_AllocationManagerId = static_cast<Uint16>(-1);
+ m_DescriptorSize = 0;
+ }
+
// No copies, only moves are allowed
DescriptorHeapAllocation (const DescriptorHeapAllocation&) = delete;
DescriptorHeapAllocation& operator= (const DescriptorHeapAllocation&) = delete;
@@ -142,7 +142,7 @@ public:
~DescriptorHeapAllocation()
{
if(!IsNull() && m_pAllocator)
- m_pAllocator->Free(std::move(*this));
+ m_pAllocator->Free(std::move(*this), ~Uint64{0});
// Allocation must have been disposed by the allocator
VERIFY(IsNull(), "Non-null descriptor is being destroyed");
}
@@ -153,10 +153,8 @@ public:
VERIFY_EXPR(Offset >= 0 && Offset < m_NumHandles);
D3D12_CPU_DESCRIPTOR_HANDLE CPUHandle = m_FirstCpuHandle;
- if (Offset != 0)
- {
- CPUHandle.ptr += m_DescriptorSize * Offset;
- }
+ CPUHandle.ptr += m_DescriptorSize * Offset;
+
return CPUHandle;
}
@@ -165,22 +163,20 @@ public:
{
VERIFY_EXPR(Offset >= 0 && Offset < m_NumHandles);
D3D12_GPU_DESCRIPTOR_HANDLE GPUHandle = m_FirstGpuHandle;
- if (Offset != 0)
- {
- GPUHandle.ptr += m_DescriptorSize * Offset;
- }
+ GPUHandle.ptr += m_DescriptorSize * Offset;
+
return GPUHandle;
}
// Returns pointer to D3D12 descriptor heap that contains this allocation
- ID3D12DescriptorHeap *GetDescriptorHeap(){return m_pDescriptorHeap;}
-
- size_t GetNumHandles()const{return m_NumHandles;}
+ ID3D12DescriptorHeap* GetDescriptorHeap(){return m_pDescriptorHeap;}
- bool IsNull() const { return m_FirstCpuHandle.ptr == 0; }
- bool IsShaderVisible() const { return m_FirstGpuHandle.ptr != 0; }
- size_t GetAllocationManagerId()const { return m_AllocationManagerId; }
- UINT GetDescriptorSize() const { return m_DescriptorSize; }
+
+ size_t GetNumHandles() const { return m_NumHandles; }
+ bool IsNull() const { return m_FirstCpuHandle.ptr == 0; }
+ bool IsShaderVisible() const { return m_FirstGpuHandle.ptr != 0; }
+ size_t GetAllocationManagerId() const { return m_AllocationManagerId; }
+ UINT GetDescriptorSize() const { return m_DescriptorSize; }
private:
@@ -226,16 +222,16 @@ class DescriptorHeapAllocationManager
public:
// Creates a new D3D12 descriptor heap
DescriptorHeapAllocationManager(IMemoryAllocator& Allocator,
- RenderDeviceD3D12Impl* pDeviceD3D12Impl,
- IDescriptorAllocator* pParentAllocator,
+ RenderDeviceD3D12Impl& DeviceD3D12Impl,
+ IDescriptorAllocator& ParentAllocator,
size_t ThisManagerId,
const D3D12_DESCRIPTOR_HEAP_DESC& HeapDesc);
// Uses subrange of descriptors in the existing D3D12 descriptor heap
// that starts at offset FirstDescriptor and uses NumDescriptors descriptors
DescriptorHeapAllocationManager(IMemoryAllocator& Allocator,
- RenderDeviceD3D12Impl* pDeviceD3D12Impl,
- IDescriptorAllocator* pParentAllocator,
+ RenderDeviceD3D12Impl& DeviceD3D12Impl,
+ IDescriptorAllocator& ParentAllocator,
size_t ThisManagerId,
ID3D12DescriptorHeap* pd3d12DescriptorHeap,
Uint32 FirstDescriptor,
@@ -253,8 +249,8 @@ public:
m_NumDescriptorsInAllocation(rhs.m_NumDescriptorsInAllocation),
// Mutex is not movable
//m_AllocationMutex(std::move(rhs.m_AllocationMutex))
- m_pDeviceD3D12Impl (rhs.m_pDeviceD3D12Impl),
- m_pParentAllocator (rhs.m_pParentAllocator),
+ m_DeviceD3D12Impl (rhs.m_DeviceD3D12Impl),
+ m_ParentAllocator (rhs.m_ParentAllocator),
m_ThisManagerId (rhs.m_ThisManagerId)
{
rhs.m_FirstCPUHandle.ptr = 0;
@@ -262,9 +258,11 @@ public:
rhs.m_DescriptorSize = 0;
rhs.m_NumDescriptorsInAllocation = 0;
rhs.m_HeapDesc.NumDescriptors = 0;
- rhs.m_pDeviceD3D12Impl = nullptr;
- rhs.m_pParentAllocator = nullptr;
rhs.m_ThisManagerId = static_cast<size_t>(-1);
+#ifdef DEVELOPMENT
+ m_AllocationsCounter.store(rhs.m_AllocationsCounter.load());
+ rhs.m_AllocationsCounter = 0;
+#endif
}
// No copies or move-assignments
@@ -276,24 +274,19 @@ public:
// Allocates Count descriptors
DescriptorHeapAllocation Allocate( uint32_t Count );
-
- // Releases descriptor heap allocation.
- // Note that the allocation is not released immediately, but
- // added to the release queue in the allocations manager
- void Free(DescriptorHeapAllocation&& Allocation);
-
- // Releases all stale allocation used by completed command lists
- // The method takes the last known completed fence value N
- // and releases all allocations whose associated fence value n <= N
- void ReleaseStaleAllocations(Uint64 LastCompletedFenceValue);
+ void FreeAllocation(DescriptorHeapAllocation&& Allocation);
+
+ size_t GetNumAvailableDescriptors()const { return m_FreeBlockManager.GetFreeSize(); }
+ Uint32 GetMaxDescriptors() const { return m_NumDescriptorsInAllocation; }
+ size_t GetMaxAllocatedSize() const { return m_MaxAllocatedSize; }
- size_t GetNumAvailableDescriptors()const { return m_FreeBlockManager.GetFreeSize(); }
- size_t GetNumStaleDescriptors() const { return m_FreeBlockManager.GetStaleAllocationsSize(); }
- Uint32 GetMaxDescriptors() const { return m_NumDescriptorsInAllocation; }
+#ifdef DEVELOPMENT
+ int32_t DvpGetAllocationsCounter() const { return m_AllocationsCounter; }
+#endif
private:
// Allocations manager used to handle descriptor allocations within the heap
- VariableSizeGPUAllocationsManager m_FreeBlockManager;
+ VariableSizeAllocationsManager m_FreeBlockManager;
// Heap description
D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
@@ -315,11 +308,17 @@ private:
Uint32 m_NumDescriptorsInAllocation = 0;
std::mutex m_AllocationMutex;
- RenderDeviceD3D12Impl* m_pDeviceD3D12Impl = nullptr;
- IDescriptorAllocator* m_pParentAllocator = nullptr;
+ RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
+ IDescriptorAllocator& m_ParentAllocator;
+ size_t m_MaxAllocatedSize = 0;
+
// External ID assigned to this descriptor allocations manager
size_t m_ThisManagerId = static_cast<size_t>(-1);
+
+#ifdef DEVELOPMENT
+ std::atomic_int32_t m_AllocationsCounter = 0;
+#endif
};
// CPU descriptor heap is intended to provide storage for resource view descriptor handles
@@ -339,12 +338,12 @@ private:
// Render device contains four CPUDescriptorHeap object instances (one for each D3D12 heap type). The heaps are accessed
// when a texture or a buffer view is created.
//
-class CPUDescriptorHeap : public IDescriptorAllocator
+class CPUDescriptorHeap final : public IDescriptorAllocator
{
public:
// Initializes the heap
CPUDescriptorHeap(IMemoryAllocator& Allocator,
- RenderDeviceD3D12Impl* pDeviceD3D12Impl,
+ RenderDeviceD3D12Impl& DeviceD3D12Impl,
Uint32 NumDescriptorsInHeap,
D3D12_DESCRIPTOR_HEAP_TYPE Type,
D3D12_DESCRIPTOR_HEAP_FLAGS Flags);
@@ -356,33 +355,27 @@ public:
~CPUDescriptorHeap();
- virtual DescriptorHeapAllocation Allocate( uint32_t Count )override;
- virtual void Free(DescriptorHeapAllocation&& Allocation)override;
- virtual Uint32 GetDescriptorSize()const override{return m_DescriptorSize;}
-
- // Releases all stale allocation used by completed command lists
- // The method takes the last known completed fence value N
- // and releases all allocations whose associated fence value n <= N
- void ReleaseStaleAllocations(Uint64 LastCompletedFenceValue);
+ virtual DescriptorHeapAllocation Allocate( uint32_t Count )override final ;
+ virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask)override final ;
+ virtual Uint32 GetDescriptorSize()const override final {return m_DescriptorSize;}
-protected:
+private:
+ void FreeAllocation(DescriptorHeapAllocation&& Allocation);
// Pool of descriptor heap managers
std::vector<DescriptorHeapAllocationManager, STDAllocatorRawMem<DescriptorHeapAllocationManager> > m_HeapPool;
// Indices of available descriptor heap managers
- std::set<size_t, std::less<size_t>, STDAllocatorRawMem<size_t> > m_AvailableHeaps;
+ std::unordered_set<size_t, std::hash<size_t>, std::equal_to<size_t>, STDAllocatorRawMem<size_t> > m_AvailableHeaps;
IMemoryAllocator &m_MemAllocator;
- std::mutex m_AllocationMutex;
+ std::mutex m_HeapPoolMutex;
D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
- RenderDeviceD3D12Impl *m_pDeviceD3D12Impl;
- UINT m_DescriptorSize;
-
+ RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
+ UINT m_DescriptorSize = 0;
// Maximum heap size during the application lifetime - for statistic purposes
- Uint32 m_MaxHeapSize = 0;
- Uint32 m_MaxStaleSize = 0;
- Uint32 m_CurrentSize = 0; // This size does not count stale allocation
+ Uint32 m_MaxSize = 0;
+ Uint32 m_CurrentSize = 0;
};
// GPU descriptor heap provides storage for shader-visible descriptors
@@ -424,11 +417,11 @@ protected:
// | m_DynamicGPUDescriptorAllocator[SAMPLER] | | m_DynamicGPUDescriptorAllocator[SAMPLER] |
// |________________________________________________| |________________________________________________|
//
-class GPUDescriptorHeap : public IDescriptorAllocator
+class GPUDescriptorHeap final : public IDescriptorAllocator
{
public:
GPUDescriptorHeap(IMemoryAllocator& Allocator,
- RenderDeviceD3D12Impl* pDevice,
+ RenderDeviceD3D12Impl& Device,
Uint32 NumDescriptorsInHeap,
Uint32 NumDynamicDescriptors,
D3D12_DESCRIPTOR_HEAP_TYPE Type,
@@ -441,16 +434,18 @@ public:
~GPUDescriptorHeap();
- virtual DescriptorHeapAllocation Allocate( uint32_t Count )override;
- virtual void Free(DescriptorHeapAllocation&& Allocation)override;
- virtual Uint32 GetDescriptorSize()const override{return m_DescriptorSize;}
+ virtual DescriptorHeapAllocation Allocate( uint32_t Count )override final
+ {
+ return m_HeapAllocationManager.Allocate(Count);
+ }
- DescriptorHeapAllocation AllocateDynamic( uint32_t Count );
+ virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask)override final;
+ virtual Uint32 GetDescriptorSize()const override final{return m_DescriptorSize;}
- // Releases all stale allocation used by completed command lists
- // The method takes the last known completed fence value N
- // and releases all allocations whose associated fence value n <= N
- void ReleaseStaleAllocations(Uint64 LastCompletedFenceValue);
+ DescriptorHeapAllocation AllocateDynamic( uint32_t Count )
+ {
+ return m_DynamicAllocationsManager.Allocate(Count);
+ }
const D3D12_DESCRIPTOR_HEAP_DESC &GetHeapDesc()const{return m_HeapDesc;}
Uint32 GetMaxStaticDescriptors() const { return m_HeapAllocationManager.GetMaxDescriptors(); }
@@ -461,24 +456,15 @@ protected:
D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
CComPtr<ID3D12DescriptorHeap> m_pd3d12DescriptorHeap;
- UINT m_DescriptorSize = 0;
+ const UINT m_DescriptorSize;
- std::mutex m_AllocMutex, m_DynAllocMutex;
// Allocation manager for static/mutable part
DescriptorHeapAllocationManager m_HeapAllocationManager;
// Allocation manager for dynamic part
DescriptorHeapAllocationManager m_DynamicAllocationsManager;
- RenderDeviceD3D12Impl *m_pDeviceD3D12;
- Uint32 m_CurrentSize = 0;
- // Maximum static/mutable part size during the application lifetime - for statistic purposes
- Uint32 m_MaxHeapSize = 0;
- Uint32 m_MaxStaleSize = 0;
- Uint32 m_CurrentDynamicSize = 0;
- // Maximum dynamic part size during the application lifetime - for statistic purposes
- Uint32 m_MaxDynamicSize = 0;
- Uint32 m_MaxDynamicStaleSize = 0;
+ RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
};
@@ -492,7 +478,7 @@ protected:
// | |
// m_Suballocations[0] m_Suballocations[1]
//
-class DynamicSuballocationsManager : public IDescriptorAllocator
+class DynamicSuballocationsManager final : public IDescriptorAllocator
{
public:
DynamicSuballocationsManager(IMemoryAllocator &Allocator, GPUDescriptorHeap& ParentGPUHeap, Uint32 DynamicChunkSize);
@@ -502,12 +488,19 @@ public:
DynamicSuballocationsManager& operator = (const DynamicSuballocationsManager&) = delete;
DynamicSuballocationsManager& operator = (DynamicSuballocationsManager&&) = delete;
- void DiscardAllocations(Uint64 /*FenceValue*/);
+ void ReleaseAllocations(Uint64 CmdQueueMask);
+
+ virtual DescriptorHeapAllocation Allocate(Uint32 Count)override final;
+ virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask)override final
+ {
+ // Do nothing. Dynamic allocations are not disposed individually, but as whole chunks
+ // at the end of the frame by ReleaseAllocations()
+ Allocation.Reset();
+ }
- virtual DescriptorHeapAllocation Allocate(Uint32 Count)override;
- virtual void Free(DescriptorHeapAllocation&& Allocation)override;
+ virtual Uint32 GetDescriptorSize()const override final{return m_ParentGPUHeap.GetDescriptorSize();}
- virtual Uint32 GetDescriptorSize()const override{return m_ParentGPUHeap.GetDescriptorSize();}
+ size_t GetSuballocationCount()const {return m_Suballocations.size();}
private:
// List of chunks allocated from the master GPU descriptor heap. All chunks are disposed at the end
@@ -518,7 +511,7 @@ private:
Uint32 m_DynamicChunkSize = 0;
// Parent GPU descriptor heap that is used to allocate chunks
- GPUDescriptorHeap &m_ParentGPUHeap;
+ GPUDescriptorHeap& m_ParentGPUHeap;
};
}
diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h
index a6dafd81..4136f517 100644
--- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h
+++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h
@@ -166,6 +166,7 @@ private:
void CommitViewports();
void CommitScissorRects(class GraphicsContext &GraphCtx, bool ScissorEnable);
void Flush(bool RequestNewCmdCtx);
+ void RequestCommandContext(RenderDeviceD3D12Impl* pDeviceD3D12Impl);
struct TextureUploadSpace
{
@@ -203,6 +204,11 @@ private:
GenerateMipsHelper m_MipsGenerator;
D3D12DynamicHeap m_DynamicHeap;
+ // Every context must use its own allocator that maintains individual list of retired descriptor heaps to
+ // avoid interference with other command contexts
+ // The allocations in heaps are discarded at the end of the frame.
+ DynamicSuballocationsManager m_DynamicGPUDescriptorAllocator[2];
+
/// Flag indicating if currently committed D3D12 vertex buffers are up to date
bool m_bCommittedD3D12VBsUpToDate = false;
diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
index a0c2d92d..85f39b5c 100644
--- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
+++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
@@ -85,11 +85,20 @@ public:
Uint64 CloseAndExecuteCommandContext(CommandContext *pCtx, bool DiscardStaleObjects, std::vector<std::pair<Uint64, RefCntAutoPtr<IFence> > >* pSignalFences);
void DisposeCommandContext(CommandContext*);
- void FinishFrame(bool ReleaseAllResources);
- virtual void FinishFrame()override final { FinishFrame(false); }
+ void FlushStaleResources(Uint32 CmdQueueIndex);
+ void ReleaseStaleResources(bool ForceRelease = false);
D3D12DynamicMemoryManager& GetDynamicMemoryManager() {return m_DynamicMemoryManager;}
+ GPUDescriptorHeap& GetGPUDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE Type)
+ {
+ return m_GPUDescriptorHeaps[Type];
+ }
+ Uint32 GetDynamicDescriptorAllocationChunkSize(D3D12_DESCRIPTOR_HEAP_TYPE Type)
+ {
+ return m_DynamicDescriptorAllocationChunkSize[Type];
+ }
+
private:
virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat )override final;
diff --git a/Graphics/GraphicsEngineD3D12/interface/RenderDeviceD3D12.h b/Graphics/GraphicsEngineD3D12/interface/RenderDeviceD3D12.h
index 1c97374c..c7d91a87 100644
--- a/Graphics/GraphicsEngineD3D12/interface/RenderDeviceD3D12.h
+++ b/Graphics/GraphicsEngineD3D12/interface/RenderDeviceD3D12.h
@@ -55,9 +55,12 @@ public:
/// that all associated work has been finished
virtual Bool IsFenceSignaled(Uint32 QueueIndex, Uint64 FenceValue) = 0;
- /// Should be called at the end of the frame when attached to existing D3D12 device
- /// Otherwise the method is automatically called before present
- virtual void FinishFrame() = 0;
+ /// Purges device release queues and releases all stale resources.
+ /// This method is automatically called by ISwapChain::Present().
+ /// \param [in] ForceRelease - Forces release of all objects. Use this option with
+ /// great care only if you are sure the resources are not
+ /// in use by the GPU (such as when the device has just been idled).
+ virtual void ReleaseStaleResources(bool ForceRelease = false) = 0;
/// Creates a texture object from native d3d12 resource
diff --git a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
index 4217b0c0..5010e1c6 100644
--- a/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/CommandContext.cpp
@@ -30,18 +30,10 @@
namespace Diligent
{
-CommandContext::CommandContext( IMemoryAllocator& MemAllocator,
- CommandListManager& CmdListManager,
- GPUDescriptorHeap GPUDescriptorHeaps[],
- const Uint32 DynamicDescriptorAllocationChunkSize[]) :
+CommandContext::CommandContext( CommandListManager& CmdListManager) :
m_pCurGraphicsRootSignature (nullptr),
m_pCurPipelineState (nullptr),
m_pCurComputeRootSignature (nullptr),
- m_DynamicGPUDescriptorAllocator
- {
- {MemAllocator, GPUDescriptorHeaps[0], DynamicDescriptorAllocationChunkSize[0]},
- {MemAllocator, GPUDescriptorHeaps[1], DynamicDescriptorAllocationChunkSize[1]}
- },
m_PendingResourceBarriers( STD_ALLOCATOR_RAW_MEM(D3D12_RESOURCE_BARRIER, GetRawAllocator(), "Allocator for vector<D3D12_RESOURCE_BARRIER>") ),
m_PendingBarrierObjects( STD_ALLOCATOR_RAW_MEM(RefCntAutoPtr<IDeviceObject>, GetRawAllocator(), "Allocator for vector<RefCntAutoPtr<IDeviceObject>>") )
{
@@ -75,6 +67,8 @@ void CommandContext::Reset( CommandListManager& CmdListManager )
m_PendingResourceBarriers.clear();
m_PendingBarrierObjects.clear();
m_BoundDescriptorHeaps = ShaderDescriptorHeaps();
+
+ m_DynamicGPUDescriptorAllocators = nullptr;
m_PrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
#if 0
@@ -298,16 +292,10 @@ void CommandContext::InsertAliasBarrier(D3D12ResourceBase& Before, D3D12Resource
FlushResourceBarriers();
}
-void CommandContext::DiscardDynamicDescriptors(Uint64 FenceValue)
-{
- for(size_t HeapType = 0; HeapType < _countof(m_DynamicGPUDescriptorAllocator); ++HeapType)
- m_DynamicGPUDescriptorAllocator[HeapType].DiscardAllocations(FenceValue);
-}
-
DescriptorHeapAllocation CommandContext::AllocateDynamicGPUVisibleDescriptor( D3D12_DESCRIPTOR_HEAP_TYPE Type, UINT Count )
{
VERIFY(Type >= D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV && Type <= D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, "Invalid heap type");
- return m_DynamicGPUDescriptorAllocator[Type].Allocate(Count);
+ return m_DynamicGPUDescriptorAllocators[Type].Allocate(Count);
}
}
diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp
index 6103e9b1..522c7512 100644
--- a/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/D3D12DynamicHeap.cpp
@@ -112,9 +112,9 @@ void D3D12DynamicMemoryManager::ReleasePages(std::vector<D3D12DynamicPage>& Page
D3D12DynamicPage Page;
D3D12DynamicMemoryManager* Mgr;
- StalePage(D3D12DynamicPage&& _Page, D3D12DynamicMemoryManager* _Mgr)noexcept :
+ StalePage(D3D12DynamicPage&& _Page, D3D12DynamicMemoryManager& _Mgr)noexcept :
Page (std::move(_Page)),
- Mgr (_Mgr)
+ Mgr (&_Mgr)
{
}
@@ -144,7 +144,7 @@ void D3D12DynamicMemoryManager::ReleasePages(std::vector<D3D12DynamicPage>& Page
};
for(auto& Page : Pages)
{
- m_DeviceD3D12Impl.SafeReleaseDeviceObject(StalePage{std::move(Page), this}, QueueMask);
+ m_DeviceD3D12Impl.SafeReleaseDeviceObject(StalePage{std::move(Page), *this}, QueueMask);
}
}
@@ -188,7 +188,7 @@ D3D12DynamicAllocation D3D12DynamicHeap::Allocate(Uint64 SizeInBytes, Uint64 Ali
while(NewPageSize < SizeInBytes)
NewPageSize *= 2;
- auto NewPage = m_DynamicMemMgr.AllocatePage(NewPageSize);
+ auto NewPage = m_GlobalDynamicMemMgr.AllocatePage(NewPageSize);
if (NewPage.IsValid())
{
m_CurrOffset = 0;
@@ -231,7 +231,7 @@ D3D12DynamicAllocation D3D12DynamicHeap::Allocate(Uint64 SizeInBytes, Uint64 Ali
void D3D12DynamicHeap::ReleaseAllocatedPages(Uint64 QueueMask)
{
- m_DynamicMemMgr.ReleasePages(m_AllocatedPages, QueueMask);
+ m_GlobalDynamicMemMgr.ReleasePages(m_AllocatedPages, QueueMask);
m_AllocatedPages.clear();
m_CurrOffset = InvalidOffset;
diff --git a/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp b/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
index d06edf85..a495b872 100644
--- a/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
@@ -31,18 +31,18 @@ namespace Diligent
// Creates a new descriptor heap and reference the entire heap
DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocator& Allocator,
- RenderDeviceD3D12Impl* pDeviceD3D12Impl,
- IDescriptorAllocator* pParentAllocator,
+ RenderDeviceD3D12Impl& DeviceD3D12Impl,
+ IDescriptorAllocator& ParentAllocator,
size_t ThisManagerId,
const D3D12_DESCRIPTOR_HEAP_DESC& HeapDesc) :
m_FreeBlockManager (HeapDesc.NumDescriptors, Allocator),
m_NumDescriptorsInAllocation (HeapDesc.NumDescriptors),
m_HeapDesc (HeapDesc),
- m_pDeviceD3D12Impl (pDeviceD3D12Impl),
- m_pParentAllocator (pParentAllocator),
+ m_DeviceD3D12Impl (DeviceD3D12Impl),
+ m_ParentAllocator (ParentAllocator),
m_ThisManagerId (ThisManagerId)
{
- auto pDevice = pDeviceD3D12Impl->GetD3D12Device();
+ auto pDevice = DeviceD3D12Impl.GetD3D12Device();
m_FirstCPUHandle.ptr = 0;
m_FirstGPUHandle.ptr = 0;
@@ -57,21 +57,21 @@ DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocato
// Uses subrange of descriptors in the existing D3D12 descriptor heap
// that starts at offset FirstDescriptor and uses NumDescriptors descriptors
DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocator& Allocator,
- RenderDeviceD3D12Impl* pDeviceD3D12Impl,
- IDescriptorAllocator* pParentAllocator,
+ RenderDeviceD3D12Impl& DeviceD3D12Impl,
+ IDescriptorAllocator& ParentAllocator,
size_t ThisManagerId,
ID3D12DescriptorHeap* pd3d12DescriptorHeap,
Uint32 FirstDescriptor,
Uint32 NumDescriptors):
m_FreeBlockManager (NumDescriptors, Allocator),
m_NumDescriptorsInAllocation (NumDescriptors),
- m_pDeviceD3D12Impl (pDeviceD3D12Impl),
- m_pParentAllocator (pParentAllocator),
+ m_DeviceD3D12Impl (DeviceD3D12Impl),
+ m_ParentAllocator (ParentAllocator),
m_ThisManagerId (ThisManagerId),
m_pd3d12DescriptorHeap (pd3d12DescriptorHeap)
{
m_HeapDesc = m_pd3d12DescriptorHeap->GetDesc();
- m_DescriptorSize = pDeviceD3D12Impl->GetD3D12Device()->GetDescriptorHandleIncrementSize(m_HeapDesc.Type);
+ m_DescriptorSize = DeviceD3D12Impl.GetD3D12Device()->GetDescriptorHandleIncrementSize(m_HeapDesc.Type);
m_FirstCPUHandle = pd3d12DescriptorHeap->GetCPUDescriptorHandleForHeapStart();
m_FirstCPUHandle.ptr += m_DescriptorSize * FirstDescriptor;
@@ -86,18 +86,21 @@ DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocato
DescriptorHeapAllocationManager::~DescriptorHeapAllocationManager()
{
- VERIFY(m_FreeBlockManager.GetFreeSize() == m_NumDescriptorsInAllocation, "Not all descriptors were released");
+ DEV_CHECK_ERR(m_AllocationsCounter == 0, m_AllocationsCounter, " allocations have not been released. If these allocations are referenced by release queue, the app will crash when DescriptorHeapAllocationManager::FreeAllocation() is called.");
+ DEV_CHECK_ERR(m_FreeBlockManager.GetFreeSize() == m_NumDescriptorsInAllocation, "Not all descriptors were released");
}
DescriptorHeapAllocation DescriptorHeapAllocationManager::Allocate(uint32_t Count)
{
+ VERIFY_EXPR(Count > 0);
+
std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
- // Methods of VariableSizeGPUAllocationsManager class are not thread safe!
+ // Methods of VariableSizeAllocationsManager class are not thread safe!
// Use variable-size GPU allocations manager to allocate the requested number of descriptors
auto Allocation = m_FreeBlockManager.Allocate(Count, 1);
auto DescriptorHandleOffset = Allocation.UnalignedOffset;
- if (DescriptorHandleOffset == VariableSizeGPUAllocationsManager::InvalidOffset)
+ if (DescriptorHandleOffset == VariableSizeAllocationsManager::InvalidOffset)
{
return DescriptorHeapAllocation{};
}
@@ -110,91 +113,77 @@ DescriptorHeapAllocation DescriptorHeapAllocationManager::Allocate(uint32_t Coun
CPUHandle.ptr += DescriptorHandleOffset * m_DescriptorSize;
auto GPUHandle = m_FirstGPUHandle; // Will be null if the heap is not GPU-visible
- if(m_HeapDesc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
+ if (m_HeapDesc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
GPUHandle.ptr += DescriptorHandleOffset * m_DescriptorSize;
+ m_MaxAllocatedSize = std::max(m_MaxAllocatedSize, m_FreeBlockManager.GetUsedSize());
+
VERIFY(m_ThisManagerId < std::numeric_limits<Uint16>::max(), "ManagerID exceeds 16-bit range");
- return DescriptorHeapAllocation( m_pParentAllocator, m_pd3d12DescriptorHeap, CPUHandle, GPUHandle, Count, static_cast<Uint16>(m_ThisManagerId));
+#ifdef DEVELOPMENT
+ ++m_AllocationsCounter;
+#endif
+ return DescriptorHeapAllocation( m_ParentAllocator, m_pd3d12DescriptorHeap, CPUHandle, GPUHandle, Count, static_cast<Uint16>(m_ThisManagerId));
}
-void DescriptorHeapAllocationManager::Free(DescriptorHeapAllocation&& Allocation)
+void DescriptorHeapAllocationManager::FreeAllocation(DescriptorHeapAllocation&& Allocation)
{
- std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
- // Methods of VariableSizeGPUAllocationsManager class are not thread safe!
-
VERIFY(Allocation.GetAllocationManagerId() == m_ThisManagerId, "Invalid descriptor heap manager Id");
-
- auto DescriptorOffset = (Allocation.GetCpuHandle().ptr - m_FirstCPUHandle.ptr) / m_DescriptorSize;
- // Note that the allocation is not released immediately, but added to the release queue in the allocations manager
-
- // The following basic requirement guarantees correctness of resource deallocation:
- //
- // A resource is never released before the last draw command referencing it is invoked on the immediate context
- //
- // See http://diligentgraphics.com/diligent-engine/architecture/d3d12/managing-resource-lifetimes/
- //
- // If basic requirement is met, GetNextFenceValue() will never return a number that is less than the fence value
- // associated with the last command list that references descriptors from the allocation
- // TODO: Rework
- m_FreeBlockManager.Free(DescriptorOffset, Allocation.GetNumHandles(), m_pDeviceD3D12Impl->GetNextFenceValue(0));
+ std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
+ auto DescriptorOffset = (Allocation.GetCpuHandle().ptr - m_FirstCPUHandle.ptr) / m_DescriptorSize;
+ // Methods of VariableSizeAllocationsManager class are not thread safe!
+ m_FreeBlockManager.Free(DescriptorOffset, Allocation.GetNumHandles());
// Clear the allocation
- Allocation = DescriptorHeapAllocation();
-}
-
-void DescriptorHeapAllocationManager::ReleaseStaleAllocations(Uint64 LastCompletedFenceValue)
-{
- std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
- // Methods of VariableSizeGPUAllocationsManager class are not thread safe!
-
- m_FreeBlockManager.ReleaseStaleAllocations(LastCompletedFenceValue);
+ Allocation.Reset();
+#ifdef DEVELOPMENT
+ --m_AllocationsCounter;
+#endif
}
-
//
// CPUDescriptorHeap implementation
//
CPUDescriptorHeap::CPUDescriptorHeap(IMemoryAllocator& Allocator,
- RenderDeviceD3D12Impl* pDeviceD3D12Impl,
+ RenderDeviceD3D12Impl& DeviceD3D12Impl,
Uint32 NumDescriptorsInHeap,
D3D12_DESCRIPTOR_HEAP_TYPE Type,
D3D12_DESCRIPTOR_HEAP_FLAGS Flags) :
- m_pDeviceD3D12Impl(pDeviceD3D12Impl),
+ m_DeviceD3D12Impl(DeviceD3D12Impl),
m_MemAllocator (Allocator),
m_HeapPool(STD_ALLOCATOR_RAW_MEM(DescriptorHeapAllocationManager, GetRawAllocator(), "Allocator for vector<DescriptorHeapAllocationManager>")),
- m_AvailableHeaps(STD_ALLOCATOR_RAW_MEM(size_t, GetRawAllocator(), "Allocator for set<size_t>"))
+ m_AvailableHeaps(STD_ALLOCATOR_RAW_MEM(size_t, GetRawAllocator(), "Allocator for unordered_set<size_t>"))
{
m_HeapDesc.Type = Type;
m_HeapDesc.NodeMask = 1;
m_HeapDesc.NumDescriptors = NumDescriptorsInHeap;
m_HeapDesc.Flags = Flags;
- m_DescriptorSize = m_pDeviceD3D12Impl->GetD3D12Device()->GetDescriptorHandleIncrementSize(Type);
+ m_DescriptorSize = m_DeviceD3D12Impl.GetD3D12Device()->GetDescriptorHandleIncrementSize(Type);
}
CPUDescriptorHeap::~CPUDescriptorHeap()
{
- VERIFY(m_CurrentSize == 0, "Not all allocations released" );
+ DEV_CHECK_ERR(m_CurrentSize == 0, "Not all allocations released" );
- VERIFY(m_AvailableHeaps.size() == m_HeapPool.size(), "Not all descriptor heap pools are released");
+ DEV_CHECK_ERR(m_AvailableHeaps.size() == m_HeapPool.size(), "Not all descriptor heap pools are released");
Uint32 TotalDescriptors = 0;
- for (auto HeapPoolIt = m_HeapPool.begin(); HeapPoolIt != m_HeapPool.end(); ++HeapPoolIt)
+ for (auto& Heap : m_HeapPool)
{
- VERIFY(HeapPoolIt->GetNumAvailableDescriptors() == HeapPoolIt->GetMaxDescriptors(), "Not all descriptors in the descriptor pool are released");
- TotalDescriptors += HeapPoolIt->GetMaxDescriptors();
+ DEV_CHECK_ERR(Heap.GetNumAvailableDescriptors() == Heap.GetMaxDescriptors(), "Not all descriptors in the descriptor pool are released");
+ TotalDescriptors += Heap.GetMaxDescriptors();
}
TotalDescriptors = std::max(TotalDescriptors, 1u);
- LOG_INFO_MESSAGE(GetD3D12DescriptorHeapTypeLiteralName(m_HeapDesc.Type), " CPU heap max size: ", m_MaxHeapSize, " (", m_MaxHeapSize*100/ TotalDescriptors, "%) "
- ". Max stale size: ", m_MaxStaleSize, " (", m_MaxStaleSize * 100 / TotalDescriptors, "%)");
+ LOG_INFO_MESSAGE(GetD3D12DescriptorHeapTypeLiteralName(m_HeapDesc.Type), " CPU heap allocated pool count: ", m_HeapPool.size(),
+ ". Max descriptors: ", m_MaxSize, '/', TotalDescriptors, " (", m_MaxSize*100/ TotalDescriptors, "%).");
}
DescriptorHeapAllocation CPUDescriptorHeap::Allocate( uint32_t Count )
{
- std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
+ std::lock_guard<std::mutex> LockGuard(m_HeapPoolMutex);
// Note that every DescriptorHeapAllocationManager object instance is itslef
// thread-safe. Nested mutexes cannot cause a deadlock
@@ -230,7 +219,7 @@ DescriptorHeapAllocation CPUDescriptorHeap::Allocate( uint32_t Count )
m_HeapDesc.NumDescriptors = std::max(m_HeapDesc.NumDescriptors, static_cast<UINT>(Count));
// Create a new descriptor heap manager. Note that this constructor creates a new D3D12 descriptor
// heap and references the entire heap. Pool index is used as manager ID
- m_HeapPool.emplace_back(m_MemAllocator, m_pDeviceD3D12Impl, this, m_HeapPool.size(), m_HeapDesc);
+ m_HeapPool.emplace_back(m_MemAllocator, m_DeviceD3D12Impl, *this, m_HeapPool.size(), m_HeapDesc);
auto NewHeapIt = m_AvailableHeaps.insert(m_HeapPool.size()-1);
// Use the new manager to allocate descriptor handles
@@ -238,47 +227,65 @@ DescriptorHeapAllocation CPUDescriptorHeap::Allocate( uint32_t Count )
}
m_CurrentSize += (Allocation.GetCpuHandle().ptr != 0) ? Count : 0;
- m_MaxHeapSize = std::max(m_MaxHeapSize, m_CurrentSize);
+ m_MaxSize = std::max(m_MaxSize, m_CurrentSize);
return Allocation;
}
-void CPUDescriptorHeap::Free(DescriptorHeapAllocation&& Allocation)
+// Method is called from ~DescriptorHeapAllocation()
+void CPUDescriptorHeap::Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask)
{
- // Method is called from ~DescriptorHeapAllocation()
- std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
- auto ManagerId = Allocation.GetAllocationManagerId();
- m_CurrentSize -= static_cast<Uint32>(Allocation.GetNumHandles());
- m_HeapPool[ManagerId].Free(std::move(Allocation));
-}
-
-void CPUDescriptorHeap::ReleaseStaleAllocations(Uint64 LastCompletedFenceValue)
-{
- std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
- size_t StaleSize = 0;
- for (size_t HeapManagerInd = 0; HeapManagerInd < m_HeapPool.size(); ++HeapManagerInd)
+ struct StaleAllocation
{
- // Update size before releasing stale allocations
- StaleSize += m_HeapPool[HeapManagerInd].GetNumStaleDescriptors();
+ DescriptorHeapAllocation Allocation;
+ CPUDescriptorHeap* Heap;
- m_HeapPool[HeapManagerInd].ReleaseStaleAllocations(LastCompletedFenceValue);
- // Return the manager to the pool of available managers if it has available descriptors
- if(m_HeapPool[HeapManagerInd].GetNumAvailableDescriptors() > 0)
- m_AvailableHeaps.insert(HeapManagerInd);
- }
- m_MaxStaleSize = std::max(m_MaxStaleSize, static_cast<Uint32>(StaleSize));
+ StaleAllocation(DescriptorHeapAllocation&& _Allocation, CPUDescriptorHeap& _Heap)noexcept :
+ Allocation(std::move(_Allocation)),
+ Heap (&_Heap)
+ {
+ }
+
+ StaleAllocation (const StaleAllocation&) = delete;
+ StaleAllocation& operator= (const StaleAllocation&) = delete;
+ StaleAllocation& operator= ( StaleAllocation&&) = delete;
+
+ StaleAllocation(StaleAllocation&& rhs)noexcept :
+ Allocation (std::move(rhs.Allocation)),
+ Heap (rhs.Heap)
+ {
+ rhs.Heap = nullptr;
+ }
+
+ ~StaleAllocation()
+ {
+ if (Heap != nullptr)
+ Heap->FreeAllocation(std::move(Allocation));
+ }
+ };
+ m_DeviceD3D12Impl.SafeReleaseDeviceObject(StaleAllocation{std::move(Allocation), *this}, CmdQueueMask);
}
+void CPUDescriptorHeap::FreeAllocation(DescriptorHeapAllocation&& Allocation)
+{
+ std::lock_guard<std::mutex> LockGuard(m_HeapPoolMutex);
+ auto ManagerId = Allocation.GetAllocationManagerId();
+ m_CurrentSize -= static_cast<Uint32>(Allocation.GetNumHandles());
+ m_HeapPool[ManagerId].FreeAllocation(std::move(Allocation));
+ // Return the manager to the pool of available managers
+ VERIFY_EXPR(m_HeapPool[ManagerId].GetNumAvailableDescriptors() > 0);
+ m_AvailableHeaps.insert(ManagerId);
+}
GPUDescriptorHeap::GPUDescriptorHeap(IMemoryAllocator& Allocator,
- RenderDeviceD3D12Impl* pDevice,
+ RenderDeviceD3D12Impl& Device,
Uint32 NumDescriptorsInHeap,
Uint32 NumDynamicDescriptors,
D3D12_DESCRIPTOR_HEAP_TYPE Type,
D3D12_DESCRIPTOR_HEAP_FLAGS Flags) :
- m_pDeviceD3D12(pDevice),
+ m_DeviceD3D12Impl(Device),
m_HeapDesc
{
Type,
@@ -286,93 +293,76 @@ GPUDescriptorHeap::GPUDescriptorHeap(IMemoryAllocator& Allocator,
Flags,
1 // UINT NodeMask;
},
- m_pd3d12DescriptorHeap([&]{
+ m_pd3d12DescriptorHeap(
+ [&]
+ {
CComPtr<ID3D12DescriptorHeap> pHeap;
- pDevice->GetD3D12Device()->CreateDescriptorHeap(&m_HeapDesc, __uuidof(pHeap), reinterpret_cast<void**>(&pHeap));
+ Device.GetD3D12Device()->CreateDescriptorHeap(&m_HeapDesc, __uuidof(pHeap), reinterpret_cast<void**>(&pHeap));
return pHeap;
- }()),
- m_DescriptorSize( pDevice->GetD3D12Device()->GetDescriptorHandleIncrementSize(Type) ),
- m_HeapAllocationManager(Allocator, pDevice, this, 0, m_pd3d12DescriptorHeap, 0, NumDescriptorsInHeap),
- m_DynamicAllocationsManager(Allocator, pDevice, this, 1, m_pd3d12DescriptorHeap, NumDescriptorsInHeap, NumDynamicDescriptors )
+ }()
+ ),
+ m_DescriptorSize( Device.GetD3D12Device()->GetDescriptorHandleIncrementSize(Type) ),
+ m_HeapAllocationManager(Allocator, Device, *this, 0, m_pd3d12DescriptorHeap, 0, NumDescriptorsInHeap),
+ m_DynamicAllocationsManager(Allocator, Device, *this, 1, m_pd3d12DescriptorHeap, NumDescriptorsInHeap, NumDynamicDescriptors )
{
}
GPUDescriptorHeap::~GPUDescriptorHeap()
{
- auto StaticSize = m_HeapAllocationManager.GetMaxDescriptors();
- auto DynamicSize = m_DynamicAllocationsManager.GetMaxDescriptors();
- LOG_INFO_MESSAGE(GetD3D12DescriptorHeapTypeLiteralName(m_HeapDesc.Type), " GPU heap max allocated size (static|dynamic): ",
- m_MaxHeapSize, " (", m_MaxHeapSize * 100 / StaticSize,"%) | ",
- m_MaxDynamicSize, " (", m_MaxDynamicSize * 100 / DynamicSize, "%). Max stale size (static|dynamic): ",
- m_MaxStaleSize, " (", m_MaxStaleSize * 100 / StaticSize, "%) | ",
- m_MaxDynamicStaleSize, " (", m_MaxDynamicStaleSize * 100 / DynamicSize, "%)");
-}
-
-DescriptorHeapAllocation GPUDescriptorHeap::Allocate(uint32_t Count)
-{
- VERIFY_EXPR(Count > 0);
- // Note: this mutex may be redundant as DescriptorHeapAllocationManager::Allocate() is itself thread-safe
- std::lock_guard<std::mutex> LockGuard(m_AllocMutex);
- DescriptorHeapAllocation Allocation = m_HeapAllocationManager.Allocate(Count);
- VERIFY(!Allocation.IsNull(), "Failed to allocate ", Count, " GPU descriptors");
-
- m_CurrentSize += (Allocation.GetCpuHandle().ptr != 0) ? Count : 0;
- m_MaxHeapSize = std::max(m_MaxHeapSize, m_CurrentSize);
-
- return Allocation;
-}
-
-DescriptorHeapAllocation GPUDescriptorHeap::AllocateDynamic(uint32_t Count)
-{
- VERIFY_EXPR(Count > 0);
- // Note: this mutex may be redundant as DescriptorHeapAllocationManager::Allocate() is itself thread-safe
- std::lock_guard<std::mutex> LockGuard(m_DynAllocMutex);
- DescriptorHeapAllocation Allocation = m_DynamicAllocationsManager.Allocate(Count);
- VERIFY(!Allocation.IsNull(), "Failed to allocate ", Count, " dynamic GPU descriptors");
-
- m_CurrentDynamicSize += (Allocation.GetCpuHandle().ptr != 0) ? Count : 0;
- m_MaxDynamicSize = std::max(m_MaxDynamicSize, m_CurrentDynamicSize);
-
- return Allocation;
-}
-
-void GPUDescriptorHeap::Free(DescriptorHeapAllocation&& Allocation)
-{
- auto MgrId = Allocation.GetAllocationManagerId();
- VERIFY(MgrId == 0 || MgrId == 1, "Unexpected allocation manager ID");
+ auto TotalStaticSize = m_HeapAllocationManager.GetMaxDescriptors();
+ auto TotalDynamicSize = m_DynamicAllocationsManager.GetMaxDescriptors();
+ auto MaxStaticSize = m_HeapAllocationManager.GetMaxAllocatedSize();
+ auto MaxDynamicSize = m_DynamicAllocationsManager.GetMaxAllocatedSize();
- // Note: mutexex may be redundant as DescriptorHeapAllocationManager::Free() is itself thread-safe
- if(MgrId == 0)
- {
- std::lock_guard<std::mutex> LockGuard(m_AllocMutex);
- m_CurrentSize -= static_cast<Uint32>(Allocation.GetNumHandles());
- m_HeapAllocationManager.Free(std::move(Allocation));
- }
- else
- {
- std::lock_guard<std::mutex> LockGuard(m_DynAllocMutex);
- m_CurrentDynamicSize -= static_cast<Uint32>(Allocation.GetNumHandles());
- m_DynamicAllocationsManager.Free(std::move(Allocation));
- }
+ LOG_INFO_MESSAGE(GetD3D12DescriptorHeapTypeLiteralName(m_HeapDesc.Type), " GPU heap max allocated size (static|dynamic): ",
+ MaxStaticSize, '/', TotalStaticSize, " (", MaxStaticSize * 100 / TotalStaticSize, "%) | ",
+ MaxDynamicSize, '/', TotalDynamicSize, " (", MaxDynamicSize * 100 / TotalDynamicSize, "%).");
}
-void GPUDescriptorHeap::ReleaseStaleAllocations(Uint64 LastCompletedFenceValue)
+void GPUDescriptorHeap::Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask)
{
+ struct StaleAllocation
{
- std::lock_guard<std::mutex> LockGuard(m_AllocMutex);
- m_MaxStaleSize = std::max(m_MaxStaleSize, static_cast<Uint32>(m_HeapAllocationManager.GetNumStaleDescriptors()));
- m_HeapAllocationManager.ReleaseStaleAllocations(LastCompletedFenceValue);
- }
-
- {
- std::lock_guard<std::mutex> LockGuard(m_DynAllocMutex);
- m_MaxDynamicStaleSize = std::max(m_MaxDynamicStaleSize, static_cast<Uint32>(m_DynamicAllocationsManager.GetNumStaleDescriptors()));
- m_DynamicAllocationsManager.ReleaseStaleAllocations(LastCompletedFenceValue);
- }
-}
+ DescriptorHeapAllocation Allocation;
+ GPUDescriptorHeap* Heap;
+ StaleAllocation(DescriptorHeapAllocation&& _Allocation, GPUDescriptorHeap& _Heap)noexcept :
+ Allocation(std::move(_Allocation)),
+ Heap (&_Heap)
+ {
+ }
+ StaleAllocation (const StaleAllocation&) = delete;
+ StaleAllocation& operator= (const StaleAllocation&) = delete;
+ StaleAllocation& operator= ( StaleAllocation&&) = delete;
+
+ StaleAllocation(StaleAllocation&& rhs)noexcept :
+ Allocation (std::move(rhs.Allocation)),
+ Heap (rhs.Heap)
+ {
+ rhs.Heap = nullptr;
+ }
+ ~StaleAllocation()
+ {
+ if (Heap != nullptr)
+ {
+ auto MgrId = Allocation.GetAllocationManagerId();
+ VERIFY(MgrId == 0 || MgrId == 1, "Unexpected allocation manager ID");
+
+ if (MgrId == 0)
+ {
+ Heap->m_HeapAllocationManager.FreeAllocation(std::move(Allocation));
+ }
+ else
+ {
+ Heap->m_DynamicAllocationsManager.FreeAllocation(std::move(Allocation));
+ }
+ }
+ }
+ };
+ m_DeviceD3D12Impl.SafeReleaseDeviceObject(StaleAllocation{std::move(Allocation), *this}, CmdQueueMask);
+}
DynamicSuballocationsManager::DynamicSuballocationsManager(IMemoryAllocator &Allocator, GPUDescriptorHeap& ParentGPUHeap, Uint32 DynamicChunkSize) :
@@ -382,10 +372,14 @@ DynamicSuballocationsManager::DynamicSuballocationsManager(IMemoryAllocator &All
{
}
-void DynamicSuballocationsManager::DiscardAllocations(Uint64 /*FenceValue*/)
+void DynamicSuballocationsManager::ReleaseAllocations(Uint64 CmdQueueMask)
{
// Clear the list and dispose all allocated chunks of GPU descriptor heap.
// The chunks will be added to the release queue in the allocations manager
+ for(auto& Allocation : m_Suballocations)
+ {
+ m_ParentGPUHeap.Free(std::move(Allocation), CmdQueueMask);
+ }
m_Suballocations.clear();
}
@@ -415,7 +409,7 @@ DescriptorHeapAllocation DynamicSuballocationsManager::Allocate(Uint32 Count)
auto ManagerId = CurrentSuballocation.GetAllocationManagerId();
VERIFY(ManagerId < std::numeric_limits<Uint16>::max(), "ManagerID exceed allowed limit");
- DescriptorHeapAllocation Allocation( this,
+ DescriptorHeapAllocation Allocation( *this,
CurrentSuballocation.GetDescriptorHeap(),
CurrentSuballocation.GetCpuHandle(m_CurrentSuballocationOffset),
CurrentSuballocation.GetGpuHandle(m_CurrentSuballocationOffset),
@@ -426,10 +420,4 @@ DescriptorHeapAllocation DynamicSuballocationsManager::Allocate(Uint32 Count)
return Allocation;
}
-void DynamicSuballocationsManager::Free(DescriptorHeapAllocation&& Allocation)
-{
- // Do nothing. Dynamic allocations are not disposed individually, but as whole chunks at the end of the frame
- Allocation = DescriptorHeapAllocation();
-}
-
}
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index 04bfa5eb..b98c526f 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -66,14 +66,33 @@ namespace Diligent
bIsDeferred ? std::numeric_limits<decltype(m_NumCommandsToFlush)>::max() : Attribs.NumCommandsToFlushCmdList,
bIsDeferred
},
- m_DynamicHeap(pDeviceD3D12Impl->GetDynamicMemoryManager(), GetDynamicHeapName(bIsDeferred, ContextId), Attribs.DynamicHeapPageSize),
+ m_DynamicHeap
+ {
+ pDeviceD3D12Impl->GetDynamicMemoryManager(),
+ GetDynamicHeapName(bIsDeferred, ContextId),
+ Attribs.DynamicHeapPageSize
+ },
+ m_DynamicGPUDescriptorAllocator
+ {
+ {
+ GetRawAllocator(),
+ pDeviceD3D12Impl->GetGPUDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV),
+ pDeviceD3D12Impl->GetDynamicDescriptorAllocationChunkSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
+ },
+ {
+ GetRawAllocator(),
+ pDeviceD3D12Impl->GetGPUDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER),
+ pDeviceD3D12Impl->GetDynamicDescriptorAllocationChunkSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER)
+ }
+ },
m_NumCommandsInCurCtx(0),
- m_pCurrCmdCtx(pDeviceD3D12Impl->AllocateCommandContext()),
m_CommittedIBFormat(VT_UNDEFINED),
m_CommittedD3D12IndexDataStartOffset(0),
m_MipsGenerator(pDeviceD3D12Impl->GetD3D12Device()),
m_CmdListAllocator(GetRawAllocator(), sizeof(CommandListD3D12Impl), 64 )
{
+ RequestCommandContext(pDeviceD3D12Impl);
+
auto *pd3d12Device = pDeviceD3D12Impl->GetD3D12Device();
D3D12_COMMAND_SIGNATURE_DESC CmdSignatureDesc = {};
@@ -109,6 +128,18 @@ namespace Diligent
Flush(false);
}
+
+ // Note: as dynamic pages are returned to the global dynamic memory manager hosted by the render device,
+ // the dynamic heap can be destroyed before all pages are actually returned to the global manager.
+ DEV_CHECK_ERR(m_DynamicHeap.GetAllocatedPagesCount() == 0, "All dynamic pages must have been released by now.");
+
+ for(size_t i=0; i < _countof(m_DynamicGPUDescriptorAllocator); ++i)
+ {
+ // Note: as dynamic decriptor suballocations are returned to the global GPU descriptor heap that
+ // is hosted by the render device, the descriptor allocator can be destroyed before all suballocations
+ // are actually returned to the global heap.
+ DEV_CHECK_ERR(m_DynamicGPUDescriptorAllocator[i].GetSuballocationCount() == 0, "All dynamic suballocations must have been released");
+ }
}
IMPLEMENT_QUERY_INTERFACE( DeviceContextD3D12Impl, IID_DeviceContextD3D12, TDeviceContextBase )
@@ -501,6 +532,12 @@ namespace Diligent
++m_NumCommandsInCurCtx;
}
+ void DeviceContextD3D12Impl::RequestCommandContext(RenderDeviceD3D12Impl* pDeviceD3D12Impl)
+ {
+ m_pCurrCmdCtx = pDeviceD3D12Impl->AllocateCommandContext();
+ m_pCurrCmdCtx->SetDynamicGPUDescriptorAllocators(m_DynamicGPUDescriptorAllocator);
+ }
+
void DeviceContextD3D12Impl::Flush(bool RequestNewCmdCtx)
{
auto pDeviceD3D12Impl = m_pDevice.RawPtr<RenderDeviceD3D12Impl>();
@@ -517,7 +554,8 @@ namespace Diligent
pDeviceD3D12Impl->DisposeCommandContext(m_pCurrCmdCtx);
}
- m_pCurrCmdCtx = RequestNewCmdCtx ? pDeviceD3D12Impl->AllocateCommandContext() : nullptr;
+ if(RequestNewCmdCtx)
+ RequestCommandContext(pDeviceD3D12Impl);
m_NumCommandsInCurCtx = 0;
m_CommittedD3D12IndexBuffer = nullptr;
@@ -538,8 +576,13 @@ namespace Diligent
void DeviceContextD3D12Impl::FinishFrame()
{
VERIFY_EXPR(m_bIsDeferred || m_SubmittedBuffersCmdQueueMask == (Uint64{1}<<m_CommandQueueId));
+
m_DynamicHeap.ReleaseAllocatedPages(m_SubmittedBuffersCmdQueueMask);
- EndFrame();
+
+ for(size_t i=0; i < _countof(m_DynamicGPUDescriptorAllocator); ++i)
+ m_DynamicGPUDescriptorAllocator[i].ReleaseAllocations(m_SubmittedBuffersCmdQueueMask);
+
+ EndFrame(*m_pDevice.RawPtr<RenderDeviceD3D12Impl>());
}
void DeviceContextD3D12Impl::SetVertexBuffers( Uint32 StartSlot, Uint32 NumBuffersSet, IBuffer** ppBuffers, Uint32* pOffsets, Uint32 Flags )
diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
index 993f1ac2..e4b07ab8 100644
--- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
@@ -66,15 +66,15 @@ RenderDeviceD3D12Impl :: RenderDeviceD3D12Impl(IReferenceCounters* pRef
m_CmdListManager(this),
m_CPUDescriptorHeaps
{
- {RawMemAllocator, this, CreationAttribs.CPUDescriptorHeapAllocationSize[0], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE},
- {RawMemAllocator, this, CreationAttribs.CPUDescriptorHeapAllocationSize[1], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE},
- {RawMemAllocator, this, CreationAttribs.CPUDescriptorHeapAllocationSize[2], D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE},
- {RawMemAllocator, this, CreationAttribs.CPUDescriptorHeapAllocationSize[3], D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE}
+ {RawMemAllocator, *this, CreationAttribs.CPUDescriptorHeapAllocationSize[0], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE},
+ {RawMemAllocator, *this, CreationAttribs.CPUDescriptorHeapAllocationSize[1], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE},
+ {RawMemAllocator, *this, CreationAttribs.CPUDescriptorHeapAllocationSize[2], D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE},
+ {RawMemAllocator, *this, CreationAttribs.CPUDescriptorHeapAllocationSize[3], D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE}
},
m_GPUDescriptorHeaps
{
- {RawMemAllocator, this, CreationAttribs.GPUDescriptorHeapSize[0], CreationAttribs.GPUDescriptorHeapDynamicSize[0], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE},
- {RawMemAllocator, this, CreationAttribs.GPUDescriptorHeapSize[1], CreationAttribs.GPUDescriptorHeapDynamicSize[1], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE}
+ {RawMemAllocator, *this, CreationAttribs.GPUDescriptorHeapSize[0], CreationAttribs.GPUDescriptorHeapDynamicSize[0], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE},
+ {RawMemAllocator, *this, CreationAttribs.GPUDescriptorHeapSize[1], CreationAttribs.GPUDescriptorHeapDynamicSize[1], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE}
},
m_DynamicDescriptorAllocationChunkSize
{
@@ -94,15 +94,9 @@ RenderDeviceD3D12Impl :: RenderDeviceD3D12Impl(IReferenceCounters* pRef
RenderDeviceD3D12Impl::~RenderDeviceD3D12Impl()
{
- // Finish current frame. This will release resources taken by previous frames, and
- // will move all stale resources to the release queues. The resources will not be
- // release until next call to FinishFrame()
- FinishFrame();
// Wait for the GPU to complete all its operations
IdleGPU(true);
- // Call FinishFrame() again to destroy resources in
- // release queues
- FinishFrame(true);
+ ReleaseStaleResources(true);
DEV_CHECK_ERR(m_DynamicMemoryManager.GetAllocatedPageCounter() == 0, "All allocated dynamic pages must have been returned to the manager at this point.");
m_DynamicMemoryManager.Destroy();
@@ -181,9 +175,6 @@ Uint64 RenderDeviceD3D12Impl::CloseAndExecuteCommandContext(CommandContext* pCtx
// DiscardAllocator() is thread-safe
// TODO: Rework
m_CmdListManager.DiscardAllocator(FenceValue, pAllocator);
-
- // TODO: Rework
- pCtx->DiscardDynamicDescriptors(FenceValue);
{
std::lock_guard<std::mutex> LockGuard(m_ContextAllocationMutex);
@@ -202,50 +193,17 @@ void RenderDeviceD3D12Impl::IdleGPU(bool ReleaseStaleObjects)
IdleCommandQueues(ReleaseStaleObjects);
}
-void RenderDeviceD3D12Impl::FinishFrame(bool ReleaseAllResources)
+void RenderDeviceD3D12Impl::FlushStaleResources(Uint32 CmdQueueIndex)
{
- // TODO: remove
- {
- if (auto pImmediateCtx = m_wpImmediateContext.Lock())
- {
- auto pImmediateCtxD3D12 = pImmediateCtx.RawPtr<DeviceContextD3D12Impl>();
- if(pImmediateCtxD3D12->GetNumCommandsInCtx() != 0)
- LOG_ERROR_MESSAGE("There are outstanding commands in the immediate device context when finishing the frame. This is an error and may cause unpredicted behaviour. Call Flush() to submit all commands for execution before finishing the frame");
- }
-
- for (auto wpDeferredCtx : m_wpDeferredContexts)
- {
- if (auto pDeferredCtx = wpDeferredCtx.Lock())
- {
- auto pDeferredCtxD3D12 = pDeferredCtx.RawPtr<DeviceContextD3D12Impl>();
- if(pDeferredCtxD3D12->GetNumCommandsInCtx() != 0)
- LOG_ERROR_MESSAGE("There are outstanding commands in the deferred device context when finishing the frame. This is an error and may cause unpredicted behaviour. Close all deferred contexts and execute them before finishing the frame");
- }
- }
- }
-
- // TODO: rework
- // Submit empty command list to set a fence on the GPU and increment command list number.
- // Discard all remaining objects which is important to do if there were
- // no command lists submitted during the frame
+ // Submit empty command list to the queue. This will effectively signal the fence and
+ // discard all resources
ID3D12GraphicsCommandList* pNullCmdList = nullptr;
TRenderDeviceBase::SubmitCommandBuffer(0, pNullCmdList, true);
+}
- auto CompletedFenceValue = ReleaseAllResources ? std::numeric_limits<Uint64>::max() : GetCompletedFenceValue(0);
-
- PurgeReleaseQueues(ReleaseAllResources);
-
- for(Uint32 CPUHeap=0; CPUHeap < _countof(m_CPUDescriptorHeaps); ++CPUHeap)
- {
- // This is OK if other thread disposes descriptor heap allocation at this time
- // The allocation will be registered as part of the current frame
- m_CPUDescriptorHeaps[CPUHeap].ReleaseStaleAllocations(CompletedFenceValue);
- }
-
- for(Uint32 GPUHeap=0; GPUHeap < _countof(m_GPUDescriptorHeaps); ++GPUHeap)
- {
- m_GPUDescriptorHeaps[GPUHeap].ReleaseStaleAllocations(CompletedFenceValue);
- }
+void RenderDeviceD3D12Impl::ReleaseStaleResources(bool ForceRelease)
+{
+ PurgeReleaseQueues(ForceRelease);
}
@@ -258,7 +216,7 @@ CommandContext* RenderDeviceD3D12Impl::AllocateCommandContext(const Char* ID)
{
auto &CmdCtxAllocator = GetRawAllocator();
auto *pRawMem = ALLOCATE(CmdCtxAllocator, "CommandContext instance", sizeof(CommandContext));
- ret = new (pRawMem) CommandContext( GetRawAllocator(), m_CmdListManager, m_GPUDescriptorHeaps, m_DynamicDescriptorAllocationChunkSize);
+ ret = new (pRawMem) CommandContext(m_CmdListManager);
m_ContextPool.emplace_back(ret, STDDeleterRawMem<CommandContext>(CmdCtxAllocator) );
}
else
diff --git a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp
index d9caef16..30a56b67 100644
--- a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp
@@ -132,7 +132,7 @@ void SwapChainD3D12Impl::Present(Uint32 SyncInterval)
VERIFY(SUCCEEDED(hr), "Present failed");
pImmediateCtxD3D12->FinishFrame();
- pDeviceD3D12->FinishFrame();
+ pDeviceD3D12->ReleaseStaleResources();
#if 0
#if PLATFORM_UNIVERSAL_WINDOWS