summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-10-06 20:17:26 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-10-06 20:17:26 +0000
commit1a8406ee55f95c44e9bb096c7954543f505b7a0d (patch)
tree806b9480a844e673ba8bd8d088ce42da008ba89e /Graphics/GraphicsEngineD3D12
parentFixed minor issue in PurgeReleaseQueues() (diff)
downloadDiligentCore-1a8406ee55f95c44e9bb096c7954543f505b7a0d.tar.gz
DiligentCore-1a8406ee55f95c44e9bb096c7954543f505b7a0d.zip
Some mostly cosmetic code changes + better reporting of dynamic descriptor allocation in D3D12 + some additional debug checks
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h133
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp112
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp21
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp11
4 files changed, 176 insertions, 101 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h
index a4dfa0e9..a9660cc9 100644
--- a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h
+++ b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.h
@@ -79,7 +79,7 @@ public:
D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle,
D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle,
Uint32 NHandles,
- Uint16 AllocationManagerId = static_cast<Uint16>(-1) )noexcept :
+ Uint16 AllocationManagerId )noexcept :
m_FirstCpuHandle (CpuHandle),
m_FirstGpuHandle (GpuHandle),
m_pAllocator (&Allocator),
@@ -210,7 +210,7 @@ private:
// The class performs suballocations within one D3D12 descriptor heap.
-// It uses VariableSizeGPUAllocationsManager to manage free space in the heap
+// It uses VariableSizeAllocationsManager to manage free space in the heap
//
// | X X X X O O O X X O O X O O O O | D3D12 descriptor heap
//
@@ -240,25 +240,25 @@ public:
// = default causes compiler error when instantiating std::vector::emplace_back() in Visual Studio 2015 (Version 14.0.23107.0 D14REL)
DescriptorHeapAllocationManager(DescriptorHeapAllocationManager&& rhs)noexcept :
- m_FreeBlockManager (std::move(rhs.m_FreeBlockManager)),
+ m_ParentAllocator (rhs.m_ParentAllocator),
+ m_DeviceD3D12Impl (rhs.m_DeviceD3D12Impl),
+ m_ThisManagerId (rhs.m_ThisManagerId),
m_HeapDesc (rhs.m_HeapDesc),
- m_pd3d12DescriptorHeap (std::move(rhs.m_pd3d12DescriptorHeap)),
- m_FirstCPUHandle (rhs.m_FirstCPUHandle),
- m_FirstGPUHandle (rhs.m_FirstGPUHandle),
m_DescriptorSize (rhs.m_DescriptorSize),
m_NumDescriptorsInAllocation(rhs.m_NumDescriptorsInAllocation),
+ m_FirstCPUHandle (rhs.m_FirstCPUHandle),
+ m_FirstGPUHandle (rhs.m_FirstGPUHandle),
+ m_MaxAllocatedSize (rhs.m_MaxAllocatedSize),
// Mutex is not movable
- //m_AllocationMutex(std::move(rhs.m_AllocationMutex))
- m_DeviceD3D12Impl (rhs.m_DeviceD3D12Impl),
- m_ParentAllocator (rhs.m_ParentAllocator),
- m_ThisManagerId (rhs.m_ThisManagerId)
+ //m_FreeBlockManagerMutex (std::move(rhs.m_FreeBlockManagerMutex))
+ m_FreeBlockManager (std::move(rhs.m_FreeBlockManager)),
+ m_pd3d12DescriptorHeap (std::move(rhs.m_pd3d12DescriptorHeap))
{
+ rhs.m_NumDescriptorsInAllocation = 0; // Must be set to zero so that debug check in dtor passes
+ rhs.m_ThisManagerId = static_cast<size_t>(-1);
rhs.m_FirstCPUHandle.ptr = 0;
rhs.m_FirstGPUHandle.ptr = 0;
- rhs.m_DescriptorSize = 0;
- rhs.m_NumDescriptorsInAllocation = 0;
- rhs.m_HeapDesc.NumDescriptors = 0;
- rhs.m_ThisManagerId = static_cast<size_t>(-1);
+ rhs.m_MaxAllocatedSize = 0;
#ifdef DEVELOPMENT
m_AllocationsCounter.store(rhs.m_AllocationsCounter.load());
rhs.m_AllocationsCounter = 0;
@@ -285,11 +285,25 @@ public:
#endif
private:
- // Allocations manager used to handle descriptor allocations within the heap
- VariableSizeAllocationsManager m_FreeBlockManager;
+ IDescriptorAllocator& m_ParentAllocator;
+ RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
+
+ // External ID assigned to this descriptor allocations manager
+ size_t m_ThisManagerId = static_cast<size_t>(-1);
// Heap description
- D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
+ const D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
+
+ const UINT m_DescriptorSize = 0;
+
+ // Number of descriptors in the allocation.
+ // If this manager was initialized as a subrange in the existing heap,
+ // this value may be different from m_HeapDesc.NumDescriptors
+ Uint32 m_NumDescriptorsInAllocation = 0;
+
+ // Allocations manager used to handle descriptor allocations within the heap
+ std::mutex m_FreeBlockManagerMutex;
+ VariableSizeAllocationsManager m_FreeBlockManager;
// Strong reference to D3D12 descriptor heap object
CComPtr<ID3D12DescriptorHeap> m_pd3d12DescriptorHeap;
@@ -300,28 +314,16 @@ private:
// First GPU descriptor handle in the available descriptor range
D3D12_GPU_DESCRIPTOR_HANDLE m_FirstGPUHandle = {0};
- UINT m_DescriptorSize = 0;
-
- // Number of descriptors in the allocation.
- // If this manager was initialized as a subrange in the existing heap,
- // this value may be different from m_HeapDesc.NumDescriptors
- Uint32 m_NumDescriptorsInAllocation = 0;
-
- std::mutex m_AllocationMutex;
- 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
+
+ // Note: when adding new members, do not forget to update move ctor
};
-// CPU descriptor heap is intended to provide storage for resource view descriptor handles
+// CPU descriptor heap is intended to provide storage for resource view descriptor handles.
// It contains a pool of DescriptorHeapAllocationManager object instances, where every instance manages
// its own CPU-only D3D12 descriptor heap:
//
@@ -355,35 +357,40 @@ public:
~CPUDescriptorHeap();
- virtual DescriptorHeapAllocation Allocate( uint32_t Count )override final ;
- virtual void Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask)override final ;
+ 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;}
+#ifdef DEVELOPMENT
+ int32_t DvpGetTotalAllocationCount();
+#endif
+
private:
void FreeAllocation(DescriptorHeapAllocation&& Allocation);
+ IMemoryAllocator& m_MemAllocator;
+ RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
+
// Pool of descriptor heap managers
- std::vector<DescriptorHeapAllocationManager, STDAllocatorRawMem<DescriptorHeapAllocationManager> > m_HeapPool;
+ std::mutex m_HeapPoolMutex;
+ std::vector<DescriptorHeapAllocationManager, STDAllocatorRawMem<DescriptorHeapAllocationManager>> m_HeapPool;
// Indices of available descriptor heap managers
- 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_HeapPoolMutex;
-
+ std::unordered_set<size_t, std::hash<size_t>, std::equal_to<size_t>, STDAllocatorRawMem<size_t>> m_AvailableHeaps;
+
D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
- RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
- UINT m_DescriptorSize = 0;
+ const UINT m_DescriptorSize = 0;
+
// Maximum heap size during the application lifetime - for statistic purposes
Uint32 m_MaxSize = 0;
Uint32 m_CurrentSize = 0;
};
// GPU descriptor heap provides storage for shader-visible descriptors
-// The heap contains single D3D12 descriptor heap that is broken into two parts.
+// The heap contains single D3D12 descriptor heap that is split into two parts.
// The first part stores static and mutable resource descriptor handles.
-// The second part is intended to provide temporary storage for dynamic resources
+// The second part is intended to provide temporary storage for dynamic resources.
// Space for dynamic resources is allocated in chunks, and then descriptors are suballocated within every
-// chunk. DynamicSuballocationsManager facilitates this process
+// chunk. DynamicSuballocationsManager facilitates this process.
//
//
// static and mutable handles || dynamic space
@@ -447,13 +454,22 @@ public:
return m_DynamicAllocationsManager.Allocate(Count);
}
- const D3D12_DESCRIPTOR_HEAP_DESC &GetHeapDesc()const{return m_HeapDesc;}
+ const D3D12_DESCRIPTOR_HEAP_DESC& GetHeapDesc()const{return m_HeapDesc;}
Uint32 GetMaxStaticDescriptors() const { return m_HeapAllocationManager.GetMaxDescriptors(); }
Uint32 GetMaxDynamicDescriptors()const { return m_DynamicAllocationsManager.GetMaxDescriptors(); }
+#ifdef DEVELOPMENT
+ int32_t DvpGetTotalAllocationCount()const
+ {
+ return m_HeapAllocationManager.DvpGetAllocationsCounter() +
+ m_DynamicAllocationsManager.DvpGetAllocationsCounter();
+ }
+#endif
+
protected:
+ RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
- D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
+ const D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
CComPtr<ID3D12DescriptorHeap> m_pd3d12DescriptorHeap;
const UINT m_DescriptorSize;
@@ -463,8 +479,6 @@ protected:
// Allocation manager for dynamic part
DescriptorHeapAllocationManager m_DynamicAllocationsManager;
-
- RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
};
@@ -481,13 +495,18 @@ protected:
class DynamicSuballocationsManager final : public IDescriptorAllocator
{
public:
- DynamicSuballocationsManager(IMemoryAllocator &Allocator, GPUDescriptorHeap& ParentGPUHeap, Uint32 DynamicChunkSize);
+ DynamicSuballocationsManager(IMemoryAllocator& Allocator,
+ GPUDescriptorHeap& ParentGPUHeap,
+ Uint32 DynamicChunkSize,
+ String ManagerName);
DynamicSuballocationsManager (const DynamicSuballocationsManager&) = delete;
DynamicSuballocationsManager (DynamicSuballocationsManager&&) = delete;
DynamicSuballocationsManager& operator = (const DynamicSuballocationsManager&) = delete;
DynamicSuballocationsManager& operator = (DynamicSuballocationsManager&&) = delete;
+ ~DynamicSuballocationsManager();
+
void ReleaseAllocations(Uint64 CmdQueueMask);
virtual DescriptorHeapAllocation Allocate(Uint32 Count)override final;
@@ -503,15 +522,21 @@ public:
size_t GetSuballocationCount()const {return m_Suballocations.size();}
private:
+ // Parent GPU descriptor heap that is used to allocate chunks
+ GPUDescriptorHeap& m_ParentGPUHeap;
+ const String m_ManagerName;
+
// List of chunks allocated from the master GPU descriptor heap. All chunks are disposed at the end
// of the frame
std::vector<DescriptorHeapAllocation, STDAllocatorRawMem<DescriptorHeapAllocation> > m_Suballocations;
- Uint32 m_CurrentSuballocationOffset = 0;
- Uint32 m_DynamicChunkSize = 0;
+ Uint32 m_CurrentSuballocationOffset = 0;
+ Uint32 m_DynamicChunkSize = 0;
- // Parent GPU descriptor heap that is used to allocate chunks
- GPUDescriptorHeap& m_ParentGPUHeap;
+ Uint32 m_CurrDescriptorCount = 0;
+ Uint32 m_PeakDescriptorCount = 0;
+ Uint32 m_CurrSuballocationsTotalSize = 0;
+ Uint32 m_PeakSuballocationsTotalSize = 0;
};
}
diff --git a/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp b/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
index a495b872..c7bd6272 100644
--- a/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
@@ -35,18 +35,18 @@ DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocato
IDescriptorAllocator& ParentAllocator,
size_t ThisManagerId,
const D3D12_DESCRIPTOR_HEAP_DESC& HeapDesc) :
- m_FreeBlockManager (HeapDesc.NumDescriptors, Allocator),
- m_NumDescriptorsInAllocation (HeapDesc.NumDescriptors),
- m_HeapDesc (HeapDesc),
- m_DeviceD3D12Impl (DeviceD3D12Impl),
m_ParentAllocator (ParentAllocator),
- m_ThisManagerId (ThisManagerId)
+ m_DeviceD3D12Impl (DeviceD3D12Impl),
+ m_ThisManagerId (ThisManagerId),
+ m_HeapDesc (HeapDesc),
+ m_DescriptorSize (DeviceD3D12Impl.GetD3D12Device()->GetDescriptorHandleIncrementSize(m_HeapDesc.Type)),
+ m_NumDescriptorsInAllocation (HeapDesc.NumDescriptors),
+ m_FreeBlockManager (HeapDesc.NumDescriptors, Allocator)
{
auto pDevice = DeviceD3D12Impl.GetD3D12Device();
m_FirstCPUHandle.ptr = 0;
m_FirstGPUHandle.ptr = 0;
- m_DescriptorSize = pDevice->GetDescriptorHandleIncrementSize(HeapDesc.Type);
pDevice->CreateDescriptorHeap(&m_HeapDesc, __uuidof(m_pd3d12DescriptorHeap), reinterpret_cast<void**>(static_cast<ID3D12DescriptorHeap**>(&m_pd3d12DescriptorHeap)));
m_FirstCPUHandle = m_pd3d12DescriptorHeap->GetCPUDescriptorHandleForHeapStart();
@@ -63,16 +63,15 @@ DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocato
ID3D12DescriptorHeap* pd3d12DescriptorHeap,
Uint32 FirstDescriptor,
Uint32 NumDescriptors):
- m_FreeBlockManager (NumDescriptors, Allocator),
- m_NumDescriptorsInAllocation (NumDescriptors),
- m_DeviceD3D12Impl (DeviceD3D12Impl),
m_ParentAllocator (ParentAllocator),
+ m_DeviceD3D12Impl (DeviceD3D12Impl),
m_ThisManagerId (ThisManagerId),
+ m_HeapDesc (pd3d12DescriptorHeap->GetDesc()),
+ m_DescriptorSize (DeviceD3D12Impl.GetD3D12Device()->GetDescriptorHandleIncrementSize(m_HeapDesc.Type)),
+ m_NumDescriptorsInAllocation (NumDescriptors),
+ m_FreeBlockManager (NumDescriptors, Allocator),
m_pd3d12DescriptorHeap (pd3d12DescriptorHeap)
{
- m_HeapDesc = m_pd3d12DescriptorHeap->GetDesc();
- m_DescriptorSize = DeviceD3D12Impl.GetD3D12Device()->GetDescriptorHandleIncrementSize(m_HeapDesc.Type);
-
m_FirstCPUHandle = pd3d12DescriptorHeap->GetCPUDescriptorHandleForHeapStart();
m_FirstCPUHandle.ptr += m_DescriptorSize * FirstDescriptor;
@@ -94,7 +93,7 @@ DescriptorHeapAllocation DescriptorHeapAllocationManager::Allocate(uint32_t Coun
{
VERIFY_EXPR(Count > 0);
- std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
+ std::lock_guard<std::mutex> LockGuard(m_FreeBlockManagerMutex);
// Methods of VariableSizeAllocationsManager class are not thread safe!
// Use variable-size GPU allocations manager to allocate the requested number of descriptors
@@ -118,18 +117,22 @@ DescriptorHeapAllocation DescriptorHeapAllocationManager::Allocate(uint32_t Coun
m_MaxAllocatedSize = std::max(m_MaxAllocatedSize, m_FreeBlockManager.GetUsedSize());
- VERIFY(m_ThisManagerId < std::numeric_limits<Uint16>::max(), "ManagerID exceeds 16-bit range");
#ifdef DEVELOPMENT
++m_AllocationsCounter;
#endif
- return DescriptorHeapAllocation( m_ParentAllocator, m_pd3d12DescriptorHeap, CPUHandle, GPUHandle, Count, static_cast<Uint16>(m_ThisManagerId));
+
+ VERIFY(m_ThisManagerId < std::numeric_limits<Uint16>::max(), "ManagerID exceeds 16-bit range");
+ return DescriptorHeapAllocation{m_ParentAllocator, m_pd3d12DescriptorHeap, CPUHandle, GPUHandle, Count, static_cast<Uint16>(m_ThisManagerId)};
}
void DescriptorHeapAllocationManager::FreeAllocation(DescriptorHeapAllocation&& Allocation)
{
VERIFY(Allocation.GetAllocationManagerId() == m_ThisManagerId, "Invalid descriptor heap manager Id");
- std::lock_guard<std::mutex> LockGuard(m_AllocationMutex);
+ if (Allocation.IsNull())
+ return;
+
+ std::lock_guard<std::mutex> LockGuard(m_FreeBlockManagerMutex);
auto DescriptorOffset = (Allocation.GetCpuHandle().ptr - m_FirstCPUHandle.ptr) / m_DescriptorSize;
// Methods of VariableSizeAllocationsManager class are not thread safe!
m_FreeBlockManager.Free(DescriptorOffset, Allocation.GetNumHandles());
@@ -151,17 +154,22 @@ CPUDescriptorHeap::CPUDescriptorHeap(IMemoryAllocator& Allocator,
Uint32 NumDescriptorsInHeap,
D3D12_DESCRIPTOR_HEAP_TYPE Type,
D3D12_DESCRIPTOR_HEAP_FLAGS Flags) :
- 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 unordered_set<size_t>"))
+ m_MemAllocator (Allocator),
+ m_DeviceD3D12Impl(DeviceD3D12Impl),
+ m_HeapPool (STD_ALLOCATOR_RAW_MEM(DescriptorHeapAllocationManager, GetRawAllocator(), "Allocator for vector<DescriptorHeapAllocationManager>")),
+ m_AvailableHeaps (STD_ALLOCATOR_RAW_MEM(size_t, GetRawAllocator(), "Allocator for unordered_set<size_t>")),
+ m_HeapDesc
+ {
+ Type,
+ NumDescriptorsInHeap,
+ Flags,
+ 1 // NodeMask
+ },
+ m_DescriptorSize(DeviceD3D12Impl.GetD3D12Device()->GetDescriptorHandleIncrementSize(Type))
{
- m_HeapDesc.Type = Type;
- m_HeapDesc.NodeMask = 1;
- m_HeapDesc.NumDescriptors = NumDescriptorsInHeap;
- m_HeapDesc.Flags = Flags;
-
- m_DescriptorSize = m_DeviceD3D12Impl.GetD3D12Device()->GetDescriptorHandleIncrementSize(Type);
+ // Create one pool
+ m_HeapPool.emplace_back(m_MemAllocator, m_DeviceD3D12Impl, *this, 0, m_HeapDesc);
+ m_AvailableHeaps.insert(0);
}
CPUDescriptorHeap::~CPUDescriptorHeap()
@@ -177,10 +185,22 @@ CPUDescriptorHeap::~CPUDescriptorHeap()
}
TotalDescriptors = std::max(TotalDescriptors, 1u);
- LOG_INFO_MESSAGE(GetD3D12DescriptorHeapTypeLiteralName(m_HeapDesc.Type), " CPU heap allocated pool count: ", m_HeapPool.size(),
- ". Max descriptors: ", m_MaxSize, '/', TotalDescriptors, " (", m_MaxSize*100/ TotalDescriptors, "%).");
+ LOG_INFO_MESSAGE(std::setw(38), std::left, GetD3D12DescriptorHeapTypeLiteralName(m_HeapDesc.Type), " CPU heap allocated pool count: ", m_HeapPool.size(),
+ ". Max descriptors: ", m_MaxSize, '/', TotalDescriptors,
+ " (", std::fixed, std::setprecision(2), m_MaxSize*100.0 / TotalDescriptors, "%).");
}
+#ifdef DEVELOPMENT
+int32_t CPUDescriptorHeap::DvpGetTotalAllocationCount()
+{
+ int32_t AllocationCount = 0;
+ std::lock_guard<std::mutex> LockGuard(m_HeapPoolMutex);
+ for (auto& Heap : m_HeapPool)
+ AllocationCount += Heap.DvpGetAllocationsCounter();
+ return AllocationCount;
+}
+#endif
+
DescriptorHeapAllocation CPUDescriptorHeap::Allocate( uint32_t Count )
{
std::lock_guard<std::mutex> LockGuard(m_HeapPoolMutex);
@@ -202,31 +222,32 @@ DescriptorHeapAllocation CPUDescriptorHeap::Allocate( uint32_t Count )
// Terminate the loop if descriptor was successfully allocated, otherwise
// go to the next manager
- if(Allocation.GetCpuHandle().ptr != 0)
+ if (!Allocation.IsNull())
break;
AvailableHeapIt = NextIt;
}
// If there were no available descriptor heap managers or no manager was able
// to suffice the allocation request, create a new manager
- if(Allocation.GetCpuHandle().ptr == 0)
+ if (Allocation.IsNull())
{
// Make sure the heap is large enough to accomodate the requested number of descriptors
if(Count > m_HeapDesc.NumDescriptors)
{
- LOG_WARNING_MESSAGE("Number of requested CPU descriptors handles (", Count, ") exceeds the descriptor heap size (", m_HeapDesc.NumDescriptors,"). Increasing the number of descriptors in the heap");
+ LOG_INFO_MESSAGE("Number of requested CPU descriptors handles (", Count, ") exceeds the descriptor heap size (", m_HeapDesc.NumDescriptors,"). Increasing the number of descriptors in the heap");
}
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_DeviceD3D12Impl, *this, m_HeapPool.size(), m_HeapDesc);
auto NewHeapIt = m_AvailableHeaps.insert(m_HeapPool.size()-1);
+ VERIFY_EXPR(NewHeapIt.second);
// Use the new manager to allocate descriptor handles
Allocation = m_HeapPool[*NewHeapIt.first].Allocate(Count);
}
- m_CurrentSize += (Allocation.GetCpuHandle().ptr != 0) ? Count : 0;
+ m_CurrentSize += static_cast<Uint32>(Allocation.GetNumHandles());
m_MaxSize = std::max(m_MaxSize, m_CurrentSize);
return Allocation;
@@ -314,9 +335,9 @@ GPUDescriptorHeap::~GPUDescriptorHeap()
auto MaxStaticSize = m_HeapAllocationManager.GetMaxAllocatedSize();
auto MaxDynamicSize = m_DynamicAllocationsManager.GetMaxAllocatedSize();
- LOG_INFO_MESSAGE(GetD3D12DescriptorHeapTypeLiteralName(m_HeapDesc.Type), " GPU heap max allocated size (static|dynamic): ",
- MaxStaticSize, '/', TotalStaticSize, " (", MaxStaticSize * 100 / TotalStaticSize, "%) | ",
- MaxDynamicSize, '/', TotalDynamicSize, " (", MaxDynamicSize * 100 / TotalDynamicSize, "%).");
+ LOG_INFO_MESSAGE(std::setw(38), std::left, GetD3D12DescriptorHeapTypeLiteralName(m_HeapDesc.Type), " GPU heap max allocated size (static|dynamic): ",
+ MaxStaticSize, '/', TotalStaticSize, " (", std::fixed, std::setprecision(2), MaxStaticSize * 100.0 / TotalStaticSize, "%) | ",
+ MaxDynamicSize, '/', TotalDynamicSize, " (", std::fixed, std::setprecision(2), MaxDynamicSize * 100.0 / TotalDynamicSize, "%).");
}
void GPUDescriptorHeap::Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQueueMask)
@@ -365,13 +386,23 @@ void GPUDescriptorHeap::Free(DescriptorHeapAllocation&& Allocation, Uint64 CmdQu
}
-DynamicSuballocationsManager::DynamicSuballocationsManager(IMemoryAllocator &Allocator, GPUDescriptorHeap& ParentGPUHeap, Uint32 DynamicChunkSize) :
+DynamicSuballocationsManager::DynamicSuballocationsManager(IMemoryAllocator& Allocator,
+ GPUDescriptorHeap& ParentGPUHeap,
+ Uint32 DynamicChunkSize,
+ String ManagerName) :
m_ParentGPUHeap(ParentGPUHeap),
m_DynamicChunkSize(DynamicChunkSize),
- m_Suballocations(STD_ALLOCATOR_RAW_MEM(DescriptorHeapAllocation, GetRawAllocator(), "Allocator for vector<DescriptorHeapAllocation>"))
+ m_Suballocations(STD_ALLOCATOR_RAW_MEM(DescriptorHeapAllocation, GetRawAllocator(), "Allocator for vector<DescriptorHeapAllocation>")),
+ m_ManagerName(std::move(ManagerName))
{
}
+DynamicSuballocationsManager::~DynamicSuballocationsManager()
+{
+ DEV_CHECK_ERR(m_Suballocations.empty() && m_CurrDescriptorCount == 0 && m_CurrSuballocationsTotalSize == 0, "All dynamic suballocations must be released!");
+ LOG_INFO_MESSAGE(m_ManagerName, " usage stats: peak descriptor count: ", m_PeakDescriptorCount, '/', m_PeakSuballocationsTotalSize);
+}
+
void DynamicSuballocationsManager::ReleaseAllocations(Uint64 CmdQueueMask)
{
// Clear the list and dispose all allocated chunks of GPU descriptor heap.
@@ -381,6 +412,8 @@ void DynamicSuballocationsManager::ReleaseAllocations(Uint64 CmdQueueMask)
m_ParentGPUHeap.Free(std::move(Allocation), CmdQueueMask);
}
m_Suballocations.clear();
+ m_CurrDescriptorCount = 0;
+ m_CurrSuballocationsTotalSize = 0;
}
DescriptorHeapAllocation DynamicSuballocationsManager::Allocate(Uint32 Count)
@@ -402,6 +435,9 @@ DescriptorHeapAllocation DynamicSuballocationsManager::Allocate(Uint32 Count)
}
m_Suballocations.emplace_back(std::move(NewDynamicSubAllocation));
m_CurrentSuballocationOffset = 0;
+
+ m_CurrSuballocationsTotalSize += SuballocationSize;
+ m_PeakSuballocationsTotalSize = std::max(m_PeakSuballocationsTotalSize, m_CurrSuballocationsTotalSize);
}
// Perform suballocation from the last chunk
@@ -416,6 +452,8 @@ DescriptorHeapAllocation DynamicSuballocationsManager::Allocate(Uint32 Count)
Count,
static_cast<Uint16>(ManagerId) );
m_CurrentSuballocationOffset += Count;
+ m_CurrDescriptorCount += Count;
+ m_PeakDescriptorCount = std::max(m_PeakDescriptorCount, m_CurrDescriptorCount);
return Allocation;
}
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index 12d981d5..c9aa0f6a 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -39,16 +39,15 @@
namespace Diligent
{
- static std::string GetDynamicHeapName(bool bIsDeferred, Uint32 ContextId)
+ static std::string GetContextObjectName(const char* Object, bool bIsDeferred, Uint32 ContextId)
{
+ std::stringstream ss;
+ ss << Object;
if (bIsDeferred)
- {
- std::stringstream ss;
- ss << "Dynamic heap of deferred context #" << ContextId;
- return ss.str();
- }
+ ss << " of deferred context #" << ContextId;
else
- return "Dynamic heap of immediate context";
+ ss << " of immediate context";
+ return ss.str();
}
DeviceContextD3D12Impl::DeviceContextD3D12Impl( IReferenceCounters* pRefCounters,
@@ -69,7 +68,7 @@ namespace Diligent
m_DynamicHeap
{
pDeviceD3D12Impl->GetDynamicMemoryManager(),
- GetDynamicHeapName(bIsDeferred, ContextId),
+ GetContextObjectName("Dynamic heap", bIsDeferred, ContextId),
Attribs.DynamicHeapPageSize
},
m_DynamicGPUDescriptorAllocator
@@ -77,12 +76,14 @@ namespace Diligent
{
GetRawAllocator(),
pDeviceD3D12Impl->GetGPUDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV),
- Attribs.DynamicDescriptorAllocationChunkSize[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]
+ Attribs.DynamicDescriptorAllocationChunkSize[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV],
+ GetContextObjectName("CBV_SRV_UAV dynamic descriptor allocator", bIsDeferred, ContextId)
},
{
GetRawAllocator(),
pDeviceD3D12Impl->GetGPUDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER),
- Attribs.DynamicDescriptorAllocationChunkSize[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]
+ Attribs.DynamicDescriptorAllocationChunkSize[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER],
+ GetContextObjectName("SAMPLER dynamic descriptor allocator", bIsDeferred, ContextId)
}
},
m_NumCommandsInCurCtx(0),
diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
index 4049d468..bf4fd7e4 100644
--- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
@@ -92,6 +92,17 @@ RenderDeviceD3D12Impl::~RenderDeviceD3D12Impl()
IdleGPU(true);
ReleaseStaleResources(true);
+#ifdef DEVELOPMENT
+ for (auto i=0; i < _countof(m_CPUDescriptorHeaps); ++i)
+ {
+ DEV_CHECK_ERR(m_CPUDescriptorHeaps[i].DvpGetTotalAllocationCount() == 0, "All CPU descriptor heap allocations must be released");
+ }
+ for (auto i=0; i < _countof(m_GPUDescriptorHeaps); ++i)
+ {
+ DEV_CHECK_ERR(m_GPUDescriptorHeaps[i].DvpGetTotalAllocationCount() == 0, "All GPU descriptor heap allocations must be released");
+ }
+#endif
+
DEV_CHECK_ERR(m_DynamicMemoryManager.GetAllocatedPageCounter() == 0, "All allocated dynamic pages must have been returned to the manager at this point.");
m_DynamicMemoryManager.Destroy();
DEV_CHECK_ERR(m_CmdListManager.GetAllocatorCounter() == 0, "All allocators must have been returned to the manager at this point.");