@@ -107,6 +107,16 @@ especially to test compatibility with D3D12_RESOURCE_HEAP_TIER_1 on modern GPUs.
107107 #define D3D12MA_DEFAULT_BLOCK_SIZE (64ull * 1024 * 1024 )
108108#endif
109109
110+ #ifndef D3D12MA_DEBUG_LOG
111+ #define D3D12MA_DEBUG_LOG (format, ...)
112+ /*
113+ #define D3D12MA_DEBUG_LOG(format, ...) do { \
114+ wprintf(format, __VA_ARGS__); \
115+ wprintf(L"\n"); \
116+ } while(false)
117+ */
118+ #endif
119+
110120#endif // _D3D12MA_CONFIGURATION
111121// //////////////////////////////////////////////////////////////////////////////
112122// //////////////////////////////////////////////////////////////////////////////
@@ -900,6 +910,7 @@ class Vector
900910public:
901911 using value_type = T;
902912 using iterator = T*;
913+ using const_iterator = const T*;
903914
904915 // allocationCallbacks externally owned, must outlive this object.
905916 Vector (const ALLOCATION_CALLBACKS& allocationCallbacks);
@@ -916,13 +927,10 @@ class Vector
916927
917928 iterator begin () { return m_pArray; }
918929 iterator end () { return m_pArray + m_Count; }
919- iterator rend () { return begin () - 1 ; }
920- iterator rbegin () { return end () - 1 ; }
921-
922- const iterator cbegin () const { return m_pArray; }
923- const iterator cend () const { return m_pArray + m_Count; }
924- const iterator crbegin () const { return cend () - 1 ; }
925- const iterator crend () const { return cbegin () - 1 ; }
930+ const_iterator cbegin () const { return m_pArray; }
931+ const_iterator cend () const { return m_pArray + m_Count; }
932+ const_iterator begin () const { return cbegin (); }
933+ const_iterator end () const { return cend (); }
926934
927935 void push_front (const T& src) { insert (0 , src); }
928936 void push_back (const T& src);
@@ -2968,11 +2976,13 @@ class BlockMetadata
29682976 virtual void AddStatistics (Statistics& inoutStats) const = 0;
29692977 virtual void AddDetailedStatistics (DetailedStatistics& inoutStats) const = 0;
29702978 virtual void WriteAllocationInfoToJson (JsonWriter& json) const = 0;
2979+ virtual void DebugLogAllAllocations () const = 0;
29712980
29722981protected:
29732982 const ALLOCATION_CALLBACKS* GetAllocs () const { return m_pAllocationCallbacks; }
29742983 UINT64 GetDebugMargin () const { return IsVirtual () ? 0 : D3D12MA_DEBUG_MARGIN; }
29752984
2985+ void DebugLogAllocation (UINT64 offset, UINT64 size, void * privateData) const ;
29762986 void PrintDetailedMap_Begin (JsonWriter& json,
29772987 UINT64 unusedBytes,
29782988 size_t allocationCount,
@@ -3000,6 +3010,25 @@ BlockMetadata::BlockMetadata(const ALLOCATION_CALLBACKS* allocationCallbacks, bo
30003010 D3D12MA_ASSERT (allocationCallbacks);
30013011}
30023012
3013+ void BlockMetadata::DebugLogAllocation (UINT64 offset, UINT64 size, void * privateData) const
3014+ {
3015+ if (IsVirtual ())
3016+ {
3017+ D3D12MA_DEBUG_LOG (L" UNFREED VIRTUAL ALLOCATION; Offset: %llu; Size: %llu; PrivateData: %p" , offset, size, privateData);
3018+ }
3019+ else
3020+ {
3021+ D3D12MA_ASSERT (privateData != NULL );
3022+ Allocation* allocation = reinterpret_cast <Allocation*>(privateData);
3023+
3024+ privateData = allocation->GetPrivateData ();
3025+ LPCWSTR name = allocation->GetName ();
3026+
3027+ D3D12MA_DEBUG_LOG (L" UNFREED ALLOCATION; Offset: %llu; Size: %llu; PrivateData: %p; Name: %s" ,
3028+ offset, size, privateData, name ? name : L" D3D12MA_Empty" );
3029+ }
3030+ }
3031+
30033032void BlockMetadata::PrintDetailedMap_Begin (JsonWriter& json,
30043033 UINT64 unusedBytes, size_t allocationCount, size_t unusedRangeCount) const
30053034{
@@ -3715,6 +3744,7 @@ class BlockMetadata_Linear : public BlockMetadata
37153744 void AddStatistics (Statistics& inoutStats) const override ;
37163745 void AddDetailedStatistics (DetailedStatistics& inoutStats) const override ;
37173746 void WriteAllocationInfoToJson (JsonWriter& json) const override ;
3747+ void DebugLogAllAllocations () const override ;
37183748
37193749private:
37203750 /*
@@ -4671,6 +4701,19 @@ void BlockMetadata_Linear::WriteAllocationInfoToJson(JsonWriter& json) const
46714701 PrintDetailedMap_End (json);
46724702}
46734703
4704+ void BlockMetadata_Linear::DebugLogAllAllocations () const
4705+ {
4706+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st ();
4707+ for (auto it = suballocations1st.begin () + m_1stNullItemsBeginCount; it != suballocations1st.end (); ++it)
4708+ if (it->type != SUBALLOCATION_TYPE_FREE)
4709+ DebugLogAllocation (it->offset , it->size , it->privateData );
4710+
4711+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd ();
4712+ for (auto it = suballocations2nd.begin (); it != suballocations2nd.end (); ++it)
4713+ if (it->type != SUBALLOCATION_TYPE_FREE)
4714+ DebugLogAllocation (it->offset , it->size , it->privateData );
4715+ }
4716+
46744717Suballocation& BlockMetadata_Linear::FindSuballocation (UINT64 offset) const
46754718{
46764719 const SuballocationVectorType& suballocations1st = AccessSuballocations1st ();
@@ -4682,31 +4725,31 @@ Suballocation& BlockMetadata_Linear::FindSuballocation(UINT64 offset) const
46824725
46834726 // Item from the 1st vector.
46844727 {
4685- const SuballocationVectorType::iterator it = BinaryFindSorted (
4686- suballocations1st.cbegin () + m_1stNullItemsBeginCount,
4687- suballocations1st.cend (),
4728+ const SuballocationVectorType::const_iterator it = BinaryFindSorted (
4729+ suballocations1st.begin () + m_1stNullItemsBeginCount,
4730+ suballocations1st.end (),
46884731 refSuballoc,
46894732 SuballocationOffsetLess ());
4690- if (it != suballocations1st.cend ())
4733+ if (it != suballocations1st.end ())
46914734 {
4692- return *it;
4735+ return const_cast <Suballocation&>( *it) ;
46934736 }
46944737 }
46954738
46964739 if (m_2ndVectorMode != SECOND_VECTOR_EMPTY)
46974740 {
46984741 // Rest of members stays uninitialized intentionally for better performance.
4699- const SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?
4700- BinaryFindSorted (suballocations2nd.cbegin (), suballocations2nd.cend (), refSuballoc, SuballocationOffsetLess ()) :
4701- BinaryFindSorted (suballocations2nd.cbegin (), suballocations2nd.cend (), refSuballoc, SuballocationOffsetGreater ());
4702- if (it != suballocations2nd.cend ())
4742+ const SuballocationVectorType::const_iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?
4743+ BinaryFindSorted (suballocations2nd.begin (), suballocations2nd.end (), refSuballoc, SuballocationOffsetLess ()) :
4744+ BinaryFindSorted (suballocations2nd.begin (), suballocations2nd.end (), refSuballoc, SuballocationOffsetGreater ());
4745+ if (it != suballocations2nd.end ())
47034746 {
4704- return *it;
4747+ return const_cast <Suballocation&>( *it) ;
47054748 }
47064749 }
47074750
47084751 D3D12MA_ASSERT (0 && " Allocation not found in linear allocator!" );
4709- return * suballocations1st.crbegin ( ); // Should never occur.
4752+ return const_cast <Suballocation&>( suballocations1st.back () ); // Should never occur.
47104753}
47114754
47124755bool BlockMetadata_Linear::ShouldCompact1st () const
@@ -4997,6 +5040,7 @@ class BlockMetadata_TLSF : public BlockMetadata
49975040 void AddStatistics (Statistics& inoutStats) const override ;
49985041 void AddDetailedStatistics (DetailedStatistics& inoutStats) const override ;
49995042 void WriteAllocationInfoToJson (JsonWriter& json) const override ;
5043+ void DebugLogAllAllocations () const override ;
50005044
50015045private:
50025046 // According to original paper it should be preferable 4 or 5:
@@ -5641,6 +5685,17 @@ void BlockMetadata_TLSF::WriteAllocationInfoToJson(JsonWriter& json) const
56415685 PrintDetailedMap_End (json);
56425686}
56435687
5688+ void BlockMetadata_TLSF::DebugLogAllAllocations () const
5689+ {
5690+ for (Block* block = m_NullBlock->prevPhysical ; block != NULL ; block = block->prevPhysical )
5691+ {
5692+ if (!block->IsFree ())
5693+ {
5694+ DebugLogAllocation (block->offset , block->size , block->PrivateData ());
5695+ }
5696+ }
5697+ }
5698+
56445699UINT8 BlockMetadata_TLSF::SizeToMemoryClass (UINT64 size) const
56455700{
56465701 if (size > SMALL_BUFFER_SIZE)
@@ -8130,6 +8185,10 @@ NormalBlock::~NormalBlock()
81308185{
81318186 if (m_pMetadata != NULL )
81328187 {
8188+ // Define macro VMA_DEBUG_LOG to receive the list of the unfreed allocations
8189+ if (!m_pMetadata->IsEmpty ())
8190+ m_pMetadata->DebugLogAllAllocations ();
8191+
81338192 // THIS IS THE MOST IMPORTANT ASSERT IN THE ENTIRE LIBRARY!
81348193 // Hitting it means you have some memory leak - unreleased Allocation objects.
81358194 D3D12MA_ASSERT (m_pMetadata->IsEmpty () && " Some allocations were not freed before destruction of this memory block!" );
0 commit comments