Improvements in JSON dump - now prints Flags, Layout, CreationFrameIndex, more detailed Type.
Added function Allocator::SetCurrentFrameIndex.
diff --git a/src/Common.h b/src/Common.h
index 3495357..794c572 100644
--- a/src/Common.h
+++ b/src/Common.h
@@ -22,11 +22,12 @@
#pragma once
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+
#include <dxgi1_4.h>
#include <d3d12.h>
-#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX
#include <Windows.h>
#include <atlbase.h> // For CComPtr
diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp
index 14e008f..931fbb7 100644
--- a/src/D3D12MemAlloc.cpp
+++ b/src/D3D12MemAlloc.cpp
@@ -842,6 +842,7 @@
void ContinueString(LPCWSTR pStr);
void ContinueString(UINT num);
void ContinueString(UINT64 num);
+ void AddAllocationToObject(const Allocation& alloc);
// void ContinueString_Pointer(const void* ptr);
void EndString(LPCWSTR pStr = NULL);
@@ -1105,6 +1106,52 @@
}
}
+void JsonWriter::AddAllocationToObject(const Allocation& alloc)
+{
+ WriteString(L"Type");
+ switch (alloc.m_ResourceDimension) {
+ case D3D12_RESOURCE_DIMENSION_UNKNOWN:
+ WriteString(L"UNKNOWN");
+ break;
+ case D3D12_RESOURCE_DIMENSION_BUFFER:
+ WriteString(L"BUFFER");
+ break;
+ case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
+ WriteString(L"TEXTURE1D");
+ break;
+ case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
+ WriteString(L"TEXTURE2D");
+ break;
+ case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
+ WriteString(L"TEXTURE3D");
+ break;
+ default: D3D12MA_ASSERT(0); break;
+ }
+ WriteString(L"Size");
+ WriteNumber(alloc.GetSize());
+ LPCWSTR name = alloc.GetName();
+ if(name != NULL)
+ {
+ WriteString(L"Name");
+ WriteString(name);
+ }
+ if(alloc.m_ResourceFlags)
+ {
+ WriteString(L"Flags");
+ WriteNumber((UINT)alloc.m_ResourceFlags);
+ }
+ if(alloc.m_TextureLayout)
+ {
+ WriteString(L"Layout");
+ WriteNumber((UINT)alloc.m_TextureLayout);
+ }
+ if(alloc.m_CreationFrameIndex)
+ {
+ WriteString(L"CreationFrameIndex");
+ WriteNumber(alloc.m_CreationFrameIndex);
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// Private class PoolAllocator
@@ -2073,6 +2120,10 @@
// Allocation object must be deleted externally afterwards.
void FreeHeapMemory(Allocation* allocation);
+ void SetCurrentFrameIndex(UINT frameIndex);
+
+ UINT GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); }
+
void CalculateStats(Stats& outStats);
void BuildStatsString(WCHAR** ppStatsString, BOOL DetailedMap);
@@ -2092,6 +2143,7 @@
ID3D12Device* m_Device;
UINT64 m_PreferredBlockSize;
ALLOCATION_CALLBACKS m_AllocationCallbacks;
+ D3D12MA_ATOMIC_UINT32 m_CurrentFrameIndex;
D3D12_FEATURE_DATA_D3D12_OPTIONS m_D3D12Options;
@@ -2686,25 +2738,19 @@
json.BeginObject(true);
json.WriteString(L"Offset");
json.WriteNumber(suballoc.offset);
- json.WriteString(L"Type");
if(suballoc.type == SUBALLOCATION_TYPE_FREE)
{
+ json.WriteString(L"Type");
json.WriteString(L"FREE");
+ json.WriteString(L"Size");
+ json.WriteNumber(suballoc.size);
}
else
{
- json.WriteString(L"ALLOCATION");
const Allocation* const alloc = suballoc.allocation;
D3D12MA_ASSERT(alloc);
- const WCHAR* const name = alloc->GetName();
- if(name != NULL)
- {
- json.WriteString(L"Name");
- json.WriteString(name);
- }
+ json.AddAllocationToObject(*alloc);
}
- json.WriteString(L"Size");
- json.WriteNumber(suballoc.size);
json.EndObject();
}
json.EndArray();
@@ -3195,7 +3241,8 @@
m_UseMutex((desc.Flags & ALLOCATOR_FLAG_SINGLETHREADED) == 0),
m_Device(desc.pDevice),
m_PreferredBlockSize(desc.PreferredBlockSize != 0 ? desc.PreferredBlockSize : D3D12MA_DEFAULT_BLOCK_SIZE),
- m_AllocationCallbacks(allocationCallbacks)
+ m_AllocationCallbacks(allocationCallbacks),
+ m_CurrentFrameIndex(0)
// Below this line don't use allocationCallbacks but m_AllocationCallbacks!!!
{
// desc.pAllocationCallbacks intentionally ignored here, preprocessed by CreateAllocator.
@@ -3334,7 +3381,7 @@
(void**)&res);
if(SUCCEEDED(hr))
{
- (*ppAllocation)->SetResource(res);
+ (*ppAllocation)->SetResource(res, pResourceDesc);
if(ppvResource != NULL)
{
res->AddRef();
@@ -3447,7 +3494,7 @@
{
Allocation* alloc = D3D12MA_NEW(m_AllocationCallbacks, Allocation)();
alloc->InitCommitted(this, resAllocInfo.SizeInBytes, pAllocDesc->HeapType);
- alloc->SetResource(res);
+ alloc->SetResource(res, pResourceDesc);
*ppAllocation = alloc;
if(ppvResource != NULL)
@@ -3654,6 +3701,11 @@
allocation->m_Heap.heap->Release();
}
+void AllocatorPimpl::SetCurrentFrameIndex(UINT frameIndex)
+{
+ m_CurrentFrameIndex.store(frameIndex);
+}
+
void AllocatorPimpl::CalculateStats(Stats& outStats)
{
// Init stats
@@ -3832,16 +3884,7 @@
D3D12MA_ASSERT(alloc);
json.BeginObject(true);
- json.WriteString(L"Type");
- json.WriteString(L"ALLOCATION");
- json.WriteString(L"Size");
- json.WriteNumber(alloc->GetSize());
- LPCWSTR name = alloc->GetName();
- if(name != NULL)
- {
- json.WriteString(L"Name");
- json.WriteString(name);
- }
+ json.AddAllocationToObject(*alloc);
json.EndObject();
}
json.EndArray();
@@ -3961,16 +4004,22 @@
void Allocation::InitCommitted(AllocatorPimpl* allocator, UINT64 size, D3D12_HEAP_TYPE heapType)
{
+ D3D12MA_ASSERT(allocator);
m_Allocator = allocator;
m_Type = TYPE_COMMITTED;
m_Size = size;
m_Resource = NULL;
m_Name = NULL;
m_Committed.heapType = heapType;
+ m_CreationFrameIndex = allocator->GetCurrentFrameIndex();
+ m_ResourceDimension = D3D12_RESOURCE_DIMENSION_UNKNOWN;
+ m_ResourceFlags = D3D12_RESOURCE_FLAG_NONE;
+ m_TextureLayout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
}
void Allocation::InitPlaced(AllocatorPimpl* allocator, UINT64 size, UINT64 offset, UINT64 alignment, NormalBlock* block)
{
+ D3D12MA_ASSERT(allocator);
m_Allocator = allocator;
m_Type = TYPE_PLACED;
m_Size = size;
@@ -3978,22 +4027,35 @@
m_Name = NULL;
m_Placed.offset = offset;
m_Placed.block = block;
+ m_CreationFrameIndex = allocator->GetCurrentFrameIndex();
+ m_ResourceDimension = D3D12_RESOURCE_DIMENSION_UNKNOWN;
+ m_ResourceFlags = D3D12_RESOURCE_FLAG_NONE;
+ m_TextureLayout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
}
void Allocation::InitHeap(AllocatorPimpl* allocator, UINT64 size, D3D12_HEAP_TYPE heapType, ID3D12Heap* heap)
{
+ D3D12MA_ASSERT(allocator);
m_Allocator = allocator;
m_Type = TYPE_HEAP;
m_Size = size;
m_Name = NULL;
m_Heap.heapType = heapType;
m_Heap.heap = heap;
+ m_CreationFrameIndex = allocator->GetCurrentFrameIndex();
+ m_ResourceDimension = D3D12_RESOURCE_DIMENSION_UNKNOWN;
+ m_ResourceFlags = D3D12_RESOURCE_FLAG_NONE;
+ m_TextureLayout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
}
-void Allocation::SetResource(ID3D12Resource* resource)
+void Allocation::SetResource(ID3D12Resource* resource, const D3D12_RESOURCE_DESC* pResourceDesc)
{
D3D12MA_ASSERT(m_Resource == NULL);
+ D3D12MA_ASSERT(pResourceDesc);
m_Resource = resource;
+ m_ResourceDimension = pResourceDesc->Dimension;
+ m_ResourceFlags = pResourceDesc->Flags;
+ m_TextureLayout = pResourceDesc->Layout;
}
void Allocation::FreeName()
@@ -4076,6 +4138,12 @@
return m_Pimpl->AllocateMemory(pAllocDesc, heapFlags, pAllocInfo, ppAllocation);
}
+void Allocator::SetCurrentFrameIndex(UINT frameIndex)
+{
+ D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK
+ m_Pimpl->SetCurrentFrameIndex(frameIndex);
+}
+
void Allocator::CalculateStats(Stats* pStats)
{
D3D12MA_ASSERT(pStats);
diff --git a/src/D3D12MemAlloc.h b/src/D3D12MemAlloc.h
index bffec84..c78a900 100644
--- a/src/D3D12MemAlloc.h
+++ b/src/D3D12MemAlloc.h
@@ -347,6 +347,7 @@
class AllocatorPimpl;
class NormalBlock;
class BlockVector;
+class JsonWriter;
/// \endcond
/// Pointer to custom callback function that allocates CPU memory.
@@ -474,6 +475,7 @@
private:
friend class AllocatorPimpl;
friend class BlockVector;
+ friend class JsonWriter;
template<typename T> friend void D3D12MA_DELETE(const ALLOCATION_CALLBACKS&, T*);
AllocatorPimpl* m_Allocator;
@@ -486,6 +488,10 @@
} m_Type;
UINT64 m_Size;
ID3D12Resource* m_Resource;
+ D3D12_RESOURCE_DIMENSION m_ResourceDimension;
+ D3D12_RESOURCE_FLAGS m_ResourceFlags;
+ D3D12_TEXTURE_LAYOUT m_TextureLayout;
+ UINT m_CreationFrameIndex;
wchar_t* m_Name;
union
@@ -513,7 +519,7 @@
void InitCommitted(AllocatorPimpl* allocator, UINT64 size, D3D12_HEAP_TYPE heapType);
void InitPlaced(AllocatorPimpl* allocator, UINT64 size, UINT64 offset, UINT64 alignment, NormalBlock* block);
void InitHeap(AllocatorPimpl* allocator, UINT64 size, D3D12_HEAP_TYPE heapType, ID3D12Heap* heap);
- void SetResource(ID3D12Resource* resource);
+ void SetResource(ID3D12Resource* resource, const D3D12_RESOURCE_DESC* pResourceDesc);
void FreeName();
D3D12MA_CLASS_NO_COPY(Allocation)
@@ -675,6 +681,12 @@
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation);
+ /** \brief Sets the index of the current frame.
+
+ This function is used to set the frame index in the allocator when a new game frame begins.
+ */
+ void SetCurrentFrameIndex(UINT frameIndex);
+
/** \brief Retrieves statistics from the current state of the allocator.
*/
void CalculateStats(Stats* pStats);
diff --git a/src/D3D12Sample.cpp b/src/D3D12Sample.cpp
index 5348827..9d8032d 100644
--- a/src/D3D12Sample.cpp
+++ b/src/D3D12Sample.cpp
@@ -1392,6 +1392,15 @@
ExecuteTests();
break;
+ case 'J':
+ {
+ WCHAR* statsString = NULL;
+ g_Allocator->BuildStatsString(&statsString, TRUE);
+ wprintf(L"%s\n", statsString);
+ g_Allocator->FreeStatsString(statsString);
+ }
+ break;
+
case VK_ESCAPE:
PostMessage(g_Wnd, WM_CLOSE, 0, 0);
break;
diff --git a/src/Tests.cpp b/src/Tests.cpp
index 6ae268e..2e69e95 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -20,8 +20,8 @@
// THE SOFTWARE.
//
-#include "Tests.h"
#include "Common.h"
+#include "Tests.h"
#include <thread>
extern ID3D12GraphicsCommandList* BeginCommandList();
@@ -91,6 +91,54 @@
return true;
}
+static void TestFrameIndexAndJson(const TestContext& ctx)
+{
+ const UINT64 bufSize = 32ull * 1024;
+
+ D3D12MA::ALLOCATION_DESC allocDesc = {};
+ allocDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
+ allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_COMMITTED;
+
+ D3D12_RESOURCE_DESC resourceDesc;
+ FillResourceDescForBuffer(resourceDesc, bufSize);
+
+ const UINT BEGIN_INDEX = 10;
+ const UINT END_INDEX = 20;
+ UINT frameIndex = 0;
+ for (UINT frameIndex = BEGIN_INDEX; frameIndex < END_INDEX; ++frameIndex)
+ {
+ ctx.allocator->SetCurrentFrameIndex(frameIndex);
+ D3D12MA::Allocation* alloc = nullptr;
+ CHECK_HR(ctx.allocator->CreateResource(
+ &allocDesc,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_GENERIC_READ,
+ NULL,
+ &alloc,
+ __uuidof(ID3D12Resource),
+ NULL));
+
+ WCHAR* statsString;
+ ctx.allocator->BuildStatsString(&statsString, TRUE);
+ const UINT BUFFER_SIZE = 1024;
+ WCHAR buffer[BUFFER_SIZE];
+ for (UINT testIndex = BEGIN_INDEX; testIndex < END_INDEX; ++testIndex)
+ {
+ swprintf(buffer, BUFFER_SIZE, L"\"CreationFrameIndex\": %u", testIndex);
+ if (testIndex == frameIndex)
+ {
+ CHECK_BOOL(wcsstr(statsString, buffer) != NULL);
+ }
+ else
+ {
+ CHECK_BOOL(wcsstr(statsString, buffer) == NULL);
+ }
+ }
+ ctx.allocator->FreeStatsString(statsString);
+ alloc->Release();
+ }
+}
+
static void TestCommittedResourcesAndJson(const TestContext& ctx)
{
wprintf(L"Test committed resources and JSON\n");
@@ -261,6 +309,77 @@
renderTargetRes.allocation.reset(alloc);
}
+static void TestAliasingMemory(const TestContext& ctx)
+{
+ wprintf(L"Test aliasing memory\n");
+
+ D3D12MA::ALLOCATION_DESC allocDesc = {};
+ allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
+
+ D3D12_RESOURCE_DESC resourceDesc1 = {};
+ resourceDesc1.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ resourceDesc1.Alignment = 0;
+ resourceDesc1.Width = 1920;
+ resourceDesc1.Height = 1080;
+ resourceDesc1.DepthOrArraySize = 1;
+ resourceDesc1.MipLevels = 1;
+ resourceDesc1.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ resourceDesc1.SampleDesc.Count = 1;
+ resourceDesc1.SampleDesc.Quality = 0;
+ resourceDesc1.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ resourceDesc1.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+
+ D3D12_RESOURCE_DESC resourceDesc2 = {};
+ resourceDesc2.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ resourceDesc2.Alignment = 0;
+ resourceDesc2.Width = 1024;
+ resourceDesc2.Height = 1024;
+ resourceDesc2.DepthOrArraySize = 1;
+ resourceDesc2.MipLevels = 0;
+ resourceDesc2.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ resourceDesc2.SampleDesc.Count = 1;
+ resourceDesc2.SampleDesc.Quality = 0;
+ resourceDesc2.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ resourceDesc2.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+
+ const D3D12_RESOURCE_ALLOCATION_INFO allocInfo1 = ctx.device->GetResourceAllocationInfo(0, 1, &resourceDesc1);
+ const D3D12_RESOURCE_ALLOCATION_INFO allocInfo2 = ctx.device->GetResourceAllocationInfo(0, 1, &resourceDesc2);
+
+ D3D12_RESOURCE_ALLOCATION_INFO allocInfo = {};
+ allocInfo.Alignment = std::max(allocInfo1.Alignment, allocInfo2.Alignment);
+ allocInfo.SizeInBytes = std::max(allocInfo1.SizeInBytes, allocInfo2.SizeInBytes);
+
+ D3D12MA::Allocation* allocPtr = NULL;
+ CHECK_HR( ctx.allocator->AllocateMemory(
+ &allocDesc,
+ D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES,
+ &allocInfo,
+ &allocPtr) );
+ AllocationUniquePtr alloc(allocPtr);
+ CHECK_BOOL(allocPtr != NULL && allocPtr->GetHeap() != NULL);
+
+ ID3D12Resource* resPtr = NULL;
+ CHECK_HR( ctx.device->CreatePlacedResource(
+ alloc->GetHeap(),
+ alloc->GetOffset(),
+ &resourceDesc1,
+ D3D12_RESOURCE_STATE_COMMON,
+ NULL, // pOptimizedClearValue
+ IID_PPV_ARGS(&resPtr)) );
+ CComPtr<ID3D12Resource> res1(resPtr);
+ CHECK_BOOL(resPtr != NULL);
+
+ CHECK_HR( ctx.device->CreatePlacedResource(
+ alloc->GetHeap(),
+ alloc->GetOffset(),
+ &resourceDesc2,
+ D3D12_RESOURCE_STATE_COMMON,
+ NULL, // pOptimizedClearValue
+ IID_PPV_ARGS(&resPtr)) );
+ CComPtr<ID3D12Resource> res2(resPtr);
+ CHECK_BOOL(resPtr != NULL);
+}
+
static void TestMapping(const TestContext& ctx)
{
wprintf(L"Test mapping\n");
@@ -632,8 +751,10 @@
static void TestGroupBasics(const TestContext& ctx)
{
+ TestFrameIndexAndJson(ctx);
TestCommittedResourcesAndJson(ctx);
TestPlacedResources(ctx);
+ TestAliasingMemory(ctx);
TestMapping(ctx);
TestStats(ctx);
TestTransfer(ctx);