2019-05-20 11:46:23 +00:00
//
2022-01-21 12:01:05 +00:00
// Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
2019-05-20 11:46:23 +00:00
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
# pragma once
/** \mainpage D3D12 Memory Allocator
2021-07-26 19:29:05 +00:00
< b > Version 2.0 .0 - development < / b > ( 2021 - 07 - 26 )
2019-05-20 11:46:23 +00:00
2022-01-21 12:01:05 +00:00
Copyright ( c ) 2019 - 2022 Advanced Micro Devices , Inc . All rights reserved . \ n
2019-05-20 11:46:23 +00:00
License : MIT
Documentation of all members : D3D12MemAlloc . h
\ section main_table_of_contents Table of contents
- < b > User guide < / b >
- \ subpage quick_start
- [ Project setup ] ( @ ref quick_start_project_setup )
- [ Creating resources ] ( @ ref quick_start_creating_resources )
- [ Mapping memory ] ( @ ref quick_start_mapping_memory )
2021-03-11 13:17:56 +00:00
- \ subpage custom_pools
2020-08-18 15:14:45 +00:00
- \ subpage resource_aliasing
2020-07-16 15:59:18 +00:00
- \ subpage virtual_allocator
2019-05-20 11:46:23 +00:00
- \ subpage configuration
- [ Custom CPU memory allocator ] ( @ ref custom_memory_allocator )
- \ subpage general_considerations
- [ Thread safety ] ( @ ref general_considerations_thread_safety )
- [ Future plans ] ( @ ref general_considerations_future_plans )
- [ Features not supported ] ( @ ref general_considerations_features_not_supported )
\ section main_see_also See also
2019-07-23 11:21:08 +00:00
- [ Product page on GPUOpen ] ( https : //gpuopen.com/gaming-product/d3d12-memory-allocator/)
2019-05-20 11:46:23 +00:00
- [ Source repository on GitHub ] ( https : //github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator)
2021-07-28 13:44:27 +00:00
*/
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
// If using this library on a platform different than Windows PC or want to use different version of DXGI,
// you should include D3D12-compatible headers before this library on your own and define this macro.
# ifndef D3D12MA_D3D12_HEADERS_ALREADY_INCLUDED
# include <d3d12.h>
# include <dxgi1_4.h>
# endif
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
// Define this macro to 0 to disable usage of DXGI 1.4 (needed for IDXGIAdapter3 and query for memory budget).
# ifndef D3D12MA_DXGI_1_4
# ifdef __IDXGIAdapter3_INTERFACE_DEFINED__
# define D3D12MA_DXGI_1_4 1
# else
# define D3D12MA_DXGI_1_4 0
# endif
# endif
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/*
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 K and their size a multiply of 4 K instead of 64 K .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
# define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 0
Disables small texture alignment .
# define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 1
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 .
*/
# ifndef D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT
# define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 1
# endif
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/// \cond INTERNAL
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
# define D3D12MA_CLASS_NO_COPY(className) \
private : \
className ( const className & ) = delete ; \
className ( className & & ) = delete ; \
className & operator = ( const className & ) = delete ; \
className & operator = ( className & & ) = delete ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
// To be used with MAKE_HRESULT to define custom error codes.
# define FACILITY_D3D12MA 3542
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/*
If providing your own implementation , you need to implement a subset of std : : atomic .
*/
# if !defined(D3D12MA_ATOMIC_UINT32) || !defined(D3D12MA_ATOMIC_UINT64)
# include <atomic>
# endif
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
# ifndef D3D12MA_ATOMIC_UINT32
# define D3D12MA_ATOMIC_UINT32 std::atomic<UINT>
# endif
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
# ifndef D3D12MA_ATOMIC_UINT64
# define D3D12MA_ATOMIC_UINT64 std::atomic<UINT64>
# endif
2019-05-20 11:46:23 +00:00
2021-11-24 00:22:58 +00:00
# ifdef D3D12MA_EXPORTS
# define D3D12MA_API __declspec(dllexport)
# elif defined(D3D12MA_IMPORTS)
# define D3D12MA_API __declspec(dllimport)
# else
# define D3D12MA_API
# endif
2022-01-13 12:14:49 +00:00
// Forward declaration if ID3D12ProtectedResourceSession is not defined inside the headers (older SDK, pre ID3D12Device4)
struct ID3D12ProtectedResourceSession ;
2021-07-28 13:44:27 +00:00
namespace D3D12MA
{
2021-11-24 00:22:58 +00:00
class D3D12MA_API IUnknownImpl : public IUnknown
2021-07-28 13:44:27 +00:00
{
public :
2021-11-03 12:22:58 +00:00
virtual ~ IUnknownImpl ( ) = default ;
2021-10-06 09:31:26 +00:00
virtual HRESULT STDMETHODCALLTYPE QueryInterface ( REFIID riid , void * * ppvObject ) ;
2021-07-28 13:44:27 +00:00
virtual ULONG STDMETHODCALLTYPE AddRef ( ) ;
virtual ULONG STDMETHODCALLTYPE Release ( ) ;
protected :
virtual void ReleaseThis ( ) { delete this ; }
private :
D3D12MA_ATOMIC_UINT32 m_RefCount = 1 ;
} ;
} // namespace D3D12MA
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/// \endcond
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
namespace D3D12MA
{
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/// \cond INTERNAL
class AllocatorPimpl ;
class PoolPimpl ;
class NormalBlock ;
class BlockVector ;
class CommittedAllocationList ;
class JsonWriter ;
class VirtualBlockPimpl ;
/// \endcond
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
class Pool ;
class Allocator ;
struct StatInfo ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/// Pointer to custom callback function that allocates CPU memory.
2021-09-16 18:24:12 +00:00
using ALLOCATE_FUNC_PTR = void * ( * ) ( size_t Size , size_t Alignment , void * pUserData ) ;
2021-07-28 13:44:27 +00:00
/**
\ brief Pointer to custom callback function that deallocates CPU memory .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
` pMemory = null ` should be accepted and ignored .
*/
2021-09-16 18:24:12 +00:00
using FREE_FUNC_PTR = void ( * ) ( void * pMemory , void * pUserData ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/// Custom callbacks to CPU memory allocation functions.
struct ALLOCATION_CALLBACKS
{
/// %Allocation function.
ALLOCATE_FUNC_PTR pAllocate ;
/// Dellocation function.
FREE_FUNC_PTR pFree ;
/// Custom data that will be passed to allocation and deallocation functions as `pUserData` parameter.
void * pUserData ;
} ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/// \brief Bit flags to be used with ALLOCATION_DESC::Flags.
2021-09-16 18:12:48 +00:00
enum ALLOCATION_FLAGS
2021-07-28 13:44:27 +00:00
{
/// Zero
ALLOCATION_FLAG_NONE = 0 ,
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/**
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 .
*/
ALLOCATION_FLAG_COMMITTED = 0x1 ,
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/**
Set this flag to only try to allocate from existing memory heaps and never create new such heap .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
If new allocation cannot be placed in any of the existing heaps , allocation
fails with ` E_OUTOFMEMORY ` error .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
You should not use D3D12MA : : ALLOCATION_FLAG_COMMITTED and
D3D12MA : : ALLOCATION_FLAG_NEVER_ALLOCATE at the same time . It makes no sense .
*/
ALLOCATION_FLAG_NEVER_ALLOCATE = 0x2 ,
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** Create allocation only if additional memory required for it, if any, won't exceed
memory budget . Otherwise return ` E_OUTOFMEMORY ` .
*/
ALLOCATION_FLAG_WITHIN_BUDGET = 0x4 ,
2021-09-16 18:12:48 +00:00
} ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/// \brief Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource.
struct ALLOCATION_DESC
{
/// Flags.
ALLOCATION_FLAGS Flags ;
/** \brief The type of memory heap where the new allocation should be placed.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
It must be one of : ` D3D12_HEAP_TYPE_DEFAULT ` , ` D3D12_HEAP_TYPE_UPLOAD ` , ` D3D12_HEAP_TYPE_READBACK ` .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
When D3D12MA : : ALLOCATION_DESC : : CustomPool ! = NULL this member is ignored .
*/
D3D12_HEAP_TYPE HeapType ;
/** \brief Additional heap flags to be used when allocating memory.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
In most cases it can be 0.
- If you use D3D12MA : : Allocator : : CreateResource ( ) , you don ' t need to care .
Necessary flag ` 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 .
- If you use D3D12MA : : Allocator : : AllocateMemory ( ) , you should specify one of those ` ALLOW_ONLY ` flags .
Except when you validate that D3D12MA : : Allocator : : GetD3D12Options ( ) ` . ResourceHeapTier = = D3D12_RESOURCE_HEAP_TIER_1 ` -
then you can leave it 0.
- You can specify additional flags if needed . Then the memory will always be allocated as
separate block using ` D3D12Device : : CreateCommittedResource ` or ` CreateHeap ` , not as part of an existing larget block .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
When D3D12MA : : ALLOCATION_DESC : : CustomPool ! = NULL this member is ignored .
*/
D3D12_HEAP_FLAGS ExtraHeapFlags ;
/** \brief Custom pool to place the new resource in. Optional.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
When not NULL , the resource will be created inside specified custom pool .
It will then never be created as committed .
*/
Pool * CustomPool ;
} ;
2019-11-05 15:29:45 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Represents single memory allocation.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
It may be either implicit memory heap dedicated to a single resource or a
specific region of a bigger heap plus unique offset .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
To create such object , fill structure D3D12MA : : ALLOCATION_DESC and call function
Allocator : : CreateResource .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
The object remembers size and some other information .
To retrieve this information , use methods of this class .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
The object also remembers ` ID3D12Resource ` and " owns " a reference to it ,
so it calls ` % Release ( ) ` on the resource when destroyed .
*/
2021-11-24 00:22:58 +00:00
class D3D12MA_API Allocation : public IUnknownImpl
2021-07-28 13:44:27 +00:00
{
public :
/** \brief Returns offset in bytes from the start of memory heap.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
You usually don ' t need to use this offset . If you create a buffer or a texture together with the allocation using function
D3D12MA : : Allocator : : CreateResource , functions that operate on that resource refer to the beginning of the resource ,
not entire memory heap .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
If the Allocation represents committed resource with implicit heap , returns 0.
*/
UINT64 GetOffset ( ) const ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Returns size in bytes of the allocation.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
- If you created a buffer or a texture together with the allocation using function D3D12MA : : Allocator : : CreateResource ,
this is the size of the resource returned by ` ID3D12Device : : GetResourceAllocationInfo ` .
- For allocations made out of bigger memory blocks , this also is the size of the memory region assigned exclusively to this allocation .
- For resources created as committed , this value may not be accurate . DirectX implementation may optimize memory usage internally
so that you may even observe regions of ` ID3D12Resource : : GetGPUVirtualAddress ( ) ` + Allocation : : GetSize ( ) to overlap in memory and still work correctly .
*/
UINT64 GetSize ( ) const { return m_Size ; }
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Returns D3D12 resource associated with this object.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Calling this method doesn ' t increment resource ' s reference counter .
*/
ID3D12Resource * GetResource ( ) const { return m_Resource ; }
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Returns memory heap that the resource is created in.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
If the Allocation represents committed resource with implicit heap , returns NULL .
*/
ID3D12Heap * GetHeap ( ) const ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Associates a name with the allocation object. This name is for use in debug diagnostics and tools.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Internal copy of the string is made , so the memory pointed by the argument can be
changed of freed immediately after this call .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
` Name ` can be null .
*/
void SetName ( LPCWSTR Name ) ;
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Returns the name associated with the allocation object.
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
Returned string points to an internal copy .
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
If no name was associated with the allocation , returns null .
*/
LPCWSTR GetName ( ) const { return m_Name ; }
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Returns `TRUE` if the memory of the allocation was filled with zeros when the allocation was created.
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
Returns ` TRUE ` only if the allocator is sure that the entire memory where the
allocation was created was filled with zeros at the moment the allocation was made .
Returns ` FALSE ` if the memory could potentially contain garbage data .
If it ' s a render - target or depth - stencil texture , it then needs proper
initialization with ` ClearRenderTargetView ` , ` ClearDepthStencilView ` , ` DiscardResource ` ,
or a copy operation , as described on page :
[ ID3D12Device : : CreatePlacedResource method - Notes on the required resource initialization ] ( https : //docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createplacedresource#notes-on-the-required-resource-initialization).
Please note that rendering a fullscreen triangle or quad to the texture as
a render target is not a proper way of initialization !
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
See also articles :
[ " Coming to DirectX 12: More control over memory allocation " ] ( https : //devblogs.microsoft.com/directx/coming-to-directx-12-more-control-over-memory-allocation/),
[ " Initializing DX12 Textures After Allocation and Aliasing " ] ( https : //asawicki.info/news_1724_initializing_dx12_textures_after_allocation_and_aliasing).
*/
BOOL WasZeroInitialized ( ) const { return m_PackedData . WasZeroInitialized ( ) ; }
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
protected :
virtual void ReleaseThis ( ) ;
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
private :
friend class AllocatorPimpl ;
friend class BlockVector ;
friend class CommittedAllocationList ;
friend class JsonWriter ;
friend struct CommittedAllocationListItemTraits ;
template < typename T > friend void D3D12MA_DELETE ( const ALLOCATION_CALLBACKS & , T * ) ;
template < typename T > friend class PoolAllocator ;
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
enum Type
{
TYPE_COMMITTED ,
TYPE_PLACED ,
TYPE_HEAP ,
TYPE_COUNT
} ;
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
AllocatorPimpl * m_Allocator ;
UINT64 m_Size ;
ID3D12Resource * m_Resource ;
UINT m_CreationFrameIndex ;
wchar_t * m_Name ;
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
union
{
struct
{
CommittedAllocationList * list ;
Allocation * prev ;
Allocation * next ;
} m_Committed ;
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
struct
{
UINT64 offset ;
NormalBlock * block ;
} m_Placed ;
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
struct
{
// Beginning must be compatible with m_Committed.
CommittedAllocationList * list ;
Allocation * prev ;
Allocation * next ;
ID3D12Heap * heap ;
} m_Heap ;
} ;
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
struct PackedData
{
public :
PackedData ( ) :
m_Type ( 0 ) , m_ResourceDimension ( 0 ) , m_ResourceFlags ( 0 ) , m_TextureLayout ( 0 ) , m_WasZeroInitialized ( 0 ) { }
2021-03-22 10:33:29 +00:00
2021-07-28 13:44:27 +00:00
Type GetType ( ) const { return ( Type ) m_Type ; }
D3D12_RESOURCE_DIMENSION GetResourceDimension ( ) const { return ( D3D12_RESOURCE_DIMENSION ) m_ResourceDimension ; }
D3D12_RESOURCE_FLAGS GetResourceFlags ( ) const { return ( D3D12_RESOURCE_FLAGS ) m_ResourceFlags ; }
D3D12_TEXTURE_LAYOUT GetTextureLayout ( ) const { return ( D3D12_TEXTURE_LAYOUT ) m_TextureLayout ; }
BOOL WasZeroInitialized ( ) const { return ( BOOL ) m_WasZeroInitialized ; }
2021-03-22 10:33:29 +00:00
2021-07-28 13:44:27 +00:00
void SetType ( Type type ) ;
void SetResourceDimension ( D3D12_RESOURCE_DIMENSION resourceDimension ) ;
void SetResourceFlags ( D3D12_RESOURCE_FLAGS resourceFlags ) ;
void SetTextureLayout ( D3D12_TEXTURE_LAYOUT textureLayout ) ;
void SetWasZeroInitialized ( BOOL wasZeroInitialized ) { m_WasZeroInitialized = wasZeroInitialized ? 1 : 0 ; }
2021-03-22 10:33:29 +00:00
2021-07-28 13:44:27 +00:00
private :
UINT m_Type : 2 ; // enum Type
UINT m_ResourceDimension : 3 ; // enum D3D12_RESOURCE_DIMENSION
UINT m_ResourceFlags : 24 ; // flags D3D12_RESOURCE_FLAGS
UINT m_TextureLayout : 9 ; // enum D3D12_TEXTURE_LAYOUT
UINT m_WasZeroInitialized : 1 ; // BOOL
} m_PackedData ;
2021-03-22 10:33:29 +00:00
2021-07-28 13:44:27 +00:00
Allocation ( AllocatorPimpl * allocator , UINT64 size , BOOL wasZeroInitialized ) ;
2021-09-16 17:21:19 +00:00
// Nothing here, everything already done in Release.
// ~Allocation() {}
2021-07-28 13:44:27 +00:00
void InitCommitted ( CommittedAllocationList * list ) ;
void InitPlaced ( UINT64 offset , UINT64 alignment , NormalBlock * block ) ;
void InitHeap ( CommittedAllocationList * list , ID3D12Heap * heap ) ;
template < typename D3D12_RESOURCE_DESC_T >
void SetResource ( ID3D12Resource * resource , const D3D12_RESOURCE_DESC_T * pResourceDesc ) ;
void FreeName ( ) ;
2021-03-11 13:17:56 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA_CLASS_NO_COPY ( Allocation )
} ;
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
/// \brief Parameters of created D3D12MA::Pool object. To be used with D3D12MA::Allocator::CreatePool.
struct POOL_DESC
{
/** \brief The parameters of memory heap where allocations of this pool should be placed.
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
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 .
*/
D3D12_HEAP_PROPERTIES HeapProperties ;
/** \brief Heap flags to be used when allocating heaps of this pool.
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
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.
You can specify additional flags if needed .
*/
D3D12_HEAP_FLAGS HeapFlags ;
/** \brief Size of a single heap (memory block) to be allocated as part of this pool, in bytes. Optional.
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
Specify nonzero to set explicit , constant size of memory blocks used by this pool .
Leave 0 to use default and let the library manage block sizes automatically .
Then sizes of particular blocks may vary .
*/
UINT64 BlockSize ;
/** \brief Minimum number of heaps (memory blocks) to be always allocated in this pool, even if they stay empty. Optional.
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
Set to 0 to have no preallocated blocks and allow the pool be completely empty .
*/
UINT MinBlockCount ;
/** \brief Maximum number of heaps (memory blocks) that can be allocated in this pool. Optional.
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
Set to 0 to use default , which is ` UINT64_MAX ` , which means no limit .
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
Set to same value as D3D12MA : : POOL_DESC : : MinBlockCount to have fixed amount of memory allocated
throughout whole lifetime of this pool .
*/
UINT MaxBlockCount ;
/** \brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0.
Leave 0 ( default ) not to impose any additional alignment . If not 0 , it must be a power of two .
*/
UINT64 MinAllocationAlignment ;
2022-01-13 12:14:49 +00:00
/** \brief Additional parameter allowing pool to create resources with passed protected session.
If not null then all the heaps and committed resources will be created with this parameter .
Valid only if ID3D12Device4 interface is present in current Windows SDK !
*/
ID3D12ProtectedResourceSession * pProtectedSession ;
2021-07-28 13:44:27 +00:00
} ;
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Custom memory pool
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
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 .
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
To create custom pool , fill D3D12MA : : POOL_DESC and call D3D12MA : : Allocator : : CreatePool .
*/
2021-11-24 00:22:58 +00:00
class D3D12MA_API Pool : public IUnknownImpl
2021-07-28 13:44:27 +00:00
{
public :
/** \brief Returns copy of parameters of the pool.
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
These are the same parameters as passed to D3D12MA : : Allocator : : CreatePool .
*/
POOL_DESC GetDesc ( ) const ;
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Retrieves statistics from the current state of this pool.
*/
void CalculateStats ( StatInfo * pStats ) ;
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Associates a name with the pool. This name is for use in debug diagnostics and tools.
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
Internal copy of the string is made , so the memory pointed by the argument can be
changed of freed immediately after this call .
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
` Name ` can be NULL .
*/
void SetName ( LPCWSTR Name ) ;
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Returns the name associated with the pool object.
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
Returned string points to an internal copy .
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
If no name was associated with the allocation , returns NULL .
*/
LPCWSTR GetName ( ) const ;
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
protected :
virtual void ReleaseThis ( ) ;
2020-08-18 15:14:45 +00:00
2021-07-28 13:44:27 +00:00
private :
friend class Allocator ;
friend class AllocatorPimpl ;
template < typename T > friend void D3D12MA_DELETE ( const ALLOCATION_CALLBACKS & , T * ) ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
PoolPimpl * m_Pimpl ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
Pool ( Allocator * allocator , const POOL_DESC & desc ) ;
~ Pool ( ) ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA_CLASS_NO_COPY ( Pool )
} ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/// \brief Bit flags to be used with ALLOCATOR_DESC::Flags.
2021-09-16 18:12:48 +00:00
enum ALLOCATOR_FLAGS
2021-07-28 13:44:27 +00:00
{
/// Zero
ALLOCATOR_FLAG_NONE = 0 ,
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/**
Allocator and all objects created from it will not be synchronized internally ,
so you must guarantee they are used from only one thread at a time or
synchronized by you .
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
Using this flag may increase performance because internal mutexes are not used .
*/
ALLOCATOR_FLAG_SINGLETHREADED = 0x1 ,
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/**
Every allocation will have its own memory block .
To be used for debugging purposes .
*/
ALLOCATOR_FLAG_ALWAYS_COMMITTED = 0x2 ,
2021-09-16 18:12:48 +00:00
} ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/// \brief Parameters of created Allocator object. To be used with CreateAllocator().
struct ALLOCATOR_DESC
{
/// Flags.
ALLOCATOR_FLAGS Flags ;
/** Direct3D device object that the allocator should be attached to.
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
Allocator is doing ` AddRef ` / ` Release ` on this object .
*/
ID3D12Device * pDevice ;
/** \brief Preferred size of a single `ID3D12Heap` block to be allocated.
Set to 0 to use default , which is currently 64 MiB .
*/
UINT64 PreferredBlockSize ;
/** \brief Custom CPU memory allocation callbacks. Optional.
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
Optional , can be null . When specified , will be used for all CPU - side memory allocations .
*/
const ALLOCATION_CALLBACKS * pAllocationCallbacks ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/** DXGI Adapter object that you use for D3D12 and this allocator.
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
Allocator is doing ` AddRef ` / ` Release ` on this object .
*/
IDXGIAdapter * pAdapter ;
} ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/**
\ brief Number of D3D12 memory heap types supported .
*/
const UINT HEAP_TYPE_COUNT = 4 ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/**
\ brief Calculated statistics of memory usage in entire allocator .
*/
struct StatInfo
2020-07-16 15:59:18 +00:00
{
2021-07-28 13:44:27 +00:00
/// Number of memory blocks (heaps) allocated.
UINT BlockCount ;
/// Number of D3D12MA::Allocation objects allocated.
UINT AllocationCount ;
/// Number of free ranges of memory between allocations.
UINT UnusedRangeCount ;
/// Total number of bytes occupied by all allocations.
UINT64 UsedBytes ;
/// Total number of bytes occupied by unused ranges.
UINT64 UnusedBytes ;
UINT64 AllocationSizeMin ;
UINT64 AllocationSizeAvg ;
UINT64 AllocationSizeMax ;
UINT64 UnusedRangeSizeMin ;
UINT64 UnusedRangeSizeAvg ;
UINT64 UnusedRangeSizeMax ;
} ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/**
\ brief General statistics from the current state of the allocator .
*/
struct Stats
{
/// Total statistics from all heap types.
StatInfo Total ;
/**
One StatInfo for each type of heap located at the following indices :
0 - DEFAULT , 1 - UPLOAD , 2 - READBACK , 3 - CUSTOM .
*/
StatInfo HeapType [ HEAP_TYPE_COUNT ] ;
} ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Statistics of current memory usage and available budget, in bytes, for GPU or CPU memory.
*/
struct Budget
{
/** \brief Sum size of all memory blocks allocated from particular heap type, in bytes.
*/
UINT64 BlockBytes ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Sum size of all allocations created in particular heap type, in bytes.
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
Always less or equal than ` BlockBytes ` .
Difference ` BlockBytes - AllocationBytes ` is the amount of memory allocated but unused -
available for new allocations or wasted due to fragmentation .
*/
UINT64 AllocationBytes ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Estimated current memory usage of the program, in bytes.
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
Fetched from system using ` IDXGIAdapter3 : : QueryVideoMemoryInfo ` if enabled .
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
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
memory blocks allocated outside of this library , if any .
*/
UINT64 UsageBytes ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Estimated amount of memory available to the program, in bytes.
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
Fetched from system using ` IDXGIAdapter3 : : QueryVideoMemoryInfo ` if enabled .
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
It might be different ( most probably smaller ) than memory sizes reported in ` DXGI_ADAPTER_DESC ` due to factors
external to the program , like other programs also consuming system resources .
Difference ` BudgetBytes - UsageBytes ` is the amount of additional memory that can probably
be allocated without problems . Exceeding the budget may result in various problems .
*/
UINT64 BudgetBytes ;
} ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/**
\ brief Represents main object of this library initialized for particular ` ID3D12Device ` .
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
Fill structure D3D12MA : : ALLOCATOR_DESC and call function CreateAllocator ( ) to create it .
Call method ` Release ( ) ` to destroy it .
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
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 .
*/
2021-11-24 00:22:58 +00:00
class D3D12MA_API Allocator : public IUnknownImpl
2021-07-28 13:44:27 +00:00
{
public :
/// Returns cached options retrieved from D3D12 device.
const D3D12_FEATURE_DATA_D3D12_OPTIONS & GetD3D12Options ( ) const ;
/** \brief 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 :
- https : //docs.microsoft.com/en-us/windows/win32/direct3d12/default-texture-mapping
- https : //docs.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_feature_data_architecture
- https : //docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-getcustomheapproperties
*/
BOOL IsUMA ( ) const ;
/** \brief Returns true if `D3D12_FEATURE_DATA_ARCHITECTURE1::CacheCoherentUMA` was found to be true.
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
For more information about how to use it , see articles in Microsoft Docs :
- https : //docs.microsoft.com/en-us/windows/win32/direct3d12/default-texture-mapping
- https : //docs.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_feature_data_architecture
- https : //docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-getcustomheapproperties
*/
BOOL IsCacheCoherentUMA ( ) const ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Allocates memory and creates a D3D12 resource (buffer or texture). This is the main allocation function.
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
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 .
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
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 .
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
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 .
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
\ param pAllocDesc Parameters of the allocation .
\ param pResourceDesc Description of created resource .
\ param InitialResourceState Initial resource state .
\ param pOptimizedClearValue Optional . Either null or optimized clear value .
\ param [ out ] ppAllocation Filled with pointer to new allocation object created .
\ param riidResource IID of a resource to be returned via ` ppvResource ` .
\ param [ out ] ppvResource Optional . If not null , filled with pointer to new resouce created .
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
\ note This function creates a new resource . Sub - allocation of parts of one large buffer ,
although recommended as a good practice , is out of scope of this library and could be implemented
by the user as a higher - level logic on top of it , e . g . using the \ ref virtual_allocator feature .
*/
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 ) ;
2020-07-16 15:59:18 +00:00
2021-07-28 13:44:27 +00:00
# ifdef __ID3D12Device8_INTERFACE_DEFINED__
2022-01-13 12:14:49 +00:00
/** \brief Similar to Allocator::CreateResource, but supports new structure `D3D12_RESOURCE_DESC1`.
2021-07-28 13:44:27 +00:00
It internally uses ` ID3D12Device8 : : CreateCommittedResource2 ` or ` ID3D12Device8 : : CreatePlacedResource1 ` .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
To work correctly , ` ID3D12Device8 ` interface must be available in the current system . Otherwise , ` E_NOINTERFACE ` is returned .
*/
HRESULT CreateResource2 (
const ALLOCATION_DESC * pAllocDesc ,
const D3D12_RESOURCE_DESC1 * pResourceDesc ,
D3D12_RESOURCE_STATES InitialResourceState ,
const D3D12_CLEAR_VALUE * pOptimizedClearValue ,
Allocation * * ppAllocation ,
REFIID riidResource ,
void * * ppvResource ) ;
# endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Allocates memory without creating any resource placed in it.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
This function is similar to ` ID3D12Device : : CreateHeap ` , but it may really assign
part of a larger , existing heap to the allocation .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
` 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 .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
` pAllocInfo - > SizeInBytes ` must be multiply of 64 KB .
` pAllocInfo - > Alignment ` must be one of the legal values as described in documentation of ` D3D12_HEAP_DESC ` .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
If you use D3D12MA : : ALLOCATION_FLAG_COMMITTED you will get a separate memory block -
a heap that always has offset 0.
*/
HRESULT AllocateMemory (
const ALLOCATION_DESC * pAllocDesc ,
const D3D12_RESOURCE_ALLOCATION_INFO * pAllocInfo ,
Allocation * * ppAllocation ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Creates a new resource in place of an existing allocation. This is useful for memory aliasing.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ param 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 .
\ param 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.
\ param pResourceDesc Description of the new resource to be created .
\ param InitialResourceState
\ param pOptimizedClearValue
\ param riidResource
\ param [ 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 .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
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 ` .
*/
HRESULT CreateAliasingResource (
Allocation * pAllocation ,
UINT64 AllocationLocalOffset ,
const D3D12_RESOURCE_DESC * pResourceDesc ,
D3D12_RESOURCE_STATES InitialResourceState ,
const D3D12_CLEAR_VALUE * pOptimizedClearValue ,
REFIID riidResource ,
void * * ppvResource ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Creates custom pool.
*/
HRESULT CreatePool (
const POOL_DESC * pPoolDesc ,
Pool * * ppPool ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Sets the index of the current frame.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
This function is used to set the frame index in the allocator when a new game frame begins .
*/
void SetCurrentFrameIndex ( UINT frameIndex ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Retrieves statistics from the current state of the allocator.
*/
void CalculateStats ( Stats * pStats ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Retrieves information about current memory budget.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ param [ out ] pGpuBudget Optional , can be null .
\ param [ out ] pCpuBudget Optional , can be null .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
This function is called " get " not " calculate " because it is very fast , suitable to be called
every frame or every allocation . For more detailed statistics use CalculateStats ( ) .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Note that when using allocator from multiple threads , returned information may immediately
become outdated .
*/
void GetBudget ( Budget * pGpuBudget , Budget * pCpuBudget ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/// Builds and returns statistics as a string in JSON format.
/** @param[out] ppStatsString Must be freed using Allocator::FreeStatsString.
@ param DetailedMap ` TRUE ` to include full list of allocations ( can make the string quite long ) , ` FALSE ` to only return statistics .
*/
void BuildStatsString ( WCHAR * * ppStatsString , BOOL DetailedMap ) const ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/// Frees memory of a string returned from Allocator::BuildStatsString.
void FreeStatsString ( WCHAR * pStatsString ) const ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
protected :
virtual void ReleaseThis ( ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
private :
2021-11-24 00:22:58 +00:00
friend D3D12MA_API HRESULT CreateAllocator ( const ALLOCATOR_DESC * , Allocator * * ) ;
2021-07-28 13:44:27 +00:00
template < typename T > friend void D3D12MA_DELETE ( const ALLOCATION_CALLBACKS & , T * ) ;
friend class Pool ;
2021-03-10 13:12:23 +00:00
2021-07-28 13:44:27 +00:00
Allocator ( const ALLOCATION_CALLBACKS & allocationCallbacks , const ALLOCATOR_DESC & desc ) ;
~ Allocator ( ) ;
AllocatorPimpl * m_Pimpl ;
D3D12MA_CLASS_NO_COPY ( Allocator )
} ;
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
/// Parameters of created D3D12MA::VirtualBlock object to be passed to CreateVirtualBlock().
struct VIRTUAL_BLOCK_DESC
{
/** \brief Total size of the block.
2020-03-11 15:48:40 +00:00
2021-07-28 13:44:27 +00:00
Sizes can be expressed in bytes or any units you want as long as you are consistent in using them .
For example , if you allocate from some array of structures , 1 can mean single instance of entire structure .
*/
UINT64 Size ;
/** \brief Custom CPU memory allocation callbacks. Optional.
2020-03-11 15:48:40 +00:00
2021-07-28 13:44:27 +00:00
Optional , can be null . When specified , will be used for all CPU - side memory allocations .
*/
const ALLOCATION_CALLBACKS * pAllocationCallbacks ;
} ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/// Parameters of created virtual allocation to be passed to VirtualBlock::Allocate().
struct VIRTUAL_ALLOCATION_DESC
{
/** \brief Size of the allocation.
Cannot be zero .
*/
UINT64 Size ;
/** \brief Required alignment of the allocation.
Must be power of two . Special value 0 has the same meaning as 1 - means no special alignment is required , so allocation can start at any offset .
*/
UINT64 Alignment ;
/** \brief Custom pointer to be associated with the allocation.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
It can be fetched or changed later .
*/
void * pUserData ;
} ;
/// Parameters of an existing virtual allocation, returned by VirtualBlock::GetAllocationInfo().
struct VIRTUAL_ALLOCATION_INFO
{
/** \brief Size of the allocation.
Same value as passed in VIRTUAL_ALLOCATION_DESC : : Size .
*/
UINT64 size ;
/** \brief Custom pointer associated with the allocation.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Same value as passed in VIRTUAL_ALLOCATION_DESC : : pUserData or VirtualBlock : : SetAllocationUserData ( ) .
*/
void * pUserData ;
} ;
2021-07-26 19:18:52 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Represents pure allocation algorithm and a data structure with allocations in some memory block, without actually allocating any GPU memory.
2021-07-26 19:18:52 +00:00
2021-07-28 13:44:27 +00:00
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 .
2021-07-26 19:18:52 +00:00
2021-07-28 13:44:27 +00:00
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 .
2021-12-03 17:08:24 +00:00
This object is not thread - safe - should not be used from multiple threads simultaneously , must be synchronized externally .
2021-07-28 13:44:27 +00:00
*/
2021-11-24 00:22:58 +00:00
class D3D12MA_API VirtualBlock : public IUnknownImpl
2021-07-26 19:18:52 +00:00
{
public :
2021-07-28 13:44:27 +00:00
/** \brief Returns true if the block is empty - contains 0 allocations.
*/
BOOL IsEmpty ( ) const ;
/** \brief Returns information about an allocation at given offset - its size and custom pointer.
*/
void GetAllocationInfo ( UINT64 offset , VIRTUAL_ALLOCATION_INFO * pInfo ) const ;
2021-07-26 19:18:52 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Creates new allocation.
\ param pDesc
\ param [ out ] pOffset Offset of the new allocation , which can also be treated as an unique identifier of the allocation within this block . ` UINT64_MAX ` if allocation failed .
\ return ` S_OK ` if allocation succeeded , ` E_OUTOFMEMORY ` if it failed .
*/
HRESULT Allocate ( const VIRTUAL_ALLOCATION_DESC * pDesc , UINT64 * pOffset ) ;
/** \brief Frees the allocation at given offset.
*/
void FreeAllocation ( UINT64 offset ) ;
/** \brief Frees all the allocations.
*/
void Clear ( ) ;
/** \brief Changes custom pointer for an allocation at given offset to a new value.
*/
void SetAllocationUserData ( UINT64 offset , void * pUserData ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Retrieves statistics from the current state of the block.
*/
void CalculateStats ( StatInfo * pInfo ) const ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Builds and returns statistics as a string in JSON format, including the list of allocations with their parameters.
@ param [ out ] ppStatsString Must be freed using VirtualBlock : : FreeStatsString .
*/
void BuildStatsString ( WCHAR * * ppStatsString ) const ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Frees memory of a string returned from VirtualBlock::BuildStatsString.
*/
void FreeStatsString ( WCHAR * pStatsString ) const ;
protected :
virtual void ReleaseThis ( ) ;
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
private :
2021-11-24 00:22:58 +00:00
friend D3D12MA_API HRESULT CreateVirtualBlock ( const VIRTUAL_BLOCK_DESC * , VirtualBlock * * ) ;
2021-07-28 13:44:27 +00:00
template < typename T > friend void D3D12MA_DELETE ( const ALLOCATION_CALLBACKS & , T * ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
VirtualBlockPimpl * m_Pimpl ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
VirtualBlock ( const ALLOCATION_CALLBACKS & allocationCallbacks , const VIRTUAL_BLOCK_DESC & desc ) ;
~ VirtualBlock ( ) ;
D3D12MA_CLASS_NO_COPY ( VirtualBlock )
2019-05-20 11:46:23 +00:00
} ;
2021-07-28 13:44:27 +00:00
/** \brief Creates new main D3D12MA::Allocator object and returns it through `ppAllocator`.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
You normally only need to call it once and keep a single Allocator object for your ` ID3D12Device ` .
*/
2021-11-24 00:22:58 +00:00
D3D12MA_API HRESULT CreateAllocator ( const ALLOCATOR_DESC * pDesc , Allocator * * ppAllocator ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/** \brief Creates new D3D12MA::VirtualBlock object and returns it through `ppVirtualBlock`.
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Note you don ' t need to create D3D12MA : : Allocator to use virtual blocks .
*/
2021-11-24 00:22:58 +00:00
D3D12MA_API HRESULT CreateVirtualBlock ( const VIRTUAL_BLOCK_DESC * pDesc , VirtualBlock * * ppVirtualBlock ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
} // namespace D3D12MA
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
/// \cond INTERNAL
DEFINE_ENUM_FLAG_OPERATORS ( D3D12MA : : ALLOCATION_FLAGS ) ;
DEFINE_ENUM_FLAG_OPERATORS ( D3D12MA : : ALLOCATOR_FLAGS ) ;
/// \endcond
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
/**
\ page quick_start Quick start
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ section quick_start_project_setup Project setup and initialization
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
This is a small , standalone C + + library . It consists of a pair of 2 files :
" D3D12MemAlloc.h " header file with public interface and " D3D12MemAlloc.cpp " with
internal implementation . The only external dependencies are WinAPI , Direct3D 12 ,
and parts of C / C + + standard library ( but STL containers , exceptions , or RTTI are
not used ) .
2020-03-19 10:59:16 +00:00
2021-07-28 13:44:27 +00:00
The library is developed and tested using Microsoft Visual Studio 2019 , but it
should work with other compilers as well . It is designed for 64 - bit code .
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
To use the library in your project :
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
( 1. ) Copy files ` D3D12MemAlloc . cpp ` , ` % D3D12MemAlloc . h ` to your project .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
( 2. ) Make ` D3D12MemAlloc . cpp ` compiling as part of the project , as C + + code .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
( 3. ) Include library header in each CPP file that needs to use the library .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ code
# include "D3D12MemAlloc.h"
\ endcode
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
( 4. ) Right after you created ` ID3D12Device ` , fill D3D12MA : : ALLOCATOR_DESC
structure and call function D3D12MA : : CreateAllocator to create the main
D3D12MA : : Allocator object .
2019-10-11 09:11:28 +00:00
2021-07-28 13:44:27 +00:00
Please note that all symbols of the library are declared inside # D3D12MA namespace .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ code
IDXGIAdapter * adapter = ( . . . )
ID3D12Device * device = ( . . . )
2020-11-03 15:55:25 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA : : ALLOCATOR_DESC allocatorDesc = { } ;
allocatorDesc . pDevice = device ;
allocatorDesc . pAdapter = adapter ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA : : Allocator * allocator ;
HRESULT hr = D3D12MA : : CreateAllocator ( & allocatorDesc , & allocator ) ;
\ endcode
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
( 5. ) Right before destroying the D3D12 device , destroy the allocator object .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
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 .
2019-10-11 09:11:28 +00:00
2021-07-28 13:44:27 +00:00
\ code
allocator - > Release ( ) ;
\ endcode
2019-10-11 09:11:28 +00:00
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ section quick_start_creating_resources Creating resources
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 ` .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
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 ` .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
The function also returns a new object of type D3D12MA : : Allocation , created along
with usual ` ID3D12Resource ` . It represents allocated memory and can be queried
for size , offset , ` ID3D12Resource ` , and ` ID3D12Heap ` if needed .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ code
D3D12_RESOURCE_DESC resourceDesc = { } ;
resourceDesc . Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D ;
resourceDesc . Alignment = 0 ;
resourceDesc . Width = 1024 ;
resourceDesc . Height = 1024 ;
resourceDesc . DepthOrArraySize = 1 ;
resourceDesc . MipLevels = 1 ;
resourceDesc . Format = DXGI_FORMAT_R8G8B8A8_UNORM ;
resourceDesc . SampleDesc . Count = 1 ;
resourceDesc . SampleDesc . Quality = 0 ;
resourceDesc . Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN ;
resourceDesc . Flags = D3D12_RESOURCE_FLAG_NONE ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA : : ALLOCATION_DESC allocationDesc = { } ;
allocDesc . HeapType = D3D12_HEAP_TYPE_DEFAULT ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
D3D12Resource * resource ;
D3D12MA : : Allocation * allocation ;
HRESULT hr = allocator - > CreateResource (
& allocationDesc ,
& resourceDesc ,
D3D12_RESOURCE_STATE_COPY_DEST ,
NULL ,
& allocation ,
IID_PPV_ARGS ( & resource ) ) ;
\ endcode
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
You need to remember both resource and allocation objects and destroy them
separately when no longer needed .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ code
allocation - > Release ( ) ;
resource - > Release ( ) ;
\ endcode
2020-03-16 18:36:15 +00:00
2021-07-28 13:44:27 +00:00
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 .
2020-03-16 18:36:15 +00:00
2021-07-28 13:44:27 +00:00
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 ` ) .
2020-03-16 18:36:15 +00:00
2021-07-28 13:44:27 +00:00
The library also automatically handles resource heap tier .
When ` D3D12_FEATURE_DATA_D3D12_OPTIONS : : ResourceHeapTier ` equals ` 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 .
2021-07-26 19:18:52 +00:00
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ section quick_start_mapping_memory Mapping memory
2020-03-16 15:36:37 +00:00
2021-07-28 13:44:27 +00:00
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 ] ( https : //docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12resource-map).
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Mapping happens on the level of particular resources , not entire memory heaps ,
and so it is out of scope of this library . Just as the linked documentation says :
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
- Returned pointer refers to data of particular subresource , not entire memory heap .
- You can map same resource multiple times . It is ref - counted internally .
- Mapping is thread - safe .
- Unmapping is not required before resource destruction .
- Unmapping may not be required before using written data - some heap types on
some platforms support resources persistently mapped .
2019-10-11 09:11:28 +00:00
2021-07-28 13:44:27 +00:00
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 .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Example for buffer created and filled in ` UPLOAD ` heap type :
2020-03-16 15:36:37 +00:00
2021-07-28 13:44:27 +00:00
\ code
const UINT64 bufSize = 65536 ;
const float * bufData = ( . . . ) ;
2020-03-16 15:36:37 +00:00
2021-07-28 13:44:27 +00:00
D3D12_RESOURCE_DESC resourceDesc = { } ;
resourceDesc . Dimension = D3D12_RESOURCE_DIMENSION_BUFFER ;
resourceDesc . Alignment = 0 ;
resourceDesc . Width = bufSize ;
resourceDesc . Height = 1 ;
resourceDesc . DepthOrArraySize = 1 ;
resourceDesc . MipLevels = 1 ;
resourceDesc . Format = DXGI_FORMAT_UNKNOWN ;
resourceDesc . SampleDesc . Count = 1 ;
resourceDesc . SampleDesc . Quality = 0 ;
resourceDesc . Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR ;
resourceDesc . Flags = D3D12_RESOURCE_FLAG_NONE ;
2020-03-16 15:36:37 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA : : ALLOCATION_DESC allocationDesc = { } ;
allocationDesc . HeapType = D3D12_HEAP_TYPE_UPLOAD ;
2020-03-16 15:36:37 +00:00
2021-07-28 13:44:27 +00:00
D3D12Resource * resource ;
D3D12MA : : Allocation * allocation ;
HRESULT hr = allocator - > CreateResource (
& allocationDesc ,
& resourceDesc ,
D3D12_RESOURCE_STATE_GENERIC_READ ,
NULL ,
& allocation ,
IID_PPV_ARGS ( & resource ) ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
void * mappedPtr ;
hr = resource - > Map ( 0 , NULL , & mappedPtr ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
memcpy ( mappedPtr , bufData , bufSize ) ;
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
resource - > Unmap ( 0 , NULL ) ;
\ endcode
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
\ page custom_pools Custom memory pools
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
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 .
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
\ section custom_pools_usage Usage
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
To create a custom pool , fill in structure D3D12MA : : POOL_DESC and call function D3D12MA : : Allocator : : CreatePool
to obtain object D3D12MA : : Pool . Example :
\ code
POOL_DESC poolDesc = { } ;
poolDesc . HeapProperties . Type = D3D12_HEAP_TYPE_DEFAULT ;
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
Pool * pool ;
HRESULT hr = allocator - > CreatePool ( & poolDesc , & pool ) ;
\ endcode
2020-04-02 14:59:13 +00:00
2021-07-28 13:44:27 +00:00
To allocate resources out of a custom pool , only set member D3D12MA : : ALLOCATION_DESC : : CustomPool .
Example :
2020-04-02 14:59:13 +00:00
2021-07-28 13:44:27 +00:00
\ code
ALLOCATION_DESC allocDesc = { } ;
allocDesc . CustomPool = pool ;
2020-04-02 14:59:13 +00:00
2021-07-28 13:44:27 +00:00
D3D12_RESOURCE_DESC resDesc = . . .
Allocation * alloc ;
hr = allocator - > CreateResource ( & allocDesc , & resDesc ,
D3D12_RESOURCE_STATE_GENERIC_READ , NULL , & alloc , IID_NULL , NULL ) ;
\ endcode
2020-04-02 15:15:19 +00:00
2021-07-28 13:44:27 +00:00
All allocations must be released before releasing the pool .
The pool must be released before relasing the allocator .
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
\ code
alloc - > Release ( ) ;
pool - > Release ( ) ;
\ endcode
2020-04-02 15:45:13 +00:00
2021-07-28 13:44:27 +00:00
\ section custom_pools_features_and_benefits Features and benefits
2020-04-02 15:45:13 +00:00
2021-07-28 13:44:27 +00:00
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 :
2020-04-02 15:45:13 +00:00
2021-07-28 13:44:27 +00:00
- To keep some resources separate from others in memory .
- To keep track of memory usage of just a specific group of resources . Statistics can be queried using
D3D12MA : : Pool : : CalculateStats .
- To use specific size of a memory block ( ` ID3D12Heap ` ) . To set it , use member D3D12MA : : POOL_DESC : : BlockSize .
When set to 0 , the library uses automatically determined , variable block sizes .
- To reserve some minimum amount of memory allocated . To use it , set member D3D12MA : : POOL_DESC : : MinBlockCount .
- To limit maximum amount of memory allocated . To use it , set member D3D12MA : : POOL_DESC : : MaxBlockCount .
- To use extended parameters of the D3D12 memory allocation . While resources created from default pools
can only specify ` 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 ) .
2020-04-02 15:45:13 +00:00
2021-07-28 13:44:27 +00:00
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 :
2020-04-02 15:45:13 +00:00
2021-07-28 13:44:27 +00:00
\ code
ALLOCATION_DESC allocDesc = { } ;
allocDesc . CustomPool = pool ;
allocDesc . Flags = ALLOCATION_FLAG_COMMITTED ;
2020-04-02 15:45:13 +00:00
2021-07-28 13:44:27 +00:00
D3D12_RESOURCE_DESC resDesc = . . .
Allocation * alloc ;
ID3D12Resource * res ;
hr = allocator - > CreateResource ( & allocDesc , & resDesc ,
D3D12_RESOURCE_STATE_GENERIC_READ , NULL , & alloc , IID_PPV_ARGS ( & res ) ) ;
\ endcode
2021-07-26 19:18:52 +00:00
2021-07-28 13:44:27 +00:00
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 .
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
\ page resource_aliasing Resource aliasing ( overlap )
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
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 .
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
For example , if you know the flow of your whole render frame in advance , you
are going to use some intermediate textures or buffers only during a small range of render passes ,
and you know these ranges don ' t overlap in time , you can create these resources in
the same place in memory , even if they have completely different parameters ( width , height , format etc . ) .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
! [ Resource aliasing ( overlap ) ] ( . . / gfx / Aliasing . png )
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Such scenario is possible using D3D12MA , but you need to create your resources
using special function D3D12MA : : Allocator : : CreateAliasingResource .
Before that , you need to allocate memory with parameters calculated using formula :
2019-10-23 13:21:21 +00:00
2021-07-28 13:44:27 +00:00
- allocation size = max ( size of each resource )
- allocation alignment = max ( alignment of each resource )
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Following example shows two different textures created in the same place in memory ,
allocated to fit largest of them .
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
\ code
D3D12_RESOURCE_DESC resDesc1 = { } ;
resDesc1 . Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D ;
resDesc1 . Alignment = 0 ;
resDesc1 . Width = 1920 ;
resDesc1 . Height = 1080 ;
resDesc1 . DepthOrArraySize = 1 ;
resDesc1 . MipLevels = 1 ;
resDesc1 . Format = DXGI_FORMAT_R8G8B8A8_UNORM ;
resDesc1 . SampleDesc . Count = 1 ;
resDesc1 . SampleDesc . Quality = 0 ;
resDesc1 . Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN ;
resDesc1 . Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
D3D12_RESOURCE_DESC resDesc2 = { } ;
resDesc2 . Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D ;
resDesc2 . Alignment = 0 ;
resDesc2 . Width = 1024 ;
resDesc2 . Height = 1024 ;
resDesc2 . DepthOrArraySize = 1 ;
resDesc2 . MipLevels = 0 ;
resDesc2 . Format = DXGI_FORMAT_R8G8B8A8_UNORM ;
resDesc2 . SampleDesc . Count = 1 ;
resDesc2 . SampleDesc . Quality = 0 ;
resDesc2 . Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN ;
resDesc2 . Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET ;
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
const D3D12_RESOURCE_ALLOCATION_INFO allocInfo1 =
device - > GetResourceAllocationInfo ( 0 , 1 , & resDesc1 ) ;
const D3D12_RESOURCE_ALLOCATION_INFO allocInfo2 =
device - > GetResourceAllocationInfo ( 0 , 1 , & resDesc2 ) ;
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
D3D12_RESOURCE_ALLOCATION_INFO finalAllocInfo = { } ;
finalAllocInfo . Alignment = std : : max ( allocInfo1 . Alignment , allocInfo2 . Alignment ) ;
finalAllocInfo . SizeInBytes = std : : max ( allocInfo1 . SizeInBytes , allocInfo2 . SizeInBytes ) ;
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA : : ALLOCATION_DESC allocDesc = { } ;
allocDesc . HeapType = D3D12_HEAP_TYPE_DEFAULT ;
allocDesc . ExtraHeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES ;
2019-09-30 12:30:04 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA : : Allocation * alloc ;
hr = allocator - > AllocateMemory ( & allocDesc , & finalAllocInfo , & alloc ) ;
assert ( alloc ! = NULL & & alloc - > GetHeap ( ) ! = NULL ) ;
2019-09-30 12:30:04 +00:00
2021-07-28 13:44:27 +00:00
ID3D12Resource * res1 ;
hr = allocator - > CreateAliasingResource (
alloc ,
0 , // AllocationLocalOffset
& resDesc1 ,
D3D12_RESOURCE_STATE_COMMON ,
NULL , // pOptimizedClearValue
IID_PPV_ARGS ( & res1 ) ) ;
2019-09-30 12:30:04 +00:00
2021-07-28 13:44:27 +00:00
ID3D12Resource * res2 ;
hr = allocator - > CreateAliasingResource (
alloc ,
0 , // AllocationLocalOffset
& resDesc2 ,
D3D12_RESOURCE_STATE_COMMON ,
NULL , // pOptimizedClearValue
IID_PPV_ARGS ( & res2 ) ) ;
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
// You can use res1 and res2, but not at the same time!
res2 - > Release ( ) ;
res1 - > Release ( ) ;
alloc - > Release ( ) ;
\ endcode
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
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 .
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
Additional considerations :
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
- D3D12 also allows to interpret contents of memory between aliasing resources consistently in some cases ,
which is called " data inheritance " . For details , see
Microsoft documentation , chapter [ Memory Aliasing and Data Inheritance ] ( https : //docs.microsoft.com/en-us/windows/win32/direct3d12/memory-aliasing-and-data-inheritance).
- You can create more complex layout where different textures and buffers are bound
at different offsets inside one large allocation . For example , one can imagine
a big texture used in some render passes , aliasing with a set of many small buffers
used in some further passes . To bind a resource at non - zero offset of an allocation ,
call D3D12MA : : Allocator : : CreateAliasingResource with appropriate value of ` AllocationLocalOffset ` parameter .
- Resources of the three categories : buffers , textures with ` 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 .
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
\ page virtual_allocator Virtual allocator
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
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 .
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
\ section virtual_allocator_creating_virtual_block Creating virtual block
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
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 :
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
- # Fill in D3D12MA : : ALLOCATOR_DESC structure .
- # Call D3D12MA : : CreateVirtualBlock . Get new D3D12MA : : VirtualBlock object .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Example :
2021-03-11 12:40:24 +00:00
2021-07-28 13:44:27 +00:00
\ code
D3D12MA : : VIRTUAL_BLOCK_DESC blockDesc = { } ;
blockDesc . Size = 1048576 ; // 1 MB
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA : : VirtualBlock * block ;
HRESULT hr = CreateVirtualBlock ( & blockDesc , & block ) ;
\ endcode
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ section virtual_allocator_making_virtual_allocations Making virtual allocations
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
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 .
However , there is no " virtual allocation " object .
When you request a new allocation , a ` UINT64 ` number is returned .
It is an offset inside the block where the allocation has been placed , but it also uniquely identifies the allocation within this block .
2019-10-11 09:11:28 +00:00
2021-07-28 13:44:27 +00:00
In order to make an allocation :
2019-10-11 09:11:28 +00:00
2021-07-28 13:44:27 +00:00
- # Fill in D3D12MA : : VIRTUAL_ALLOCATION_DESC structure .
- # Call D3D12MA : : VirtualBlock : : Allocate . Get new ` UINT64 offset ` that identifies the allocation .
2020-11-03 14:38:08 +00:00
2021-07-28 13:44:27 +00:00
Example :
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ code
D3D12MA : : VIRTUAL_ALLOCATION_DESC allocDesc = { } ;
allocDesc . Size = 4096 ; // 4 KB
2020-11-04 13:16:44 +00:00
2021-07-28 13:44:27 +00:00
UINT64 allocOffset ;
hr = block - > Allocate ( & allocDesc , & allocOffset ) ;
if ( SUCCEEDED ( hr ) )
{
// Use the 4 KB of your memory starting at allocOffset.
}
else
{
// Allocation failed - no space for it could be found. Handle this error!
}
\ endcode
2020-11-04 13:16:44 +00:00
2021-07-28 13:44:27 +00:00
\ section virtual_allocator_deallocation Deallocation
2020-11-04 14:23:30 +00:00
2021-07-28 13:44:27 +00:00
When no longer needed , an allocation can be freed by calling D3D12MA : : VirtualBlock : : FreeAllocation .
You can only pass to this function the exact offset that was previously returned by D3D12MA : : VirtualBlock : : Allocate
and not any other location within the memory .
2020-11-04 14:23:30 +00:00
2021-07-28 13:44:27 +00:00
When whole block is no longer needed , the block object can be released by calling D3D12MA : : VirtualBlock : : 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 :
2019-10-11 09:11:28 +00:00
2021-07-28 13:44:27 +00:00
\ code
block - > FreeAllocation ( allocOffset ) ;
block - > Release ( ) ;
\ endcode
2019-10-11 09:11:28 +00:00
2021-07-28 13:44:27 +00:00
\ section virtual_allocator_allocation_parameters Allocation parameters
2019-10-11 09:11:28 +00:00
2021-07-28 13:44:27 +00:00
You can attach a custom pointer to each allocation by using D3D12MA : : VirtualBlock : : SetAllocationUserData .
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 :
2020-01-23 12:24:28 +00:00
2021-07-28 13:44:27 +00:00
\ code
struct CustomAllocData
{
std : : string m_AllocName ;
} ;
CustomAllocData * allocData = new CustomAllocData ( ) ;
allocData - > m_AllocName = " My allocation 1 " ;
block - > SetAllocationUserData ( allocOffset , allocData ) ;
\ endcode
2019-10-11 09:11:28 +00:00
2021-07-28 13:44:27 +00:00
The pointer can later be fetched , along with allocation size , by passing the allocation offset to function
D3D12MA : : VirtualBlock : : GetAllocationInfo and inspecting returned structure D3D12MA : : VIRTUAL_ALLOCATION_INFO .
If you allocated a new object to be used as the custom pointer , don ' t forget to delete that object before freeing the allocation !
Example :
2020-11-04 13:16:44 +00:00
2021-07-28 13:44:27 +00:00
\ code
VIRTUAL_ALLOCATION_INFO allocInfo ;
block - > GetAllocationInfo ( allocOffset , & allocInfo ) ;
delete ( CustomAllocData * ) allocInfo . pUserData ;
2020-11-04 13:16:44 +00:00
2021-07-28 13:44:27 +00:00
block - > FreeAllocation ( allocOffset ) ;
\ endcode
2020-03-25 16:41:35 +00:00
2021-07-28 13:44:27 +00:00
\ section virtual_allocator_alignment_and_units Alignment and units
2020-03-25 16:41:35 +00:00
2021-07-28 13:44:27 +00:00
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 :
2020-03-25 16:41:35 +00:00
2021-07-28 13:44:27 +00:00
\ code
D3D12MA : : VIRTUAL_ALLOCATION_DESC allocDesc = { } ;
allocDesc . Size = 4096 ; // 4 KB
allocDesc . Alignment = 4 ; // Returned offset must be a multiply of 4 B
2020-04-02 14:12:14 +00:00
2021-07-28 13:44:27 +00:00
UINT64 allocOffset ;
hr = block - > Allocate ( & allocDesc , & allocOffset ) ;
\ endcode
2019-10-11 14:20:45 +00:00
2021-07-28 13:44:27 +00:00
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 :
2019-10-11 14:20:45 +00:00
2021-07-28 13:44:27 +00:00
- D3D12MA : : VIRTUAL_BLOCK_DESC : : Size
- D3D12MA : : VIRTUAL_ALLOCATION_DESC : : Size and D3D12MA : : VIRTUAL_ALLOCATION_DESC : : Alignment
- Using offset returned by D3D12MA : : VirtualBlock : : Allocate
2019-09-30 12:30:04 +00:00
2021-07-28 13:44:27 +00:00
\ section virtual_allocator_statistics Statistics
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
You can obtain statistics of a virtual block using D3D12MA : : VirtualBlock : : CalculateStats .
The function fills structure D3D12MA : : StatInfo - same as used by the normal D3D12 memory allocator .
Example :
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
\ code
D3D12MA : : StatInfo statInfo ;
block - > CalculateStats ( & statInfo ) ;
printf ( " My virtual block has %llu bytes used by %u virtual allocations \n " ,
statInfo . UsedBytes , statInfo . AllocationCount ) ;
\ endcode
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
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 .
2019-11-20 13:07:21 +00:00
2021-07-28 13:44:27 +00:00
\ section virtual_allocator_additional_considerations Additional considerations
2019-10-11 09:11:28 +00:00
2021-07-28 13:44:27 +00:00
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 .
2019-10-11 09:11:28 +00:00
2021-07-26 19:18:52 +00:00
2021-07-28 13:44:27 +00:00
\ page configuration Configuration
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
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 .
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ section custom_memory_allocator Custom CPU memory allocator
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
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 :
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
\ code
# include <malloc.h>
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
void * CustomAllocate ( size_t Size , size_t Alignment , void * pUserData )
2020-06-15 15:43:54 +00:00
{
2021-07-28 13:44:27 +00:00
void * memory = _aligned_malloc ( Size , Alignment ) ;
// Your extra bookkeeping here...
return memory ;
}
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
void CustomFree ( void * pMemory , void * pUserData )
2020-06-15 15:43:54 +00:00
{
2021-07-28 13:44:27 +00:00
// Your extra bookkeeping here...
_aligned_free ( pMemory ) ;
}
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
( . . . )
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA : : ALLOCATION_CALLBACKS allocationCallbacks = { } ;
allocationCallbacks . pAllocate = & CustomAllocate ;
allocationCallbacks . pFree = & CustomFree ;
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA : : ALLOCATOR_DESC allocatorDesc = { } ;
allocatorDesc . pDevice = device ;
allocatorDesc . pAdapter = adapter ;
allocatorDesc . pAllocationCallbacks = & allocationCallbacks ;
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
D3D12MA : : Allocator * allocator ;
HRESULT hr = D3D12MA : : CreateAllocator ( & allocatorDesc , & allocator ) ;
\ endcode
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
\ page general_considerations General considerations
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
\ section general_considerations_thread_safety Thread safety
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
- The library has no global state , so separate D3D12MA : : Allocator objects can be used independently .
In typical applications there should be no need to create multiple such objects though - one per ` ID3D12Device ` is enough .
- All calls to methods of D3D12MA : : Allocator class are safe to be made from multiple
threads simultaneously because they are synchronized internally when needed .
- When the allocator is created with D3D12MA : : ALLOCATOR_FLAG_SINGLETHREADED ,
calls to methods of D3D12MA : : Allocator class must be made from a single thread or synchronized by the user .
Using this flag may improve performance .
2021-12-03 17:08:24 +00:00
- D3D12MA : : VirtualBlock is not safe to be used from multiple threads simultaneously .
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
\ section general_considerations_future_plans Future plans
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
Features planned for future releases :
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
Near future : feature parity with [ Vulkan Memory Allocator ] ( https : //github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/), including:
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
- Alternative allocation algorithms : linear allocator , buddy allocator
- Support for priorities using ` ID3D12Device1 : : SetResidencyPriority `
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
Later :
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
- Memory defragmentation
- Support for multi - GPU ( multi - adapter )
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
\ section general_considerations_features_not_supported Features not supported
2019-05-20 11:46:23 +00:00
2021-07-28 13:44:27 +00:00
Features deliberately excluded from the scope of this library :
2020-06-15 15:43:54 +00:00
2021-07-28 13:44:27 +00:00
- * * Descriptor allocation . * * Although also called " heaps " , objects that represent
descriptors are separate part of the D3D12 API from buffers and textures .
- * * Support for reserved ( tiled ) resources . * * We don ' t recommend using them .
- Support for ` 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 .
- * * Handling CPU memory allocation failures . * * When dynamically creating small C + +
objects in CPU memory ( not the GPU memory ) , allocation failures are not
handled gracefully , because that would complicate code significantly and
is usually not needed in desktop PC applications anyway .
Success of an allocation is just checked with an assert .
- * * Code free of any compiler warnings . * *
There are many preprocessor macros that 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 .
- This is a C + + library . * * Bindings or ports to any other programming languages * * are welcome as external projects but
are not going to be included into this repository .
2020-06-15 15:43:54 +00:00
*/