Allocate Allocation objects using PoolAllocator
diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp
index e428eaf..eae75d2 100644
--- a/src/D3D12MemAlloc.cpp
+++ b/src/D3D12MemAlloc.cpp
@@ -1183,7 +1183,7 @@
     union Item

     {

         UINT NextFreeIndex; // UINT32_MAX means end of list.

-        T Value;

+        alignas(T) char Value[sizeof(T)];

     };

 

     struct ItemBlock

@@ -1230,7 +1230,9 @@
         {

             Item* const pItem = &block.pItems[block.FirstFreeIndex];

             block.FirstFreeIndex = pItem->NextFreeIndex;

-            return &pItem->Value;

+            T* result = (T*)&pItem->Value;

+            new(result)T(); // Explicit constructor call.

+            return result;

         }

     }

 

@@ -1238,7 +1240,9 @@
     ItemBlock& newBlock = CreateNewBlock();

     Item* const pItem = &newBlock.pItems[0];

     newBlock.FirstFreeIndex = pItem->NextFreeIndex;

-    return &pItem->Value;

+    T* result = (T*)pItem->Value;

+    new(result)T(); // Explicit constructor call.

+    return result;

 }

 

 template<typename T>

@@ -1255,6 +1259,7 @@
         // Check if pItemPtr is in address range of this block.

         if((pItemPtr >= block.pItems) && (pItemPtr < block.pItems + block.Capacity))

         {

+            ptr->~T(); // Explicit destructor call.

             const UINT index = static_cast<UINT>(pItemPtr - block.pItems);

             pItemPtr->NextFreeIndex = block.FirstFreeIndex;

             block.FirstFreeIndex = index;

@@ -1744,6 +1749,26 @@
 }

 

 ////////////////////////////////////////////////////////////////////////////////

+// Private class AllocationObjectAllocator definition

+

+/*

+Thread-safe wrapper over PoolAllocator free list, for allocation of Allocation objects.

+*/

+class AllocationObjectAllocator

+{

+    D3D12MA_CLASS_NO_COPY(AllocationObjectAllocator);

+public:

+    AllocationObjectAllocator(const ALLOCATION_CALLBACKS& allocationCallbacks);

+

+    Allocation* Allocate();

+    void Free(Allocation* alloc);

+

+private:

+    D3D12MA_MUTEX m_Mutex;

+    PoolAllocator<Allocation> m_Allocator;

+};

+

+////////////////////////////////////////////////////////////////////////////////

 // Private class BlockMetadata and derived classes - declarations

 

 enum SuballocationType

@@ -2141,6 +2166,7 @@
     const D3D12_FEATURE_DATA_D3D12_OPTIONS& GetD3D12Options() const { return m_D3D12Options; }

     bool SupportsResourceHeapTier2() const { return m_D3D12Options.ResourceHeapTier >= D3D12_RESOURCE_HEAP_TIER_2; }

     bool UseMutex() const { return m_UseMutex; }

+    AllocationObjectAllocator& GetAllocationObjectAllocator() { return m_AllocationObjectAllocator; }

 

     HRESULT CreateResource(

         const ALLOCATION_DESC* pAllocDesc,

@@ -2201,6 +2227,7 @@
     D3D12MA_ATOMIC_UINT32 m_CurrentFrameIndex;

     DXGI_ADAPTER_DESC m_AdapterDesc;

     D3D12_FEATURE_DATA_D3D12_OPTIONS m_D3D12Options;

+    AllocationObjectAllocator m_AllocationObjectAllocator;

 

     typedef Vector<Allocation*> AllocationVectorType;

     AllocationVectorType* m_pCommittedAllocations[HEAP_TYPE_COUNT];

@@ -3248,7 +3275,7 @@
             m_HasEmptyBlock = false;

         }

 

-        *pAllocation = D3D12MA_NEW(m_hAllocator->GetAllocs(), Allocation)();

