diff --git a/CMakeLists.txt b/CMakeLists.txt index 40a45d8..831d43f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.25) -project(D3D12MemoryAllocator VERSION 3.0.1) +project(D3D12MemoryAllocator VERSION 3.0.2) set_property(GLOBAL PROPERTY USE_FOLDERS ON) diff --git a/README.md b/README.md index 053d0a7..87964cc 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Easy to integrate memory allocation library for Direct3D 12. **Changelog:** See [CHANGELOG.md](CHANGELOG.md) -**Product page:** [D3D12 Memory Allocator on GPUOpen](https://gpuopen.com/gaming-product/d3d12-memory-allocator/) +**Product page:** [D3D12 Memory Allocator on GPUOpen](https://gpuopen.com/d3d12-memory-allocator/) [](http://isitmaintained.com/project/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator "Average time to resolve an issue") diff --git a/docs/html/_d3_d12_mem_alloc_8h.html b/docs/html/_d3_d12_mem_alloc_8h.html index dea8ef7..99d4b5a 100644 --- a/docs/html/_d3_d12_mem_alloc_8h.html +++ b/docs/html/_d3_d12_mem_alloc_8h.html @@ -3,15 +3,13 @@
- +#include <d3d12.h>#include <dxgi1_4.h>
+Classesstruct | D3D12MA::ALLOCATION_CALLBACKS | | Custom callbacks to CPU memory allocation functions. More... | | struct | D3D12MA::ALLOCATION_DESC | | Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource. More... | | struct | D3D12MA::Statistics | | Calculated statistics of memory usage e.g. in a specific memory heap type, memory segment group, custom pool, or total. More... | | struct | D3D12MA::DetailedStatistics | | More detailed statistics than D3D12MA::Statistics. More... | | struct | D3D12MA::TotalStatistics | | General statistics from current state of the allocator - total memory usage across all memory heaps and segments. More... | | struct | D3D12MA::Budget | | Statistics of current memory usage and available budget for a specific memory segment group. More... | | struct | D3D12MA::VirtualAllocation | | Represents single memory allocation done inside VirtualBlock. More... | | class | D3D12MA::Allocation | | Represents single memory allocation. More... | | struct | D3D12MA::DEFRAGMENTATION_DESC | | Parameters for defragmentation. More... | | struct | D3D12MA::DEFRAGMENTATION_MOVE | | Single move of an allocation to be done for defragmentation. More... | | struct | D3D12MA::DEFRAGMENTATION_PASS_MOVE_INFO | | Parameters for incremental defragmentation steps. More... | | struct | D3D12MA::DEFRAGMENTATION_STATS | | Statistics returned for defragmentation process by function DefragmentationContext::GetStats(). More... | | class | D3D12MA::DefragmentationContext | | Represents defragmentation process in progress. More... | | struct | D3D12MA::POOL_DESC | | Parameters of created D3D12MA::Pool object. To be used with D3D12MA::Allocator::CreatePool. More... | | class | D3D12MA::Pool | | Custom memory pool. More... | | struct | D3D12MA::ALLOCATOR_DESC | | Parameters of created Allocator object. To be used with CreateAllocator(). More... | | class | D3D12MA::Allocator | | Represents main object of this library initialized for particular | ID3D12Device. More... | struct | D3D12MA::VIRTUAL_BLOCK_DESC | class | D3D12MA::Allocator | | Represents main object of this library initialized for particular ID3D12Device. More... | | Parameters of created D3D12MA::VirtualBlock object to be passed to CreateVirtualBlock(). More... | | struct | D3D12MA::VIRTUAL_ALLOCATION_DESC | | Parameters of created virtual allocation to be passed to VirtualBlock::Allocate(). More... | | struct | D3D12MA::VIRTUAL_ALLOCATION_INFO | | Parameters of an existing virtual allocation, returned by VirtualBlock::GetAllocationInfo(). More... | | class | D3D12MA::VirtualBlock | | Represents pure allocation algorithm and a data structure with allocations in some memory block, without actually allocating any GPU memory. More... | | struct | D3D12MA::CALLOCATION_DESC | | Helper structure that helps with complete and conscise initialization of the D3D12MA::ALLOCATION_DESC structure. More... | | struct | D3D12MA::CPOOL_DESC | | Helper structure that helps with complete and conscise initialization of the D3D12MA::POOL_DESC structure. More... | | struct | D3D12MA::CVIRTUAL_BLOCK_DESC | | Helper structure that helps with complete and conscise initialization of the D3D12MA::VIRTUAL_BLOCK_DESC structure. More... | | struct | D3D12MA::CVIRTUAL_ALLOCATION_DESC | | Helper structure that helps with complete and conscise initialization of the D3D12MA::VIRTUAL_ALLOCATION_DESC structure. More... | | struct | D3D12MA::ALLOCATION_CALLBACKS | struct | D3D12MA::ALLOCATION_DESC | struct | D3D12MA::Statistics | struct | D3D12MA::DetailedStatistics | struct | D3D12MA::TotalStatistics | struct | D3D12MA::Budget | struct | D3D12MA::VirtualAllocation | class | D3D12MA::Allocation | struct | D3D12MA::DEFRAGMENTATION_DESC | struct | D3D12MA::DEFRAGMENTATION_MOVE | struct | D3D12MA::DEFRAGMENTATION_PASS_MOVE_INFO | struct | D3D12MA::DEFRAGMENTATION_STATS | class | D3D12MA::DefragmentationContext | struct | D3D12MA::POOL_DESC | class | D3D12MA::Pool | struct | D3D12MA::ALLOCATOR_DESC | struct | D3D12MA::VIRTUAL_BLOCK_DESC | struct | D3D12MA::VIRTUAL_ALLOCATION_DESC | struct | D3D12MA::VIRTUAL_ALLOCATION_INFO | class | D3D12MA::VirtualBlock | struct | D3D12MA::CALLOCATION_DESC | struct | D3D12MA::CPOOL_DESC | struct | D3D12MA::CVIRTUAL_BLOCK_DESC | struct | D3D12MA::CVIRTUAL_ALLOCATION_DESC | |||||||||||||||||||||||||||||
+Namespacesnamespace | D3D12MA | | | namespace | D3D12MA | ||||
+Macros | Define this macro to 0 to disable usage of DXGI 1.4 (which is used for IDXGIAdapter3 and query for memory budget). | | This macro is defined to 0 or 1 automatically. Define it to 0 to disable support for D3D12_HEAP_FLAG_CREATE_NOT_ZEROED. | | When defined to value other than 0, the library will try to use D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT or D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT for created textures when possible, which can save memory because some small textures may get their alignment 4 KB and their size a multiply of 4 KB instead of 64 KB. | #define | D3D12MA_RECOMMENDED_ALLOCATOR_FLAGS (D3D12MA::ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED | D3D12MA::ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED) | | #define | D3D12MA_RECOMMENDED_HEAP_FLAGS (D3D12_HEAP_FLAG_NONE) | | #define | D3D12MA_RECOMMENDED_POOL_FLAGS (D3D12MA::POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED) | | | ||||||||||||||||||||||||||||||
IDXGIAdapter3 and query for memory budget). D3D12_HEAP_FLAG_CREATE_NOT_ZEROED. D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT or D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT for created textures when possible, which can save memory because some small textures may get their alignment 4 KB and their size a multiply of 4 KB instead of 64 KB.
+Typedefstypedef UINT64 | D3D12MA::AllocHandle | | using | D3D12MA::ALLOCATE_FUNC_PTR = void* (*)(size_t Size, size_t Alignment, void* pPrivateData) | | using | D3D12MA::FREE_FUNC_PTR = void (*)(void* pMemory, void* pPrivateData) | | | ||||||||||||
+Functions | Creates new main D3D12MA::Allocator object and returns it through ppAllocator. | | Creates new D3D12MA::VirtualBlock object and returns it through ppVirtualBlock. | | |||||||||||||||
ppAllocator. ppVirtualBlock. This macro is defined to 0 or 1 automatically. Define it to 0 to disable support for D3D12_HEAP_FLAG_CREATE_NOT_ZEROED.
This macro is defined to 0 or 1 automatically. Define it to 0 to disable support for D3D12_HEAP_FLAG_CREATE_NOT_ZEROED.
Define this macro to 0 to disable usage of DXGI 1.4 (which is used for IDXGIAdapter3 and query for memory budget).
Define this macro to 0 to disable usage of DXGI 1.4 (which is used for IDXGIAdapter3 and query for memory budget).
@@ -395,11 +338,11 @@When defined to value other than 0, the library will try to use D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT or D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT for created textures when possible, which can save memory because some small textures may get their alignment 4 KB and their size a multiply of 4 KB instead of 64 KB.
When defined to value other than 0, the library will try to use D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT or D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT for created textures when possible, which can save memory because some small textures may get their alignment 4 KB and their size a multiply of 4 KB instead of 64 KB.
#define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 0 - Disables small texture alignment.#define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 1 (the default) - Enables conservative algorithm that will use small alignment only for some textures that are surely known to support it.#define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 2 - Enables query for small alignment to D3D12 (based on Microsoft sample) which will enable small alignment for more textures, but will also generate D3D Debug Layer error #721 on call to ID3D12Device::GetResourceAllocationInfo, which you should just ignore. | ▼ND3D12MA | |
| ND3D12MA | |
| CAllocation | Represents single memory allocation |
| CALLOCATION_CALLBACKS | Custom callbacks to CPU memory allocation functions |
| CALLOCATION_DESC | Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource |
| CAllocator | Represents main object of this library initialized for particular ID3D12Device |
| CAllocator | Represents main object of this library initialized for particular ID3D12Device |
| CALLOCATOR_DESC | Parameters of created Allocator object. To be used with CreateAllocator() |
| CBudget | Statistics of current memory usage and available budget for a specific memory segment group |
| CCALLOCATION_DESC | Helper structure that helps with complete and conscise initialization of the D3D12MA::ALLOCATION_DESC structure |
+Public Member FunctionsUINT64 | GetOffset () const | | UINT64 | GetAlignment () const | | UINT64 | GetSize () const | | ID3D12Resource * | GetResource () const | | void | SetResource (ID3D12Resource *pResource) | | ID3D12Heap * | GetHeap () const | | void | SetPrivateData (void *pPrivateData) | | void * | GetPrivateData () const | | void | SetName (LPCWSTR Name) | | LPCWSTR | GetName () const | | | |||||||||||||||||||||||||||||||||
Represents single memory allocation.
It may be either implicit memory heap dedicated to a single resource or a specific region of a bigger heap plus unique offset.
To create such object, fill structure D3D12MA::ALLOCATION_DESC and call function Allocator::CreateResource.
The object remembers size and some other information. To retrieve this information, use methods of this class.
-The object also remembers ID3D12Resource and "owns" a reference to it, so it calls Release() on the resource when destroyed.
The object also remembers ID3D12Resource and "owns" a reference to it, so it calls Release() on the resource when destroyed.
+ID3D12Device::GetResourceAllocationInfo.
+ID3D12Resource::GetGPUVirtualAddress() + Allocation::GetSize() to overlap in memory and still work correctly. Represents main object of this library initialized for particular ID3D12Device.
+
Represents main object of this library initialized for particular ID3D12Device. More...
#include <D3D12MemAlloc.h>
+Public Member Functionsconst D3D12_FEATURE_DATA_D3D12_OPTIONS & | GetD3D12Options () const | | | Returns true if D3D12_FEATURE_DATA_ARCHITECTURE1::UMA was found to be true. | | Returns true if D3D12_FEATURE_DATA_ARCHITECTURE1::CacheCoherentUMA was found to be true. | BOOL | IsGPUUploadHeapSupported () const | | UINT64 | GetMemoryCapacity (UINT memorySegmentGroup) const | | 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) | | | Similar to Allocator::CreateResource, but supports new structure D3D12_RESOURCE_DESC1. | HRESULT | CreateResource3 (const ALLOCATION_DESC *pAllocDesc, const D3D12_RESOURCE_DESC1 *pResourceDesc, D3D12_BARRIER_LAYOUT InitialLayout, const D3D12_CLEAR_VALUE *pOptimizedClearValue, UINT32 NumCastableFormats, const DXGI_FORMAT *pCastableFormats, Allocation **ppAllocation, REFIID riidResource, void **ppvResource) | | HRESULT | AllocateMemory (const ALLOCATION_DESC *pAllocDesc, const D3D12_RESOURCE_ALLOCATION_INFO *pAllocInfo, Allocation **ppAllocation) | | HRESULT | CreateAliasingResource (Allocation *pAllocation, UINT64 AllocationLocalOffset, const D3D12_RESOURCE_DESC *pResourceDesc, D3D12_RESOURCE_STATES InitialResourceState, const D3D12_CLEAR_VALUE *pOptimizedClearValue, REFIID riidResource, void **ppvResource) | | | Similar to Allocator::CreateAliasingResource, but supports new structure D3D12_RESOURCE_DESC1. | HRESULT | CreateAliasingResource2 (Allocation *pAllocation, UINT64 AllocationLocalOffset, const D3D12_RESOURCE_DESC1 *pResourceDesc, D3D12_BARRIER_LAYOUT InitialLayout, const D3D12_CLEAR_VALUE *pOptimizedClearValue, UINT32 NumCastableFormats, const DXGI_FORMAT *pCastableFormats, REFIID riidResource, void **ppvResource) | | HRESULT | CreatePool (const POOL_DESC *pPoolDesc, Pool **ppPool) | | void | SetCurrentFrameIndex (UINT frameIndex) | | void | GetBudget (Budget *pLocalBudget, Budget *pNonLocalBudget) | | void | CalculateStatistics (TotalStatistics *pStats) | | void | BuildStatsString (WCHAR **ppStatsString, BOOL DetailedMap) const | | void | FreeStatsString (WCHAR *pStatsString) const | | void | BeginDefragmentation (const DEFRAGMENTATION_DESC *pDesc, DefragmentationContext **ppContext) | | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
D3D12_FEATURE_DATA_ARCHITECTURE1::UMA was found to be true. D3D12_FEATURE_DATA_ARCHITECTURE1::CacheCoherentUMA was found to be true. D3D12_RESOURCE_DESC1. D3D12_RESOURCE_DESC1. Represents main object of this library initialized for particular ID3D12Device.
Fill structure D3D12MA::ALLOCATOR_DESC and call function CreateAllocator() to create it. Call method Release() to destroy it.
It is recommended to create just one object of this type per ID3D12Device object, right after Direct3D 12 is initialized and keep it alive until before Direct3D device is destroyed.
Represents main object of this library initialized for particular ID3D12Device.
+Fill structure D3D12MA::ALLOCATOR_DESC and call function CreateAllocator() to create it. Call method Release() to destroy it.
+It is recommended to create just one object of this type per ID3D12Device object, right after Direct3D 12 is initialized and keep it alive until before Direct3D device is destroyed.
+Allocates memory without creating any resource placed in it.
-This function is similar to ID3D12Device::CreateHeap, but it may really assign part of a larger, existing heap to the allocation.
pAllocDesc->heapFlags should contain one of these values, depending on type of resources you are going to create in this memory: D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES, D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES. Except if you validate that ResourceHeapTier = 2 - then heapFlags may be D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES = 0. Additional flags in heapFlags are allowed as well.
pAllocInfo->SizeInBytes must be multiply of 64KB. pAllocInfo->Alignment must be one of the legal values as described in documentation of D3D12_HEAP_DESC.
This function is similar to ID3D12Device::CreateHeap, but it may really assign part of a larger, existing heap to the allocation.
+pAllocDesc->heapFlags should contain one of these values, depending on type of resources you are going to create in this memory: D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES, D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES. Except if you validate that ResourceHeapTier = 2 - then heapFlags may be D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES = 0. Additional flags in heapFlags are allowed as well.
+pAllocInfo->SizeInBytes must be multiply of 64KB. pAllocInfo->Alignment must be one of the legal values as described in documentation of D3D12_HEAP_DESC.
If you use D3D12MA::ALLOCATION_FLAG_COMMITTED you will get a separate memory block - a heap that always has offset 0.
@@ -257,7 +225,7 @@| [out] | ppStatsString | Must be freed using Allocator::FreeStatsString. |
| DetailedMap | TRUE to include full list of allocations (can make the string quite long), FALSE to only return statistics. | |
| DetailedMap | TRUE to include full list of allocations (can make the string quite long), FALSE to only return statistics. |
| pAllocation | Existing allocation indicating the memory where the new resource should be created. It can be created using D3D12MA::Allocator::CreateResource and already have a resource bound to it, or can be a raw memory allocated with D3D12MA::Allocator::AllocateMemory. It must not be created as committed so that ID3D12Heap is available and not implicit. | |
| AllocationLocalOffset | Additional offset in bytes to be applied when allocating the resource. Local from the start of pAllocation, not the beginning of the whole ID3D12Heap! If the new resource should start from the beginning of the pAllocation it should be 0. | |
| pAllocation | Existing allocation indicating the memory where the new resource should be created. It can be created using D3D12MA::Allocator::CreateResource and already have a resource bound to it, or can be a raw memory allocated with D3D12MA::Allocator::AllocateMemory. It must not be created as committed so that ID3D12Heap is available and not implicit. | |
| AllocationLocalOffset | Additional offset in bytes to be applied when allocating the resource. Local from the start of pAllocation, not the beginning of the whole ID3D12Heap! If the new resource should start from the beginning of the pAllocation it should be 0. | |
| pResourceDesc | Description of the new resource to be created. | |
| InitialResourceState | ||
| pOptimizedClearValue | ||
| riidResource | ||
| [out] | ppvResource | Returns pointer to the new resource. The resource is not bound with pAllocation. This pointer must not be null - you must get the resource pointer and Release it when no longer needed. |
| [out] | ppvResource | Returns pointer to the new resource. The resource is not bound with pAllocation. This pointer must not be null - you must get the resource pointer and Release it when no longer needed. |
Memory requirements of the new resource are checked for validation. If its size exceeds the end of pAllocation or required alignment is not fulfilled considering pAllocation->GetOffset() + AllocationLocalOffset, the function returns E_INVALIDARG.
Memory requirements of the new resource are checked for validation. If its size exceeds the end of pAllocation or required alignment is not fulfilled considering pAllocation->GetOffset() + AllocationLocalOffset, the function returns E_INVALIDARG.
@@ -390,9 +358,9 @@Similar to Allocator::CreateAliasingResource, but supports new structure D3D12_RESOURCE_DESC1.
It internally uses ID3D12Device8::CreatePlacedResource1.
To work correctly, ID3D12Device8 interface must be available in the current system. Otherwise, E_NOINTERFACE is returned.
Similar to Allocator::CreateAliasingResource, but supports new structure D3D12_RESOURCE_DESC1.
+It internally uses ID3D12Device8::CreatePlacedResource1.
+To work correctly, ID3D12Device8 interface must be available in the current system. Otherwise, E_NOINTERFACE is returned.
@@ -451,8 +419,8 @@Similar to Allocator::CreateAliasingResource1, but there are initial layout instead of state and castable formats list.
-It internally uses ID3D12Device10::CreatePlacedResource2.
To work correctly, ID3D12Device10 interface must be available in the current system. Otherwise, E_NOINTERFACE is returned. If you use pCastableFormats, ID3D12Device12 must albo be available.
It internally uses ID3D12Device10::CreatePlacedResource2.
+To work correctly, ID3D12Device10 interface must be available in the current system. Otherwise, E_NOINTERFACE is returned. If you use pCastableFormats, ID3D12Device12 must albo be available.
@@ -524,9 +492,9 @@Allocates memory and creates a D3D12 resource (buffer or texture). This is the main allocation function.
-The function is similar to ID3D12Device::CreateCommittedResource, but it may really call ID3D12Device::CreatePlacedResource to assign part of a larger, existing memory heap to the new resource, which is the main purpose of this whole library.
If ppvResource is null, you receive only ppAllocation object from this function. It holds pointer to ID3D12Resource that can be queried using function D3D12MA::Allocation::GetResource(). Reference count of the resource object is 1. It is automatically destroyed when you destroy the allocation object.
If ppvResource is not null, you receive pointer to the resource next to allocation object. Reference count of the resource object is then increased by calling QueryInterface, so you need to manually Release it along with the allocation.
The function is similar to ID3D12Device::CreateCommittedResource, but it may really call ID3D12Device::CreatePlacedResource to assign part of a larger, existing memory heap to the new resource, which is the main purpose of this whole library.
+If ppvResource is null, you receive only ppAllocation object from this function. It holds pointer to ID3D12Resource that can be queried using function D3D12MA::Allocation::GetResource(). Reference count of the resource object is 1. It is automatically destroyed when you destroy the allocation object.
+If ppvResource is not null, you receive pointer to the resource next to allocation object. Reference count of the resource object is then increased by calling QueryInterface, so you need to manually Release it along with the allocation.
Similar to Allocator::CreateResource, but supports new structure D3D12_RESOURCE_DESC1.
It internally uses ID3D12Device8::CreateCommittedResource2 or ID3D12Device8::CreatePlacedResource1.
To work correctly, ID3D12Device8 interface must be available in the current system. Otherwise, E_NOINTERFACE is returned.
Similar to Allocator::CreateResource, but supports new structure D3D12_RESOURCE_DESC1.
+It internally uses ID3D12Device8::CreateCommittedResource2 or ID3D12Device8::CreatePlacedResource1.
+To work correctly, ID3D12Device8 interface must be available in the current system. Otherwise, E_NOINTERFACE is returned.
@@ -648,8 +616,8 @@Similar to Allocator::CreateResource2, but there are initial layout instead of state and castable formats list.
-It internally uses ID3D12Device10::CreateCommittedResource3 or ID3D12Device10::CreatePlacedResource2.
To work correctly, ID3D12Device10 interface must be available in the current system. Otherwise, E_NOINTERFACE is returned. If you use pCastableFormats, ID3D12Device12 must albo be available.
It internally uses ID3D12Device10::CreateCommittedResource3 or ID3D12Device10::CreatePlacedResource2.
+To work correctly, ID3D12Device10 interface must be available in the current system. Otherwise, E_NOINTERFACE is returned. If you use pCastableFormats, ID3D12Device12 must albo be available.
@@ -700,14 +668,14 @@== FALSE (discrete graphics card):pLocalBudget returns the budget of the video memory.pNonLocalBudget returns the budget of the system memory available for D3D12 resources.== TRUE (integrated graphics chip):pLocalBudget returns the budget of the shared memory available for all D3D12 resources. All memory is considered "local".pNonLocalBudget is not applicable and returns zeros.| memorySegmentGroup | use DXGI_MEMORY_SEGMENT_GROUP_LOCAL or DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL. |
| memorySegmentGroup | use DXGI_MEMORY_SEGMENT_GROUP_LOCAL or DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL. |
This information is taken from DXGI_ADAPTER_DESC. It is not recommended to use this number. You should preferably call GetBudget() and limit memory usage to D3D12MA::Budget::BudgetBytes instead.
This information is taken from DXGI_ADAPTER_DESC. It is not recommended to use this number. You should preferably call GetBudget() and limit memory usage to D3D12MA::Budget::BudgetBytes instead.
== FALSE (discrete graphics card):GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_LOCAL) returns the size of the video memory.GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL) returns the size of the system memory available for D3D12 resources.== TRUE (integrated graphics chip):GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_LOCAL) returns the size of the shared memory available for all D3D12 resources. All memory is considered "local".GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL) is not applicable and returns 0. Returns true if D3D12_FEATURE_DATA_ARCHITECTURE1::CacheCoherentUMA was found to be true.
Returns true if D3D12_FEATURE_DATA_ARCHITECTURE1::CacheCoherentUMA was found to be true.
For more information about how to use it, see articles in Microsoft Docs articles:
Returns true if GPU Upload Heaps are supported on the current system.
-When true, you can use D3D12_HEAP_TYPE_GPU_UPLOAD.
This flag is fetched from D3D12_FEATURE_D3D12_OPTIONS16::GPUUploadHeapSupported.
When true, you can use D3D12_HEAP_TYPE_GPU_UPLOAD.
+This flag is fetched from D3D12_FEATURE_D3D12_OPTIONS16::GPUUploadHeapSupported.
@@ -834,7 +802,7 @@Returns true if D3D12_FEATURE_DATA_ARCHITECTURE1::UMA was found to be true.
Returns true if D3D12_FEATURE_DATA_ARCHITECTURE1::UMA was found to be true.
For more information about how to use it, see articles in Microsoft Docs articles:
+Public Member FunctionsHRESULT | BeginPass (DEFRAGMENTATION_PASS_MOVE_INFO *pPassInfo) | | HRESULT | EndPass (DEFRAGMENTATION_PASS_MOVE_INFO *pPassInfo) | | void | GetStats (DEFRAGMENTATION_STATS *pStats) | | | ||||||||||||
Represents defragmentation process in progress.
You can create this object using Allocator::BeginDefragmentation (for default pools) or Pool::BeginDefragmentation (for a custom pool).
-S_OK if no more moves are possible. Then you can omit call to DefragmentationContext::EndPass() and simply end whole defragmentation.S_FALSE if there are pending moves returned in pPassInfo. You need to perform them, call DefragmentationContext::EndPass(), and then preferably try another pass with DefragmentationContext::BeginPass(). S_OK if no more moves are possible or S_FALSE if more defragmentations are possible.Ends incremental defragmentation pass and commits all defragmentation moves from pPassInfo. After this call:
Ends incremental defragmentation pass and commits all defragmentation moves from pPassInfo. After this call:
pPassInfo[i].pSrcAllocation that had pPassInfo[i].Operation == DEFRAGMENTATION_MOVE_OPERATION_COPY (which is the default) will be pointing to the new destination place.pPassInfo[i].pSrcAllocation that had pPassInfo[i].operation == DEFRAGMENTATION_MOVE_OPERATION_DESTROY will be released.If no more moves are possible you can end whole defragmentation.
@@ -209,7 +193,7 @@
+Public Member FunctionsPOOL_DESC | GetDesc () const | | void | GetStatistics (Statistics *pStats) | | void | CalculateStatistics (DetailedStatistics *pStats) | | void | SetName (LPCWSTR Name) | | LPCWSTR | GetName () const | | HRESULT | BeginDefragmentation (const DEFRAGMENTATION_DESC *pDesc, DefragmentationContext **ppContext) | | | |||||||||||||||||||||
Custom memory pool.
Represents a separate set of heaps (memory blocks) that can be used to create D3D12MA::Allocation-s and resources in it. Usually there is no need to create custom pools - creating resources in default pool is sufficient.
To create custom pool, fill D3D12MA::POOL_DESC and call D3D12MA::Allocator::CreatePool.
-S_OK if defragmentation can begin.E_NOINTERFACE if defragmentation is not supported.For more information about defragmentation, see documentation chapter: Defragmentation.
@@ -276,7 +257,7 @@
+Public Member FunctionsBOOL | IsEmpty () const | | void | GetAllocationInfo (VirtualAllocation allocation, VIRTUAL_ALLOCATION_INFO *pInfo) const | | HRESULT | Allocate (const VIRTUAL_ALLOCATION_DESC *pDesc, VirtualAllocation *pAllocation, UINT64 *pOffset) | | void | FreeAllocation (VirtualAllocation allocation) | | void | Clear () | | void | SetAllocationPrivateData (VirtualAllocation allocation, void *pPrivateData) | | void | GetStatistics (Statistics *pStats) const | | void | CalculateStatistics (DetailedStatistics *pStats) const | | void | BuildStatsString (WCHAR **ppStatsString) const | | void | FreeStatsString (WCHAR *pStatsString) const | | | |||||||||||||||||||||||||||||||||
Represents pure allocation algorithm and a data structure with allocations in some memory block, without actually allocating any GPU memory.
This class allows to use the core algorithm of the library custom allocations e.g. CPU memory or sub-allocation regions inside a single GPU buffer.
-To create this object, fill in D3D12MA::VIRTUAL_BLOCK_DESC and call CreateVirtualBlock(). To destroy it, call its method VirtualBlock::Release(). You need to free all the allocations within this block or call Clear() before destroying it.
To create this object, fill in D3D12MA::VIRTUAL_BLOCK_DESC and call CreateVirtualBlock(). To destroy it, call its method VirtualBlock::Release(). You need to free all the allocations within this block or call Clear() before destroying it.
This object is not thread-safe - should not be used from multiple threads simultaneously, must be synchronized externally.
-S_OK if allocation succeeded, E_OUTOFMEMORY if it failed.If the allocation failed, pAllocation->AllocHandle is set to 0 and pOffset, if not null, is set to UINT64_MAX.
If the allocation failed, pAllocation->AllocHandle is set to 0 and pOffset, if not null, is set to UINT64_MAX.
@@ -268,7 +245,7 @@Frees the allocation.
-Calling this function with allocation.AllocHandle == 0 is correct and does nothing.
Calling this function with allocation.AllocHandle == 0 is correct and does nothing.
@@ -387,7 +364,7 @@Please check file D3D12MemAlloc.cpp lines between "Configuration Begin" and "Configuration End" to find macros that you can define to change the behavior of the library, primarily for debugging purposes.
Please check file D3D12MemAlloc.cpp lines between "Configuration Begin" and "Configuration End" to find macros that you can define to change the behavior of the library, primarily for debugging purposes.
+If you use custom allocator for CPU memory rather than default C++ operator new and delete or malloc and free functions, you can make this library using your allocator as well by filling structure D3D12MA::ALLOCATION_CALLBACKS and passing it as optional member D3D12MA::ALLOCATOR_DESC::pAllocationCallbacks. Functions pointed there will be used by the library to make any CPU-side allocations. Example:
If you use custom allocator for CPU memory rather than default C++ operator new and delete or malloc and free functions, you can make this library using your allocator as well by filling structure D3D12MA::ALLOCATION_CALLBACKS and passing it as optional member D3D12MA::ALLOCATOR_DESC::pAllocationCallbacks. Functions pointed there will be used by the library to make any CPU-side allocations. Example:
By default, allocations are laid out in memory blocks next to each other if possible (considering required alignment returned by ID3D12Device::GetResourceAllocationInfo).
By default, allocations are laid out in memory blocks next to each other if possible (considering required alignment returned by ID3D12Device::GetResourceAllocationInfo).

