<p>This is a small, standalone C++ library. It consists of a pair of 2 files: "D3D12MemAlloc.h" header file with public interface and "D3D12MemAlloc.cpp" with internal implementation. The only external dependencies are WinAPI, Direct3D 12, and parts of C/C++ standard library (but STL containers, exceptions, or RTTI are not used).</p>
<p>The library is developed and tested using Microsoft Visual Studio 2019, but it should work with other compilers as well. It is designed for 64-bit code.</p>
<p>To use the library in your project:</p>
<p>(1.) Copy files <code>D3D12MemAlloc.cpp</code>, <code>D3D12MemAlloc.h</code> to your project.</p>
<p>(2.) Make <code>D3D12MemAlloc.cpp</code> compiling as part of the project, as C++ code.</p>
<p>(3.) Include library header in each CPP file that needs to use the library.</p>
</div><!-- fragment --><p>(4.) Right after you created <code>ID3D12Device</code>, fill <aclass="el"href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c.html"title="Parameters of created Allocator object. To be used with CreateAllocator().">D3D12MA::ALLOCATOR_DESC</a> structure and call function <aclass="el"href="namespace_d3_d12_m_a.html#ab7a1cd1683986d75ce1488b0920f4cb0"title="Creates new main D3D12MA::Allocator object and returns it through ppAllocator.">D3D12MA::CreateAllocator</a> to create the main <aclass="el"href="class_d3_d12_m_a_1_1_allocator.html"title="Represents main object of this library initialized for particular ID3D12Device.">D3D12MA::Allocator</a> object.</p>
<p>Please note that all symbols of the library are declared inside <aclass="el"href="namespace_d3_d12_m_a.html">D3D12MA</a> namespace.</p>
<divclass="ttc"id="aclass_d3_d12_m_a_1_1_allocator_html"><divclass="ttname"><ahref="class_d3_d12_m_a_1_1_allocator.html">D3D12MA::Allocator</a></div><divclass="ttdoc">Represents main object of this library initialized for particular ID3D12Device.</div><divclass="ttdef"><b>Definition</b> D3D12MemAlloc.h:1099</div></div>
<divclass="ttc"id="anamespace_d3_d12_m_a_html_ab7a1cd1683986d75ce1488b0920f4cb0"><divclass="ttname"><ahref="namespace_d3_d12_m_a.html#ab7a1cd1683986d75ce1488b0920f4cb0">D3D12MA::CreateAllocator</a></div><divclass="ttdeci">D3D12MA_API HRESULT CreateAllocator(const ALLOCATOR_DESC *pDesc, Allocator **ppAllocator)</div><divclass="ttdoc">Creates new main D3D12MA::Allocator object and returns it through ppAllocator.</div></div>
<divclass="ttc"id="astruct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c_html"><divclass="ttname"><ahref="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c.html">D3D12MA::ALLOCATOR_DESC</a></div><divclass="ttdoc">Parameters of created Allocator object. To be used with CreateAllocator().</div><divclass="ttdef"><b>Definition</b> D3D12MemAlloc.h:1060</div></div>
</div><!-- fragment --><p>(5.) Right before destroying the D3D12 device, destroy the allocator object.</p>
<p>Objects of this library must be destroyed by calling <code>Release</code> method. They are somewhat compatible with COM: they implement <code>IUnknown</code> interface with its virtual methods: <code>AddRef</code>, <code>Release</code>, <code>QueryInterface</code>, and they are reference-counted internally. You can use smart pointers designed for COM with objects of this library - e.g. <code>CComPtr</code> or <code>Microsoft::WRL::ComPtr</code>. The reference counter is thread-safe. <code>QueryInterface</code> method supports only <code>IUnknown</code>, as classes of this library don't define their own GUIDs.</p>
<p>To use the library for creating resources (textures and buffers), call method <aclass="el"href="class_d3_d12_m_a_1_1_allocator.html#aa37d6b9fe8ea0864f7a35b9d68e8345a"title="Allocates memory and creates a D3D12 resource (buffer or texture). This is the main allocation functi...">D3D12MA::Allocator::CreateResource</a> in the place where you would previously call <code>ID3D12Device::CreateCommittedResource</code>.</p>
<p>The function has similar syntax, but it expects structure <aclass="el"href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html"title="Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource.">D3D12MA::ALLOCATION_DESC</a> to be passed along with <code>D3D12_RESOURCE_DESC</code> and other parameters for created resource. This structure describes parameters of the desired memory allocation, including choice of <code>D3D12_HEAP_TYPE</code>.</p>
<p>The function returns a new object of type <aclass="el"href="class_d3_d12_m_a_1_1_allocation.html"title="Represents single memory allocation.">D3D12MA::Allocation</a>. It represents allocated memory and can be queried for size, offset, <code>ID3D12Heap</code>. It also holds a reference to the <code>ID3D12Resource</code>, which can be accessed by calling <aclass="el"href="class_d3_d12_m_a_1_1_allocation.html#ad00308118252f82d8f803c623c67bf18"title="Returns D3D12 resource associated with this object.">D3D12MA::Allocation::GetResource()</a>.</p>
<divclass="ttc"id="aclass_d3_d12_m_a_1_1_allocation_html"><divclass="ttname"><ahref="class_d3_d12_m_a_1_1_allocation.html">D3D12MA::Allocation</a></div><divclass="ttdoc">Represents single memory allocation.</div><divclass="ttdef"><b>Definition</b> D3D12MemAlloc.h:483</div></div>
<divclass="ttc"id="aclass_d3_d12_m_a_1_1_allocator_html_aa37d6b9fe8ea0864f7a35b9d68e8345a"><divclass="ttname"><ahref="class_d3_d12_m_a_1_1_allocator.html#aa37d6b9fe8ea0864f7a35b9d68e8345a">D3D12MA::Allocator::CreateResource</a></div><divclass="ttdeci">HRESULT CreateResource(const ALLOCATION_DESC *pAllocDesc, const D3D12_RESOURCE_DESC *pResourceDesc, D3D12_RESOURCE_STATES InitialResourceState, const D3D12_CLEAR_VALUE *pOptimizedClearValue, Allocation **ppAllocation, REFIID riidResource, void **ppvResource)</div><divclass="ttdoc">Allocates memory and creates a D3D12 resource (buffer or texture). This is the main allocation functi...</div></div>
<divclass="ttc"id="astruct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c_html"><divclass="ttname"><ahref="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html">D3D12MA::ALLOCATION_DESC</a></div><divclass="ttdoc">Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource.</div><divclass="ttdef"><b>Definition</b> D3D12MemAlloc.h:299</div></div>
<divclass="ttc"id="astruct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c_html_aa46b3c0456e5a23edef3328607ebf4d7"><divclass="ttname"><ahref="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html#aa46b3c0456e5a23edef3328607ebf4d7">D3D12MA::ALLOCATION_DESC::HeapType</a></div><divclass="ttdeci">D3D12_HEAP_TYPE HeapType</div><divclass="ttdoc">The type of memory heap where the new allocation should be placed.</div><divclass="ttdef"><b>Definition</b> D3D12MemAlloc.h:308</div></div>
</div><!-- fragment --><p>The advantage of using the allocator instead of creating committed resource, and the main purpose of this library, is that it can decide to allocate bigger memory heap internally using <code>ID3D12Device::CreateHeap</code> and place multiple resources in it, at different offsets, using <code>ID3D12Device::CreatePlacedResource</code>. The library manages its own collection of allocated memory blocks (heaps) and remembers which parts of them are occupied and which parts are free to be used for new resources.</p>
<p>It is important to remember that resources created as placed don't have their memory initialized to zeros, but may contain garbage data, so they need to be fully initialized before usage, e.g. using Clear (<code>ClearRenderTargetView</code>), Discard (<code>DiscardResource</code>), or copy (<code>CopyResource</code>).</p>
<p>The library also automatically handles resource heap tier. When <code>D3D12_FEATURE_DATA_D3D12_OPTIONS::ResourceHeapTier</code> equals <code>D3D12_RESOURCE_HEAP_TIER_1</code>, resources of 3 types: buffers, textures that are render targets or depth-stencil, and other textures must be kept in separate heaps. When <code>D3D12_RESOURCE_HEAP_TIER_2</code>, they can be kept together. By using this library, you don't need to handle this manually.</p>
<p><code>ID3D12Resource</code> and other interfaces of Direct3D 12 use COM, so they are reference-counted. Objects of this library are reference-counted as well. An object of type <aclass="el"href="class_d3_d12_m_a_1_1_allocation.html"title="Represents single memory allocation.">D3D12MA::Allocation</a> remembers the resource (buffer or texture) that was created together with this memory allocation and holds a reference to the <code>ID3D12Resource</code> object. (Note this is a difference to Vulkan Memory Allocator, where a <code>VmaAllocation</code> object has no connection with the buffer or image that was created with it.) Thus, it is important to manage the resource reference counter properly.</p>
<p><b>The simplest use case</b> is shown in the code snippet above. When only <aclass="el"href="class_d3_d12_m_a_1_1_allocation.html"title="Represents single memory allocation.">D3D12MA::Allocation</a> object is obtained from a function call like <aclass="el"href="class_d3_d12_m_a_1_1_allocator.html#aa37d6b9fe8ea0864f7a35b9d68e8345a"title="Allocates memory and creates a D3D12 resource (buffer or texture). This is the main allocation functi...">D3D12MA::Allocator::CreateResource</a>, it remembers the <code>ID3D12Resource</code> that was created with it and holds a reference to it. The resource can be obtained by calling <code>allocation->GetResource()</code>, which doesn't increment the resource reference counter. Calling <code>allocation->Release()</code> will decrease the resource reference counter, which is = 1 in this case, so the resource will be released.</p>
<p><b>Second option</b> is to retrieve a pointer to the resource along with <aclass="el"href="class_d3_d12_m_a_1_1_allocation.html"title="Represents single memory allocation.">D3D12MA::Allocation</a>. Last parameters of the resource creation function can be used for this purpose.</p>
</div><!-- fragment --><p>In this case, returned pointer <code>resource</code> is equal to <code>allocation->GetResource()</code>, but the creation function additionally increases resource reference counter for the purpose of returning it from this call (it actually calls <code>QueryInterface</code> internally), so the resource will have the counter = 2. The resource then need to be released along with the allocation, in this particular order, to make sure the resource is destroyed before its memory heap can potentially be freed.</p>
</div><!-- fragment --><p><b>More advanced use cases</b> are possible when we consider that an <aclass="el"href="class_d3_d12_m_a_1_1_allocation.html"title="Represents single memory allocation.">D3D12MA::Allocation</a> object can just hold a reference to any resource. It can be changed by calling <aclass="el"href="class_d3_d12_m_a_1_1_allocation.html#a414a088c22bae0f29b1038f5f9346d14"title="Releases the resource currently pointed by the allocation (if any), sets it to new one,...">D3D12MA::Allocation::SetResource</a>. This function releases the old resource and calls <code>AddRef</code> on the new one.</p>
<p>Special care must be taken when performing <b>defragmentation</b>. The new resource created at the destination place should be set as <code>pass.pMoves[i].pDstTmpAllocation->SetResource(newRes)</code>, but it is moved to the source allocation at end of the defragmentation pass, while the old resource accessible through <code>pass.pMoves[i].pSrcAllocation->GetResource()</code> is then released. For more information, see documentation chapter <aclass="el"href="defragmentation.html">Defragmentation</a>.</p>
<p>The process of getting regular CPU-side pointer to the memory of a resource in Direct3D is called "mapping". There are rules and restrictions to this process, as described in D3D12 documentation of <code>ID3D12Resource::Map</code> method.</p>
<p>Mapping happens on the level of particular resources, not entire memory heaps, and so it is out of scope of this library. Just as the documentation of the <code>Map</code> function says:</p>
<p>When using this library, you can map and use your resources normally without considering whether they are created as committed resources or placed resources in one large heap.</p>
<p>Example for buffer created and filled in <code>UPLOAD</code> heap type:</p>