+        *pAllocation = m_hAllocator->GetAllocationObjectAllocator().Allocate();

         pBlock->m_pMetadata->Alloc(currRequest, size, *pAllocation);

         (*pAllocation)->InitPlaced(

             m_hAllocator,

@@ -3341,8 +3368,9 @@
 #endif

     m_PreferredBlockSize(desc.PreferredBlockSize != 0 ? desc.PreferredBlockSize : D3D12MA_DEFAULT_BLOCK_SIZE),

     m_AllocationCallbacks(allocationCallbacks),

-    m_CurrentFrameIndex(0)

+    m_CurrentFrameIndex(0),

     // Below this line don't use allocationCallbacks but m_AllocationCallbacks!!!

+    m_AllocationObjectAllocator(m_AllocationCallbacks)

 {

     // desc.pAllocationCallbacks intentionally ignored here, preprocessed by CreateAllocator.

     ZeroMemory(&m_D3D12Options, sizeof(m_D3D12Options));

@@ -3627,7 +3655,7 @@
         pOptimizedClearValue, riidResource, (void**)&res);

     if(SUCCEEDED(hr))

     {

-        Allocation* alloc = D3D12MA_NEW(m_AllocationCallbacks, Allocation)();

+        Allocation* alloc = m_AllocationObjectAllocator.Allocate();

         alloc->InitCommitted(this, resAllocInfo.SizeInBytes, pAllocDesc->HeapType);

         alloc->SetResource(res, pResourceDesc);

 

@@ -3680,7 +3708,7 @@
     HRESULT hr = m_Device->CreateHeap(&heapDesc, __uuidof(*heap), (void**)&heap);

     if(SUCCEEDED(hr))

     {

-        (*ppAllocation) = D3D12MA_NEW(m_AllocationCallbacks, Allocation)();

+        (*ppAllocation) = m_AllocationObjectAllocator.Allocate();

         (*ppAllocation)->InitHeap(this, allocInfo.SizeInBytes, pAllocDesc->HeapType, heap);

         RegisterCommittedAllocation(*ppAllocation, pAllocDesc->HeapType);

 

@@ -4266,7 +4294,7 @@
 

     FreeName();

 

-    D3D12MA_DELETE(m_Allocator->GetAllocs(), this);

+    m_Allocator->GetAllocationObjectAllocator().Free(this);

 }

 

 UINT64 Allocation::GetOffset() const

@@ -4314,14 +4342,14 @@
 

 Allocation::Allocation()

 {

-    // Must be empty because Allocation objects will be allocated out of PoolAllocator

+    // Must be empty because Allocation objects are allocated out of PoolAllocator

     // and may not call constructor and destructor at the right time.

     // Use Init* methods instead.

 }

 

 Allocation::~Allocation()

 {

-    // Must be empty because Allocation objects will be allocated out of PoolAllocator

+    // Must be empty because Allocation objects are allocated out of PoolAllocator

     // and may not call constructor and destructor at the right time.

     // Use Release method instead.

 }

@@ -4394,6 +4422,26 @@
 }

 

 ////////////////////////////////////////////////////////////////////////////////

+// Private class AllocationObjectAllocator implementation

+

+AllocationObjectAllocator::AllocationObjectAllocator(const ALLOCATION_CALLBACKS& allocationCallbacks) :

+    m_Allocator(allocationCallbacks, 1024)

+{

+}

+

+Allocation* AllocationObjectAllocator::Allocate()

+{

+    MutexLock mutexLock(m_Mutex);

+    return m_Allocator.Alloc();

+}

+

+void AllocationObjectAllocator::Free(Allocation* alloc)

+{

+    MutexLock mutexLock(m_Mutex);

+    m_Allocator.Free(alloc);

+}

+

+////////////////////////////////////////////////////////////////////////////////

 // Public class Allocator implementation

 

 Allocator::Allocator(const ALLOCATION_CALLBACKS& allocationCallbacks, const ALLOCATOR_DESC& desc) :

diff --git a/src/D3D12MemAlloc.h b/src/D3D12MemAlloc.h
index 4951f66..1134ac7 100644
--- a/src/D3D12MemAlloc.h
+++ b/src/D3D12MemAlloc.h
@@ -24,7 +24,7 @@
 

 /** \mainpage D3D12 Memory Allocator

 

-<b>Version 2.0.0-development</b> (2019-11-20)

+<b>Version 2.0.0-development</b> (2020-01-22)

 

 Copyright (c) 2019 Advanced Micro Devices, Inc. All rights reserved. \n

 License: MIT

@@ -490,6 +490,7 @@
     friend class BlockVector;

     friend class JsonWriter;

     template<typename T> friend void D3D12MA_DELETE(const ALLOCATION_CALLBACKS&, T*);

+    template<typename T> friend class PoolAllocator;

 

     AllocatorPimpl* m_Allocator;

     enum Type