diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-10-06 20:17:26 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-10-06 20:17:26 +0000 |
| commit | 1a8406ee55f95c44e9bb096c7954543f505b7a0d (patch) | |
| tree | 806b9480a844e673ba8bd8d088ce42da008ba89e /Graphics/GraphicsEngineD3D12 | |
| parent | Fixed minor issue in PurgeReleaseQueues() (diff) | |
| download | DiligentCore-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')
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."); |
