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);