blob: 2bcad3b5ecd0c8e1a5dff46484dccc0aa4341b31 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.9.1"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Direct3D 12 Memory Allocator: Quick start</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">Direct3D 12 Memory Allocator
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.1 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
initMenu('',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div id="nav-path" class="navpath">
<ul>
<li class="navelem"><a class="el" href="index.html">D3D12 Memory Allocator</a></li> </ul>
</div>
</div><!-- top -->
<div class="PageDoc"><div class="header">
<div class="headertitle">
<div class="title">Quick start </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h1><a class="anchor" id="quick_start_project_setup"></a>
Project setup and initialization</h1>
<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 class="fragment"><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="_d3_d12_mem_alloc_8h.html">D3D12MemAlloc.h</a>&quot;</span></div>
<div class="ttc" id="a_d3_d12_mem_alloc_8h_html"><div class="ttname"><a href="_d3_d12_mem_alloc_8h.html">D3D12MemAlloc.h</a></div></div>
</div><!-- fragment --><p>(4.) Right after you created <code>ID3D12Device</code>, fill <a class="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 <a class="el" href="namespace_d3_d12_m_a.html#aa341b796fdffb16c976e659ccce80332" title="Creates new main D3D12MA::Allocator object and returns it through ppAllocator.">D3D12MA::CreateAllocator</a> to create the main <a class="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 <a class="el" href="namespace_d3_d12_m_a.html">D3D12MA</a> namespace.</p>
<div class="fragment"><div class="line">IDXGIAdapter* adapter = (...)</div>
<div class="line">ID3D12Device* device = (...)</div>
<div class="line"> </div>
<div class="line"><a class="code" href="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> allocatorDesc = {};</div>
<div class="line">allocatorDesc.<a class="code" href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c.html#ada1bf21205065b3aa0284b5a9ee1cb3c">pDevice</a> = device;</div>
<div class="line">allocatorDesc.<a class="code" href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c.html#abf9a9f87f0ffea52816efd363c5fcd7b">pAdapter</a> = adapter;</div>
<div class="line"> </div>
<div class="line"><a class="code" href="class_d3_d12_m_a_1_1_allocator.html">D3D12MA::Allocator</a>* allocator;</div>
<div class="line">HRESULT hr = <a class="code" href="namespace_d3_d12_m_a.html#aa341b796fdffb16c976e659ccce80332">D3D12MA::CreateAllocator</a>(&amp;allocatorDesc, &amp;allocator);</div>
<div class="ttc" id="aclass_d3_d12_m_a_1_1_allocator_html"><div class="ttname"><a href="class_d3_d12_m_a_1_1_allocator.html">D3D12MA::Allocator</a></div><div class="ttdoc">Represents main object of this library initialized for particular ID3D12Device.</div><div class="ttdef"><b>Definition:</b> D3D12MemAlloc.h:659</div></div>
<div class="ttc" id="anamespace_d3_d12_m_a_html_aa341b796fdffb16c976e659ccce80332"><div class="ttname"><a href="namespace_d3_d12_m_a.html#aa341b796fdffb16c976e659ccce80332">D3D12MA::CreateAllocator</a></div><div class="ttdeci">HRESULT CreateAllocator(const ALLOCATOR_DESC *pDesc, Allocator **ppAllocator)</div><div class="ttdoc">Creates new main D3D12MA::Allocator object and returns it through ppAllocator.</div></div>
<div class="ttc" id="astruct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c_html"><div class="ttname"><a href="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><div class="ttdoc">Parameters of created Allocator object. To be used with CreateAllocator().</div><div class="ttdef"><b>Definition:</b> D3D12MemAlloc.h:540</div></div>
<div class="ttc" id="astruct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c_html_abf9a9f87f0ffea52816efd363c5fcd7b"><div class="ttname"><a href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c.html#abf9a9f87f0ffea52816efd363c5fcd7b">D3D12MA::ALLOCATOR_DESC::pAdapter</a></div><div class="ttdeci">IDXGIAdapter * pAdapter</div><div class="ttdef"><b>Definition:</b> D3D12MemAlloc.h:566</div></div>
<div class="ttc" id="astruct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c_html_ada1bf21205065b3aa0284b5a9ee1cb3c"><div class="ttname"><a href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c.html#ada1bf21205065b3aa0284b5a9ee1cb3c">D3D12MA::ALLOCATOR_DESC::pDevice</a></div><div class="ttdeci">ID3D12Device * pDevice</div><div class="ttdef"><b>Definition:</b> D3D12MemAlloc.h:548</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>
<div class="fragment"><div class="line">allocator-&gt;Release();</div>
</div><!-- fragment --><h1><a class="anchor" id="quick_start_creating_resources"></a>
Creating resources</h1>
<p>To use the library for creating resources (textures and buffers), call method <a class="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 <a class="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 also returns a new object of type <a class="el" href="class_d3_d12_m_a_1_1_allocation.html" title="Represents single memory allocation.">D3D12MA::Allocation</a>, created along with usual <code>ID3D12Resource</code>. It represents allocated memory and can be queried for size, offset, <code>ID3D12Resource</code>, and <code>ID3D12Heap</code> if needed.</p>
<div class="fragment"><div class="line">D3D12_RESOURCE_DESC resourceDesc = {};</div>
<div class="line">resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;</div>
<div class="line">resourceDesc.Alignment = 0;</div>
<div class="line">resourceDesc.Width = 1024;</div>
<div class="line">resourceDesc.Height = 1024;</div>
<div class="line">resourceDesc.DepthOrArraySize = 1;</div>
<div class="line">resourceDesc.MipLevels = 1;</div>
<div class="line">resourceDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;</div>
<div class="line">resourceDesc.SampleDesc.Count = 1;</div>
<div class="line">resourceDesc.SampleDesc.Quality = 0;</div>
<div class="line">resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;</div>
<div class="line">resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;</div>
<div class="line"> </div>
<div class="line"><a class="code" href="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> allocationDesc = {};</div>
<div class="line">allocDesc.<a class="code" href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html#aa46b3c0456e5a23edef3328607ebf4d7">HeapType</a> = D3D12_HEAP_TYPE_DEFAULT;</div>
<div class="line"> </div>
<div class="line">D3D12Resource* resource;</div>
<div class="line"><a class="code" href="class_d3_d12_m_a_1_1_allocation.html">D3D12MA::Allocation</a>* allocation;</div>
<div class="line">HRESULT hr = allocator-&gt;<a class="code" href="class_d3_d12_m_a_1_1_allocator.html#aa37d6b9fe8ea0864f7a35b9d68e8345a">CreateResource</a>(</div>
<div class="line"> &amp;allocationDesc,</div>
<div class="line"> &amp;resourceDesc,</div>
<div class="line"> D3D12_RESOURCE_STATE_COPY_DEST,</div>
<div class="line"> NULL,</div>
<div class="line"> &amp;allocation,</div>
<div class="line"> IID_PPV_ARGS(&amp;resource));</div>
<div class="ttc" id="aclass_d3_d12_m_a_1_1_allocation_html"><div class="ttname"><a href="class_d3_d12_m_a_1_1_allocation.html">D3D12MA::Allocation</a></div><div class="ttdoc">Represents single memory allocation.</div><div class="ttdef"><b>Definition:</b> D3D12MemAlloc.h:256</div></div>
<div class="ttc" id="aclass_d3_d12_m_a_1_1_allocator_html_aa37d6b9fe8ea0864f7a35b9d68e8345a"><div class="ttname"><a href="class_d3_d12_m_a_1_1_allocator.html#aa37d6b9fe8ea0864f7a35b9d68e8345a">D3D12MA::Allocator::CreateResource</a></div><div class="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><div class="ttdoc">Allocates memory and creates a D3D12 resource (buffer or texture). This is the main allocation functi...</div></div>
<div class="ttc" id="astruct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c_html"><div class="ttname"><a href="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><div class="ttdoc">Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource.</div><div class="ttdef"><b>Definition:</b> D3D12MemAlloc.h:207</div></div>
<div class="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"><div class="ttname"><a href="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><div class="ttdeci">D3D12_HEAP_TYPE HeapType</div><div class="ttdoc">The type of memory heap where the new allocation should be placed.</div><div class="ttdef"><b>Definition:</b> D3D12MemAlloc.h:216</div></div>
</div><!-- fragment --><p>You need to remember both resource and allocation objects and destroy them separately when no longer needed.</p>
<div class="fragment"><div class="line">allocation-&gt;Release();</div>
<div class="line">resource-&gt;Release();</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>
<h1><a class="anchor" id="quick_start_mapping_memory"></a>
Mapping memory</h1>
<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 <a href="https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12resource-map">ID3D12Resource::Map method</a>.</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 linked documentation says:</p>
<ul>
<li>Returned pointer refers to data of particular subresource, not entire memory heap.</li>
<li>You can map same resource multiple times. It is ref-counted internally.</li>
<li>Mapping is thread-safe.</li>
<li>Unmapping is not required before resource destruction.</li>
<li>Unmapping may not be required before using written data - some heap types on some platforms support resources persistently mapped.</li>
</ul>
<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>
<div class="fragment"><div class="line"><span class="keyword">const</span> UINT64 bufSize = 65536;</div>
<div class="line"><span class="keyword">const</span> <span class="keywordtype">float</span>* bufData = (...);</div>
<div class="line"> </div>
<div class="line">D3D12_RESOURCE_DESC resourceDesc = {};</div>
<div class="line">resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;</div>
<div class="line">resourceDesc.Alignment = 0;</div>
<div class="line">resourceDesc.Width = bufSize;</div>
<div class="line">resourceDesc.Height = 1;</div>
<div class="line">resourceDesc.DepthOrArraySize = 1;</div>
<div class="line">resourceDesc.MipLevels = 1;</div>
<div class="line">resourceDesc.Format = DXGI_FORMAT_UNKNOWN;</div>
<div class="line">resourceDesc.SampleDesc.Count = 1;</div>
<div class="line">resourceDesc.SampleDesc.Quality = 0;</div>
<div class="line">resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;</div>
<div class="line">resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;</div>
<div class="line"> </div>
<div class="line"><a class="code" href="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> allocationDesc = {};</div>
<div class="line">allocationDesc.<a class="code" href="struct_d3_d12_m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html#aa46b3c0456e5a23edef3328607ebf4d7">HeapType</a> = D3D12_HEAP_TYPE_UPLOAD;</div>
<div class="line"> </div>
<div class="line">D3D12Resource* resource;</div>
<div class="line"><a class="code" href="class_d3_d12_m_a_1_1_allocation.html">D3D12MA::Allocation</a>* allocation;</div>
<div class="line">HRESULT hr = allocator-&gt;<a class="code" href="class_d3_d12_m_a_1_1_allocator.html#aa37d6b9fe8ea0864f7a35b9d68e8345a">CreateResource</a>(</div>
<div class="line"> &amp;allocationDesc,</div>
<div class="line"> &amp;resourceDesc,</div>
<div class="line"> D3D12_RESOURCE_STATE_GENERIC_READ,</div>
<div class="line"> NULL,</div>
<div class="line"> &amp;allocation,</div>
<div class="line"> IID_PPV_ARGS(&amp;resource));</div>
<div class="line"> </div>
<div class="line"><span class="keywordtype">void</span>* mappedPtr;</div>
<div class="line">hr = resource-&gt;Map(0, NULL, &amp;mappedPtr);</div>
<div class="line"> </div>
<div class="line">memcpy(mappedPtr, bufData, bufSize);</div>
<div class="line"> </div>
<div class="line">resource-&gt;Unmap(0, NULL);</div>
</div><!-- fragment --> </div></div><!-- contents -->
</div><!-- PageDoc -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.1
</small></address>
</body>
</html>