Added macro D3D12MA_DEBUG_LOG (empty by default), virtual function BlockMetadata::DebugLogAllAllocations

This commit is contained in:
Adam Sawicki 2022-10-19 14:55:09 +02:00
parent 9da647a833
commit 50ef8f39a4
2 changed files with 86 additions and 18 deletions

View File

@ -107,6 +107,16 @@ especially to test compatibility with D3D12_RESOURCE_HEAP_TIER_1 on modern GPUs.
#define D3D12MA_DEFAULT_BLOCK_SIZE (64ull * 1024 * 1024)
#endif
#ifndef D3D12MA_DEBUG_LOG
#define D3D12MA_DEBUG_LOG(format, ...)
/*
#define D3D12MA_DEBUG_LOG(format, ...) do { \
wprintf(format, __VA_ARGS__); \
wprintf(L"\n"); \
} while(false)
*/
#endif
#endif // _D3D12MA_CONFIGURATION
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@ -900,6 +910,7 @@ class Vector
public:
using value_type = T;
using iterator = T*;
using const_iterator = const T*;
// allocationCallbacks externally owned, must outlive this object.
Vector(const ALLOCATION_CALLBACKS& allocationCallbacks);
@ -916,13 +927,10 @@ public:
iterator begin() { return m_pArray; }
iterator end() { return m_pArray + m_Count; }
iterator rend() { return begin() - 1; }
iterator rbegin() { return end() - 1; }
const iterator cbegin() const { return m_pArray; }
const iterator cend() const { return m_pArray + m_Count; }
const iterator crbegin() const { return cend() - 1; }
const iterator crend() const { return cbegin() - 1; }
const_iterator cbegin() const { return m_pArray; }
const_iterator cend() const { return m_pArray + m_Count; }
const_iterator begin() const { return cbegin(); }
const_iterator end() const { return cend(); }
void push_front(const T& src) { insert(0, src); }
void push_back(const T& src);
@ -2968,11 +2976,13 @@ public:
virtual void AddStatistics(Statistics& inoutStats) const = 0;
virtual void AddDetailedStatistics(DetailedStatistics& inoutStats) const = 0;
virtual void WriteAllocationInfoToJson(JsonWriter& json) const = 0;
virtual void DebugLogAllAllocations() const = 0;
protected:
const ALLOCATION_CALLBACKS* GetAllocs() const { return m_pAllocationCallbacks; }
UINT64 GetDebugMargin() const { return IsVirtual() ? 0 : D3D12MA_DEBUG_MARGIN; }
void DebugLogAllocation(UINT64 offset, UINT64 size, void* privateData) const;
void PrintDetailedMap_Begin(JsonWriter& json,
UINT64 unusedBytes,
size_t allocationCount,
@ -3000,6 +3010,25 @@ BlockMetadata::BlockMetadata(const ALLOCATION_CALLBACKS* allocationCallbacks, bo
D3D12MA_ASSERT(allocationCallbacks);
}
void BlockMetadata::DebugLogAllocation(UINT64 offset, UINT64 size, void* privateData) const
{
if (IsVirtual())
{
D3D12MA_DEBUG_LOG(L"UNFREED VIRTUAL ALLOCATION; Offset: %llu; Size: %llu; PrivateData: %p", offset, size, privateData);
}
else
{
D3D12MA_ASSERT(privateData != NULL);
Allocation* allocation = reinterpret_cast<Allocation*>(privateData);
privateData = allocation->GetPrivateData();
LPCWSTR name = allocation->GetName();
D3D12MA_DEBUG_LOG(L"UNFREED ALLOCATION; Offset: %llu; Size: %llu; PrivateData: %p; Name: %s",
offset, size, privateData, name ? name : L"D3D12MA_Empty");
}
}
void BlockMetadata::PrintDetailedMap_Begin(JsonWriter& json,
UINT64 unusedBytes, size_t allocationCount, size_t unusedRangeCount) const
{
@ -3715,6 +3744,7 @@ public:
void AddStatistics(Statistics& inoutStats) const override;
void AddDetailedStatistics(DetailedStatistics& inoutStats) const override;
void WriteAllocationInfoToJson(JsonWriter& json) const override;
void DebugLogAllAllocations() const override;
private:
/*
@ -4671,6 +4701,19 @@ void BlockMetadata_Linear::WriteAllocationInfoToJson(JsonWriter& json) const
PrintDetailedMap_End(json);
}
void BlockMetadata_Linear::DebugLogAllAllocations() const
{
const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
for (auto it = suballocations1st.begin() + m_1stNullItemsBeginCount; it != suballocations1st.end(); ++it)
if (it->type != SUBALLOCATION_TYPE_FREE)
DebugLogAllocation(it->offset, it->size, it->privateData);
const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
for (auto it = suballocations2nd.begin(); it != suballocations2nd.end(); ++it)
if (it->type != SUBALLOCATION_TYPE_FREE)
DebugLogAllocation(it->offset, it->size, it->privateData);
}
Suballocation& BlockMetadata_Linear::FindSuballocation(UINT64 offset) const
{
const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
@ -4682,31 +4725,31 @@ Suballocation& BlockMetadata_Linear::FindSuballocation(UINT64 offset) const
// Item from the 1st vector.
{
const SuballocationVectorType::iterator it = BinaryFindSorted(
suballocations1st.cbegin() + m_1stNullItemsBeginCount,
suballocations1st.cend(),
const SuballocationVectorType::const_iterator it = BinaryFindSorted(
suballocations1st.begin() + m_1stNullItemsBeginCount,
suballocations1st.end(),
refSuballoc,
SuballocationOffsetLess());
if (it != suballocations1st.cend())
if (it != suballocations1st.end())
{
return *it;
return const_cast<Suballocation&>(*it);
}
}
if (m_2ndVectorMode != SECOND_VECTOR_EMPTY)
{
// Rest of members stays uninitialized intentionally for better performance.
const SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?
BinaryFindSorted(suballocations2nd.cbegin(), suballocations2nd.cend(), refSuballoc, SuballocationOffsetLess()) :
BinaryFindSorted(suballocations2nd.cbegin(), suballocations2nd.cend(), refSuballoc, SuballocationOffsetGreater());
if (it != suballocations2nd.cend())
const SuballocationVectorType::const_iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?
BinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, SuballocationOffsetLess()) :
BinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, SuballocationOffsetGreater());
if (it != suballocations2nd.end())
{
return *it;
return const_cast<Suballocation&>(*it);
}
}
D3D12MA_ASSERT(0 && "Allocation not found in linear allocator!");
return *suballocations1st.crbegin(); // Should never occur.
return const_cast<Suballocation&>(suballocations1st.back()); // Should never occur.
}
bool BlockMetadata_Linear::ShouldCompact1st() const
@ -4997,6 +5040,7 @@ public:
void AddStatistics(Statistics& inoutStats) const override;
void AddDetailedStatistics(DetailedStatistics& inoutStats) const override;
void WriteAllocationInfoToJson(JsonWriter& json) const override;
void DebugLogAllAllocations() const override;
private:
// According to original paper it should be preferable 4 or 5:
@ -5641,6 +5685,17 @@ void BlockMetadata_TLSF::WriteAllocationInfoToJson(JsonWriter& json) const
PrintDetailedMap_End(json);
}
void BlockMetadata_TLSF::DebugLogAllAllocations() const
{
for (Block* block = m_NullBlock->prevPhysical; block != NULL; block = block->prevPhysical)
{
if (!block->IsFree())
{
DebugLogAllocation(block->offset, block->size, block->PrivateData());
}
}
}
UINT8 BlockMetadata_TLSF::SizeToMemoryClass(UINT64 size) const
{
if (size > SMALL_BUFFER_SIZE)
@ -8130,6 +8185,10 @@ NormalBlock::~NormalBlock()
{
if (m_pMetadata != NULL)
{
// Define macro VMA_DEBUG_LOG to receive the list of the unfreed allocations
if (!m_pMetadata->IsEmpty())
m_pMetadata->DebugLogAllAllocations();
// THIS IS THE MOST IMPORTANT ASSERT IN THE ENTIRE LIBRARY!
// Hitting it means you have some memory leak - unreleased Allocation objects.
D3D12MA_ASSERT(m_pMetadata->IsEmpty() && "Some allocations were not freed before destruction of this memory block!");

View File

@ -795,6 +795,7 @@ static void InitD3D() // initializes direct3d 12
IID_PPV_ARGS(&g_DepthStencilBuffer)
) );
CHECK_HR( g_DepthStencilBuffer->SetName(L"Depth/Stencil Resource Heap") );
g_DepthStencilAllocation->SetName(L"Depth/Stencil Resource Heap");
D3D12_DEPTH_STENCIL_VIEW_DESC depthStencilDesc = {};
depthStencilDesc.Format = DEPTH_STENCIL_FORMAT;
@ -917,6 +918,7 @@ static void InitD3D() // initializes direct3d 12
&g_ConstantBufferUploadAllocation[i],
IID_PPV_ARGS(&g_ConstantBufferUploadHeap[i])) );
g_ConstantBufferUploadHeap[i]->SetName(L"Constant Buffer Upload Resource Heap");
g_ConstantBufferUploadAllocation[i]->SetName(L"Constant Buffer Upload Resource Heap");
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {};
cbvDesc.BufferLocation = g_ConstantBufferUploadHeap[i]->GetGPUVirtualAddress();
@ -1045,6 +1047,7 @@ static void InitD3D() // initializes direct3d 12
// we can give resource heaps a name so when we debug with the graphics debugger we know what resource we are looking at
g_VertexBuffer->SetName(L"Vertex Buffer Resource Heap");
g_VertexBufferAllocation->SetName(L"Vertex Buffer Resource Heap");
// create upload heap
// 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
&vBufferUploadHeapAllocation,
IID_PPV_ARGS(&vBufferUploadHeap)) );
vBufferUploadHeap->SetName(L"Vertex Buffer Upload Resource Heap");
vBufferUploadHeapAllocation->SetName(L"Vertex Buffer Upload Resource Heap");
// store vertex buffer in upload heap
D3D12_SUBRESOURCE_DATA vertexData = {};
@ -1154,6 +1158,7 @@ static void InitD3D() // initializes direct3d 12
// we can give resource heaps a name so when we debug with the graphics debugger we know what resource we are looking at
g_IndexBuffer->SetName(L"Index Buffer Resource Heap");
g_IndexBufferAllocation->SetName(L"Index Buffer Resource Heap");
// create upload heap to upload index buffer
D3D12MA::ALLOCATION_DESC iBufferUploadAllocDesc = {};
@ -1180,6 +1185,7 @@ static void InitD3D() // initializes direct3d 12
&iBufferUploadHeapAllocation,
IID_PPV_ARGS(&iBufferUploadHeap)) );
CHECK_HR( iBufferUploadHeap->SetName(L"Index Buffer Upload Resource Heap") );
iBufferUploadHeapAllocation->SetName(L"Index Buffer Upload Resource Heap");
// store vertex buffer in upload heap
D3D12_SUBRESOURCE_DATA indexData = {};
@ -1236,6 +1242,7 @@ static void InitD3D() // initializes direct3d 12
&g_CbPerObjectUploadHeapAllocations[i],
IID_PPV_ARGS(&g_CbPerObjectUploadHeaps[i])) );
g_CbPerObjectUploadHeaps[i]->SetName(L"Constant Buffer Upload Resource Heap");
g_CbPerObjectUploadHeapAllocations[i]->SetName(L"Constant Buffer Upload Resource Heap");
CHECK_HR( g_CbPerObjectUploadHeaps[i]->Map(0, &EMPTY_RANGE, &g_CbPerObjectAddress[i]) );
}
@ -1298,6 +1305,7 @@ static void InitD3D() // initializes direct3d 12
&g_TextureAllocation,
IID_PPV_ARGS(&g_Texture)) );
g_Texture->SetName(L"g_Texture");
g_TextureAllocation->SetName(L"g_Texture");
UINT64 textureUploadBufferSize;
device->GetCopyableFootprints(
@ -1334,6 +1342,7 @@ static void InitD3D() // initializes direct3d 12
&textureUploadAllocation,
IID_PPV_ARGS(&textureUpload)) );
textureUpload->SetName(L"textureUpload");
textureUploadAllocation->SetName(L"textureUpload");
D3D12_SUBRESOURCE_DATA textureSubresourceData = {};
textureSubresourceData.pData = imageData.data();