Define macro D3D12MA_DEBUG_MARGIN to some non-zero value (e.g. 16) inside "D3D12MemAlloc.cpp" to enforce specified number of bytes as a margin after every allocation.
Define macro D3D12MA_DEBUG_MARGIN to some non-zero value (e.g. 16) inside "D3D12MemAlloc.cpp" to enforce specified number of bytes as a margin after every allocation.

If your bug goes away after enabling margins, it means it may be caused by memory being overwritten outside of allocation boundaries. It is not 100% certain though. Change in application behavior may also be caused by different order and distribution of allocations across memory blocks after margins are applied.
Margins work with all memory heap types.
@@ -149,7 +136,7 @@A "pool" is a collection of memory blocks that share certain properties. Allocator creates 3 default pools: for D3D12_HEAP_TYPE_DEFAULT, UPLOAD, READBACK. A default pool automatically grows in size. Size of allocated blocks is also variable and managed automatically. Typical allocations are created in these pools. You can also create custom pools.
A "pool" is a collection of memory blocks that share certain properties. Allocator creates 3 default pools: for D3D12_HEAP_TYPE_DEFAULT, UPLOAD, READBACK. A default pool automatically grows in size. Size of allocated blocks is also variable and managed automatically. Typical allocations are created in these pools. You can also create custom pools.
+To create a custom pool, fill in structure D3D12MA::POOL_DESC and call function D3D12MA::Allocator::CreatePool to obtain object D3D12MA::Pool. Example:
All allocations must be released before releasing the pool. The pool must be released before relasing the allocator.
While it is recommended to use default pools whenever possible for simplicity and to give the allocator more opportunities for internal optimizations, custom pools may be useful in following cases:
ID3D12Heap). To set it, use member D3D12MA::POOL_DESC::BlockSize. When set to 0, the library uses automatically determined, variable block sizes.D3D12_HEAP_TYPE_DEFAULT, UPLOAD, READBACK, a custom pool may use non-standard D3D12_HEAP_PROPERTIES (member D3D12MA::POOL_DESC::HeapProperties) and D3D12_HEAP_FLAGS (D3D12MA::POOL_DESC::HeapFlags), which is useful e.g. for cross-adapter sharing or UMA (see also D3D12MA::Allocator::IsUMA).New versions of this library support creating committed allocations in custom pools. It is supported only when D3D12MA::POOL_DESC::BlockSize = 0. To use this feature, set D3D12MA::ALLOCATION_DESC::CustomPool to the pointer to your custom pool and D3D12MA::ALLOCATION_DESC::Flags to D3D12MA::ALLOCATION_FLAG_COMMITTED. Example:
This feature may seem unnecessary, but creating committed allocations from custom pools may be useful in some cases, e.g. to have separate memory usage statistics for some group of resources or to use extended allocation parameters, like custom D3D12_HEAP_PROPERTIES, which are available only in custom pools.
This feature may seem unnecessary, but creating committed allocations from custom pools may be useful in some cases, e.g. to have separate memory usage statistics for some group of resources or to use extended allocation parameters, like custom D3D12_HEAP_PROPERTIES, which are available only in custom pools.
Interleaved allocations and deallocations of many objects of varying size can cause fragmentation over time, which can lead to a situation where the library is unable to find a continuous range of free memory for a new allocation despite there is enough free space, just scattered across many small free ranges between existing allocations.
-To mitigate this problem, you can use defragmentation feature. It doesn't happen automatically though and needs your cooperation, because D3D12MA is a low level library that only allocates memory. It cannot recreate buffers and textures in a new place as it doesn't remember the contents of D3D12_RESOURCE_DESC structure. It cannot copy their contents as it doesn't record any commands to a command list.
To mitigate this problem, you can use defragmentation feature. It doesn't happen automatically though and needs your cooperation, because D3D12MA is a low level library that only allocates memory. It cannot recreate buffers and textures in a new place as it doesn't remember the contents of D3D12_RESOURCE_DESC structure. It cannot copy their contents as it doesn't record any commands to a command list.
Example:
Although functions like D3D12MA::Allocator::CreateResource() create an allocation and a buffer/texture at once, these are just a shortcut for allocating memory and creating a placed resource. Defragmentation works on memory allocations only. You must handle the rest manually. Defragmentation is an iterative process that should repreat "passes" as long as related functions return S_FALSE not S_OK. In each pass:
Although functions like D3D12MA::Allocator::CreateResource() create an allocation and a buffer/texture at once, these are just a shortcut for allocating memory and creating a placed resource. Defragmentation works on memory allocations only. You must handle the rest manually. Defragmentation is an iterative process that should repreat "passes" as long as related functions return S_FALSE not S_OK. In each pass:
ID3D12Heap + offset using methods like D3D12MA::Allocation::GetHeap().ID3D12Heap blocks that became empty.Defragmentation algorithm tries to move all suitable allocations. You can, however, refuse to move some of them inside a defragmentation pass, by setting pass.pMoves[i].Operation to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_IGNORE. This is not recommended and may result in suboptimal packing of the allocations after defragmentation. If you cannot ensure any allocation can be moved, it is better to keep movable allocations separate in a custom pool.
Defragmentation algorithm tries to move all suitable allocations. You can, however, refuse to move some of them inside a defragmentation pass, by setting pass.pMoves[i].Operation to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_IGNORE. This is not recommended and may result in suboptimal packing of the allocations after defragmentation. If you cannot ensure any allocation can be moved, it is better to keep movable allocations separate in a custom pool.
Inside a pass, for each allocation that should be moved:
CopyResource().D3D12_HEAP_TYPE_READBACK memory, you can copy its data on the CPU using memcpy().pass.pMoves[i].Operation to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_IGNORE. This will cancel the move.pass.pMoves[i].Operation to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_DESTROY.You can defragment a specific custom pool by calling D3D12MA::Pool::BeginDefragmentation or all the default pools by calling D3D12MA::Allocator::BeginDefragmentation (like in the example above).
-Defragmentation is always performed in each pool separately. Allocations are never moved between different heap types. The size of the destination memory reserved for a moved allocation is the same as the original one. Alignment of an allocation as it was determined using GetResourceAllocationInfo() is also respected after defragmentation. Buffers/textures should be recreated with the same D3D12_RESOURCE_DESC parameters as the original ones.
Defragmentation is always performed in each pool separately. Allocations are never moved between different heap types. The size of the destination memory reserved for a moved allocation is the same as the original one. Alignment of an allocation as it was determined using GetResourceAllocationInfo() is also respected after defragmentation. Buffers/textures should be recreated with the same D3D12_RESOURCE_DESC parameters as the original ones.
You can perform the defragmentation incrementally to limit the number of allocations and bytes to be moved in each pass, e.g. to call it in sync with render frames and not to experience too big hitches. See members: D3D12MA::DEFRAGMENTATION_DESC::MaxBytesPerPass, D3D12MA::DEFRAGMENTATION_DESC::MaxAllocationsPerPass.
Thread safety: It is safe to perform the defragmentation asynchronously to render frames and other Direct3D 12 and D3D12MA usage, possibly from multiple threads, with the exception that allocations returned in D3D12MA::DEFRAGMENTATION_PASS_MOVE_INFO::pMoves shouldn't be released until the defragmentation pass is ended. During the call to D3D12MA::DefragmentationContext::BeginPass(), any operations on the memory pool affected by the defragmentation are blocked by a mutex.
-What it means in practice is that you shouldn't free any allocations from the defragmented pool since the moment a call to BeginPass begins. Otherwise, a thread performing the allocation->Release() would block for the time BeginPass executes and then free the allocation when it finishes, while the allocation could have ended up on the list of allocations to move. A solution to freeing allocations during defragmentation is to find such allocation on the list pass.pMoves[i] and set its operation to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_DESTROY instead of calling allocation->Release(), or simply deferring the release to the time after defragmentation finished.
What it means in practice is that you shouldn't free any allocations from the defragmented pool since the moment a call to BeginPass begins. Otherwise, a thread performing the allocation->Release() would block for the time BeginPass executes and then free the allocation when it finishes, while the allocation could have ended up on the list of allocations to move. A solution to freeing allocations during defragmentation is to find such allocation on the list pass.pMoves[i] and set its operation to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_DESTROY instead of calling allocation->Release(), or simply deferring the release to the time after defragmentation finished.
Mapping is out of scope of this library and so it is not preserved after an allocation is moved during defragmentation. You need to map the new resource yourself if needed.
+Files | D3D12MemAlloc.h | | | D3D12MemAlloc.h | |||||
What is D3D12MA?
@@ -96,18 +83,18 @@What is the license of D3D12MA?
D3D12MA is licensed under MIT, which means it is open source and free software.
What is the purpose of D3D12MA?
-D3D12MA helps with handling one aspect of DX12 usage, which is GPU memory management - allocation of ID3D12Heap objects and creation of ID3D12Resource objects - buffers and textures.
D3D12MA helps with handling one aspect of DX12 usage, which is GPU memory management - allocation of ID3D12Heap objects and creation of ID3D12Resource objects - buffers and textures.
Do I need to use D3D12MA?
You don't need to, but it may be beneficial in many cases. DX12 is a complex and low-level API, so libraries like this that abstract certain aspects of the API and bring them to a higher level are useful. When developing any non-trivial graphics application, you may benefit from using a memory allocator. Using D3D12MA can save time compared to implementing your own.
-In DX12 you can create each resource separately with its own implicit memory heap by calling CreateCommittedResource, but this may not be the optimal solution. For more information, see Committed versus placed resources.
In DX12 you can create each resource separately with its own implicit memory heap by calling CreateCommittedResource, but this may not be the optimal solution. For more information, see Committed versus placed resources.
When should I not use D3D12MA?
While D3D12MA is useful for many applications that use the DX12 API, there are cases when it may be a better choice not to use it. For example, if the application is very simple, e.g. serving as a sample or a learning exercise to help you understand or teach others the basics of DX12, and it creates only a small number of buffers and textures, then including D3D12MA may be an overkill. Developing your own memory allocator may also be a good learning exercise.
What are the benefits of using D3D12MA?
ID3D12Heap memory and sub-allocates parts of them to create your placed resources. Allocating a new block of GPU memory may be a time-consuming operation. Sub-allocating parts of a memory block requires implementing an allocation algorithm, which is a non-trivial task. D3D12MA does that, using an advanced and efficient algorithm that works well in various use cases.The library is doing much more under the hood. For example, it keeps buffers separate from textures when needed, respecting D3D12_RESOURCE_HEAP_TIER. It also makes use of the "small texture alignment" automatically, so you don't need to think about it.
The library is doing much more under the hood. For example, it keeps buffers separate from textures when needed, respecting D3D12_RESOURCE_HEAP_TIER. It also makes use of the "small texture alignment" automatically, so you don't need to think about it.
Which version should I pick?
You can just pick the latest version from the "master" branch. It is kept in a good shape most of the time, compiling and working correctly, with no compatibility-breaking changes and no unfinished code.
If you want an even more stable version, you can pick the latest official release. Current code from the master branch is occasionally tagged as a release, with CHANGELOG carefully curated to enumerate all important changes since the previous version.
@@ -119,10 +106,10 @@I am not a fan of modern C++. Can I still use it?
Very likely yes. We acknowledge that many C++ developers, especially in the games industry, do not appreciate all the latest features that the language has to offer.
HRESULT value instead, just like DX12. If you don't use exceptions in your project, your code is not exception-safe, or even if you disable exception handling in the compiler options, you can still use D3D12MA.typeid or dynamic_cast, so if you disable RTTI in the compiler options, you can still use the library.std::vector, map, or string, either in the public interface nor in the internal implementation. It implements its own containers instead.malloc/free or new/delete but implement your own allocator instead, you can pass it to D3D12MA as D3D12MA::ALLOCATOR_DESC::pAllocationCallbacks and the library will use your functions for every dynamic heap allocation made internally.Is it available for other programming languages?
D3D12MA is a C++ library in similar style as DX12. Bindings to other programming languages are out of scope of this project, but they are welcome as external projects. Some of them are listed in README.md, "See also" section, including binding to C. Before using any of them, please check if they are still maintained and updated to use a recent version of D3D12MA.
@@ -132,7 +119,7 @@No! While D3D12MA is published by AMD, it works on any GPU that supports DX12, whether a discrete PC graphics card or a processor integrated graphics. It doesn't give AMD GPUs any advantage over any other GPUs.
What DirectX 12 versions are supported?
D3D12MA is updated to support latest versions of DirectX 12, as available through recent retail versions of the DirectX 12 Agility SDK. Support for new features added in the preview version of the Agility SDK is developed on separate branches until they are included in the retail version.
-The library also supports older versions down to the base DX12 shipping with Windows SDK. Features added by later versions of the Agility SDK are automatically enabled conditionally using #ifdef preprocessor macros depending on the version of the SDK that you compile your project with.
The library also supports older versions down to the base DX12 shipping with Windows SDK. Features added by later versions of the Agility SDK are automatically enabled conditionally using #ifdef preprocessor macros depending on the version of the SDK that you compile your project with.
Does it support other graphics APIs, like Vulkan(R)?
No, but we offer an equivalent library for Vulkan: Vulkan Memory Allocator. It uses the same core allocation algorithm. It also shares many features with D3D12MA, like the support for custom pools and virtual allocator. However, it is not identical in terms of the features supported. Its API also looks different, because while the interface of D3D12MA is similar in style to DX12, the interface of VMA is similar to Vulkan.
Is the library lightweight?
@@ -154,8 +141,8 @@If you want to report a suspected bug, you can also create a ticket the same way. Before doing this, please put some effort into the investigation of whether the bug is really in the library and not in your code or in the DX12 implementation (the GPU driver) on your platform:
D3D12MA_ASSERT is defined to an implementation that can report a failure and not ignore it.CreateCommittedResource() rather than D3D12MA and see if the bug persists.I found some compilation warnings. How can we fix them?
Seeing compiler warnings may be annoying to some developers, but it is a design decision to not fix all of them. Due to the nature of the C++ language, certain preprocessor macros can make some variables unused, function parameters unreferenced, or conditional expressions constant in some configurations. The code of this library should not be bigger or more complicated just to silence these warnings. It is recommended to disable such warnings instead. For more information, see Features not supported.
@@ -164,7 +151,7 @@| ▼ include | |
| D3D12MemAlloc.h | |
| include | |
| D3D12MemAlloc.h |
ID3D12Device is enough.The library uses Semantic Versioning, which means version numbers follow convention: Major.Minor.Patch (e.g. 2.3.0), where:
All changes between official releases are documented in file "CHANGELOG.md".
Features deliberately excluded from the scope of this library:
ID3D12Device::Evict and MakeResident. We don't recommend using them. You can call them on the D3D12 objects manually. Plese keep in mind, however, that eviction happens on the level of entire ID3D12Heap memory blocks and not individual buffers or textures which may be placed inside them.| CD3D12MA::ALLOCATION_CALLBACKS | Custom callbacks to CPU memory allocation functions |
| ▼CD3D12MA::ALLOCATION_DESC | Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource |
| CD3D12MA::ALLOCATION_DESC | Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource |
| CD3D12MA::CALLOCATION_DESC | Helper structure that helps with complete and conscise initialization of the D3D12MA::ALLOCATION_DESC structure |
| CD3D12MA::ALLOCATOR_DESC | Parameters of created Allocator object. To be used with CreateAllocator() |
| CD3D12MA::Budget | Statistics of current memory usage and available budget for a specific memory segment group |
| CD3D12MA::DEFRAGMENTATION_PASS_MOVE_INFO | Parameters for incremental defragmentation steps |
| CD3D12MA::DEFRAGMENTATION_STATS | Statistics returned for defragmentation process by function DefragmentationContext::GetStats() |
| CD3D12MA::DetailedStatistics | More detailed statistics than D3D12MA::Statistics |
| ▼CIUnknownImpl | |
| CIUnknownImpl | |
| CD3D12MA::Allocation | Represents single memory allocation |
| CD3D12MA::Allocator | Represents main object of this library initialized for particular ID3D12Device |
| CD3D12MA::Allocator | Represents main object of this library initialized for particular ID3D12Device |
| CD3D12MA::DefragmentationContext | Represents defragmentation process in progress |
| CD3D12MA::Pool | Custom memory pool |
| CD3D12MA::VirtualBlock | Represents pure allocation algorithm and a data structure with allocations in some memory block, without actually allocating any GPU memory |
| ▼CD3D12MA::POOL_DESC | Parameters of created D3D12MA::Pool object. To be used with D3D12MA::Allocator::CreatePool |
| CD3D12MA::POOL_DESC | Parameters of created D3D12MA::Pool object. To be used with D3D12MA::Allocator::CreatePool |
| CD3D12MA::CPOOL_DESC | Helper structure that helps with complete and conscise initialization of the D3D12MA::POOL_DESC structure |
| CD3D12MA::Statistics | Calculated statistics of memory usage e.g. in a specific memory heap type, memory segment group, custom pool, or total |
| CD3D12MA::TotalStatistics | General statistics from current state of the allocator - total memory usage across all memory heaps and segments |
| ▼CD3D12MA::VIRTUAL_ALLOCATION_DESC | Parameters of created virtual allocation to be passed to VirtualBlock::Allocate() |
| CD3D12MA::VIRTUAL_ALLOCATION_DESC | Parameters of created virtual allocation to be passed to VirtualBlock::Allocate() |
| CD3D12MA::CVIRTUAL_ALLOCATION_DESC | Helper structure that helps with complete and conscise initialization of the D3D12MA::VIRTUAL_ALLOCATION_DESC structure |
| CD3D12MA::VIRTUAL_ALLOCATION_INFO | Parameters of an existing virtual allocation, returned by VirtualBlock::GetAllocationInfo() |
| ▼CD3D12MA::VIRTUAL_BLOCK_DESC | Parameters of created D3D12MA::VirtualBlock object to be passed to CreateVirtualBlock() |
| CD3D12MA::VIRTUAL_BLOCK_DESC | Parameters of created D3D12MA::VirtualBlock object to be passed to CreateVirtualBlock() |
| CD3D12MA::CVIRTUAL_BLOCK_DESC | Helper structure that helps with complete and conscise initialization of the D3D12MA::VIRTUAL_BLOCK_DESC structure |
| CD3D12MA::VirtualAllocation | Represents single memory allocation done inside VirtualBlock |
Version 3.0.1 (2025-05-08)
+Version 3.0.2 (2025-XX-XX)
Copyright (c) 2019-2025 Advanced Micro Devices, Inc. All rights reserved.
License: MIT
Documentation of all members: D3D12MemAlloc.h
-Documentation of all members: D3D12MemAlloc.h
+Each D3D12 memory block managed by this library has accompanying metadata that keeps track of used and unused regions. By default, the metadata structure and algorithm tries to find best place for new allocations among free regions to optimize memory usage. This way you can allocate and free objects in any order.
@@ -96,17 +83,17 @@Sometimes there is a need to use simpler, linear allocation algorithm. You can create custom pool that uses such algorithm by adding flag D3D12MA::POOL_FLAG_ALGORITHM_LINEAR to D3D12MA::POOL_DESC::Flags while creating D3D12MA::Pool object. Then an alternative metadata management is used. It always creates new allocations after last one and doesn't reuse free regions after allocations freed in the middle. It results in better allocation performance and less memory consumed by metadata.

