Skip to content

Commit 50ef8f3

Browse files
Added macro D3D12MA_DEBUG_LOG (empty by default), virtual function BlockMetadata::DebugLogAllAllocations
1 parent 9da647a commit 50ef8f3

File tree

2 files changed

+86
-18
lines changed

2 files changed

+86
-18
lines changed

src/D3D12MemAlloc.cpp

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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
900910
public:
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

29722981
protected:
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+
30033032
void 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

37193749
private:
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+
46744717
Suballocation& 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

47124755
bool 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

50015045
private:
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+
56445699
UINT8 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!");

src/D3D12Sample.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ static void InitD3D() // initializes direct3d 12
795795
IID_PPV_ARGS(&g_DepthStencilBuffer)
796796
) );
797797
CHECK_HR( g_DepthStencilBuffer->SetName(L"Depth/Stencil Resource Heap") );
798+
g_DepthStencilAllocation->SetName(L"Depth/Stencil Resource Heap");
798799

799800
D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {};
800801
depthStencilDesc.Format = DEPTH_STENCIL_FORMAT;
@@ -917,6 +918,7 @@ static void InitD3D() // initializes direct3d 12
917918
&g_ConstantBufferUploadAllocation[i],
918919
IID_PPV_ARGS(&g_ConstantBufferUploadHeap[i])) );
919920
g_ConstantBufferUploadHeap[i]->SetName(L"Constant Buffer Upload Resource Heap");
921+
g_ConstantBufferUploadAllocation[i]->SetName(L"Constant Buffer Upload Resource Heap");
920922

921923
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
922924
cbvDesc.BufferLocation = g_ConstantBufferUploadHeap[i]->GetGPUVirtualAddress();
@@ -1045,6 +1047,7 @@ static void InitD3D() // initializes direct3d 12
10451047

10461048
// we can give resource heaps a name so when we debug with the graphics debugger we know what resource we are looking at
10471049
g_VertexBuffer->SetName(L"Vertex Buffer Resource Heap");
1050+
g_VertexBufferAllocation->SetName(L"Vertex Buffer Resource Heap");
10481051

10491052
// create upload heap
10501053
// upload heaps are used to upload data to the GPU. CPU can write to it, GPU can read from it
@@ -1073,6 +1076,7 @@ static void InitD3D() // initializes direct3d 12
10731076
&vBufferUploadHeapAllocation,
10741077
IID_PPV_ARGS(&vBufferUploadHeap)) );
10751078
vBufferUploadHeap->SetName(L"Vertex Buffer Upload Resource Heap");
1079+
vBufferUploadHeapAllocation->SetName(L"Vertex Buffer Upload Resource Heap");
10761080

10771081
// store vertex buffer in upload heap
10781082
D3D12_SUBRESOURCE_DATA vertexData = {};
@@ -1154,6 +1158,7 @@ static void InitD3D() // initializes direct3d 12
11541158

11551159
// we can give resource heaps a name so when we debug with the graphics debugger we know what resource we are looking at
11561160
g_IndexBuffer->SetName(L"Index Buffer Resource Heap");
1161+
g_IndexBufferAllocation->SetName(L"Index Buffer Resource Heap");
11571162

11581163
// create upload heap to upload index buffer
11591164
D3D12MA::ALLOCATION_DESC iBufferUploadAllocDesc = {};
@@ -1180,6 +1185,7 @@ static void InitD3D() // initializes direct3d 12
11801185
&iBufferUploadHeapAllocation,
11811186
IID_PPV_ARGS(&iBufferUploadHeap)) );
11821187
CHECK_HR( iBufferUploadHeap->SetName(L"Index Buffer Upload Resource Heap") );
1188+
iBufferUploadHeapAllocation->SetName(L"Index Buffer Upload Resource Heap");
11831189

11841190
// store vertex buffer in upload heap
11851191
D3D12_SUBRESOURCE_DATA indexData = {};
@@ -1236,6 +1242,7 @@ static void InitD3D() // initializes direct3d 12
12361242
&g_CbPerObjectUploadHeapAllocations[i],
12371243
IID_PPV_ARGS(&g_CbPerObjectUploadHeaps[i])) );
12381244
g_CbPerObjectUploadHeaps[i]->SetName(L"Constant Buffer Upload Resource Heap");
1245+
g_CbPerObjectUploadHeapAllocations[i]->SetName(L"Constant Buffer Upload Resource Heap");
12391246

12401247
CHECK_HR( g_CbPerObjectUploadHeaps[i]->Map(0, &EMPTY_RANGE, &g_CbPerObjectAddress[i]) );
12411248
}
@@ -1298,6 +1305,7 @@ static void InitD3D() // initializes direct3d 12
12981305
&g_TextureAllocation,
12991306
IID_PPV_ARGS(&g_Texture)) );
13001307
g_Texture->SetName(L"g_Texture");
1308+
g_TextureAllocation->SetName(L"g_Texture");
13011309

13021310
UINT64 textureUploadBufferSize;
13031311
device->GetCopyableFootprints(
@@ -1334,6 +1342,7 @@ static void InitD3D() // initializes direct3d 12
13341342
&textureUploadAllocation,
13351343
IID_PPV_ARGS(&textureUpload)) );
13361344
textureUpload->SetName(L"textureUpload");
1345+
textureUploadAllocation->SetName(L"textureUpload");
13371346

13381347
D3D12_SUBRESOURCE_DATA textureSubresourceData = {};
13391348
textureSubresourceData.pData = imageData.data();

0 commit comments

Comments
 (0)