With this one flag, you can create a custom pool that can be used in many ways: free-at-once, stack, double stack, and ring buffer. See below for details. You don't need to specify explicitly which of these options you are going to use - it is detected automatically.
-In a pool that uses linear algorithm, you still need to free all the allocations individually by calling allocation->Release(). You can free them in any order. New allocations are always made after last one - free space in the middle is not reused. However, when you release all the allocation and the pool becomes empty, allocation starts from the beginning again. This way you can use linear algorithm to speed up creation of allocations that you are going to release all at once.
In a pool that uses linear algorithm, you still need to free all the allocations individually by calling allocation->Release(). You can free them in any order. New allocations are always made after last one - free space in the middle is not reused. However, when you release all the allocation and the pool becomes empty, allocation starts from the beginning again. This way you can use linear algorithm to speed up creation of allocations that you are going to release all at once.

This mode is also available for pools created with D3D12MA::POOL_DESC::MaxBlockCount value that allows multiple memory blocks.
-When you free an allocation that was created last, its space can be reused. Thanks to this, if you always release allocations in the order opposite to their creation (LIFO - Last In First Out), you can achieve behavior of a stack.

This mode is also available for pools created with D3D12MA::POOL_DESC::MaxBlockCount value that allows multiple memory blocks.
-The space reserved by a custom pool with linear algorithm may be used by two stacks:
To make allocation from the upper stack, add flag D3D12MA::ALLOCATION_FLAG_UPPER_ADDRESS to D3D12MA::ALLOCATION_DESC::Flags.

Double stack is available only in pools with one memory block - D3D12MA::POOL_DESC::MaxBlockCount must be 1. Otherwise behavior is undefined.
-When the two stacks' ends meet so there is not enough space between them for a new allocation, such allocation fails with usual E_OUTOFMEMORY error.
When the two stacks' ends meet so there is not enough space between them for a new allocation, such allocation fails with usual E_OUTOFMEMORY error.
+When you free some allocations from the beginning and there is not enough free space for a new one at the end of a pool, allocator's "cursor" wraps around to the beginning and starts allocation there. Thanks to this, if you always release allocations in the same order as you created them (FIFO - First In First Out), you can achieve behavior of a ring buffer / queue.

Ring buffer is available only in pools with one memory block - D3D12MA::POOL_DESC::MaxBlockCount must be 1. Otherwise behavior is undefined.
-Linear algorithm can also be used with Virtual allocator. See flag D3D12MA::VIRTUAL_BLOCK_FLAG_ALGORITHM_LINEAR.
+Classesclass | Allocation | | Represents single memory allocation. More... | | struct | ALLOCATION_CALLBACKS | | Custom callbacks to CPU memory allocation functions. More... | | struct | ALLOCATION_DESC | | Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource. More... | | class | Allocator | | Represents main object of this library initialized for particular | ID3D12Device. More... | struct | ALLOCATOR_DESC | class | Allocator | | Represents main object of this library initialized for particular ID3D12Device. More... | | Parameters of created Allocator object. To be used with CreateAllocator(). More... | | struct | Budget | | Statistics of current memory usage and available budget for a specific memory segment group. More... | | struct | CALLOCATION_DESC | | Helper structure that helps with complete and conscise initialization of the D3D12MA::ALLOCATION_DESC structure. More... | | struct | CPOOL_DESC | | Helper structure that helps with complete and conscise initialization of the D3D12MA::POOL_DESC structure. More... | | struct | CVIRTUAL_ALLOCATION_DESC | | Helper structure that helps with complete and conscise initialization of the D3D12MA::VIRTUAL_ALLOCATION_DESC structure. More... | | struct | CVIRTUAL_BLOCK_DESC | | Helper structure that helps with complete and conscise initialization of the D3D12MA::VIRTUAL_BLOCK_DESC structure. More... | | struct | DEFRAGMENTATION_DESC | | Parameters for defragmentation. More... | | struct | DEFRAGMENTATION_MOVE | | Single move of an allocation to be done for defragmentation. More... | | struct | DEFRAGMENTATION_PASS_MOVE_INFO | | Parameters for incremental defragmentation steps. More... | | struct | DEFRAGMENTATION_STATS | | Statistics returned for defragmentation process by function DefragmentationContext::GetStats(). More... | | class | DefragmentationContext | | Represents defragmentation process in progress. More... | | struct | DetailedStatistics | | More detailed statistics than D3D12MA::Statistics. More... | | class | Pool | | Custom memory pool. More... | | struct | POOL_DESC | | Parameters of created D3D12MA::Pool object. To be used with D3D12MA::Allocator::CreatePool. More... | | struct | Statistics | | Calculated statistics of memory usage e.g. in a specific memory heap type, memory segment group, custom pool, or total. More... | | struct | TotalStatistics | | General statistics from current state of the allocator - total memory usage across all memory heaps and segments. More... | | struct | VIRTUAL_ALLOCATION_DESC | | Parameters of created virtual allocation to be passed to VirtualBlock::Allocate(). More... | | struct | VIRTUAL_ALLOCATION_INFO | | Parameters of an existing virtual allocation, returned by VirtualBlock::GetAllocationInfo(). More... | | struct | VIRTUAL_BLOCK_DESC | | Parameters of created D3D12MA::VirtualBlock object to be passed to CreateVirtualBlock(). More... | | struct | VirtualAllocation | | Represents single memory allocation done inside VirtualBlock. More... | | class | VirtualBlock | | Represents pure allocation algorithm and a data structure with allocations in some memory block, without actually allocating any GPU memory. More... | | class | Allocation | struct | ALLOCATION_CALLBACKS | struct | ALLOCATION_DESC | struct | ALLOCATOR_DESC | struct | Budget | struct | CALLOCATION_DESC | struct | CPOOL_DESC | struct | CVIRTUAL_ALLOCATION_DESC | struct | CVIRTUAL_BLOCK_DESC | struct | DEFRAGMENTATION_DESC | struct | DEFRAGMENTATION_MOVE | struct | DEFRAGMENTATION_PASS_MOVE_INFO | struct | DEFRAGMENTATION_STATS | class | DefragmentationContext | struct | DetailedStatistics | class | Pool | struct | POOL_DESC | struct | Statistics | struct | TotalStatistics | struct | VIRTUAL_ALLOCATION_DESC | struct | VIRTUAL_ALLOCATION_INFO | struct | VIRTUAL_BLOCK_DESC | struct | VirtualAllocation | class | VirtualBlock | |||||||||||||||||||||||||||||
+Typedefstypedef UINT64 | AllocHandle | | using | ALLOCATE_FUNC_PTR = void* (*)(size_t Size, size_t Alignment, void* pPrivateData) | | using | FREE_FUNC_PTR = void (*)(void* pMemory, void* pPrivateData) | | | ||||||||||||
+Enumerationsenum | ALLOCATION_FLAGS { | ALLOCATION_FLAG_NONE = 0 @@ -203,20 +162,17 @@ } | enum | DEFRAGMENTATION_FLAGS { DEFRAGMENTATION_FLAG_ALGORITHM_FAST = 0x1
, DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED = 0x2
, DEFRAGMENTATION_FLAG_ALGORITHM_FULL = 0x4
, DEFRAGMENTATION_FLAG_ALGORITHM_MASK
} | | enum | DEFRAGMENTATION_MOVE_OPERATION { DEFRAGMENTATION_MOVE_OPERATION_COPY = 0
, DEFRAGMENTATION_MOVE_OPERATION_IGNORE = 1
, DEFRAGMENTATION_MOVE_OPERATION_DESTROY = 2
} | | enum | POOL_FLAGS { | POOL_FLAG_NONE = 0 , POOL_FLAG_ALGORITHM_LINEAR = 0x1 @@ -227,7 +183,6 @@ } | enum | ALLOCATOR_FLAGS { | ALLOCATOR_FLAG_NONE = 0 , ALLOCATOR_FLAG_SINGLETHREADED = 0x1 @@ -239,13 +194,11 @@ } | enum | VIRTUAL_BLOCK_FLAGS { VIRTUAL_BLOCK_FLAG_NONE = 0
, VIRTUAL_BLOCK_FLAG_ALGORITHM_LINEAR = POOL_FLAG_ALGORITHM_LINEAR
, VIRTUAL_BLOCK_FLAG_ALGORITHM_MASK = POOL_FLAG_ALGORITHM_MASK
} | | enum | VIRTUAL_ALLOCATION_FLAGS { | VIRTUAL_ALLOCATION_FLAG_NONE = 0 , VIRTUAL_ALLOCATION_FLAG_UPPER_ADDRESS = ALLOCATION_FLAG_UPPER_ADDRESS @@ -257,18 +210,15 @@ } | | ||||||||||||||||||||||||
+Functions | Creates new main D3D12MA::Allocator object and returns it through ppAllocator. | | Creates new D3D12MA::VirtualBlock object and returns it through ppVirtualBlock. | | |||||||||||||||
ppAllocator. ppVirtualBlock. Pointer to custom callback function that deallocates CPU memory.
-pMemory = null should be accepted and ignored.
pMemory = null should be accepted and ignored.
Set this flag if the allocation should have its own dedicated memory allocation (committed resource with implicit heap).
Use it for special, big resources, like fullscreen textures used as render targets.
ID3D12Device::CreateCommittedResource, so the created allocation will contain a resource (D3D12MA::Allocation::GetResource() != NULL) but will not have a heap (D3D12MA::Allocation::GetHeap() == NULL), as the heap is implicit.ID3D12Device::CreateHeap, so the created allocation will contain a heap (D3D12MA::Allocation::GetHeap() != NULL) and its offset will always be 0. Set this flag to only try to allocate from existing memory heaps and never create new such heap.
-If new allocation cannot be placed in any of the existing heaps, allocation fails with E_OUTOFMEMORY error.
If new allocation cannot be placed in any of the existing heaps, allocation fails with E_OUTOFMEMORY error.
You should not use D3D12MA::ALLOCATION_FLAG_COMMITTED and D3D12MA::ALLOCATION_FLAG_NEVER_ALLOCATE at the same time. It makes no sense.
Create allocation only if additional memory required for it, if any, won't exceed memory budget. Otherwise return E_OUTOFMEMORY.
Create allocation only if additional memory required for it, if any, won't exceed memory budget. Otherwise return E_OUTOFMEMORY.
Allocation will be created from upper stack in a double stack pool.
This flag is only allowed for custom pools created with POOL_FLAG_ALGORITHM_LINEAR flag.
Set this flag if the allocated memory will have aliasing resources.
-Use this when calling D3D12MA::Allocator::CreateResource() and similar to guarantee creation of explicit heap for desired allocation and prevent it from using CreateCommittedResource, so that new allocation object will always have allocation->GetHeap() != NULL.
Use this when calling D3D12MA::Allocator::CreateResource() and similar to guarantee creation of explicit heap for desired allocation and prevent it from using CreateCommittedResource, so that new allocation object will always have allocation->GetHeap() != NULL.
Allocation strategy that chooses smallest possible free range for the allocation to minimize memory usage and fragmentation, possibly at the expense of allocation time.
Alias to ALLOCATION_FLAG_STRATEGY_MIN_TIME.
A bit mask to extract only STRATEGY bits from entire set of flags.
A bit mask to extract only STRATEGY bits from entire set of flags.
Every allocation will be created as a committed resource - will have its own memory block.
Affects both default pools and custom pools. To be used for debugging purposes only. There is also an equivalent flag for custom pools: D3D12MA::POOL_FLAG_ALWAYS_COMMITTED.
Heaps created for the default pools will be created with flag D3D12_HEAP_FLAG_CREATE_NOT_ZEROED, allowing for their memory to be not zeroed by the system if possible, which can speed up allocation.
Heaps created for the default pools will be created with flag D3D12_HEAP_FLAG_CREATE_NOT_ZEROED, allowing for their memory to be not zeroed by the system if possible, which can speed up allocation.
Only affects default pools. To use the flag with Custom memory pools, you need to add it manually:
Only avaiable if ID3D12Device8 is present. Otherwise, the flag is ignored.
Only avaiable if ID3D12Device8 is present. Otherwise, the flag is ignored.
Optimization, allocate MSAA textures as committed resources always.
Specify this flag to create MSAA textures with implicit heaps, as if they were created with flag D3D12MA::ALLOCATION_FLAG_COMMITTED. Usage of this flags enables all default pools to create its heaps on smaller alignment not suitable for MSAA textures.
@@ -424,11 +374,11 @@Use simple but fast algorithm for defragmentation. May not achieve best results but will require least time to compute and least allocations to copy.
Default defragmentation algorithm, applied also when no ALGORITHM flag is specified. Offers a balance between defragmentation quality and the amount of allocations and bytes that need to be moved.
Default defragmentation algorithm, applied also when no ALGORITHM flag is specified. Offers a balance between defragmentation quality and the amount of allocations and bytes that need to be moved.
Perform full defragmentation of memory. Can result in notably more time to compute and allocations to copy, but will achieve best memory packing.
A bit mask to extract only ALGORITHM bits from entire set of flags.
A bit mask to extract only ALGORITHM bits from entire set of flags.
Resource has been recreated at pDstTmpAllocation, data has been copied, old resource has been destroyed. pSrcAllocation will be changed to point to the new place. This is the default value set by DefragmentationContext::BeginPass().
Resource has been recreated at pDstTmpAllocation, data has been copied, old resource has been destroyed. pSrcAllocation will be changed to point to the new place. This is the default value set by DefragmentationContext::BeginPass().
Set this value if you cannot move the allocation. New place reserved at pDstTmpAllocation will be freed. pSrcAllocation will remain unchanged.
Set this value if you cannot move the allocation. New place reserved at pDstTmpAllocation will be freed. pSrcAllocation will remain unchanged.
Set this value if you decide to abandon the allocation and you destroyed the resource. New place reserved pDstTmpAllocation will be freed, along with pSrcAllocation.
Set this value if you decide to abandon the allocation and you destroyed the resource. New place reserved pDstTmpAllocation will be freed, along with pSrcAllocation.
Allocation strategy that chooses always the lowest offset in available space. This is not the most efficient strategy but achieves highly packed data.
A bit mask to extract only STRATEGY bits from entire set of flags.
A bit mask to extract only STRATEGY bits from entire set of flags.
These strategy flags are binary compatible with equivalent flags in ALLOCATION_FLAGS.
Creates new main D3D12MA::Allocator object and returns it through ppAllocator.
You normally only need to call it once and keep a single Allocator object for your ID3D12Device.
Creates new main D3D12MA::Allocator object and returns it through ppAllocator.
+You normally only need to call it once and keep a single Allocator object for your ID3D12Device.
@@ -591,7 +541,7 @@Creates new D3D12MA::VirtualBlock object and returns it through ppVirtualBlock.
Creates new D3D12MA::VirtualBlock object and returns it through ppVirtualBlock.
Note you don't need to create D3D12MA::Allocator to use virtual blocks.
@@ -599,7 +549,7 @@This library tries to automatically make optimal choices for the resources you create, so you don't need to care about them. There are some advanced features of Direct3D 12 that you may use to optimize your memory management. There are also some settings in D3D12MA that you may change to alter its default behavior. This page provides miscellaneous advice about features of D3D12 and D3D12MA that are non-essential, but may improve the stability or performance of your app.
-When trying to allocate more memory than available in the current heap (e.g., video memory on the graphics card, system memory), one of few bad things can happen:
HRESULT value other than S_OK.IDXGIAdapter3::QueryVideoMemoryInfo that queries the current memory usage and budget. This library automatically makes use of it when available (when you use recent enough version of the DirectX SDK). If not, it falls back to estimating the usage and budget based on the total amount of the allocated memory and 80% of the full memory capacity, respectively.When creating non-essential resources, you can use D3D12MA::ALLOCATION_FLAG_WITHIN_BUDGET. Then, in case the allocation would exceed the budget, the library will return failure from the function without attempting to allocate the actual D3D12 memory.
-It may also be a good idea to support failed resource creation. For non-essential resources, when function D3D12MA::Allocator::CreateResource fails with a result other than S_OK, it is worth implementing some way of recovery instead of terminating or crashing the entire app.
It may also be a good idea to support failed resource creation. For non-essential resources, when function D3D12MA::Allocator::CreateResource fails with a result other than S_OK, it is worth implementing some way of recovery instead of terminating or crashing the entire app.
+Creating D3D12 resources (buffers and textures) can be a time-consuming operation. The duration can be unpredictable, spanning from a small fraction of a millisecond to a significant fraction of a second. Thus, it is recommended to allocate all the memory and create all the resources needed upfront rather than doing it during application runtime. For example, a video game can try to create its resources on startup or when loading a new level. Of course, is is not always possible. For example, open-world games may require loading and unloading some graphical assets in the background (often called "streaming").
-Creating and releasing D3D12 resources on a separate thread in the background may help. Both ID3D12Device and D3D12MA::Allocator objects are thread-safe, synchronized internally. However, cases were observed where resource creation calls like ID3D12Device::CreateCommittedResource were blocking other D3D12 calls like ExecuteCommandLists or Present somewhere inside the graphics driver, so hitches can happen even when using multithreading.
The most expensive part is typically the allocation of a new D3D12 memory heap. This library tackles this problem by automatically allocating large heaps (64 MB by default) and creating resources as placed inside of them. When a new requested resource can be placed in a free space of an existing heap and doesn't require allocating a new heap, this operation is typically much faster, as it only requires creating a new ID3D12Resource object and not allocating new memory. This is the main benefit of using D3D12MA compared to the naive approach of using Direct3D 12 directly and creating each resource as committed with CreateCommittedResource, which would result in a separate allocation of an implicit heap every time.
When a large number of small buffers needs to be created, the overhead of creating even just separate ID3D12Resource objects can be significant. It can be avoided by creating one or few larger buffers and manually sub-allocating parts of them for specific needs. This library can also help with it. See section "Sub-allocating buffers" below.
Creating and releasing D3D12 resources on a separate thread in the background may help. Both ID3D12Device and D3D12MA::Allocator objects are thread-safe, synchronized internally. However, cases were observed where resource creation calls like ID3D12Device::CreateCommittedResource were blocking other D3D12 calls like ExecuteCommandLists or Present somewhere inside the graphics driver, so hitches can happen even when using multithreading.
+The most expensive part is typically the allocation of a new D3D12 memory heap. This library tackles this problem by automatically allocating large heaps (64 MB by default) and creating resources as placed inside of them. When a new requested resource can be placed in a free space of an existing heap and doesn't require allocating a new heap, this operation is typically much faster, as it only requires creating a new ID3D12Resource object and not allocating new memory. This is the main benefit of using D3D12MA compared to the naive approach of using Direct3D 12 directly and creating each resource as committed with CreateCommittedResource, which would result in a separate allocation of an implicit heap every time.
+When a large number of small buffers needs to be created, the overhead of creating even just separate ID3D12Resource objects can be significant. It can be avoided by creating one or few larger buffers and manually sub-allocating parts of them for specific needs. This library can also help with it. See section "Sub-allocating buffers" below.
Another reason for the slowness of D3D12 memory allocation is the guarantee that the newly allocated memory is filled with zeros. When creating and destroying resources placed in an existing heap, this overhead is not present, and the memory is not zeroed - it may contain random data left by the resource previously allocated in that place. In recent versions of the DirectX 12 SDK, clearing the memory of the newly created D3D12 heaps can also be disabled for the improved performance. D3D12MA can use this feature when:
D3D12_HEAP_FLAG_CREATE_NOT_ZEROED is passed to D3D12MA::POOL_DESC::HeapFlags during the creation of a custom pool.It is recommended to always use these flags. The downside is that when the memory is not filled with zeros, while you don't properly clear it or otherwise initialize its content before use (which is required by D3D12), you may observe incorrect behavior. This problem mostly affects render-target and depth-stencil textures.
When an allocation needs to be made in a performance-critical code, you can use D3D12MA::ALLOCATION_FLAG_STRATEGY_MIN_TIME. In influences multiple heuristics inside the library to prefer faster allocation at the expense of possibly less optimal placement in the memory.
If the resource to be created is non-essential, while the performance is paramount, you can also use D3D12MA::ALLOCATION_FLAG_NEVER_ALLOCATE. It will create the resource only if it can be placed inside and existing memory heap and return failure from the function if a new heap would need to be allocated, which should guarantee good performance of such function call.
-When a large number of small buffers needs to be created, the overhead of creating separate ID3D12Resource objects can be significant. It can also cause a significant waste of memory, as placed buffers need to be aligned to D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT = 64 KB by default. These problems can be avoided by creating one or few larger buffers and manually sub-allocating parts of them for specific needs.
When a large number of small buffers needs to be created, the overhead of creating separate ID3D12Resource objects can be significant. It can also cause a significant waste of memory, as placed buffers need to be aligned to D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT = 64 KB by default. These problems can be avoided by creating one or few larger buffers and manually sub-allocating parts of them for specific needs.
It requires implementing a custom allocator for the data inside the buffer and using offsets to individual regions. When all the regions can be allocated linearly and freed all at once, implementing such allocator is trivial. When every region has the same size, implementing an allocator is also quite simple when using a "free list" algorithm. However, when regions can have different sizes and can be allocated and freed in random order, it requires a full allocation algorithm. D3D12MA can help with it by exposing its core allocation algorithm for custom usages. For more details and example code, see chapter: Virtual allocator. It can be used for all the cases mentioned above without too much performance overhead, because the D3D12MA::VirtualAllocation object is just a lightweight handle.
-When sub-allocating a buffer, you need to remember to explicitly request proper alignment required for each region. For example, data used as a constant buffer must be aligned to D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT = 256 B.
When sub-allocating a buffer, you need to remember to explicitly request proper alignment required for each region. For example, data used as a constant buffer must be aligned to D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT = 256 B.
+When too much video memory is allocated, one of the things that can happen is the system demoting some heaps to the system memory. Moving data between memory pools or reaching out directly to the system memory through PCI Express bus can have large performance overhead, which can slow down the application, or even make the game unplayable any more. Unfortunately, it is not possible to fully control or prevent this demotion. Best thing to do is avoiding memory over-commitment. For more information, see section "Avoiding running out of memory" above.
-Recent versions of DirectX 12 SDK offer function ID3D12Device1::SetResidencyPriority that sets a hint about the priority of a resource - how important it is to stay resident in the video memory. Setting the priority happens at the level of an entire memory heap. D3D12MA offers an interface to set this priority in form of D3D12MA::POOL_DESC::ResidencyPriority parameter. It affects all allocations made out of the custom pool created with it, both placed inside large heaps and created as committed.
Recent versions of DirectX 12 SDK offer function ID3D12Device1::SetResidencyPriority that sets a hint about the priority of a resource - how important it is to stay resident in the video memory. Setting the priority happens at the level of an entire memory heap. D3D12MA offers an interface to set this priority in form of D3D12MA::POOL_DESC::ResidencyPriority parameter. It affects all allocations made out of the custom pool created with it, both placed inside large heaps and created as committed.
It is recommended to create a custom pool for the purpose of using high residency priority of all resources that are critical for the performance, especially those that are written by the GPU, like render-target, depth-stencil textures, UAV textures and buffers. It is also worth creating them as committed, so that each one will have its own implicit heap. This can minimize the chance that an entire large heap is demoted to system memory, degrading performance of all the resources placed in it.
Example:
Note this is not the same as explicit eviction controlled using ID3D12Device::Evict and MakeResident functions. Resources evicted explicitly are illegal to access until they are made resident again, while the demotion described here happens automatically and only slows down the execution.
Note this is not the same as explicit eviction controlled using ID3D12Device::Evict and MakeResident functions. Resources evicted explicitly are illegal to access until they are made resident again, while the demotion described here happens automatically and only slows down the execution.
+Direct3D 12 offers a fixed set of memory heap types:
D3D12_HEAP_TYPE_DEFAULT: Represents the video memory. It is available and fast to access for the GPU. It should be used for all resources that are written by the GPU (like render-target and depth-stencil textures, UAV) and resources that are frequently read by the GPU (like textures intended for sampling, vertex, index, and constant buffers).D3D12_HEAP_TYPE_UPLOAD: Represents the system memory that is uncached and write-combined. It can be mapped and accessed by the CPU code using a pointer. It supports only buffers, not textures. It is intended for "staging buffers" that are filled by the CPU code and then used as a source of copy operations to the DEFAULT heap. It can also be accessed directly by the GPU - shaders can read from buffers created in this memory.D3D12_HEAP_TYPE_READBACK: Represents the system memory that is cached. It is intended for buffers used as a destination of copy operations from the DEFAULT heap.Note that in systems with a discrete graphics card, access to system memory is fast from the CPU code (like the C++ code mapping D3D12 buffers and accessing them through a pointer), while access to the video memory is fast from the GPU code (like shaders reading and writing buffers and textures). Any copy operation or direct access between these memory heap types happens through PCI Express bus, which can be relatively slow.
Modern systems offer a feature called Resizable BAR (ReBAR) that gives the CPU direct access to the full video memory. To be available, this feature needs to be supported by the whole hardware-software environment, including:
@@ -192,20 +179,20 @@Recent versions of DirectX 12 SDK give access to this feature in form of a new, 4th memory pool: D3D12_HEAP_TYPE_GPU_UPLOAD. Resources created in it behave logically similar to the D3D12_HEAP_TYPE_UPLOAD heap:
Recent versions of DirectX 12 SDK give access to this feature in form of a new, 4th memory pool: D3D12_HEAP_TYPE_GPU_UPLOAD. Resources created in it behave logically similar to the D3D12_HEAP_TYPE_UPLOAD heap:
memcpy). It shouldn't be accessed randomly or read, because it is extremely slow for uncached memory.The main difference is that resources created in the new D3D12_HEAP_TYPE_GPU_UPLOAD are placed in the video memory, while resources created in the old D3D12_HEAP_TYPE_UPLOAD are placed in the system memory. This implies which budgets are consumed by new resources allocated in those heaps. This also implies which operations involve transferring data through the PCI Express bus.
The main difference is that resources created in the new D3D12_HEAP_TYPE_GPU_UPLOAD are placed in the video memory, while resources created in the old D3D12_HEAP_TYPE_UPLOAD are placed in the system memory. This implies which budgets are consumed by new resources allocated in those heaps. This also implies which operations involve transferring data through the PCI Express bus.
D3D12_HEAP_TYPE_UPLOAD uses the system memory, writes from the CPU code through a mapped pointer are faster, while copies or direct access from the GPU are slower because they need to go through PCIe.D3D12_HEAP_TYPE_GPU_UPLOAD uses the video memory, copies or direct access from the GPU are faster, while writes from the CPU code through a mapped pointer can be slower, because they need to go through PCIe. For maximum performance of copy operations from this heap, a graphics or compute queue should be used, not a copy queue.GPU Upload Heap can be used for performance optimization of some resources that need to be written by the CPU and read by the GPU. It can be beneficial especially for resources that need to change frequently (often called "dynamic").
-D3D12MA supports GPU upload heap when recent enough version of DirectX 12 SDK is used and when the current system supports it. The support can be queried using function D3D12MA::Allocator::IsGPUUploadHeapSupported(). When it returns TRUE, you can create resources using D3D12_HEAP_TYPE_GPU_UPLOAD. You can also just try creating such resource. Example:
D3D12MA supports GPU upload heap when recent enough version of DirectX 12 SDK is used and when the current system supports it. The support can be queried using function D3D12MA::Allocator::IsGPUUploadHeapSupported(). When it returns TRUE, you can create resources using D3D12_HEAP_TYPE_GPU_UPLOAD. You can also just try creating such resource. Example:
When using D3D12 API directly, there are 3 ways of creating resources:
ID3D12Device::CreateCommittedResource. It creates the resource with its own memory heap, which is called an "implicit heap" and cannot be accessed directly.ID3D12Device::CreatePlacedResource. A ID3D12Heap needs to be created beforehand using ID3D12Device::CreateHeap. Then, the resource can be created as placed inside the heap at a specific offset.ID3D12Device::CreateReservedResource. This library doesn't support them directly.A naive solution would be to create all the resources as committed. It works, because in D3D12 there is no strict limit on the number of resources or heaps that can be created. However, there are certain advantages and disadvantages of using committed versus placed resources:
ID3D12Device::Evict and MakeResident functions work at the level of the entire heap, and so does ID3D12Device1::SetResidencyPriority, so creating resources as committed allows more fine-grained control over the eviction and residency priority of individual resources.When creating resources with the help of D3D12MA using function D3D12MA::Allocator::CreateResource, you typically don't need to care about all this. The library automatically makes the choice of creating the new resource as committed or placed. However, in cases when you need the information or the control over this choice between committed and placed, the library offers facilities to do that, described below.
@@ -303,18 +290,18 @@You can request a new resource to be created as placed by using D3D12MA::ALLOCATION_FLAG_CAN_ALIAS. This is required especially if you plan to create another resource in the same region of memory, aliasing with your resource - hence the name of this flag.
Note D3D12MA::ALLOCATION_FLAG_CAN_ALIAS can be even combined with D3D12MA::ALLOCATION_FLAG_COMMITTED. In this case, the resource is not created as committed, but it is also not placed as part of a larger heap. What happens instead is that a new heap is created with the exact size required for the resource, and the resource is created in it, placed at offset 0.
-Certain types of resources require certain alignment in memory. An alignment is a requirement for the address or offset to the beginning of the resource to be a multiply of some value, which is always a power of 2. For committed resources, the problem is non-existent, because committed resources have their own implicit heaps where they are created at offset 0, which meets any alignment requirement. For placed resources, D3D12MA takes care of the alignment automatically.
-D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT = 4 MB. Default alignment required for buffers and other textures is D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT = 64 KB.Because the alignment required for buffers is 64 KB, small buffers can waste a lot of memory in between when created as placed. When such small buffers are created as committed, some graphics drivers are able to pack them better. D3D12MA automatically takes advantage of this by preferring to create small buffers as committed. This heuristics is enabled by default. It is also a tradeoff - it can make the allocation of these buffers slower. It can be disabled for an individual resource by using D3D12MA::ALLOCATION_FLAG_STRATEGY_MIN_TIME and for the entire allocator by using D3D12MA::ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED.
-For certain textures that meet a complex set of requirements, special "small alignment" can be applied. Details can be found in Microsoft documentation of the D3D12_RESOURCE_DESC structure. For MSAA textures, the small alignment is D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT = 64 KB. For other textures, the small alignment is D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT = 4 KB. D3D12MA uses this feature automatically. Detailed behavior can be disabled or controlled by predefining macro D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT.
D3D12 also has a concept of alignment of the entire heap, passed through D3D12_HEAP_DESC::Alignment. This library automatically sets the alignment as small as possible. Unfortunately, any heap that has a chance of hosting an MSAA texture needs to have the alignment set to 4 MB. This problem can be overcome by passing D3D12MA::ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED on the creation of the main allocator object and D3D12MA::POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED on the creation of any custom heap that supports textures, not only buffers. With those flags, the alignment of the heaps created by D3D12MA can be lower, but any MSAA textures are created as committed. You should always use these flags in your code unless you really need to create some MSAA textures as placed.
For certain textures that meet a complex set of requirements, special "small alignment" can be applied. Details can be found in Microsoft documentation of the D3D12_RESOURCE_DESC structure. For MSAA textures, the small alignment is D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT = 64 KB. For other textures, the small alignment is D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT = 4 KB. D3D12MA uses this feature automatically. Detailed behavior can be disabled or controlled by predefining macro D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT.
+D3D12 also has a concept of alignment of the entire heap, passed through D3D12_HEAP_DESC::Alignment. This library automatically sets the alignment as small as possible. Unfortunately, any heap that has a chance of hosting an MSAA texture needs to have the alignment set to 4 MB. This problem can be overcome by passing D3D12MA::ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED on the creation of the main allocator object and D3D12MA::POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED on the creation of any custom heap that supports textures, not only buffers. With those flags, the alignment of the heaps created by D3D12MA can be lower, but any MSAA textures are created as committed. You should always use these flags in your code unless you really need to create some MSAA textures as placed.
This is a small, standalone C++ library. It consists 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).
The library is developed and tested using Microsoft Visual Studio 2022, but it should work with other compilers as well. It is designed for 64-bit code.
To use the library in your project:
-(1.) Copy files D3D12MemAlloc.cpp, D3D12MemAlloc.h to your project.
(2.) Make D3D12MemAlloc.cpp compiling as part of the project, as C++ code.
(1.) Copy files D3D12MemAlloc.cpp, D3D12MemAlloc.h to your project.
+(2.) Make D3D12MemAlloc.cpp compiling as part of the project, as C++ code.
(3.) Include library header in each CPP file that needs to use the library.
(4.) Right after you created ID3D12Device, fill D3D12MA::ALLOCATOR_DESC structure and call function D3D12MA::CreateAllocator to create the main D3D12MA::Allocator object.
(4.) Right after you created ID3D12Device, fill D3D12MA::ALLOCATOR_DESC structure and call function D3D12MA::CreateAllocator to create the main D3D12MA::Allocator object.
Please note that all symbols of the library are declared inside D3D12MA namespace.
(5.) Right before destroying the D3D12 device, destroy the allocator object.
Objects of this library must be destroyed by calling Release method. They are somewhat compatible with COM: they implement IUnknown interface with its virtual methods: AddRef, Release, QueryInterface, and they are reference-counted internally. You can use smart pointers designed for COM with objects of this library - e.g. CComPtr or Microsoft::WRL::ComPtr. The reference counter is thread-safe. QueryInterface method supports only IUnknown, as classes of this library don't define their own GUIDs.
Objects of this library must be destroyed by calling Release method. They are somewhat compatible with COM: they implement IUnknown interface with its virtual methods: AddRef, Release, QueryInterface, and they are reference-counted internally. You can use smart pointers designed for COM with objects of this library - e.g. CComPtr or Microsoft::WRL::ComPtr. The reference counter is thread-safe. QueryInterface method supports only IUnknown, as classes of this library don't define their own GUIDs.
+To use the library for creating resources (textures and buffers), call method D3D12MA::Allocator::CreateResource in the place where you would previously call ID3D12Device::CreateCommittedResource.
The function has similar syntax, but it expects structure D3D12MA::ALLOCATION_DESC to be passed along with D3D12_RESOURCE_DESC and other parameters for created resource. This structure describes parameters of the desired memory allocation, including choice of D3D12_HEAP_TYPE.
The function returns a new object of type D3D12MA::Allocation. It represents allocated memory and can be queried for size, offset, ID3D12Heap. It also holds a reference to the ID3D12Resource, which can be accessed by calling D3D12MA::Allocation::GetResource().
To use the library for creating resources (textures and buffers), call method D3D12MA::Allocator::CreateResource in the place where you would previously call ID3D12Device::CreateCommittedResource.
+The function has similar syntax, but it expects structure D3D12MA::ALLOCATION_DESC to be passed along with D3D12_RESOURCE_DESC and other parameters for created resource. This structure describes parameters of the desired memory allocation, including choice of D3D12_HEAP_TYPE.
+The function returns a new object of type D3D12MA::Allocation. It represents allocated memory and can be queried for size, offset, ID3D12Heap. It also holds a reference to the ID3D12Resource, which can be accessed by calling D3D12MA::Allocation::GetResource().
You need to release the allocation object when no longer needed. This will also release the D3D12 resource.
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 ID3D12Device::CreateHeap and place multiple resources in it, at different offsets, using ID3D12Device::CreatePlacedResource. 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.
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 (ClearRenderTargetView), Discard (DiscardResource), or Copy (CopyResource).
The library also automatically handles resource heap tier. When D3D12_FEATURE_DATA_D3D12_OPTIONS::ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1, resources of 3 types: buffers, textures that are render targets or depth-stencil, and other textures must be kept in separate heaps. When D3D12_RESOURCE_HEAP_TIER_2, they can be kept together. By using this library, you don't need to handle this manually.
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 ID3D12Device::CreateHeap and place multiple resources in it, at different offsets, using ID3D12Device::CreatePlacedResource. 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.
+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 (ClearRenderTargetView), Discard (DiscardResource), or Copy (CopyResource).
+The library also automatically handles resource heap tier. When D3D12_FEATURE_DATA_D3D12_OPTIONS::ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1, resources of 3 types: buffers, textures that are render targets or depth-stencil, and other textures must be kept in separate heaps. When D3D12_RESOURCE_HEAP_TIER_2, they can be kept together. By using this library, you don't need to handle this manually.
+ID3D12Resource 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 D3D12MA::Allocation remembers the resource (buffer or texture) that was created together with this memory allocation and holds a reference to the ID3D12Resource object. (Note this is a difference to Vulkan Memory Allocator, where a VmaAllocation 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.
The simplest use case is shown in the code snippet above. When only D3D12MA::Allocation object is obtained from a function call like D3D12MA::Allocator::CreateResource, it remembers the ID3D12Resource that was created with it and holds a reference to it. The resource can be obtained by calling allocation->GetResource(), which doesn't increment the resource reference counter. Calling allocation->Release() will decrease the resource reference counter, which is 1 in this case, so the resource will be released.
ID3D12Resource 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 D3D12MA::Allocation remembers the resource (buffer or texture) that was created together with this memory allocation and holds a reference to the ID3D12Resource object. (Note this is a difference to Vulkan Memory Allocator, where a VmaAllocation 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.
+The simplest use case is shown in the code snippet above. When only D3D12MA::Allocation object is obtained from a function call like D3D12MA::Allocator::CreateResource, it remembers the ID3D12Resource that was created with it and holds a reference to it. The resource can be obtained by calling allocation->GetResource(), which doesn't increment the resource reference counter. Calling allocation->Release() will decrease the resource reference counter, which is 1 in this case, so the resource will be released.
Second option is to retrieve a pointer to the resource along with D3D12MA::Allocation. Last parameters of the resource creation function can be used for this purpose.
In this case, returned pointer resource is equal to allocation->GetResource(), but the creation function additionally increases resource reference counter for the purpose of returning it from this call (it actually calls QueryInterface 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.
In this case, returned pointer resource is equal to allocation->GetResource(), but the creation function additionally increases resource reference counter for the purpose of returning it from this call (it actually calls QueryInterface 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.
More advanced use cases are possible when we consider that an D3D12MA::Allocation object can just hold a reference to any resource. It can be changed by calling D3D12MA::Allocation::SetResource. This function releases the old resource and calls AddRef on the new one.
Special care must be taken when performing defragmentation. The new resource created at the destination place should be set as pass.pMoves[i].pDstTmpAllocation->SetResource(newRes), but it is moved to the source allocation at end of the defragmentation pass, while the old resource accessible through pass.pMoves[i].pSrcAllocation->GetResource() is then released. For more information, see documentation chapter Defragmentation.
More advanced use cases are possible when we consider that an D3D12MA::Allocation object can just hold a reference to any resource. It can be changed by calling D3D12MA::Allocation::SetResource. This function releases the old resource and calls AddRef on the new one.
+Special care must be taken when performing defragmentation. The new resource created at the destination place should be set as pass.pMoves[i].pDstTmpAllocation->SetResource(newRes), but it is moved to the source allocation at end of the defragmentation pass, while the old resource accessible through pass.pMoves[i].pSrcAllocation->GetResource() is then released. For more information, see documentation chapter Defragmentation.
+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 ID3D12Resource::Map method.
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 Map function says:
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 ID3D12Resource::Map method.
+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 Map function says:
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.
-Example for buffer created and filled in UPLOAD heap type:
Example for buffer created and filled in UPLOAD heap type:
DirectX 12 Agility SDK offers a library of helpers in files "build\native\include\d3dx12\*.h". They include structures that help with complete and concise initialization of the core D3D12 *_DESC structures by using some basic C++ features (constructors, static methods, default parameters). They inherit from these structures, so they support implicit casting to them. For example, structure CD3DX12_RESOURCE_DESC can be used to conveniently fill in structure D3D12_RESOURCE_DESC.
Similarly, this library provides a set of helper structures that aid in initialization of some of the *_DESC structures defined in the library. These are:
DirectX 12 Agility SDK offers a library of helpers in files "build\native\include\d3dx12\*.h". They include structures that help with complete and concise initialization of the core D3D12 *_DESC structures by using some basic C++ features (constructors, static methods, default parameters). They inherit from these structures, so they support implicit casting to them. For example, structure CD3DX12_RESOURCE_DESC can be used to conveniently fill in structure D3D12_RESOURCE_DESC.
+Similarly, this library provides a set of helper structures that aid in initialization of some of the *_DESC structures defined in the library. These are:
For example, when you want to create a buffer in the UPLAOD heap using minimal allocation time, you can use base structures:
For example, when you want to create a buffer in the UPLAOD heap using minimal allocation time, you can use base structures:
New explicit graphics APIs (Vulkan and Direct3D 12), thanks to manual memory management, give an opportunity to alias (overlap) multiple resources in the same region of memory - a feature not available in the old APIs (Direct3D 11, OpenGL). It can be useful to save video memory, but it must be used with caution.
@@ -171,18 +158,18 @@Remember that using resouces that alias in memory requires proper synchronization. You need to issue a special barrier of type D3D12_RESOURCE_BARRIER_TYPE_ALIASING. You also need to treat a resource after aliasing as uninitialized - containing garbage data. For example, if you use res1 and then want to use res2, you need to first initialize res2 using either Clear, Discard, or Copy to the entire resource.
Remember that using resouces that alias in memory requires proper synchronization. You need to issue a special barrier of type D3D12_RESOURCE_BARRIER_TYPE_ALIASING. You also need to treat a resource after aliasing as uninitialized - containing garbage data. For example, if you use res1 and then want to use res2, you need to first initialize res2 using either Clear, Discard, or Copy to the entire resource.
Additional considerations:
AllocationLocalOffset parameter.RENDER_TARGET or DEPTH_STENCIL flags, and all other textures, can be placed in the same memory only when allocator->GetD3D12Options().ResourceHeapTier >= D3D12_RESOURCE_HEAP_TIER_2. Otherwise they must be placed in different memory heap types, and thus aliasing them is not possible. This library contains several functions that return information about its internal state, especially the amount of memory allocated from D3D12.
-If you need to obtain basic statistics about memory usage per memory segment group, together with current budget, you can call function D3D12MA::Allocator::GetBudget() and inspect structure D3D12MA::Budget. This is useful to keep track of memory usage and stay withing budget. Example:
You can query for more detailed statistics per heap type, memory segment group, and totals, including minimum and maximum allocation size and unused range size, by calling function D3D12MA::Allocator::CalculateStatistics() and inspecting structure D3D12MA::TotalStatistics. This function is slower though, as it has to traverse all the internal data structures, so it should be used only for debugging purposes.
You can query for statistics of a custom pool using function D3D12MA::Pool::GetStatistics() or D3D12MA::Pool::CalculateStatistics().
-You can query for information about a specific allocation using functions of the D3D12MA::Allocation class, e.g. GetSize(), GetOffset(), GetHeap().
You can query for information about a specific allocation using functions of the D3D12MA::Allocation class, e.g. GetSize(), GetOffset(), GetHeap().
+You can dump internal state of the allocator to a string in JSON format using function D3D12MA::Allocator::BuildStatsString(). The result is guaranteed to be correct JSON. It uses Windows Unicode (UTF-16) encoding. Any strings provided by user (see D3D12MA::Allocation::SetName()) are copied as-is and properly escaped for JSON. It must be freed using function D3D12MA::Allocator::FreeStatsString().
The format of this JSON string is not part of official documentation of the library, but it will not change in backward-incompatible way without increasing library major version number and appropriate mention in changelog.
@@ -122,7 +109,7 @@#include <D3D12MemAlloc.h>
+Public AttributesALLOCATE_FUNC_PTR | pAllocate | | FREE_FUNC_PTR | pFree | | | Custom data that will be passed to allocation and deallocation functions as pUserData parameter. | | |||||||||||||||
pUserData parameter. Custom callbacks to CPU memory allocation functions.
-Custom data that will be passed to allocation and deallocation functions as pUserData parameter.
Custom data that will be passed to allocation and deallocation functions as pUserData parameter.
@@ -169,7 +153,7 @@
-
+Public AttributesALLOCATION_FLAGS | Flags | | D3D12_HEAP_TYPE | HeapType | | D3D12_HEAP_FLAGS | ExtraHeapFlags | | Pool * | CustomPool | | void * | pPrivateData | | | ||||||||||||||||||
Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource.
-Custom pool to place the new resource in. Optional.
-When not null, the resource will be created inside specified custom pool. Members HeapType, ExtraHeapFlags are then ignored.
When not null, the resource will be created inside specified custom pool. Members HeapType, ExtraHeapFlags are then ignored.
@@ -162,9 +144,9 @@D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES, or D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES is added automatically.ALLOW_ONLY flags. Except when you validate that D3D12MA::Allocator::GetD3D12Options().ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1 - then you can leave it 0.D3D12Device::CreateCommittedResource or CreateHeap, not as part of an existing larget block.When D3D12MA::ALLOCATION_DESC::CustomPool != NULL this member is ignored.
@@ -199,7 +181,7 @@The type of memory heap where the new allocation should be placed.
-It must be one of: D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_TYPE_READBACK.
It must be one of: D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_TYPE_READBACK.
When D3D12MA::ALLOCATION_DESC::CustomPool != NULL this member is ignored.
@@ -226,7 +208,7 @@#include <D3D12MemAlloc.h>
+Public AttributesALLOCATOR_FLAGS | Flags | | | | Preferred size of a single ID3D12Heap block to be allocated. | const ALLOCATION_CALLBACKS * | pAllocationCallbacks | | | | |||||||||||||||||||||
ID3D12Heap block to be allocated. Parameters of created Allocator object. To be used with CreateAllocator().
-DXGI Adapter object that you use for D3D12 and this allocator.
-Allocator is doing AddRef/Release on this object.
Allocator is doing AddRef/Release on this object.
@@ -181,7 +163,7 @@Direct3D device object that the allocator should be attached to.
-Allocator is doing AddRef/Release on this object.
Allocator is doing AddRef/Release on this object.
@@ -197,7 +179,7 @@Preferred size of a single ID3D12Heap block to be allocated.
Preferred size of a single ID3D12Heap block to be allocated.
Set to 0 to use default, which is currently 64 MiB.
@@ -208,7 +190,7 @@#include <D3D12MemAlloc.h>
+Public AttributesStatistics | Stats | | UINT64 | UsageBytes | | UINT64 | BudgetBytes | | | ||||||||||||
Statistics of current memory usage and available budget for a specific memory segment group.
These are fast to calculate. See function D3D12MA::Allocator::GetBudget().
-Estimated amount of memory available to the program.
-Fetched from system using IDXGIAdapter3::QueryVideoMemoryInfo if possible.
It might be different (most probably smaller) than memory capacity returned by D3D12MA::Allocator::GetMemoryCapacity() due to factors external to the program, decided by the operating system. Difference BudgetBytes - UsageBytes is the amount of additional memory that can probably be allocated without problems. Exceeding the budget may result in various problems.
Fetched from system using IDXGIAdapter3::QueryVideoMemoryInfo if possible.
+It might be different (most probably smaller) than memory capacity returned by D3D12MA::Allocator::GetMemoryCapacity() due to factors external to the program, decided by the operating system. Difference BudgetBytes - UsageBytes is the amount of additional memory that can probably be allocated without problems. Exceeding the budget may result in various problems.
@@ -163,8 +147,8 @@Estimated current memory usage of the program.
-Fetched from system using IDXGIAdapter3::QueryVideoMemoryInfo if possible.
It might be different than BlockBytes (usually higher) due to additional implicit objects also occupying the memory, like swapchain, pipeline state objects, descriptor heaps, command lists, or heaps and resources allocated outside of this library, if any.
Fetched from system using IDXGIAdapter3::QueryVideoMemoryInfo if possible.
+It might be different than BlockBytes (usually higher) due to additional implicit objects also occupying the memory, like swapchain, pipeline state objects, descriptor heaps, command lists, or heaps and resources allocated outside of this library, if any.
@@ -174,7 +158,7 @@
-
+
+Public Member Functions | CALLOCATION_DESC ()=default | | | CALLOCATION_DESC (const ALLOCATION_DESC &o) noexcept | | | CALLOCATION_DESC (Pool *customPool, ALLOCATION_FLAGS flags=ALLOCATION_FLAG_NONE, void *privateData=NULL) noexcept | | | Constructor initializing description of an allocation to be created in a default pool of a specific D3D12_HEAP_TYPE. | | ||||||||||||||||||
D3D12_HEAP_TYPE.
+Additional Inherited Members Public Attributes inherited from D3D12MA::ALLOCATION_DESC | Flags for the allocation. | | The type of memory heap where the new allocation should be placed. | | Additional heap flags to be used when allocating memory. | | Custom pool to place the new resource in. Optional. | | Custom general-purpose pointer that will be stored in D3D12MA::Allocation. | | Public Attributes inherited from D3D12MA::ALLOCATION_DESC | ALLOCATION_FLAGS | Flags | D3D12_HEAP_TYPE | HeapType | D3D12_HEAP_FLAGS | ExtraHeapFlags | Pool * | CustomPool | void * | pPrivateData | ||||||||||||||||
Helper structure that helps with complete and conscise initialization of the D3D12MA::ALLOCATION_DESC structure.
-Constructor initializing description of an allocation to be created in a default pool of a specific D3D12_HEAP_TYPE.
Constructor initializing description of an allocation to be created in a default pool of a specific D3D12_HEAP_TYPE.
@@ -283,7 +261,7 @@
-
+
+Public Member Functions | CPOOL_DESC ()=default | | | CPOOL_DESC (const POOL_DESC &o) noexcept | | | Constructor initializing description of a custom pool created in one of the standard D3D12_HEAP_TYPE. | | Constructor initializing description of a custom pool created with custom D3D12_HEAP_PROPERTIES. | | |||||||||||||||||||||
D3D12_HEAP_TYPE. D3D12_HEAP_PROPERTIES.
+Additional Inherited Members Public Attributes inherited from D3D12MA::POOL_DESC | Flags for the heap. | | The parameters of memory heap where allocations of this pool should be placed. | | Heap flags to be used when allocating heaps of this pool. | | Size of a single heap (memory block) to be allocated as part of this pool, in bytes. Optional. | | Minimum number of heaps (memory blocks) to be always allocated in this pool, even if they stay empty. Optional. | | Maximum number of heaps (memory blocks) that can be allocated in this pool. Optional. | | Additional minimum alignment to be used for all allocations created from this pool. Can be 0. | | Additional parameter allowing pool to create resources with passed protected session. | | Residency priority to be set for all allocations made in this pool. Optional. | | Public Attributes inherited from D3D12MA::POOL_DESC | POOL_FLAGS | Flags | D3D12_HEAP_PROPERTIES | HeapProperties | D3D12_HEAP_FLAGS | HeapFlags | UINT64 | BlockSize | UINT | MinBlockCount | UINT | MaxBlockCount | UINT64 | MinAllocationAlignment | ID3D12ProtectedResourceSession * | pProtectedSession | D3D12_RESIDENCY_PRIORITY | ResidencyPriority | ||||||||||||||||||||||||
Helper structure that helps with complete and conscise initialization of the D3D12MA::POOL_DESC structure.
-Constructor initializing description of a custom pool created in one of the standard D3D12_HEAP_TYPE.
Constructor initializing description of a custom pool created in one of the standard D3D12_HEAP_TYPE.
@@ -320,7 +294,7 @@Constructor initializing description of a custom pool created with custom D3D12_HEAP_PROPERTIES.
Constructor initializing description of a custom pool created with custom D3D12_HEAP_PROPERTIES.
@@ -330,7 +304,7 @@
-
+
+Public Member Functions | CVIRTUAL_ALLOCATION_DESC ()=default | | | CVIRTUAL_ALLOCATION_DESC (const VIRTUAL_ALLOCATION_DESC &o) noexcept | | | CVIRTUAL_ALLOCATION_DESC (UINT64 size, UINT64 alignment, VIRTUAL_ALLOCATION_FLAGS flags=VIRTUAL_ALLOCATION_FLAG_NONE, void *privateData=NULL) noexcept | | | ||||||||||||
+Additional Inherited Members Public Attributes inherited from D3D12MA::VIRTUAL_ALLOCATION_DESC | Flags for the virtual allocation. | | Size of the allocation. | | Required alignment of the allocation. | | Custom pointer to be associated with the allocation. | | Public Attributes inherited from D3D12MA::VIRTUAL_ALLOCATION_DESC | VIRTUAL_ALLOCATION_FLAGS | Flags | UINT64 | Size | UINT64 | Alignment | void * | pPrivateData | ||||||||||||||
Helper structure that helps with complete and conscise initialization of the D3D12MA::VIRTUAL_ALLOCATION_DESC structure.
-
-
+
+Public Member Functions | CVIRTUAL_BLOCK_DESC ()=default | | | CVIRTUAL_BLOCK_DESC (const VIRTUAL_BLOCK_DESC &o) noexcept | | | CVIRTUAL_BLOCK_DESC (UINT64 size, VIRTUAL_BLOCK_FLAGS flags=VIRTUAL_BLOCK_FLAG_NONE, const ALLOCATION_CALLBACKS *allocationCallbacks=NULL) noexcept | | | ||||||||||||
+Additional Inherited Members Public Attributes inherited from D3D12MA::VIRTUAL_BLOCK_DESC | Flags. | | Total size of the block. | | Custom CPU memory allocation callbacks. Optional. | | Public Attributes inherited from D3D12MA::VIRTUAL_BLOCK_DESC | VIRTUAL_BLOCK_FLAGS | Flags | UINT64 | Size | const ALLOCATION_CALLBACKS * | pAllocationCallbacks | ||||||||||||
Helper structure that helps with complete and conscise initialization of the D3D12MA::VIRTUAL_BLOCK_DESC structure.
-#include <D3D12MemAlloc.h>
+Public AttributesDEFRAGMENTATION_FLAGS | Flags | | UINT64 | MaxBytesPerPass | | UINT32 | MaxAllocationsPerPass | | | ||||||||||||
Parameters for defragmentation.
To be used with functions Allocator::BeginDefragmentation() and Pool::BeginDefragmentation().
-#include <D3D12MemAlloc.h>
+Public AttributesDEFRAGMENTATION_MOVE_OPERATION | Operation | | Allocation * | pSrcAllocation | | | Temporary allocation pointing to destination memory that will replace pSrcAllocation. | | |||||||||||||||
pSrcAllocation. Single move of an allocation to be done for defragmentation.
-Temporary allocation pointing to destination memory that will replace pSrcAllocation.
Use it to retrieve new ID3D12Heap and offset to create new ID3D12Resource and then store it here via Allocation::SetResource().
pSrcAllocation point to this memory. Temporary allocation pointing to destination memory that will replace pSrcAllocation.
+Use it to retrieve new ID3D12Heap and offset to create new ID3D12Resource and then store it here via Allocation::SetResource().
+#include <D3D12MemAlloc.h>
+Public Attributes | Number of elements in the pMoves array. | DEFRAGMENTATION_MOVE * | pMoves | | | ||||||||||||
pMoves array. Parameters for incremental defragmentation steps.
To be used with function DefragmentationContext::BeginPass().
-Number of elements in the pMoves array.
Number of elements in the pMoves array.
@@ -142,12 +127,12 @@Array of moves to be performed by the user in the current defragmentation pass.
-Pointer to an array of MoveCount elements, owned by D3D12MA, created in DefragmentationContext::BeginPass(), destroyed in DefragmentationContext::EndPass().
Pointer to an array of MoveCount elements, owned by D3D12MA, created in DefragmentationContext::BeginPass(), destroyed in DefragmentationContext::EndPass().
For each element, you should:
pMoves[i].pDstTmpAllocation->GetHeap() + pMoves[i].pDstTmpAllocation->GetOffset().pMoves[i].pDstTmpAllocation by using Allocation::SetResource(). It will later replace old resource from pMoves[i].pSrcAllocation.pMoves[i].pSrcAllocation e.g. using D3D12GraphicsCommandList::CopyResource.Only then you can finish defragmentation pass by calling DefragmentationContext::EndPass(). After this call, the allocation will point to the new place in memory.
@@ -162,7 +147,7 @@#include <D3D12MemAlloc.h>
+Public AttributesUINT64 | BytesMoved | | UINT64 | BytesFreed | | UINT32 | AllocationsMoved | | | Number of empty ID3D12Heap objects that have been released to the system. | | ||||||||||||||||||
ID3D12Heap objects that have been released to the system. Statistics returned for defragmentation process by function DefragmentationContext::GetStats().
-Number of empty ID3D12Heap objects that have been released to the system.
Number of empty ID3D12Heap objects that have been released to the system.
@@ -188,7 +171,7 @@#include <D3D12MemAlloc.h>
+Public AttributesStatistics | Stats | | UINT | UnusedRangeCount | | | Smallest allocation size. UINT64_MAX if there are 0 allocations. | UINT64 | AllocationSizeMax | | | Smallest empty range size. UINT64_MAX if there are 0 empty ranges. | UINT64 | UnusedRangeSizeMax | | | |||||||||||||||||||||||||||
UINT64_MAX if there are 0 allocations. UINT64_MAX if there are 0 empty ranges. More detailed statistics than D3D12MA::Statistics.
These are slower to calculate. Use for debugging purposes. See functions: D3D12MA::Allocator::CalculateStatistics(), D3D12MA::Pool::CalculateStatistics().
Averages are not provided because they can be easily calculated as:
Smallest allocation size. UINT64_MAX if there are 0 allocations.
Smallest allocation size. UINT64_MAX if there are 0 allocations.
@@ -221,7 +202,7 @@Smallest empty range size. UINT64_MAX if there are 0 empty ranges.
Smallest empty range size. UINT64_MAX if there are 0 empty ranges.
@@ -231,7 +212,7 @@
-
+
+Public AttributesPOOL_FLAGS | Flags | | D3D12_HEAP_PROPERTIES | HeapProperties | | D3D12_HEAP_FLAGS | HeapFlags | | UINT64 | BlockSize | | UINT | MinBlockCount | | UINT | MaxBlockCount | | UINT64 | MinAllocationAlignment | | ID3D12ProtectedResourceSession * | pProtectedSession | | D3D12_RESIDENCY_PRIORITY | ResidencyPriority | | | ||||||||||||||||||||||||||||||
Parameters of created D3D12MA::Pool object. To be used with D3D12MA::Allocator::CreatePool.
-Heap flags to be used when allocating heaps of this pool.
-It should contain one of these values, depending on type of resources you are going to create in this heap: D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES, D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES. Except if ResourceHeapTier = 2, then it may be D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES = 0.
It should contain one of these values, depending on type of resources you are going to create in this heap: D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES, D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES. Except if ResourceHeapTier = 2, then it may be D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES = 0.
It is recommended to also add D3D12MA_RECOMMENDED_POOL_FLAGS. You can specify additional flags if needed.
@@ -207,7 +185,7 @@The parameters of memory heap where allocations of this pool should be placed.
-In the simplest case, just fill it with zeros and set Type to one of: D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_TYPE_READBACK. Additional parameters can be used e.g. to utilize UMA.
In the simplest case, just fill it with zeros and set Type to one of: D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_TYPE_READBACK. Additional parameters can be used e.g. to utilize UMA.
@@ -224,7 +202,7 @@Maximum number of heaps (memory blocks) that can be allocated in this pool. Optional.
-Set to 0 to use default, which is UINT64_MAX, which means no limit.
Set to 0 to use default, which is UINT64_MAX, which means no limit.
Set to same value as D3D12MA::POOL_DESC::MinBlockCount to have fixed amount of memory allocated throughout whole lifetime of this pool.
@@ -293,10 +271,10 @@Residency priority to be set for all allocations made in this pool. Optional.
-Set this parameter to one of the possible enum values e.g. D3D12_RESIDENCY_PRIORITY_HIGH to apply specific residency priority to all allocations made in this pool: ID3D12Heap memory blocks used to sub-allocate for placed resources, as well as committed resources or heaps created when D3D12MA::ALLOCATION_FLAG_COMMITTED is used. This can increase/decrease chance that the memory will be pushed out from VRAM to system RAM when the system runs out of memory, which is invisible to the developer using D3D12 API while it can degrade performance.
Priority is set using function ID3D12Device1::SetResidencyPriority. It is performed only when ID3D12Device1 interface is defined and successfully obtained. Otherwise, this parameter is ignored.
This parameter is optional. If you set it to D3D12_RESIDENCY_PRIORITY(0), residency priority will not be set for allocations made in this pool.
There is no equivalent parameter for allocations made in default pools. If you want to set residency priority for such allocation, you need to do it manually: allocate with D3D12MA::ALLOCATION_FLAG_COMMITTED and call ID3D12Device1::SetResidencyPriority, passing allocation->GetResource().
Set this parameter to one of the possible enum values e.g. D3D12_RESIDENCY_PRIORITY_HIGH to apply specific residency priority to all allocations made in this pool: ID3D12Heap memory blocks used to sub-allocate for placed resources, as well as committed resources or heaps created when D3D12MA::ALLOCATION_FLAG_COMMITTED is used. This can increase/decrease chance that the memory will be pushed out from VRAM to system RAM when the system runs out of memory, which is invisible to the developer using D3D12 API while it can degrade performance.
+Priority is set using function ID3D12Device1::SetResidencyPriority. It is performed only when ID3D12Device1 interface is defined and successfully obtained. Otherwise, this parameter is ignored.
+This parameter is optional. If you set it to D3D12_RESIDENCY_PRIORITY(0), residency priority will not be set for allocations made in this pool.
+There is no equivalent parameter for allocations made in default pools. If you want to set residency priority for such allocation, you need to do it manually: allocate with D3D12MA::ALLOCATION_FLAG_COMMITTED and call ID3D12Device1::SetResidencyPriority, passing allocation->GetResource().
@@ -306,7 +284,7 @@#include <D3D12MemAlloc.h>
+Public Attributes | Number of D3D12 memory blocks allocated - ID3D12Heap objects and committed resources. | UINT | AllocationCount | | UINT64 | BlockBytes | | UINT64 | AllocationBytes | | | ||||||||||||||||||
ID3D12Heap objects and committed resources. Calculated statistics of memory usage e.g. in a specific memory heap type, memory segment group, custom pool, or total.
These are fast to calculate. See functions: D3D12MA::Allocator::GetBudget(), D3D12MA::Pool::GetStatistics().
-Total number of bytes occupied by all D3D12MA::Allocation objects.
-Always less or equal than BlockBytes. Difference (BlockBytes - AllocationBytes) is the amount of memory allocated from D3D12 but unused by any D3D12MA::Allocation.
Always less or equal than BlockBytes. Difference (BlockBytes - AllocationBytes) is the amount of memory allocated from D3D12 but unused by any D3D12MA::Allocation.
@@ -149,7 +132,7 @@Number of D3D12MA::Allocation objects allocated.
-Committed allocations have their own blocks, so each one adds 1 to AllocationCount as well as BlockCount.
Committed allocations have their own blocks, so each one adds 1 to AllocationCount as well as BlockCount.
@@ -181,7 +164,7 @@Number of D3D12 memory blocks allocated - ID3D12Heap objects and committed resources.
Number of D3D12 memory blocks allocated - ID3D12Heap objects and committed resources.
@@ -191,7 +174,7 @@#include <D3D12MemAlloc.h>
+Public AttributesDetailedStatistics | HeapType [5] | | DetailedStatistics | MemorySegmentGroup [2] | | DetailedStatistics | Total | | | ||||||||||||
General statistics from current state of the allocator - total memory usage across all memory heaps and segments.
These are slower to calculate. Use for debugging purposes. See function D3D12MA::Allocator::CalculateStatistics().
-Meaning of these segment groups is:
IsUMA() == FALSE (discrete graphics card):DXGI_MEMORY_SEGMENT_GROUP_LOCAL (index 0) represents GPU memory (resources allocated in D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_TYPE_GPU_UPLOAD or D3D12_MEMORY_POOL_L1).DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL (index 1) represents system memory (resources allocated in D3D12_HEAP_TYPE_UPLOAD, D3D12_HEAP_TYPE_READBACK, or D3D12_MEMORY_POOL_L0).IsUMA() == TRUE (integrated graphics chip):DXGI_MEMORY_SEGMENT_GROUP_LOCAL = (index 0) represents memory shared for all the resources.DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL = (index 1) is unused and always 0.
-
+
+Public AttributesVIRTUAL_ALLOCATION_FLAGS | Flags | | UINT64 | Size | | UINT64 | Alignment | | void * | pPrivateData | | | |||||||||||||||
Parameters of created virtual allocation to be passed to VirtualBlock::Allocate().
-#include <D3D12MemAlloc.h>
+Public AttributesUINT64 | Offset | | UINT64 | Size | | void * | pPrivateData | | | ||||||||||||
Parameters of an existing virtual allocation, returned by VirtualBlock::GetAllocationInfo().
-
-
+
+Public AttributesVIRTUAL_BLOCK_FLAGS | Flags | | UINT64 | Size | | const ALLOCATION_CALLBACKS * | pAllocationCallbacks | | | ||||||||||||
Parameters of created D3D12MA::VirtualBlock object to be passed to CreateVirtualBlock().
-#include <D3D12MemAlloc.h>
+Public AttributesAllocHandle | AllocHandle | | | ||||||
Represents single memory allocation done inside VirtualBlock.
-As an extra feature, the core allocation algorithm of the library is exposed through a simple and convenient API of "virtual allocator". It doesn't allocate any real GPU memory. It just keeps track of used and free regions of a "virtual block". You can use it to allocate your own memory or other objects, even completely unrelated to D3D12. A common use case is sub-allocation of pieces of one large GPU buffer. Another suggested use case is allocating descriptors in a ID3D12DescriptorHeap.
As an extra feature, the core allocation algorithm of the library is exposed through a simple and convenient API of "virtual allocator". It doesn't allocate any real GPU memory. It just keeps track of used and free regions of a "virtual block". You can use it to allocate your own memory or other objects, even completely unrelated to D3D12. A common use case is sub-allocation of pieces of one large GPU buffer. Another suggested use case is allocating descriptors in a ID3D12DescriptorHeap.
+To use this functionality, there is no main "allocator" object. You don't need to have D3D12MA::Allocator object created. All you need to do is to create a separate D3D12MA::VirtualBlock object for each block of memory you want to be managed by the allocator:
D3D12MA::VirtualBlock object contains internal data structure that keeps track of free and occupied regions using the same code as the main D3D12 memory allocator. A single allocation is identified by a lightweight structure D3D12MA::VirtualAllocation. You will also likely want to know the offset at which the allocation was made in the block.
In order to make an allocation:
@@ -135,17 +122,17 @@When no longer needed, an allocation can be freed by calling D3D12MA::VirtualBlock::FreeAllocation.
-When whole block is no longer needed, the block object can be released by calling block->Release(). All allocations must be freed before the block is destroyed, which is checked internally by an assert. However, if you don't want to call block->FreeAllocation for each allocation, you can use D3D12MA::VirtualBlock::Clear to free them all at once - a feature not available in normal D3D12 memory allocator.
When whole block is no longer needed, the block object can be released by calling block->Release(). All allocations must be freed before the block is destroyed, which is checked internally by an assert. However, if you don't want to call block->FreeAllocation for each allocation, you can use D3D12MA::VirtualBlock::Clear to free them all at once - a feature not available in normal D3D12 memory allocator.
Example:
You can attach a custom pointer to each allocation by using D3D12MA::VirtualBlock::SetAllocationPrivateData. Its default value is NULL. It can be used to store any data that needs to be associated with that allocation - e.g. an index, a handle, or a pointer to some larger data structure containing more information. Example:
You can attach a custom pointer to each allocation by using D3D12MA::VirtualBlock::SetAllocationPrivateData. Its default value is NULL. It can be used to store any data that needs to be associated with that allocation - e.g. an index, a handle, or a pointer to some larger data structure containing more information. Example:
It feels natural to express sizes and offsets in bytes. If an offset of an allocation needs to be aligned to a multiply of some number (e.g. 4 bytes), you can fill optional member D3D12MA::VIRTUAL_ALLOCATION_DESC::Alignment to request it. Example:
Alignments of different allocations made from one block may vary. However, if all alignments and sizes are always multiply of some size e.g. 4 B or sizeof(MyDataStruct), you can express all sizes, alignments, and offsets in multiples of that size instead of individual bytes. It might be more convenient, but you need to make sure to use this new unit consistently in all the places:
Alignments of different allocations made from one block may vary. However, if all alignments and sizes are always multiply of some size e.g. 4 B or sizeof(MyDataStruct), you can express all sizes, alignments, and offsets in multiples of that size instead of individual bytes. It might be more convenient, but you need to make sure to use this new unit consistently in all the places:
You can obtain brief statistics of a virtual block using D3D12MA::VirtualBlock::GetStatistics(). The function fills structure D3D12MA::Statistics - same as used by the normal D3D12 memory allocator. Example:
More detailed statistics can be obtained using function D3D12MA::VirtualBlock::CalculateStatistics(), but they are slower to calculate.
You can also request a full list of allocations and free regions as a string in JSON format by calling D3D12MA::VirtualBlock::BuildStatsString. Returned string must be later freed using D3D12MA::VirtualBlock::FreeStatsString. The format of this string may differ from the one returned by the main D3D12 allocator, but it is similar.
-Alternative, linear algorithm can be used with virtual allocator - see flag D3D12MA::VIRTUAL_BLOCK_FLAG_ALGORITHM_LINEAR and documentation: Linear allocation algorithm.
Note that the "virtual allocator" functionality is implemented on a level of individual memory blocks. Keeping track of a whole collection of blocks, allocating new ones when out of free space, deleting empty ones, and deciding which one to try first for a new allocation must be implemented by the user.
@@ -199,7 +186,7 @@