duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

D3D12MemAlloc.h (113613B)


      1 //
      2 // Copyright (c) 2019-2022 Advanced Micro Devices, Inc. All rights reserved.
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 //
     22 
     23 #pragma once
     24 
     25 /** \mainpage D3D12 Memory Allocator
     26 
     27 <b>Version 2.1.0-development</b> (2023-07-05)
     28 
     29 Copyright (c) 2019-2023 Advanced Micro Devices, Inc. All rights reserved. \n
     30 License: MIT
     31 
     32 Documentation of all members: D3D12MemAlloc.h
     33 
     34 \section main_table_of_contents Table of contents
     35 
     36 - \subpage quick_start
     37     - [Project setup](@ref quick_start_project_setup)
     38     - [Creating resources](@ref quick_start_creating_resources)
     39     - [Resource reference counting](@ref quick_start_resource_reference_counting)
     40     - [Mapping memory](@ref quick_start_mapping_memory)
     41 - \subpage custom_pools
     42 - \subpage defragmentation
     43 - \subpage statistics
     44 - \subpage resource_aliasing
     45 - \subpage linear_algorithm
     46 - \subpage virtual_allocator
     47 - \subpage configuration
     48   - [Custom CPU memory allocator](@ref custom_memory_allocator)
     49   - [Debug margins](@ref debug_margins)
     50 - \subpage general_considerations
     51   - [Thread safety](@ref general_considerations_thread_safety)
     52   - [Versioning and compatibility](@ref general_considerations_versioning_and_compatibility)
     53   - [Features not supported](@ref general_considerations_features_not_supported)
     54         
     55 \section main_see_also See also
     56 
     57 - [Product page on GPUOpen](https://gpuopen.com/gaming-product/d3d12-memory-allocator/)
     58 - [Source repository on GitHub](https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator)
     59 */
     60 
     61 // If using this library on a platform different than Windows PC or want to use different version of DXGI,
     62 // you should include D3D12-compatible headers before this library on your own and define 
     63 // D3D12MA_D3D12_HEADERS_ALREADY_INCLUDED.
     64 // Alternatively, if you are targeting the open sourced DirectX headers, defining D3D12MA_USING_DIRECTX_HEADERS
     65 // will include them rather the ones provided by the Windows SDK.
     66 #ifndef D3D12MA_D3D12_HEADERS_ALREADY_INCLUDED
     67     #if defined(D3D12MA_USING_DIRECTX_HEADERS)
     68         #include <directx/d3d12.h>
     69         #include <dxguids/dxguids.h>
     70     #else
     71         #include <d3d12.h>
     72     #endif
     73     
     74     #include <dxgi1_4.h>
     75 #endif
     76 
     77 // Define this macro to 0 to disable usage of DXGI 1.4 (needed for IDXGIAdapter3 and query for memory budget).
     78 #ifndef D3D12MA_DXGI_1_4
     79     #ifdef __IDXGIAdapter3_INTERFACE_DEFINED__
     80         #define D3D12MA_DXGI_1_4 1
     81     #else
     82         #define D3D12MA_DXGI_1_4 0
     83     #endif
     84 #endif
     85 
     86 /*
     87 When defined to value other than 0, the library will try to use
     88 D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT or D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT
     89 for created textures when possible, which can save memory because some small textures
     90 may get their alignment 4K and their size a multiply of 4K instead of 64K.
     91 
     92 #define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 0
     93     Disables small texture alignment.
     94 #define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 1
     95     Enables conservative algorithm that will use small alignment only for some textures
     96     that are surely known to support it.
     97 #define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 2
     98     Enables query for small alignment to D3D12 (based on Microsoft sample) which will
     99     enable small alignment for more textures, but will also generate D3D Debug Layer
    100     error #721 on call to ID3D12Device::GetResourceAllocationInfo, which you should just
    101     ignore.
    102 */
    103 #ifndef D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT
    104     #define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 1
    105 #endif
    106 
    107 /// \cond INTERNAL
    108 
    109 #define D3D12MA_CLASS_NO_COPY(className) \
    110     private: \
    111         className(const className&) = delete; \
    112         className(className&&) = delete; \
    113         className& operator=(const className&) = delete; \
    114         className& operator=(className&&) = delete;
    115 
    116 // To be used with MAKE_HRESULT to define custom error codes.
    117 #define FACILITY_D3D12MA 3542
    118 
    119 /*
    120 If providing your own implementation, you need to implement a subset of std::atomic.
    121 */
    122 #if !defined(D3D12MA_ATOMIC_UINT32) || !defined(D3D12MA_ATOMIC_UINT64)
    123     #include <atomic>
    124 #endif
    125 
    126 #ifndef D3D12MA_ATOMIC_UINT32
    127     #define D3D12MA_ATOMIC_UINT32 std::atomic<UINT>
    128 #endif
    129 
    130 #ifndef D3D12MA_ATOMIC_UINT64
    131     #define D3D12MA_ATOMIC_UINT64 std::atomic<UINT64>
    132 #endif
    133 
    134 #ifdef D3D12MA_EXPORTS
    135     #define D3D12MA_API __declspec(dllexport)
    136 #elif defined(D3D12MA_IMPORTS)
    137     #define D3D12MA_API __declspec(dllimport)
    138 #else
    139     #define D3D12MA_API
    140 #endif
    141 
    142 // Forward declaration if ID3D12ProtectedResourceSession is not defined inside the headers (older SDK, pre ID3D12Device4)
    143 struct ID3D12ProtectedResourceSession;
    144 
    145 // Define this enum even if SDK doesn't provide it, to simplify the API.
    146 #ifndef __ID3D12Device1_INTERFACE_DEFINED__
    147 typedef enum D3D12_RESIDENCY_PRIORITY
    148 {
    149     D3D12_RESIDENCY_PRIORITY_MINIMUM = 0x28000000,
    150     D3D12_RESIDENCY_PRIORITY_LOW = 0x50000000,
    151     D3D12_RESIDENCY_PRIORITY_NORMAL = 0x78000000,
    152     D3D12_RESIDENCY_PRIORITY_HIGH = 0xa0010000,
    153     D3D12_RESIDENCY_PRIORITY_MAXIMUM = 0xc8000000
    154 } D3D12_RESIDENCY_PRIORITY;
    155 #endif
    156 
    157 namespace D3D12MA
    158 {
    159 class D3D12MA_API IUnknownImpl : public IUnknown
    160 {
    161 public:
    162     virtual ~IUnknownImpl() = default;
    163     virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
    164     virtual ULONG STDMETHODCALLTYPE AddRef();
    165     virtual ULONG STDMETHODCALLTYPE Release();
    166 protected:
    167     virtual void ReleaseThis() { delete this; }
    168 private:
    169     D3D12MA_ATOMIC_UINT32 m_RefCount = {1};
    170 };
    171 } // namespace D3D12MA
    172 
    173 /// \endcond
    174 
    175 namespace D3D12MA
    176 {
    177 
    178 /// \cond INTERNAL
    179 class DefragmentationContextPimpl;
    180 class AllocatorPimpl;
    181 class PoolPimpl;
    182 class NormalBlock;
    183 class BlockVector;
    184 class CommittedAllocationList;
    185 class JsonWriter;
    186 class VirtualBlockPimpl;
    187 /// \endcond
    188 
    189 class Pool;
    190 class Allocator;
    191 struct Statistics;
    192 struct DetailedStatistics;
    193 struct TotalStatistics;
    194 
    195 /// \brief Unique identifier of single allocation done inside the memory heap.
    196 typedef UINT64 AllocHandle;
    197 
    198 /// Pointer to custom callback function that allocates CPU memory.
    199 using ALLOCATE_FUNC_PTR = void* (*)(size_t Size, size_t Alignment, void* pPrivateData);
    200 /**
    201 \brief Pointer to custom callback function that deallocates CPU memory.
    202 
    203 `pMemory = null` should be accepted and ignored.
    204 */
    205 using FREE_FUNC_PTR = void (*)(void* pMemory, void* pPrivateData);
    206 
    207 /// Custom callbacks to CPU memory allocation functions.
    208 struct ALLOCATION_CALLBACKS
    209 {
    210     /// %Allocation function.
    211     ALLOCATE_FUNC_PTR pAllocate;
    212     /// Dellocation function.
    213     FREE_FUNC_PTR pFree;
    214     /// Custom data that will be passed to allocation and deallocation functions as `pUserData` parameter.
    215     void* pPrivateData;
    216 };
    217 
    218 
    219 /// \brief Bit flags to be used with ALLOCATION_DESC::Flags.
    220 enum ALLOCATION_FLAGS
    221 {
    222     /// Zero
    223     ALLOCATION_FLAG_NONE = 0,
    224 
    225     /**
    226     Set this flag if the allocation should have its own dedicated memory allocation (committed resource with implicit heap).
    227     
    228     Use it for special, big resources, like fullscreen textures used as render targets.
    229 
    230     - When used with functions like D3D12MA::Allocator::CreateResource, it will use `ID3D12Device::CreateCommittedResource`,
    231       so the created allocation will contain a resource (D3D12MA::Allocation::GetResource() `!= NULL`) but will not have
    232       a heap (D3D12MA::Allocation::GetHeap() `== NULL`), as the heap is implicit.
    233     - When used with raw memory allocation like D3D12MA::Allocator::AllocateMemory, it will use `ID3D12Device::CreateHeap`,
    234       so the created allocation will contain a heap (D3D12MA::Allocation::GetHeap() `!= NULL`) and its offset will always be 0.
    235     */
    236     ALLOCATION_FLAG_COMMITTED = 0x1,
    237 
    238     /**
    239     Set this flag to only try to allocate from existing memory heaps and never create new such heap.
    240 
    241     If new allocation cannot be placed in any of the existing heaps, allocation
    242     fails with `E_OUTOFMEMORY` error.
    243 
    244     You should not use D3D12MA::ALLOCATION_FLAG_COMMITTED and
    245     D3D12MA::ALLOCATION_FLAG_NEVER_ALLOCATE at the same time. It makes no sense.
    246     */
    247     ALLOCATION_FLAG_NEVER_ALLOCATE = 0x2,
    248 
    249     /** Create allocation only if additional memory required for it, if any, won't exceed
    250     memory budget. Otherwise return `E_OUTOFMEMORY`.
    251     */
    252     ALLOCATION_FLAG_WITHIN_BUDGET = 0x4,
    253 
    254     /** Allocation will be created from upper stack in a double stack pool.
    255 
    256     This flag is only allowed for custom pools created with #POOL_FLAG_ALGORITHM_LINEAR flag.
    257     */
    258     ALLOCATION_FLAG_UPPER_ADDRESS = 0x8,
    259 
    260     /** Set this flag if the allocated memory will have aliasing resources.
    261     
    262     Use this when calling D3D12MA::Allocator::CreateResource() and similar to
    263     guarantee creation of explicit heap for desired allocation and prevent it from using `CreateCommittedResource`,
    264     so that new allocation object will always have `allocation->GetHeap() != NULL`.
    265     */
    266     ALLOCATION_FLAG_CAN_ALIAS = 0x10,
    267 
    268     /** Allocation strategy that chooses smallest possible free range for the allocation
    269     to minimize memory usage and fragmentation, possibly at the expense of allocation time.
    270     */
    271     ALLOCATION_FLAG_STRATEGY_MIN_MEMORY = 0x00010000,
    272 
    273     /** Allocation strategy that chooses first suitable free range for the allocation -
    274     not necessarily in terms of the smallest offset but the one that is easiest and fastest to find
    275     to minimize allocation time, possibly at the expense of allocation quality.
    276     */
    277     ALLOCATION_FLAG_STRATEGY_MIN_TIME = 0x00020000,
    278 
    279     /** Allocation strategy that chooses always the lowest offset in available space.
    280     This is not the most efficient strategy but achieves highly packed data.
    281     Used internally by defragmentation, not recomended in typical usage.
    282     */
    283     ALLOCATION_FLAG_STRATEGY_MIN_OFFSET = 0x0004000,
    284 
    285     /// Alias to #ALLOCATION_FLAG_STRATEGY_MIN_MEMORY.
    286     ALLOCATION_FLAG_STRATEGY_BEST_FIT = ALLOCATION_FLAG_STRATEGY_MIN_MEMORY,
    287     /// Alias to #ALLOCATION_FLAG_STRATEGY_MIN_TIME.
    288     ALLOCATION_FLAG_STRATEGY_FIRST_FIT = ALLOCATION_FLAG_STRATEGY_MIN_TIME,
    289 
    290     /// A bit mask to extract only `STRATEGY` bits from entire set of flags.
    291     ALLOCATION_FLAG_STRATEGY_MASK =
    292         ALLOCATION_FLAG_STRATEGY_MIN_MEMORY |
    293         ALLOCATION_FLAG_STRATEGY_MIN_TIME |
    294         ALLOCATION_FLAG_STRATEGY_MIN_OFFSET,
    295 };
    296 
    297 /// \brief Parameters of created D3D12MA::Allocation object. To be used with Allocator::CreateResource.
    298 struct ALLOCATION_DESC
    299 {
    300     /// Flags.
    301     ALLOCATION_FLAGS Flags;
    302     /** \brief The type of memory heap where the new allocation should be placed.
    303 
    304     It must be one of: `D3D12_HEAP_TYPE_DEFAULT`, `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`.
    305 
    306     When D3D12MA::ALLOCATION_DESC::CustomPool != NULL this member is ignored.
    307     */
    308     D3D12_HEAP_TYPE HeapType;
    309     /** \brief Additional heap flags to be used when allocating memory.
    310 
    311     In most cases it can be 0.
    312     
    313     - If you use D3D12MA::Allocator::CreateResource(), you don't need to care.
    314       Necessary flag `D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS`, `D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES`,
    315       or `D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES` is added automatically.
    316     - If you use D3D12MA::Allocator::AllocateMemory(), you should specify one of those `ALLOW_ONLY` flags.
    317       Except when you validate that D3D12MA::Allocator::GetD3D12Options()`.ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1` -
    318       then you can leave it 0.
    319     - You can specify additional flags if needed. Then the memory will always be allocated as
    320       separate block using `D3D12Device::CreateCommittedResource` or `CreateHeap`, not as part of an existing larget block.
    321 
    322     When D3D12MA::ALLOCATION_DESC::CustomPool != NULL this member is ignored.
    323     */
    324     D3D12_HEAP_FLAGS ExtraHeapFlags;
    325     /** \brief Custom pool to place the new resource in. Optional.
    326 
    327     When not NULL, the resource will be created inside specified custom pool.
    328     */
    329     Pool* CustomPool;
    330     /// Custom general-purpose pointer that will be stored in D3D12MA::Allocation.
    331     void* pPrivateData;
    332 };
    333 
    334 /** \brief Calculated statistics of memory usage e.g. in a specific memory heap type,
    335 memory segment group, custom pool, or total.
    336 
    337 These are fast to calculate.
    338 See functions: D3D12MA::Allocator::GetBudget(), D3D12MA::Pool::GetStatistics().
    339 */
    340 struct Statistics
    341 {
    342     /** \brief Number of D3D12 memory blocks allocated - `ID3D12Heap` objects and committed resources.
    343     */
    344     UINT BlockCount;
    345     /** \brief Number of D3D12MA::Allocation objects allocated.
    346 
    347     Committed allocations have their own blocks, so each one adds 1 to `AllocationCount` as well as `BlockCount`.
    348     */
    349     UINT AllocationCount;
    350     /** \brief Number of bytes allocated in memory blocks.
    351     */
    352     UINT64 BlockBytes;
    353     /** \brief Total number of bytes occupied by all D3D12MA::Allocation objects.
    354 
    355     Always less or equal than `BlockBytes`.
    356     Difference `(BlockBytes - AllocationBytes)` is the amount of memory allocated from D3D12
    357     but unused by any D3D12MA::Allocation.
    358     */
    359     UINT64 AllocationBytes;
    360 };
    361 
    362 /** \brief More detailed statistics than D3D12MA::Statistics.
    363 
    364 These are slower to calculate. Use for debugging purposes.
    365 See functions: D3D12MA::Allocator::CalculateStatistics(), D3D12MA::Pool::CalculateStatistics().
    366 
    367 Averages are not provided because they can be easily calculated as:
    368 
    369 \code
    370 UINT64 AllocationSizeAvg = DetailedStats.Statistics.AllocationBytes / detailedStats.Statistics.AllocationCount;
    371 UINT64 UnusedBytes = DetailedStats.Statistics.BlockBytes - DetailedStats.Statistics.AllocationBytes;
    372 UINT64 UnusedRangeSizeAvg = UnusedBytes / DetailedStats.UnusedRangeCount;
    373 \endcode
    374 */
    375 struct DetailedStatistics
    376 {
    377     /// Basic statistics.
    378     Statistics Stats;
    379     /// Number of free ranges of memory between allocations.
    380     UINT UnusedRangeCount;
    381     /// Smallest allocation size. `UINT64_MAX` if there are 0 allocations.
    382     UINT64 AllocationSizeMin;
    383     /// Largest allocation size. 0 if there are 0 allocations.
    384     UINT64 AllocationSizeMax;
    385     /// Smallest empty range size. `UINT64_MAX` if there are 0 empty ranges.
    386     UINT64 UnusedRangeSizeMin;
    387     /// Largest empty range size. 0 if there are 0 empty ranges.
    388     UINT64 UnusedRangeSizeMax;
    389 };
    390 
    391 /** \brief  General statistics from current state of the allocator -
    392 total memory usage across all memory heaps and segments.
    393 
    394 These are slower to calculate. Use for debugging purposes.
    395 See function D3D12MA::Allocator::CalculateStatistics().
    396 */
    397 struct TotalStatistics
    398 {
    399     /** \brief One element for each type of heap located at the following indices:
    400 
    401     - 0 = `D3D12_HEAP_TYPE_DEFAULT`
    402     - 1 = `D3D12_HEAP_TYPE_UPLOAD`
    403     - 2 = `D3D12_HEAP_TYPE_READBACK`
    404     - 3 = `D3D12_HEAP_TYPE_CUSTOM`
    405     */
    406     DetailedStatistics HeapType[4];
    407     /** \brief One element for each memory segment group located at the following indices:
    408 
    409     - 0 = `DXGI_MEMORY_SEGMENT_GROUP_LOCAL`
    410     - 1 = `DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL`
    411 
    412     Meaning of these segment groups is:
    413 
    414     - When `IsUMA() == FALSE` (discrete graphics card):
    415       - `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` (index 0) represents GPU memory
    416       (resources allocated in `D3D12_HEAP_TYPE_DEFAULT` or `D3D12_MEMORY_POOL_L1`).
    417       - `DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL` (index 1) represents system memory
    418       (resources allocated in `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`, or `D3D12_MEMORY_POOL_L0`).
    419     - When `IsUMA() == TRUE` (integrated graphics chip):
    420       - `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` = (index 0) represents memory shared for all the resources.
    421       - `DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL` = (index 1) is unused and always 0.
    422     */
    423     DetailedStatistics MemorySegmentGroup[2];
    424     /// Total statistics from all memory allocated from D3D12.
    425     DetailedStatistics Total;
    426 };
    427 
    428 /** \brief %Statistics of current memory usage and available budget for a specific memory segment group.
    429 
    430 These are fast to calculate. See function D3D12MA::Allocator::GetBudget().
    431 */
    432 struct Budget
    433 {
    434     /** \brief %Statistics fetched from the library.
    435     */
    436     Statistics Stats;
    437     /** \brief Estimated current memory usage of the program.
    438 
    439     Fetched from system using `IDXGIAdapter3::QueryVideoMemoryInfo` if possible.
    440 
    441     It might be different than `BlockBytes` (usually higher) due to additional implicit objects
    442     also occupying the memory, like swapchain, pipeline state objects, descriptor heaps, command lists, or
    443     heaps and resources allocated outside of this library, if any.
    444     */
    445     UINT64 UsageBytes;
    446     /** \brief Estimated amount of memory available to the program.
    447 
    448     Fetched from system using `IDXGIAdapter3::QueryVideoMemoryInfo` if possible.
    449 
    450     It might be different (most probably smaller) than memory capacity returned
    451     by D3D12MA::Allocator::GetMemoryCapacity() due to factors
    452     external to the program, decided by the operating system.
    453     Difference `BudgetBytes - UsageBytes` is the amount of additional memory that can probably
    454     be allocated without problems. Exceeding the budget may result in various problems.
    455     */
    456     UINT64 BudgetBytes;
    457 };
    458 
    459 
    460 /// \brief Represents single memory allocation done inside VirtualBlock.
    461 struct D3D12MA_API VirtualAllocation
    462 {
    463     /// \brief Unique idenitfier of current allocation. 0 means null/invalid.
    464     AllocHandle AllocHandle;
    465 };
    466 
    467 /** \brief Represents single memory allocation.
    468 
    469 It may be either implicit memory heap dedicated to a single resource or a
    470 specific region of a bigger heap plus unique offset.
    471 
    472 To create such object, fill structure D3D12MA::ALLOCATION_DESC and call function
    473 Allocator::CreateResource.
    474 
    475 The object remembers size and some other information.
    476 To retrieve this information, use methods of this class.
    477 
    478 The object also remembers `ID3D12Resource` and "owns" a reference to it,
    479 so it calls `%Release()` on the resource when destroyed.
    480 */
    481 class D3D12MA_API Allocation : public IUnknownImpl
    482 {
    483 public:
    484     /** \brief Returns offset in bytes from the start of memory heap.
    485 
    486     You usually don't need to use this offset. If you create a buffer or a texture together with the allocation using function
    487     D3D12MA::Allocator::CreateResource, functions that operate on that resource refer to the beginning of the resource,
    488     not entire memory heap.
    489 
    490     If the Allocation represents committed resource with implicit heap, returns 0.
    491     */
    492     UINT64 GetOffset() const;
    493 
    494     /// Returns alignment that resource was created with.
    495     UINT64 GetAlignment() const { return m_Alignment; }
    496 
    497     /** \brief Returns size in bytes of the allocation.
    498 
    499     - If you created a buffer or a texture together with the allocation using function D3D12MA::Allocator::CreateResource,
    500       this is the size of the resource returned by `ID3D12Device::GetResourceAllocationInfo`.
    501     - For allocations made out of bigger memory blocks, this also is the size of the memory region assigned exclusively to this allocation.
    502     - For resources created as committed, this value may not be accurate. DirectX implementation may optimize memory usage internally
    503       so that you may even observe regions of `ID3D12Resource::GetGPUVirtualAddress()` + Allocation::GetSize() to overlap in memory and still work correctly.
    504     */
    505     UINT64 GetSize() const { return m_Size; }
    506 
    507     /** \brief Returns D3D12 resource associated with this object.
    508 
    509     Calling this method doesn't increment resource's reference counter.
    510     */
    511     ID3D12Resource* GetResource() const { return m_Resource; }
    512 
    513     /// Releases the resource currently pointed by the allocation (if any), sets it to new one, incrementing its reference counter (if not null).
    514     void SetResource(ID3D12Resource* pResource);
    515 
    516     /** \brief Returns memory heap that the resource is created in.
    517 
    518     If the Allocation represents committed resource with implicit heap, returns NULL.
    519     */
    520     ID3D12Heap* GetHeap() const;
    521 
    522     /// Changes custom pointer for an allocation to a new value.
    523     void SetPrivateData(void* pPrivateData) { m_pPrivateData = pPrivateData; }
    524 
    525     /// Get custom pointer associated with the allocation.
    526     void* GetPrivateData() const { return m_pPrivateData; }
    527 
    528     /** \brief Associates a name with the allocation object. This name is for use in debug diagnostics and tools.
    529 
    530     Internal copy of the string is made, so the memory pointed by the argument can be
    531     changed of freed immediately after this call.
    532 
    533     `Name` can be null.
    534     */
    535     void SetName(LPCWSTR Name);
    536 
    537     /** \brief Returns the name associated with the allocation object.
    538 
    539     Returned string points to an internal copy.
    540 
    541     If no name was associated with the allocation, returns null.
    542     */
    543     LPCWSTR GetName() const { return m_Name; }
    544 
    545     /** \brief Returns `TRUE` if the memory of the allocation was filled with zeros when the allocation was created.
    546 
    547     Returns `TRUE` only if the allocator is sure that the entire memory where the
    548     allocation was created was filled with zeros at the moment the allocation was made.
    549     
    550     Returns `FALSE` if the memory could potentially contain garbage data.
    551     If it's a render-target or depth-stencil texture, it then needs proper
    552     initialization with `ClearRenderTargetView`, `ClearDepthStencilView`, `DiscardResource`,
    553     or a copy operation, as described on page
    554     "ID3D12Device::CreatePlacedResource method - Notes on the required resource initialization" in Microsoft documentation.
    555     Please note that rendering a fullscreen triangle or quad to the texture as
    556     a render target is not a proper way of initialization!
    557 
    558     See also articles:
    559 
    560     - "Coming to DirectX 12: More control over memory allocation" on DirectX Developer Blog
    561     - ["Initializing DX12 Textures After Allocation and Aliasing"](https://asawicki.info/news_1724_initializing_dx12_textures_after_allocation_and_aliasing).
    562     */
    563     BOOL WasZeroInitialized() const { return m_PackedData.WasZeroInitialized(); }
    564 
    565 protected:
    566     void ReleaseThis() override;
    567 
    568 private:
    569     friend class AllocatorPimpl;
    570     friend class BlockVector;
    571     friend class CommittedAllocationList;
    572     friend class JsonWriter;
    573     friend class BlockMetadata_Linear;
    574     friend class DefragmentationContextPimpl;
    575     friend struct CommittedAllocationListItemTraits;
    576     template<typename T> friend void D3D12MA_DELETE(const ALLOCATION_CALLBACKS&, T*);
    577     template<typename T> friend class PoolAllocator;
    578 
    579     enum Type
    580     {
    581         TYPE_COMMITTED,
    582         TYPE_PLACED,
    583         TYPE_HEAP,
    584         TYPE_COUNT
    585     };
    586 
    587     AllocatorPimpl* m_Allocator;
    588     UINT64 m_Size;
    589     UINT64 m_Alignment;
    590     ID3D12Resource* m_Resource;
    591     void* m_pPrivateData;
    592     wchar_t* m_Name;
    593 
    594     union
    595     {
    596         struct
    597         {
    598             CommittedAllocationList* list;
    599             Allocation* prev;
    600             Allocation* next;
    601         } m_Committed;
    602 
    603         struct
    604         {
    605             AllocHandle allocHandle;
    606             NormalBlock* block;
    607         } m_Placed;
    608 
    609         struct
    610         {
    611             // Beginning must be compatible with m_Committed.
    612             CommittedAllocationList* list;
    613             Allocation* prev;
    614             Allocation* next;
    615             ID3D12Heap* heap;
    616         } m_Heap;
    617     };
    618 
    619     struct PackedData
    620     {
    621     public:
    622         PackedData() :
    623             m_Type(0), m_ResourceDimension(0), m_ResourceFlags(0), m_TextureLayout(0), m_WasZeroInitialized(0) { }
    624 
    625         Type GetType() const { return (Type)m_Type; }
    626         D3D12_RESOURCE_DIMENSION GetResourceDimension() const { return (D3D12_RESOURCE_DIMENSION)m_ResourceDimension; }
    627         D3D12_RESOURCE_FLAGS GetResourceFlags() const { return (D3D12_RESOURCE_FLAGS)m_ResourceFlags; }
    628         D3D12_TEXTURE_LAYOUT GetTextureLayout() const { return (D3D12_TEXTURE_LAYOUT)m_TextureLayout; }
    629         BOOL WasZeroInitialized() const { return (BOOL)m_WasZeroInitialized; }
    630 
    631         void SetType(Type type);
    632         void SetResourceDimension(D3D12_RESOURCE_DIMENSION resourceDimension);
    633         void SetResourceFlags(D3D12_RESOURCE_FLAGS resourceFlags);
    634         void SetTextureLayout(D3D12_TEXTURE_LAYOUT textureLayout);
    635         void SetWasZeroInitialized(BOOL wasZeroInitialized) { m_WasZeroInitialized = wasZeroInitialized ? 1 : 0; }
    636 
    637     private:
    638         UINT m_Type : 2;               // enum Type
    639         UINT m_ResourceDimension : 3;  // enum D3D12_RESOURCE_DIMENSION
    640         UINT m_ResourceFlags : 24;     // flags D3D12_RESOURCE_FLAGS
    641         UINT m_TextureLayout : 9;      // enum D3D12_TEXTURE_LAYOUT
    642         UINT m_WasZeroInitialized : 1; // BOOL
    643     } m_PackedData;
    644 
    645     Allocation(AllocatorPimpl* allocator, UINT64 size, UINT64 alignment, BOOL wasZeroInitialized);
    646     //  Nothing here, everything already done in Release.
    647     virtual ~Allocation() = default;
    648 
    649     void InitCommitted(CommittedAllocationList* list);
    650     void InitPlaced(AllocHandle allocHandle, NormalBlock* block);
    651     void InitHeap(CommittedAllocationList* list, ID3D12Heap* heap);
    652     void SwapBlockAllocation(Allocation* allocation);
    653     // If the Allocation represents committed resource with implicit heap, returns UINT64_MAX.
    654     AllocHandle GetAllocHandle() const;
    655     NormalBlock* GetBlock();
    656     template<typename D3D12_RESOURCE_DESC_T>
    657     void SetResourcePointer(ID3D12Resource* resource, const D3D12_RESOURCE_DESC_T* pResourceDesc);
    658     void FreeName();
    659 
    660     D3D12MA_CLASS_NO_COPY(Allocation)
    661 };
    662 
    663 
    664 /// Flags to be passed as DEFRAGMENTATION_DESC::Flags.
    665 enum DEFRAGMENTATION_FLAGS
    666 {
    667     /** Use simple but fast algorithm for defragmentation.
    668     May not achieve best results but will require least time to compute and least allocations to copy.
    669     */
    670     DEFRAGMENTATION_FLAG_ALGORITHM_FAST = 0x1,
    671     /** Default defragmentation algorithm, applied also when no `ALGORITHM` flag is specified.
    672     Offers a balance between defragmentation quality and the amount of allocations and bytes that need to be moved.
    673     */
    674     DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED = 0x2,
    675     /** Perform full defragmentation of memory.
    676     Can result in notably more time to compute and allocations to copy, but will achieve best memory packing.
    677     */
    678     DEFRAGMENTATION_FLAG_ALGORITHM_FULL = 0x4,
    679 
    680     /// A bit mask to extract only `ALGORITHM` bits from entire set of flags.
    681     DEFRAGMENTATION_FLAG_ALGORITHM_MASK =
    682         DEFRAGMENTATION_FLAG_ALGORITHM_FAST |
    683         DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED |
    684         DEFRAGMENTATION_FLAG_ALGORITHM_FULL
    685 };
    686 
    687 /** \brief Parameters for defragmentation.
    688 
    689 To be used with functions Allocator::BeginDefragmentation() and Pool::BeginDefragmentation().
    690 */
    691 struct DEFRAGMENTATION_DESC
    692 {
    693     /// Flags.
    694     DEFRAGMENTATION_FLAGS Flags;
    695     /** \brief Maximum numbers of bytes that can be copied during single pass, while moving allocations to different places.
    696 
    697     0 means no limit.
    698     */
    699     UINT64 MaxBytesPerPass;
    700     /** \brief Maximum number of allocations that can be moved during single pass to a different place.
    701 
    702     0 means no limit.
    703     */
    704     UINT32 MaxAllocationsPerPass;
    705 };
    706 
    707 /// Operation performed on single defragmentation move.
    708 enum DEFRAGMENTATION_MOVE_OPERATION
    709 {
    710     /** Resource has been recreated at `pDstTmpAllocation`, data has been copied, old resource has been destroyed.
    711     `pSrcAllocation` will be changed to point to the new place. This is the default value set by DefragmentationContext::BeginPass().
    712     */
    713     DEFRAGMENTATION_MOVE_OPERATION_COPY = 0,
    714     /// Set this value if you cannot move the allocation. New place reserved at `pDstTmpAllocation` will be freed. `pSrcAllocation` will remain unchanged.
    715     DEFRAGMENTATION_MOVE_OPERATION_IGNORE = 1,
    716     /// 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`.
    717     DEFRAGMENTATION_MOVE_OPERATION_DESTROY = 2,
    718 };
    719 
    720 /// Single move of an allocation to be done for defragmentation.
    721 struct DEFRAGMENTATION_MOVE
    722 {
    723     /** \brief Operation to be performed on the allocation by DefragmentationContext::EndPass().
    724     Default value is #DEFRAGMENTATION_MOVE_OPERATION_COPY. You can modify it.
    725     */
    726     DEFRAGMENTATION_MOVE_OPERATION Operation;
    727     /// %Allocation that should be moved.
    728     Allocation* pSrcAllocation;
    729     /** \brief Temporary allocation pointing to destination memory that will replace `pSrcAllocation`.
    730 
    731     Use it to retrieve new `ID3D12Heap` and offset to create new `ID3D12Resource` and then store it here via Allocation::SetResource().
    732 
    733     \warning Do not store this allocation in your data structures! It exists only temporarily, for the duration of the defragmentation pass,
    734     to be used for storing newly created resource. DefragmentationContext::EndPass() will destroy it and make `pSrcAllocation` point to this memory.
    735     */
    736     Allocation* pDstTmpAllocation;
    737 };
    738 
    739 /** \brief Parameters for incremental defragmentation steps.
    740 
    741 To be used with function DefragmentationContext::BeginPass().
    742 */
    743 struct DEFRAGMENTATION_PASS_MOVE_INFO
    744 {
    745     /// Number of elements in the `pMoves` array.
    746     UINT32 MoveCount;
    747     /** \brief Array of moves to be performed by the user in the current defragmentation pass.
    748 
    749     Pointer to an array of `MoveCount` elements, owned by %D3D12MA, created in DefragmentationContext::BeginPass(), destroyed in DefragmentationContext::EndPass().
    750 
    751     For each element, you should:
    752 
    753     1. Create a new resource in the place pointed by `pMoves[i].pDstTmpAllocation->GetHeap()` + `pMoves[i].pDstTmpAllocation->GetOffset()`.
    754     2. Store new resource in `pMoves[i].pDstTmpAllocation` by using Allocation::SetResource(). It will later replace old resource from `pMoves[i].pSrcAllocation`.
    755     3. Copy data from the `pMoves[i].pSrcAllocation` e.g. using `D3D12GraphicsCommandList::CopyResource`.
    756     4. Make sure these commands finished executing on the GPU.
    757 
    758     Only then you can finish defragmentation pass by calling DefragmentationContext::EndPass().
    759     After this call, the allocation will point to the new place in memory.
    760 
    761     Alternatively, if you cannot move specific allocation,
    762     you can set DEFRAGMENTATION_MOVE::Operation to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_IGNORE.
    763 
    764     Alternatively, if you decide you want to completely remove the allocation,
    765     set DEFRAGMENTATION_MOVE::Operation to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_DESTROY.
    766     Then, after DefragmentationContext::EndPass() the allocation will be released.
    767     */
    768     DEFRAGMENTATION_MOVE* pMoves;
    769 };
    770 
    771 /// %Statistics returned for defragmentation process by function DefragmentationContext::GetStats().
    772 struct DEFRAGMENTATION_STATS
    773 {
    774     /// Total number of bytes that have been copied while moving allocations to different places.
    775     UINT64 BytesMoved;
    776     /// Total number of bytes that have been released to the system by freeing empty heaps.
    777     UINT64 BytesFreed;
    778     /// Number of allocations that have been moved to different places.
    779     UINT32 AllocationsMoved;
    780     /// Number of empty `ID3D12Heap` objects that have been released to the system.
    781     UINT32 HeapsFreed;
    782 };
    783 
    784 /** \brief Represents defragmentation process in progress.
    785 
    786 You can create this object using Allocator::BeginDefragmentation (for default pools) or
    787 Pool::BeginDefragmentation (for a custom pool).
    788 */
    789 class D3D12MA_API DefragmentationContext : public IUnknownImpl
    790 {
    791 public:
    792     /** \brief Starts single defragmentation pass.
    793 
    794     \param[out] pPassInfo Computed informations for current pass.
    795     \returns
    796     - `S_OK` if no more moves are possible. Then you can omit call to DefragmentationContext::EndPass() and simply end whole defragmentation.
    797     - `S_FALSE` if there are pending moves returned in `pPassInfo`. You need to perform them, call DefragmentationContext::EndPass(),
    798       and then preferably try another pass with DefragmentationContext::BeginPass().
    799     */
    800     HRESULT BeginPass(DEFRAGMENTATION_PASS_MOVE_INFO* pPassInfo);
    801     /** \brief Ends single defragmentation pass.
    802 
    803     \param pPassInfo Computed informations for current pass filled by DefragmentationContext::BeginPass() and possibly modified by you.
    804     \return Returns `S_OK` if no more moves are possible or `S_FALSE` if more defragmentations are possible.
    805 
    806     Ends incremental defragmentation pass and commits all defragmentation moves from `pPassInfo`.
    807     After this call:
    808 
    809     - %Allocation at `pPassInfo[i].pSrcAllocation` that had `pPassInfo[i].Operation ==` #DEFRAGMENTATION_MOVE_OPERATION_COPY
    810       (which is the default) will be pointing to the new destination place.
    811     - %Allocation at `pPassInfo[i].pSrcAllocation` that had `pPassInfo[i].operation ==` #DEFRAGMENTATION_MOVE_OPERATION_DESTROY
    812       will be released.
    813 
    814     If no more moves are possible you can end whole defragmentation.
    815     */
    816     HRESULT EndPass(DEFRAGMENTATION_PASS_MOVE_INFO* pPassInfo);
    817     /** \brief Returns statistics of the defragmentation performed so far.
    818     */
    819     void GetStats(DEFRAGMENTATION_STATS* pStats);
    820 
    821 protected:
    822     void ReleaseThis() override;
    823 
    824 private:
    825     friend class Pool;
    826     friend class Allocator;
    827     template<typename T> friend void D3D12MA_DELETE(const ALLOCATION_CALLBACKS&, T*);
    828 
    829     DefragmentationContextPimpl* m_Pimpl;
    830 
    831     DefragmentationContext(AllocatorPimpl* allocator,
    832         const DEFRAGMENTATION_DESC& desc,
    833         BlockVector* poolVector);
    834     ~DefragmentationContext();
    835 
    836     D3D12MA_CLASS_NO_COPY(DefragmentationContext)
    837 };
    838 
    839 /// \brief Bit flags to be used with POOL_DESC::Flags.
    840 enum POOL_FLAGS
    841 {
    842     /// Zero
    843     POOL_FLAG_NONE = 0,
    844 
    845     /** \brief Enables alternative, linear allocation algorithm in this pool.
    846 
    847     Specify this flag to enable linear allocation algorithm, which always creates
    848     new allocations after last one and doesn't reuse space from allocations freed in
    849     between. It trades memory consumption for simplified algorithm and data
    850     structure, which has better performance and uses less memory for metadata.
    851 
    852     By using this flag, you can achieve behavior of free-at-once, stack,
    853     ring buffer, and double stack.
    854     For details, see documentation chapter \ref linear_algorithm.
    855     */
    856     POOL_FLAG_ALGORITHM_LINEAR = 0x1,
    857 
    858     /** \brief Optimization, allocate MSAA textures as committed resources always.
    859     
    860     Specify this flag to create MSAA textures with implicit heaps, as if they were created
    861     with flag D3D12MA::ALLOCATION_FLAG_COMMITTED. Usage of this flags enables pool to create its heaps
    862     on smaller alignment not suitable for MSAA textures.
    863     */
    864     POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED = 0x2,
    865 
    866     // Bit mask to extract only `ALGORITHM` bits from entire set of flags.
    867     POOL_FLAG_ALGORITHM_MASK = POOL_FLAG_ALGORITHM_LINEAR
    868 };
    869 
    870 /// \brief Parameters of created D3D12MA::Pool object. To be used with D3D12MA::Allocator::CreatePool.
    871 struct POOL_DESC
    872 {
    873     /// Flags.
    874     POOL_FLAGS Flags;
    875     /** \brief The parameters of memory heap where allocations of this pool should be placed.
    876 
    877     In the simplest case, just fill it with zeros and set `Type` to one of: `D3D12_HEAP_TYPE_DEFAULT`,
    878     `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`. Additional parameters can be used e.g. to utilize UMA.
    879     */
    880     D3D12_HEAP_PROPERTIES HeapProperties;
    881     /** \brief Heap flags to be used when allocating heaps of this pool.
    882 
    883     It should contain one of these values, depending on type of resources you are going to create in this heap:
    884     `D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS`,
    885     `D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES`,
    886     `D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES`.
    887     Except if ResourceHeapTier = 2, then it may be `D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES` = 0.
    888     
    889     You can specify additional flags if needed.
    890     */
    891     D3D12_HEAP_FLAGS HeapFlags;
    892     /** \brief Size of a single heap (memory block) to be allocated as part of this pool, in bytes. Optional.
    893 
    894     Specify nonzero to set explicit, constant size of memory blocks used by this pool.
    895     Leave 0 to use default and let the library manage block sizes automatically.
    896     Then sizes of particular blocks may vary.
    897     */
    898     UINT64 BlockSize;
    899     /** \brief Minimum number of heaps (memory blocks) to be always allocated in this pool, even if they stay empty. Optional.
    900 
    901     Set to 0 to have no preallocated blocks and allow the pool be completely empty.
    902     */
    903     UINT MinBlockCount;
    904     /** \brief Maximum number of heaps (memory blocks) that can be allocated in this pool. Optional.
    905 
    906     Set to 0 to use default, which is `UINT64_MAX`, which means no limit.
    907 
    908     Set to same value as D3D12MA::POOL_DESC::MinBlockCount to have fixed amount of memory allocated
    909     throughout whole lifetime of this pool.
    910     */
    911     UINT MaxBlockCount;
    912     /** \brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0.
    913     
    914     Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two.
    915     */
    916     UINT64 MinAllocationAlignment;
    917     /** \brief Additional parameter allowing pool to create resources with passed protected session.
    918     
    919     If not null then all the heaps and committed resources will be created with this parameter.
    920     Valid only if ID3D12Device4 interface is present in current Windows SDK!
    921     */
    922     ID3D12ProtectedResourceSession* pProtectedSession;
    923     /** \brief Residency priority to be set for all allocations made in this pool. Optional.
    924     
    925     Set this parameter to one of the possible enum values e.g. `D3D12_RESIDENCY_PRIORITY_HIGH`
    926     to apply specific residency priority to all allocations made in this pool:
    927     `ID3D12Heap` memory blocks used to sub-allocate for placed resources, as well as
    928     committed resources or heaps created when D3D12MA::ALLOCATION_FLAG_COMMITTED is used.
    929     This can increase/decrease chance that the memory will be pushed out from VRAM
    930     to system RAM when the system runs out of memory, which is invisible to the developer
    931     using D3D12 API while it can degrade performance.
    932 
    933     Priority is set using function `ID3D12Device1::SetResidencyPriority`.
    934     It is performed only when `ID3D12Device1` interface is defined and successfully obtained.
    935     Otherwise, this parameter is ignored.
    936 
    937     This parameter is optional. If you set it to `D3D12_RESIDENCY_PRIORITY(0)`,
    938     residency priority will not be set for allocations made in this pool.
    939 
    940     There is no equivalent parameter for allocations made in default pools.
    941     If you want to set residency priority for such allocation, you need to do it manually:
    942     allocate with D3D12MA::ALLOCATION_FLAG_COMMITTED and call
    943     `ID3D12Device1::SetResidencyPriority`, passing `allocation->GetResource()`.
    944     */
    945     D3D12_RESIDENCY_PRIORITY ResidencyPriority;
    946 };
    947 
    948 /** \brief Custom memory pool
    949 
    950 Represents a separate set of heaps (memory blocks) that can be used to create
    951 D3D12MA::Allocation-s and resources in it. Usually there is no need to create custom
    952 pools - creating resources in default pool is sufficient.
    953 
    954 To create custom pool, fill D3D12MA::POOL_DESC and call D3D12MA::Allocator::CreatePool.
    955 */
    956 class D3D12MA_API Pool : public IUnknownImpl
    957 {
    958 public:
    959     /** \brief Returns copy of parameters of the pool.
    960 
    961     These are the same parameters as passed to D3D12MA::Allocator::CreatePool.
    962     */
    963     POOL_DESC GetDesc() const;
    964 
    965     /** \brief Retrieves basic statistics of the custom pool that are fast to calculate.
    966 
    967     \param[out] pStats %Statistics of the current pool.
    968     */
    969     void GetStatistics(Statistics* pStats);
    970 
    971     /** \brief Retrieves detailed statistics of the custom pool that are slower to calculate.
    972 
    973     \param[out] pStats %Statistics of the current pool.
    974     */
    975     void CalculateStatistics(DetailedStatistics* pStats);
    976 
    977     /** \brief Associates a name with the pool. This name is for use in debug diagnostics and tools.
    978 
    979     Internal copy of the string is made, so the memory pointed by the argument can be
    980     changed of freed immediately after this call.
    981 
    982     `Name` can be NULL.
    983     */
    984     void SetName(LPCWSTR Name);
    985 
    986     /** \brief Returns the name associated with the pool object.
    987 
    988     Returned string points to an internal copy.
    989 
    990     If no name was associated with the allocation, returns NULL.
    991     */
    992     LPCWSTR GetName() const;
    993 
    994     /** \brief Begins defragmentation process of the current pool.
    995 
    996     \param pDesc Structure filled with parameters of defragmentation.
    997     \param[out] ppContext Context object that will manage defragmentation.
    998     \returns
    999     - `S_OK` if defragmentation can begin.
   1000     - `E_NOINTERFACE` if defragmentation is not supported.
   1001 
   1002     For more information about defragmentation, see documentation chapter:
   1003     [Defragmentation](@ref defragmentation).
   1004     */
   1005     HRESULT BeginDefragmentation(const DEFRAGMENTATION_DESC* pDesc, DefragmentationContext** ppContext);
   1006 
   1007 protected:
   1008     void ReleaseThis() override;
   1009 
   1010 private:
   1011     friend class Allocator;
   1012     friend class AllocatorPimpl;
   1013     template<typename T> friend void D3D12MA_DELETE(const ALLOCATION_CALLBACKS&, T*);
   1014 
   1015     PoolPimpl* m_Pimpl;
   1016 
   1017     Pool(Allocator* allocator, const POOL_DESC &desc);
   1018     ~Pool();
   1019 
   1020     D3D12MA_CLASS_NO_COPY(Pool)
   1021 };
   1022 
   1023 
   1024 /// \brief Bit flags to be used with ALLOCATOR_DESC::Flags.
   1025 enum ALLOCATOR_FLAGS
   1026 {
   1027     /// Zero
   1028     ALLOCATOR_FLAG_NONE = 0,
   1029 
   1030     /**
   1031     Allocator and all objects created from it will not be synchronized internally,
   1032     so you must guarantee they are used from only one thread at a time or
   1033     synchronized by you.
   1034 
   1035     Using this flag may increase performance because internal mutexes are not used.
   1036     */
   1037     ALLOCATOR_FLAG_SINGLETHREADED = 0x1,
   1038 
   1039     /**
   1040     Every allocation will have its own memory block.
   1041     To be used for debugging purposes.
   1042     */
   1043     ALLOCATOR_FLAG_ALWAYS_COMMITTED = 0x2,
   1044 
   1045     /**
   1046     Heaps created for the default pools will be created with flag `D3D12_HEAP_FLAG_CREATE_NOT_ZEROED`,
   1047     allowing for their memory to be not zeroed by the system if possible,
   1048     which can speed up allocation.
   1049 
   1050     Only affects default pools.
   1051     To use the flag with @ref custom_pools, you need to add it manually:
   1052 
   1053     \code
   1054     poolDesc.heapFlags |= D3D12_HEAP_FLAG_CREATE_NOT_ZEROED;
   1055     \endcode
   1056 
   1057     Only avaiable if `ID3D12Device8` is present. Otherwise, the flag is ignored.
   1058     */
   1059     ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED = 0x4,
   1060 
   1061     /** \brief Optimization, allocate MSAA textures as committed resources always.
   1062 
   1063     Specify this flag to create MSAA textures with implicit heaps, as if they were created
   1064     with flag D3D12MA::ALLOCATION_FLAG_COMMITTED. Usage of this flags enables all default pools
   1065     to create its heaps on smaller alignment not suitable for MSAA textures.
   1066     */
   1067     ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED = 0x8,
   1068 };
   1069 
   1070 /// \brief Parameters of created Allocator object. To be used with CreateAllocator().
   1071 struct ALLOCATOR_DESC
   1072 {
   1073     /// Flags.
   1074     ALLOCATOR_FLAGS Flags;
   1075     
   1076     /** Direct3D device object that the allocator should be attached to.
   1077 
   1078     Allocator is doing `AddRef`/`Release` on this object.
   1079     */
   1080     ID3D12Device* pDevice;
   1081     
   1082     /** \brief Preferred size of a single `ID3D12Heap` block to be allocated.
   1083     
   1084     Set to 0 to use default, which is currently 64 MiB.
   1085     */
   1086     UINT64 PreferredBlockSize;
   1087     
   1088     /** \brief Custom CPU memory allocation callbacks. Optional.
   1089 
   1090     Optional, can be null. When specified, will be used for all CPU-side memory allocations.
   1091     */
   1092     const ALLOCATION_CALLBACKS* pAllocationCallbacks;
   1093 
   1094     /** DXGI Adapter object that you use for D3D12 and this allocator.
   1095 
   1096     Allocator is doing `AddRef`/`Release` on this object.
   1097     */
   1098     IDXGIAdapter* pAdapter;
   1099 };
   1100 
   1101 /**
   1102 \brief Represents main object of this library initialized for particular `ID3D12Device`.
   1103 
   1104 Fill structure D3D12MA::ALLOCATOR_DESC and call function CreateAllocator() to create it.
   1105 Call method `Release()` to destroy it.
   1106 
   1107 It is recommended to create just one object of this type per `ID3D12Device` object,
   1108 right after Direct3D 12 is initialized and keep it alive until before Direct3D device is destroyed.
   1109 */
   1110 class D3D12MA_API Allocator : public IUnknownImpl
   1111 {
   1112 public:
   1113     /// Returns cached options retrieved from D3D12 device.
   1114     const D3D12_FEATURE_DATA_D3D12_OPTIONS& GetD3D12Options() const;
   1115     /** \brief Returns true if `D3D12_FEATURE_DATA_ARCHITECTURE1::UMA` was found to be true.
   1116     
   1117     For more information about how to use it, see articles in Microsoft Docs articles:
   1118 
   1119     - "UMA Optimizations: CPU Accessible Textures and Standard Swizzle"
   1120     - "D3D12_FEATURE_DATA_ARCHITECTURE structure (d3d12.h)"
   1121     - "ID3D12Device::GetCustomHeapProperties method (d3d12.h)"
   1122     */
   1123     BOOL IsUMA() const;
   1124     /** \brief Returns true if `D3D12_FEATURE_DATA_ARCHITECTURE1::CacheCoherentUMA` was found to be true.
   1125 
   1126     For more information about how to use it, see articles in Microsoft Docs articles:
   1127 
   1128     - "UMA Optimizations: CPU Accessible Textures and Standard Swizzle"
   1129     - "D3D12_FEATURE_DATA_ARCHITECTURE structure (d3d12.h)"
   1130     - "ID3D12Device::GetCustomHeapProperties method (d3d12.h)"
   1131     */
   1132     BOOL IsCacheCoherentUMA() const;
   1133     /** \brief Returns total amount of memory of specific segment group, in bytes.
   1134     
   1135     \param memorySegmentGroup use `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` or DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL`.
   1136 
   1137     This information is taken from `DXGI_ADAPTER_DESC`.
   1138     It is not recommended to use this number.
   1139     You should preferably call GetBudget() and limit memory usage to D3D12MA::Budget::BudgetBytes instead.
   1140 
   1141     - When IsUMA() `== FALSE` (discrete graphics card):
   1142       - `GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_LOCAL)` returns the size of the video memory.
   1143       - `GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL)` returns the size of the system memory available for D3D12 resources.
   1144     - When IsUMA() `== TRUE` (integrated graphics chip):
   1145       - `GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_LOCAL)` returns the size of the shared memory available for all D3D12 resources.
   1146         All memory is considered "local".
   1147       - `GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL)` is not applicable and returns 0.
   1148     */
   1149     UINT64 GetMemoryCapacity(UINT memorySegmentGroup) const;
   1150 
   1151     /** \brief Allocates memory and creates a D3D12 resource (buffer or texture). This is the main allocation function.
   1152 
   1153     The function is similar to `ID3D12Device::CreateCommittedResource`, but it may
   1154     really call `ID3D12Device::CreatePlacedResource` to assign part of a larger,
   1155     existing memory heap to the new resource, which is the main purpose of this
   1156     whole library.
   1157 
   1158     If `ppvResource` is null, you receive only `ppAllocation` object from this function.
   1159     It holds pointer to `ID3D12Resource` that can be queried using function D3D12MA::Allocation::GetResource().
   1160     Reference count of the resource object is 1.
   1161     It is automatically destroyed when you destroy the allocation object.
   1162 
   1163     If `ppvResource` is not null, you receive pointer to the resource next to allocation object.
   1164     Reference count of the resource object is then increased by calling `QueryInterface`, so you need to manually `Release` it
   1165     along with the allocation.
   1166 
   1167     \param pAllocDesc   Parameters of the allocation.
   1168     \param pResourceDesc   Description of created resource.
   1169     \param InitialResourceState   Initial resource state.
   1170     \param pOptimizedClearValue   Optional. Either null or optimized clear value.
   1171     \param[out] ppAllocation   Filled with pointer to new allocation object created.
   1172     \param riidResource   IID of a resource to be returned via `ppvResource`.
   1173     \param[out] ppvResource   Optional. If not null, filled with pointer to new resouce created.
   1174 
   1175     \note This function creates a new resource. Sub-allocation of parts of one large buffer,
   1176     although recommended as a good practice, is out of scope of this library and could be implemented
   1177     by the user as a higher-level logic on top of it, e.g. using the \ref virtual_allocator feature.
   1178     */
   1179     HRESULT CreateResource(
   1180         const ALLOCATION_DESC* pAllocDesc,
   1181         const D3D12_RESOURCE_DESC* pResourceDesc,
   1182         D3D12_RESOURCE_STATES InitialResourceState,
   1183         const D3D12_CLEAR_VALUE *pOptimizedClearValue,
   1184         Allocation** ppAllocation,
   1185         REFIID riidResource,
   1186         void** ppvResource);
   1187 
   1188 #ifdef __ID3D12Device8_INTERFACE_DEFINED__
   1189     /** \brief Similar to Allocator::CreateResource, but supports new structure `D3D12_RESOURCE_DESC1`.
   1190     
   1191     It internally uses `ID3D12Device8::CreateCommittedResource2` or `ID3D12Device8::CreatePlacedResource1`.
   1192 
   1193     To work correctly, `ID3D12Device8` interface must be available in the current system. Otherwise, `E_NOINTERFACE` is returned.
   1194     */
   1195     HRESULT CreateResource2(
   1196         const ALLOCATION_DESC* pAllocDesc,
   1197         const D3D12_RESOURCE_DESC1* pResourceDesc,
   1198         D3D12_RESOURCE_STATES InitialResourceState,
   1199         const D3D12_CLEAR_VALUE *pOptimizedClearValue,
   1200         Allocation** ppAllocation,
   1201         REFIID riidResource,
   1202         void** ppvResource);
   1203 #endif // #ifdef __ID3D12Device8_INTERFACE_DEFINED__
   1204 
   1205 #ifdef __ID3D12Device10_INTERFACE_DEFINED__
   1206     /** \brief Similar to Allocator::CreateResource2, but there are initial layout instead of state and 
   1207     castable formats list
   1208 
   1209     It internally uses `ID3D12Device10::CreateCommittedResource3` or `ID3D12Device10::CreatePlacedResource2`.
   1210 
   1211     To work correctly, `ID3D12Device10` interface must be available in the current system. Otherwise, `E_NOINTERFACE` is returned.
   1212     */
   1213     HRESULT CreateResource3(const ALLOCATION_DESC* pAllocDesc,
   1214         const D3D12_RESOURCE_DESC1* pResourceDesc,
   1215         D3D12_BARRIER_LAYOUT InitialLayout,
   1216         const D3D12_CLEAR_VALUE* pOptimizedClearValue,
   1217         UINT32 NumCastableFormats,
   1218         DXGI_FORMAT* pCastableFormats,
   1219         Allocation** ppAllocation,
   1220         REFIID riidResource,
   1221         void** ppvResource);
   1222 #endif  // #ifdef __ID3D12Device10_INTERFACE_DEFINED__
   1223 
   1224     /** \brief Allocates memory without creating any resource placed in it.
   1225 
   1226     This function is similar to `ID3D12Device::CreateHeap`, but it may really assign
   1227     part of a larger, existing heap to the allocation.
   1228 
   1229     `pAllocDesc->heapFlags` should contain one of these values, depending on type of resources you are going to create in this memory:
   1230     `D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS`,
   1231     `D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES`,
   1232     `D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES`.
   1233     Except if you validate that ResourceHeapTier = 2 - then `heapFlags`
   1234     may be `D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES` = 0.
   1235     Additional flags in `heapFlags` are allowed as well.
   1236 
   1237     `pAllocInfo->SizeInBytes` must be multiply of 64KB.
   1238     `pAllocInfo->Alignment` must be one of the legal values as described in documentation of `D3D12_HEAP_DESC`.
   1239 
   1240     If you use D3D12MA::ALLOCATION_FLAG_COMMITTED you will get a separate memory block -
   1241     a heap that always has offset 0.
   1242     */
   1243     HRESULT AllocateMemory(
   1244         const ALLOCATION_DESC* pAllocDesc,
   1245         const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
   1246         Allocation** ppAllocation);
   1247 
   1248     /** \brief Creates a new resource in place of an existing allocation. This is useful for memory aliasing.
   1249 
   1250     \param pAllocation Existing allocation indicating the memory where the new resource should be created.
   1251         It can be created using D3D12MA::Allocator::CreateResource and already have a resource bound to it,
   1252         or can be a raw memory allocated with D3D12MA::Allocator::AllocateMemory.
   1253         It must not be created as committed so that `ID3D12Heap` is available and not implicit.
   1254     \param AllocationLocalOffset Additional offset in bytes to be applied when allocating the resource.
   1255         Local from the start of `pAllocation`, not the beginning of the whole `ID3D12Heap`!
   1256         If the new resource should start from the beginning of the `pAllocation` it should be 0.
   1257     \param pResourceDesc Description of the new resource to be created.
   1258     \param InitialResourceState
   1259     \param pOptimizedClearValue
   1260     \param riidResource
   1261     \param[out] ppvResource Returns pointer to the new resource.
   1262         The resource is not bound with `pAllocation`.
   1263         This pointer must not be null - you must get the resource pointer and `Release` it when no longer needed.
   1264 
   1265     Memory requirements of the new resource are checked for validation.
   1266     If its size exceeds the end of `pAllocation` or required alignment is not fulfilled
   1267     considering `pAllocation->GetOffset() + AllocationLocalOffset`, the function
   1268     returns `E_INVALIDARG`.
   1269     */
   1270     HRESULT CreateAliasingResource(
   1271         Allocation* pAllocation,
   1272         UINT64 AllocationLocalOffset,
   1273         const D3D12_RESOURCE_DESC* pResourceDesc,
   1274         D3D12_RESOURCE_STATES InitialResourceState,
   1275         const D3D12_CLEAR_VALUE *pOptimizedClearValue,
   1276         REFIID riidResource,
   1277         void** ppvResource);
   1278 
   1279 #ifdef __ID3D12Device8_INTERFACE_DEFINED__
   1280     /** \brief Similar to Allocator::CreateAliasingResource, but supports new structure `D3D12_RESOURCE_DESC1`.
   1281     
   1282     It internally uses `ID3D12Device8::CreatePlacedResource1`.
   1283 
   1284     To work correctly, `ID3D12Device8` interface must be available in the current system. Otherwise, `E_NOINTERFACE` is returned.
   1285     */
   1286     HRESULT CreateAliasingResource1(Allocation* pAllocation,
   1287         UINT64 AllocationLocalOffset,
   1288         const D3D12_RESOURCE_DESC1* pResourceDesc,
   1289         D3D12_RESOURCE_STATES InitialResourceState,
   1290         const D3D12_CLEAR_VALUE* pOptimizedClearValue,
   1291         REFIID riidResource,
   1292         void** ppvResource);
   1293 #endif // #ifdef __ID3D12Device8_INTERFACE_DEFINED__
   1294 
   1295 #ifdef __ID3D12Device10_INTERFACE_DEFINED__
   1296     /** \brief Similar to Allocator::CreateAliasingResource1, but there are initial layout instead of state and 
   1297     castable formats list
   1298 
   1299     It internally uses `ID3D12Device10::CreatePlacedResource2`.
   1300 
   1301     To work correctly, `ID3D12Device10` interface must be available in the current system. Otherwise, `E_NOINTERFACE` is returned.
   1302     */
   1303     HRESULT CreateAliasingResource2(Allocation* pAllocation,
   1304         UINT64 AllocationLocalOffset,
   1305         const D3D12_RESOURCE_DESC1* pResourceDesc,
   1306         D3D12_BARRIER_LAYOUT InitialLayout,
   1307         const D3D12_CLEAR_VALUE* pOptimizedClearValue,
   1308         UINT32 NumCastableFormats,
   1309         DXGI_FORMAT* pCastableFormats,
   1310         REFIID riidResource,
   1311         void** ppvResource);
   1312 #endif  // #ifdef __ID3D12Device10_INTERFACE_DEFINED__
   1313 
   1314     /** \brief Creates custom pool.
   1315     */
   1316     HRESULT CreatePool(
   1317         const POOL_DESC* pPoolDesc,
   1318         Pool** ppPool);
   1319 
   1320     /** \brief Sets the index of the current frame.
   1321 
   1322     This function is used to set the frame index in the allocator when a new game frame begins.
   1323     */
   1324     void SetCurrentFrameIndex(UINT frameIndex);
   1325 
   1326     /** \brief Retrieves information about current memory usage and budget.
   1327 
   1328     \param[out] pLocalBudget Optional, can be null.
   1329     \param[out] pNonLocalBudget Optional, can be null.
   1330 
   1331     - When IsUMA() `== FALSE` (discrete graphics card):
   1332       - `pLocalBudget` returns the budget of the video memory.
   1333       - `pNonLocalBudget` returns the budget of the system memory available for D3D12 resources.
   1334     - When IsUMA() `== TRUE` (integrated graphics chip):
   1335       - `pLocalBudget` returns the budget of the shared memory available for all D3D12 resources.
   1336          All memory is considered "local".
   1337       - `pNonLocalBudget` is not applicable and returns zeros.
   1338 
   1339     This function is called "get" not "calculate" because it is very fast, suitable to be called
   1340     every frame or every allocation. For more detailed statistics use CalculateStatistics().
   1341 
   1342     Note that when using allocator from multiple threads, returned information may immediately
   1343     become outdated.
   1344     */
   1345     void GetBudget(Budget* pLocalBudget, Budget* pNonLocalBudget);
   1346 
   1347     /** \brief Retrieves statistics from current state of the allocator.
   1348 
   1349     This function is called "calculate" not "get" because it has to traverse all
   1350     internal data structures, so it may be quite slow. Use it for debugging purposes.
   1351     For faster but more brief statistics suitable to be called every frame or every allocation,
   1352     use GetBudget().
   1353 
   1354     Note that when using allocator from multiple threads, returned information may immediately
   1355     become outdated.
   1356     */
   1357     void CalculateStatistics(TotalStatistics* pStats);
   1358 
   1359     /** \brief Builds and returns statistics as a string in JSON format.
   1360     * 
   1361     @param[out] ppStatsString Must be freed using Allocator::FreeStatsString.
   1362     @param DetailedMap `TRUE` to include full list of allocations (can make the string quite long), `FALSE` to only return statistics.
   1363     */
   1364     void BuildStatsString(WCHAR** ppStatsString, BOOL DetailedMap) const;
   1365 
   1366     /// Frees memory of a string returned from Allocator::BuildStatsString.
   1367     void FreeStatsString(WCHAR* pStatsString) const;
   1368 
   1369     /** \brief Begins defragmentation process of the default pools.
   1370 
   1371     \param pDesc Structure filled with parameters of defragmentation.
   1372     \param[out] ppContext Context object that will manage defragmentation.
   1373 
   1374     For more information about defragmentation, see documentation chapter:
   1375     [Defragmentation](@ref defragmentation).
   1376     */
   1377     void BeginDefragmentation(const DEFRAGMENTATION_DESC* pDesc, DefragmentationContext** ppContext);
   1378 
   1379 protected:
   1380     void ReleaseThis() override;
   1381 
   1382 private:
   1383     friend D3D12MA_API HRESULT CreateAllocator(const ALLOCATOR_DESC*, Allocator**);
   1384     template<typename T> friend void D3D12MA_DELETE(const ALLOCATION_CALLBACKS&, T*);
   1385     friend class DefragmentationContext;
   1386     friend class Pool;
   1387 
   1388     Allocator(const ALLOCATION_CALLBACKS& allocationCallbacks, const ALLOCATOR_DESC& desc);
   1389     ~Allocator();
   1390     
   1391     AllocatorPimpl* m_Pimpl;
   1392     
   1393     D3D12MA_CLASS_NO_COPY(Allocator)
   1394 };
   1395 
   1396 
   1397 /// \brief Bit flags to be used with VIRTUAL_BLOCK_DESC::Flags.
   1398 enum VIRTUAL_BLOCK_FLAGS
   1399 {
   1400     /// Zero
   1401     VIRTUAL_BLOCK_FLAG_NONE = 0,
   1402 
   1403     /** \brief Enables alternative, linear allocation algorithm in this virtual block.
   1404 
   1405     Specify this flag to enable linear allocation algorithm, which always creates
   1406     new allocations after last one and doesn't reuse space from allocations freed in
   1407     between. It trades memory consumption for simplified algorithm and data
   1408     structure, which has better performance and uses less memory for metadata.
   1409 
   1410     By using this flag, you can achieve behavior of free-at-once, stack,
   1411     ring buffer, and double stack.
   1412     For details, see documentation chapter \ref linear_algorithm.
   1413     */
   1414     VIRTUAL_BLOCK_FLAG_ALGORITHM_LINEAR = POOL_FLAG_ALGORITHM_LINEAR,
   1415 
   1416     // Bit mask to extract only `ALGORITHM` bits from entire set of flags.
   1417     VIRTUAL_BLOCK_FLAG_ALGORITHM_MASK = POOL_FLAG_ALGORITHM_MASK
   1418 };
   1419 
   1420 /// Parameters of created D3D12MA::VirtualBlock object to be passed to CreateVirtualBlock().
   1421 struct VIRTUAL_BLOCK_DESC
   1422 {
   1423     /// Flags.
   1424     VIRTUAL_BLOCK_FLAGS Flags;
   1425     /** \brief Total size of the block.
   1426 
   1427     Sizes can be expressed in bytes or any units you want as long as you are consistent in using them.
   1428     For example, if you allocate from some array of structures, 1 can mean single instance of entire structure.
   1429     */
   1430     UINT64 Size;
   1431     /** \brief Custom CPU memory allocation callbacks. Optional.
   1432 
   1433     Optional, can be null. When specified, will be used for all CPU-side memory allocations.
   1434     */
   1435     const ALLOCATION_CALLBACKS* pAllocationCallbacks;
   1436 };
   1437 
   1438 /// \brief Bit flags to be used with VIRTUAL_ALLOCATION_DESC::Flags.
   1439 enum VIRTUAL_ALLOCATION_FLAGS
   1440 {
   1441     /// Zero
   1442     VIRTUAL_ALLOCATION_FLAG_NONE = 0,
   1443 
   1444     /** \brief Allocation will be created from upper stack in a double stack pool.
   1445 
   1446     This flag is only allowed for virtual blocks created with #VIRTUAL_BLOCK_FLAG_ALGORITHM_LINEAR flag.
   1447     */
   1448     VIRTUAL_ALLOCATION_FLAG_UPPER_ADDRESS = ALLOCATION_FLAG_UPPER_ADDRESS,
   1449 
   1450     /// Allocation strategy that tries to minimize memory usage.
   1451     VIRTUAL_ALLOCATION_FLAG_STRATEGY_MIN_MEMORY = ALLOCATION_FLAG_STRATEGY_MIN_MEMORY,
   1452     /// Allocation strategy that tries to minimize allocation time.
   1453     VIRTUAL_ALLOCATION_FLAG_STRATEGY_MIN_TIME = ALLOCATION_FLAG_STRATEGY_MIN_TIME,
   1454     /** \brief Allocation strategy that chooses always the lowest offset in available space.
   1455     This is not the most efficient strategy but achieves highly packed data.
   1456     */
   1457     VIRTUAL_ALLOCATION_FLAG_STRATEGY_MIN_OFFSET = ALLOCATION_FLAG_STRATEGY_MIN_OFFSET,
   1458     /** \brief A bit mask to extract only `STRATEGY` bits from entire set of flags.
   1459 
   1460     These strategy flags are binary compatible with equivalent flags in #ALLOCATION_FLAGS.
   1461     */
   1462     VIRTUAL_ALLOCATION_FLAG_STRATEGY_MASK = ALLOCATION_FLAG_STRATEGY_MASK,
   1463 };
   1464 
   1465 /// Parameters of created virtual allocation to be passed to VirtualBlock::Allocate().
   1466 struct VIRTUAL_ALLOCATION_DESC
   1467 {
   1468     /// Flags.
   1469     VIRTUAL_ALLOCATION_FLAGS Flags;
   1470     /** \brief Size of the allocation.
   1471     
   1472     Cannot be zero.
   1473     */
   1474     UINT64 Size;
   1475     /** \brief Required alignment of the allocation.
   1476     
   1477     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.
   1478     */
   1479     UINT64 Alignment;
   1480     /** \brief Custom pointer to be associated with the allocation.
   1481 
   1482     It can be fetched or changed later.
   1483     */
   1484     void* pPrivateData;
   1485 };
   1486 
   1487 /// Parameters of an existing virtual allocation, returned by VirtualBlock::GetAllocationInfo().
   1488 struct VIRTUAL_ALLOCATION_INFO
   1489 {
   1490     /// \brief Offset of the allocation.
   1491     UINT64 Offset;
   1492     /** \brief Size of the allocation.
   1493 
   1494     Same value as passed in VIRTUAL_ALLOCATION_DESC::Size.
   1495     */
   1496     UINT64 Size;
   1497     /** \brief Custom pointer associated with the allocation.
   1498 
   1499     Same value as passed in VIRTUAL_ALLOCATION_DESC::pPrivateData or VirtualBlock::SetAllocationPrivateData().
   1500     */
   1501     void* pPrivateData;
   1502 };
   1503 
   1504 /** \brief Represents pure allocation algorithm and a data structure with allocations in some memory block, without actually allocating any GPU memory.
   1505 
   1506 This class allows to use the core algorithm of the library custom allocations e.g. CPU memory or
   1507 sub-allocation regions inside a single GPU buffer.
   1508 
   1509 To create this object, fill in D3D12MA::VIRTUAL_BLOCK_DESC and call CreateVirtualBlock().
   1510 To destroy it, call its method `VirtualBlock::Release()`.
   1511 You need to free all the allocations within this block or call Clear() before destroying it.
   1512 
   1513 This object is not thread-safe - should not be used from multiple threads simultaneously, must be synchronized externally.
   1514 */
   1515 class D3D12MA_API VirtualBlock : public IUnknownImpl
   1516 {
   1517 public:
   1518     /** \brief Returns true if the block is empty - contains 0 allocations.
   1519     */
   1520     BOOL IsEmpty() const;
   1521     /** \brief Returns information about an allocation - its offset, size and custom pointer.
   1522     */
   1523     void GetAllocationInfo(VirtualAllocation allocation, VIRTUAL_ALLOCATION_INFO* pInfo) const;
   1524 
   1525     /** \brief Creates new allocation.
   1526     \param pDesc
   1527     \param[out] pAllocation Unique indentifier of the new allocation within single block.
   1528     \param[out] pOffset Returned offset of the new allocation. Optional, can be null.
   1529     \return `S_OK` if allocation succeeded, `E_OUTOFMEMORY` if it failed.
   1530 
   1531     If the allocation failed, `pAllocation->AllocHandle` is set to 0 and `pOffset`, if not null, is set to `UINT64_MAX`.
   1532     */
   1533     HRESULT Allocate(const VIRTUAL_ALLOCATION_DESC* pDesc, VirtualAllocation* pAllocation, UINT64* pOffset);
   1534     /** \brief Frees the allocation.
   1535     
   1536     Calling this function with `allocation.AllocHandle == 0` is correct and does nothing.
   1537     */
   1538     void FreeAllocation(VirtualAllocation allocation);
   1539     /** \brief Frees all the allocations.
   1540     */
   1541     void Clear();
   1542     /** \brief Changes custom pointer for an allocation to a new value.
   1543     */
   1544     void SetAllocationPrivateData(VirtualAllocation allocation, void* pPrivateData);
   1545     /** \brief Retrieves basic statistics of the virtual block that are fast to calculate.
   1546 
   1547     \param[out] pStats %Statistics of the virtual block.
   1548     */
   1549     void GetStatistics(Statistics* pStats) const;
   1550     /** \brief Retrieves detailed statistics of the virtual block that are slower to calculate.
   1551 
   1552     \param[out] pStats %Statistics of the virtual block.
   1553     */
   1554     void CalculateStatistics(DetailedStatistics* pStats) const;
   1555 
   1556     /** \brief Builds and returns statistics as a string in JSON format, including the list of allocations with their parameters.
   1557     @param[out] ppStatsString Must be freed using VirtualBlock::FreeStatsString.
   1558     */
   1559     void BuildStatsString(WCHAR** ppStatsString) const;
   1560 
   1561     /** \brief Frees memory of a string returned from VirtualBlock::BuildStatsString.
   1562     */
   1563     void FreeStatsString(WCHAR* pStatsString) const;
   1564    
   1565 protected:
   1566     void ReleaseThis() override;
   1567 
   1568 private:
   1569     friend D3D12MA_API HRESULT CreateVirtualBlock(const VIRTUAL_BLOCK_DESC*, VirtualBlock**);
   1570     template<typename T> friend void D3D12MA_DELETE(const ALLOCATION_CALLBACKS&, T*);
   1571 
   1572     VirtualBlockPimpl* m_Pimpl;
   1573 
   1574     VirtualBlock(const ALLOCATION_CALLBACKS& allocationCallbacks, const VIRTUAL_BLOCK_DESC& desc);
   1575     ~VirtualBlock();
   1576 
   1577     D3D12MA_CLASS_NO_COPY(VirtualBlock)
   1578 };
   1579 
   1580 
   1581 /** \brief Creates new main D3D12MA::Allocator object and returns it through `ppAllocator`.
   1582 
   1583 You normally only need to call it once and keep a single Allocator object for your `ID3D12Device`.
   1584 */
   1585 D3D12MA_API HRESULT CreateAllocator(const ALLOCATOR_DESC* pDesc, Allocator** ppAllocator);
   1586 
   1587 /** \brief Creates new D3D12MA::VirtualBlock object and returns it through `ppVirtualBlock`.
   1588 
   1589 Note you don't need to create D3D12MA::Allocator to use virtual blocks.
   1590 */
   1591 D3D12MA_API HRESULT CreateVirtualBlock(const VIRTUAL_BLOCK_DESC* pDesc, VirtualBlock** ppVirtualBlock);
   1592 
   1593 } // namespace D3D12MA
   1594 
   1595 /// \cond INTERNAL
   1596 DEFINE_ENUM_FLAG_OPERATORS(D3D12MA::ALLOCATION_FLAGS);
   1597 DEFINE_ENUM_FLAG_OPERATORS(D3D12MA::DEFRAGMENTATION_FLAGS);
   1598 DEFINE_ENUM_FLAG_OPERATORS(D3D12MA::ALLOCATOR_FLAGS);
   1599 DEFINE_ENUM_FLAG_OPERATORS(D3D12MA::POOL_FLAGS);
   1600 DEFINE_ENUM_FLAG_OPERATORS(D3D12MA::VIRTUAL_BLOCK_FLAGS);
   1601 DEFINE_ENUM_FLAG_OPERATORS(D3D12MA::VIRTUAL_ALLOCATION_FLAGS);
   1602 /// \endcond
   1603 
   1604 /**
   1605 \page quick_start Quick start
   1606 
   1607 \section quick_start_project_setup Project setup and initialization
   1608 
   1609 This is a small, standalone C++ library. It consists of a pair of 2 files:
   1610 "D3D12MemAlloc.h" header file with public interface and "D3D12MemAlloc.cpp" with
   1611 internal implementation. The only external dependencies are WinAPI, Direct3D 12,
   1612 and parts of C/C++ standard library (but STL containers, exceptions, or RTTI are
   1613 not used).
   1614 
   1615 The library is developed and tested using Microsoft Visual Studio 2019, but it
   1616 should work with other compilers as well. It is designed for 64-bit code.
   1617 
   1618 To use the library in your project:
   1619 
   1620 (1.) Copy files `D3D12MemAlloc.cpp`, `%D3D12MemAlloc.h` to your project.
   1621 
   1622 (2.) Make `D3D12MemAlloc.cpp` compiling as part of the project, as C++ code.
   1623 
   1624 (3.) Include library header in each CPP file that needs to use the library.
   1625 
   1626 \code
   1627 #include "D3D12MemAlloc.h"
   1628 \endcode
   1629 
   1630 (4.) Right after you created `ID3D12Device`, fill D3D12MA::ALLOCATOR_DESC
   1631 structure and call function D3D12MA::CreateAllocator to create the main
   1632 D3D12MA::Allocator object.
   1633 
   1634 Please note that all symbols of the library are declared inside #D3D12MA namespace.
   1635 
   1636 \code
   1637 IDXGIAdapter* adapter = (...)
   1638 ID3D12Device* device = (...)
   1639 
   1640 D3D12MA::ALLOCATOR_DESC allocatorDesc = {};
   1641 allocatorDesc.pDevice = device;
   1642 allocatorDesc.pAdapter = adapter;
   1643 
   1644 D3D12MA::Allocator* allocator;
   1645 HRESULT hr = D3D12MA::CreateAllocator(&allocatorDesc, &allocator);
   1646 \endcode
   1647 
   1648 (5.) Right before destroying the D3D12 device, destroy the allocator object.
   1649 
   1650 Objects of this library must be destroyed by calling `Release` method.
   1651 They are somewhat compatible with COM: they implement `IUnknown` interface with its virtual methods: `AddRef`, `Release`, `QueryInterface`,
   1652 and they are reference-counted internally.
   1653 You can use smart pointers designed for COM with objects of this library - e.g. `CComPtr` or `Microsoft::WRL::ComPtr`.
   1654 The reference counter is thread-safe.
   1655 `QueryInterface` method supports only `IUnknown`, as classes of this library don't define their own GUIDs.
   1656 
   1657 \code
   1658 allocator->Release();
   1659 \endcode
   1660 
   1661 
   1662 \section quick_start_creating_resources Creating resources
   1663 
   1664 To use the library for creating resources (textures and buffers), call method
   1665 D3D12MA::Allocator::CreateResource in the place where you would previously call
   1666 `ID3D12Device::CreateCommittedResource`.
   1667 
   1668 The function has similar syntax, but it expects structure D3D12MA::ALLOCATION_DESC
   1669 to be passed along with `D3D12_RESOURCE_DESC` and other parameters for created
   1670 resource. This structure describes parameters of the desired memory allocation,
   1671 including choice of `D3D12_HEAP_TYPE`.
   1672 
   1673 The function returns a new object of type D3D12MA::Allocation.
   1674 It represents allocated memory and can be queried for size, offset, `ID3D12Heap`.
   1675 It also holds a reference to the `ID3D12Resource`, which can be accessed by calling D3D12MA::Allocation::GetResource().
   1676 
   1677 \code
   1678 D3D12_RESOURCE_DESC resourceDesc = {};
   1679 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
   1680 resourceDesc.Alignment = 0;
   1681 resourceDesc.Width = 1024;
   1682 resourceDesc.Height = 1024;
   1683 resourceDesc.DepthOrArraySize = 1;
   1684 resourceDesc.MipLevels = 1;
   1685 resourceDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
   1686 resourceDesc.SampleDesc.Count = 1;
   1687 resourceDesc.SampleDesc.Quality = 0;
   1688 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
   1689 resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
   1690 
   1691 D3D12MA::ALLOCATION_DESC allocationDesc = {};
   1692 allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
   1693 
   1694 D3D12MA::Allocation* allocation;
   1695 HRESULT hr = allocator->CreateResource(
   1696     &allocationDesc,
   1697     &resourceDesc,
   1698     D3D12_RESOURCE_STATE_COPY_DEST,
   1699     NULL,
   1700     &allocation,
   1701     IID_NULL, NULL);
   1702 
   1703 // Use allocation->GetResource()...
   1704 \endcode
   1705 
   1706 You need to release the allocation object when no longer needed.
   1707 This will also release the D3D12 resource.
   1708 
   1709 \code
   1710 allocation->Release();
   1711 \endcode
   1712 
   1713 The advantage of using the allocator instead of creating committed resource, and
   1714 the main purpose of this library, is that it can decide to allocate bigger memory
   1715 heap internally using `ID3D12Device::CreateHeap` and place multiple resources in
   1716 it, at different offsets, using `ID3D12Device::CreatePlacedResource`. The library
   1717 manages its own collection of allocated memory blocks (heaps) and remembers which
   1718 parts of them are occupied and which parts are free to be used for new resources.
   1719 
   1720 It is important to remember that resources created as placed don't have their memory
   1721 initialized to zeros, but may contain garbage data, so they need to be fully initialized
   1722 before usage, e.g. using Clear (`ClearRenderTargetView`), Discard (`DiscardResource`),
   1723 or copy (`CopyResource`).
   1724 
   1725 The library also automatically handles resource heap tier.
   1726 When `D3D12_FEATURE_DATA_D3D12_OPTIONS::ResourceHeapTier` equals `D3D12_RESOURCE_HEAP_TIER_1`,
   1727 resources of 3 types: buffers, textures that are render targets or depth-stencil,
   1728 and other textures must be kept in separate heaps. When `D3D12_RESOURCE_HEAP_TIER_2`,
   1729 they can be kept together. By using this library, you don't need to handle this
   1730 manually.
   1731 
   1732 
   1733 \section quick_start_resource_reference_counting Resource reference counting
   1734 
   1735 `ID3D12Resource` and other interfaces of Direct3D 12 use COM, so they are reference-counted.
   1736 Objects of this library are reference-counted as well.
   1737 An object of type D3D12MA::Allocation remembers the resource (buffer or texture)
   1738 that was created together with this memory allocation
   1739 and holds a reference to the `ID3D12Resource` object.
   1740 (Note this is a difference to Vulkan Memory Allocator, where a `VmaAllocation` object has no connection
   1741 with the buffer or image that was created with it.)
   1742 Thus, it is important to manage the resource reference counter properly.
   1743 
   1744 <b>The simplest use case</b> is shown in the code snippet above.
   1745 When only D3D12MA::Allocation object is obtained from a function call like D3D12MA::Allocator::CreateResource,
   1746 it remembers the `ID3D12Resource` that was created with it and holds a reference to it.
   1747 The resource can be obtained by calling `allocation->GetResource()`, which doesn't increment the resource
   1748 reference counter.
   1749 Calling `allocation->Release()` will decrease the resource reference counter, which is = 1 in this case,
   1750 so the resource will be released.
   1751 
   1752 <b>Second option</b> is to retrieve a pointer to the resource along with D3D12MA::Allocation.
   1753 Last parameters of the resource creation function can be used for this purpose.
   1754 
   1755 \code
   1756 D3D12MA::Allocation* allocation;
   1757 ID3D12Resource* resource;
   1758 HRESULT hr = allocator->CreateResource(
   1759     &allocationDesc,
   1760     &resourceDesc,
   1761     D3D12_RESOURCE_STATE_COPY_DEST,
   1762     NULL,
   1763     &allocation,
   1764     IID_PPV_ARGS(&resource));
   1765 
   1766 // Use resource...
   1767 \endcode
   1768 
   1769 In this case, returned pointer `resource` is equal to `allocation->GetResource()`,
   1770 but the creation function additionally increases resource reference counter for the purpose of returning it from this call
   1771 (it actually calls `QueryInterface` internally), so the resource will have the counter = 2.
   1772 The resource then need to be released along with the allocation, in this particular order,
   1773 to make sure the resource is destroyed before its memory heap can potentially be freed.
   1774 
   1775 \code
   1776 resource->Release();
   1777 allocation->Release();
   1778 \endcode
   1779 
   1780 <b>More advanced use cases</b> are possible when we consider that an D3D12MA::Allocation object can just hold
   1781 a reference to any resource.
   1782 It can be changed by calling D3D12MA::Allocation::SetResource. This function
   1783 releases the old resource and calls `AddRef` on the new one.
   1784 
   1785 Special care must be taken when performing <b>defragmentation</b>.
   1786 The new resource created at the destination place should be set as `pass.pMoves[i].pDstTmpAllocation->SetResource(newRes)`,
   1787 but it is moved to the source allocation at end of the defragmentation pass,
   1788 while the old resource accessible through `pass.pMoves[i].pSrcAllocation->GetResource()` is then released.
   1789 For more information, see documentation chapter \ref defragmentation.
   1790 
   1791 
   1792 \section quick_start_mapping_memory Mapping memory
   1793 
   1794 The process of getting regular CPU-side pointer to the memory of a resource in
   1795 Direct3D is called "mapping". There are rules and restrictions to this process,
   1796 as described in D3D12 documentation of `ID3D12Resource::Map` method.
   1797 
   1798 Mapping happens on the level of particular resources, not entire memory heaps,
   1799 and so it is out of scope of this library. Just as the documentation of the `Map` function says:
   1800 
   1801 - Returned pointer refers to data of particular subresource, not entire memory heap.
   1802 - You can map same resource multiple times. It is ref-counted internally.
   1803 - Mapping is thread-safe.
   1804 - Unmapping is not required before resource destruction.
   1805 - Unmapping may not be required before using written data - some heap types on
   1806   some platforms support resources persistently mapped.
   1807 
   1808 When using this library, you can map and use your resources normally without
   1809 considering whether they are created as committed resources or placed resources in one large heap.
   1810 
   1811 Example for buffer created and filled in `UPLOAD` heap type:
   1812 
   1813 \code
   1814 const UINT64 bufSize = 65536;
   1815 const float* bufData = (...);
   1816 
   1817 D3D12_RESOURCE_DESC resourceDesc = {};
   1818 resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
   1819 resourceDesc.Alignment = 0;
   1820 resourceDesc.Width = bufSize;
   1821 resourceDesc.Height = 1;
   1822 resourceDesc.DepthOrArraySize = 1;
   1823 resourceDesc.MipLevels = 1;
   1824 resourceDesc.Format = DXGI_FORMAT_UNKNOWN;
   1825 resourceDesc.SampleDesc.Count = 1;
   1826 resourceDesc.SampleDesc.Quality = 0;
   1827 resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
   1828 resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
   1829 
   1830 D3D12MA::ALLOCATION_DESC allocationDesc = {};
   1831 allocationDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
   1832 
   1833 D3D12Resource* resource;
   1834 D3D12MA::Allocation* allocation;
   1835 HRESULT hr = allocator->CreateResource(
   1836     &allocationDesc,
   1837     &resourceDesc,
   1838     D3D12_RESOURCE_STATE_GENERIC_READ,
   1839     NULL,
   1840     &allocation,
   1841     IID_PPV_ARGS(&resource));
   1842 
   1843 void* mappedPtr;
   1844 hr = resource->Map(0, NULL, &mappedPtr);
   1845 
   1846 memcpy(mappedPtr, bufData, bufSize);
   1847 
   1848 resource->Unmap(0, NULL);
   1849 \endcode
   1850 
   1851 
   1852 \page custom_pools Custom memory pools
   1853 
   1854 A "pool" is a collection of memory blocks that share certain properties.
   1855 Allocator creates 3 default pools: for `D3D12_HEAP_TYPE_DEFAULT`, `UPLOAD`, `READBACK`.
   1856 A default pool automatically grows in size. Size of allocated blocks is also variable and managed automatically.
   1857 Typical allocations are created in these pools. You can also create custom pools.
   1858 
   1859 \section custom_pools_usage Usage
   1860 
   1861 To create a custom pool, fill in structure D3D12MA::POOL_DESC and call function D3D12MA::Allocator::CreatePool
   1862 to obtain object D3D12MA::Pool. Example:
   1863 
   1864 \code
   1865 POOL_DESC poolDesc = {};
   1866 poolDesc.HeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
   1867 
   1868 Pool* pool;
   1869 HRESULT hr = allocator->CreatePool(&poolDesc, &pool);
   1870 \endcode
   1871 
   1872 To allocate resources out of a custom pool, only set member D3D12MA::ALLOCATION_DESC::CustomPool.
   1873 Example:
   1874 
   1875 \code
   1876 ALLOCATION_DESC allocDesc = {};
   1877 allocDesc.CustomPool = pool;
   1878 
   1879 D3D12_RESOURCE_DESC resDesc = ...
   1880 Allocation* alloc;
   1881 hr = allocator->CreateResource(&allocDesc, &resDesc,
   1882     D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &alloc, IID_NULL, NULL);
   1883 \endcode
   1884 
   1885 All allocations must be released before releasing the pool.
   1886 The pool must be released before relasing the allocator.
   1887 
   1888 \code
   1889 alloc->Release();
   1890 pool->Release();
   1891 \endcode
   1892 
   1893 \section custom_pools_features_and_benefits Features and benefits
   1894 
   1895 While it is recommended to use default pools whenever possible for simplicity and to give the allocator
   1896 more opportunities for internal optimizations, custom pools may be useful in following cases:
   1897 
   1898 - To keep some resources separate from others in memory.
   1899 - To keep track of memory usage of just a specific group of resources. %Statistics can be queried using
   1900   D3D12MA::Pool::CalculateStatistics.
   1901 - To use specific size of a memory block (`ID3D12Heap`). To set it, use member D3D12MA::POOL_DESC::BlockSize.
   1902   When set to 0, the library uses automatically determined, variable block sizes.
   1903 - To reserve some minimum amount of memory allocated. To use it, set member D3D12MA::POOL_DESC::MinBlockCount.
   1904 - To limit maximum amount of memory allocated. To use it, set member D3D12MA::POOL_DESC::MaxBlockCount.
   1905 - To use extended parameters of the D3D12 memory allocation. While resources created from default pools
   1906   can only specify `D3D12_HEAP_TYPE_DEFAULT`, `UPLOAD`, `READBACK`, a custom pool may use non-standard
   1907   `D3D12_HEAP_PROPERTIES` (member D3D12MA::POOL_DESC::HeapProperties) and `D3D12_HEAP_FLAGS`
   1908   (D3D12MA::POOL_DESC::HeapFlags), which is useful e.g. for cross-adapter sharing or UMA
   1909   (see also D3D12MA::Allocator::IsUMA).
   1910 
   1911 New versions of this library support creating **committed allocations in custom pools**.
   1912 It is supported only when D3D12MA::POOL_DESC::BlockSize = 0.
   1913 To use this feature, set D3D12MA::ALLOCATION_DESC::CustomPool to the pointer to your custom pool and
   1914 D3D12MA::ALLOCATION_DESC::Flags to D3D12MA::ALLOCATION_FLAG_COMMITTED. Example:
   1915 
   1916 \code
   1917 ALLOCATION_DESC allocDesc = {};
   1918 allocDesc.CustomPool = pool;
   1919 allocDesc.Flags = ALLOCATION_FLAG_COMMITTED;
   1920 
   1921 D3D12_RESOURCE_DESC resDesc = ...
   1922 Allocation* alloc;
   1923 ID3D12Resource* res;
   1924 hr = allocator->CreateResource(&allocDesc, &resDesc,
   1925     D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &alloc, IID_PPV_ARGS(&res));
   1926 \endcode
   1927 
   1928 This feature may seem unnecessary, but creating committed allocations from custom pools may be useful
   1929 in some cases, e.g. to have separate memory usage statistics for some group of resources or to use
   1930 extended allocation parameters, like custom `D3D12_HEAP_PROPERTIES`, which are available only in custom pools.
   1931 
   1932 
   1933 \page defragmentation Defragmentation
   1934 
   1935 Interleaved allocations and deallocations of many objects of varying size can
   1936 cause fragmentation over time, which can lead to a situation where the library is unable
   1937 to find a continuous range of free memory for a new allocation despite there is
   1938 enough free space, just scattered across many small free ranges between existing
   1939 allocations.
   1940 
   1941 To mitigate this problem, you can use defragmentation feature.
   1942 It doesn't happen automatically though and needs your cooperation,
   1943 because %D3D12MA is a low level library that only allocates memory.
   1944 It cannot recreate buffers and textures in a new place as it doesn't remember the contents of `D3D12_RESOURCE_DESC` structure.
   1945 It cannot copy their contents as it doesn't record any commands to a command list.
   1946 
   1947 Example:
   1948 
   1949 \code
   1950 D3D12MA::DEFRAGMENTATION_DESC defragDesc = {};
   1951 defragDesc.Flags = D3D12MA::DEFRAGMENTATION_FLAG_ALGORITHM_FAST;
   1952 
   1953 D3D12MA::DefragmentationContext* defragCtx;
   1954 allocator->BeginDefragmentation(&defragDesc, &defragCtx);
   1955 
   1956 for(;;)
   1957 {
   1958     D3D12MA::DEFRAGMENTATION_PASS_MOVE_INFO pass;
   1959     HRESULT hr = defragCtx->BeginPass(&pass);
   1960     if(hr == S_OK)
   1961         break;
   1962     else if(hr != S_FALSE)
   1963         // Handle error...
   1964 
   1965     for(UINT i = 0; i < pass.MoveCount; ++i)
   1966     {
   1967         // Inspect pass.pMoves[i].pSrcAllocation, identify what buffer/texture it represents.
   1968         MyEngineResourceData* resData = (MyEngineResourceData*)pMoves[i].pSrcAllocation->GetPrivateData();
   1969             
   1970         // Recreate this buffer/texture as placed at pass.pMoves[i].pDstTmpAllocation.
   1971         D3D12_RESOURCE_DESC resDesc = ...
   1972         ID3D12Resource* newRes;
   1973         hr = device->CreatePlacedResource(
   1974             pass.pMoves[i].pDstTmpAllocation->GetHeap(),
   1975             pass.pMoves[i].pDstTmpAllocation->GetOffset(), &resDesc,
   1976             D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&newRes));
   1977         // Check hr...
   1978 
   1979         // Store new resource in the pDstTmpAllocation.
   1980         pass.pMoves[i].pDstTmpAllocation->SetResource(newRes);
   1981 
   1982         // Copy its content to the new place.
   1983         cmdList->CopyResource(
   1984             pass.pMoves[i].pDstTmpAllocation->GetResource(),
   1985             pass.pMoves[i].pSrcAllocation->GetResource());
   1986     }
   1987         
   1988     // Make sure the copy commands finished executing.
   1989     cmdQueue->ExecuteCommandLists(...);
   1990     // ...
   1991     WaitForSingleObject(fenceEvent, INFINITE);
   1992 
   1993     // Update appropriate descriptors to point to the new places...
   1994         
   1995     hr = defragCtx->EndPass(&pass);
   1996     if(hr == S_OK)
   1997         break;
   1998     else if(hr != S_FALSE)
   1999         // Handle error...
   2000 }
   2001 
   2002 defragCtx->Release();
   2003 \endcode
   2004 
   2005 Although functions like D3D12MA::Allocator::CreateResource()
   2006 create an allocation and a buffer/texture at once, these are just a shortcut for
   2007 allocating memory and creating a placed resource.
   2008 Defragmentation works on memory allocations only. You must handle the rest manually.
   2009 Defragmentation is an iterative process that should repreat "passes" as long as related functions
   2010 return `S_FALSE` not `S_OK`.
   2011 In each pass:
   2012 
   2013 1. D3D12MA::DefragmentationContext::BeginPass() function call:
   2014    - Calculates and returns the list of allocations to be moved in this pass.
   2015      Note this can be a time-consuming process.
   2016    - Reserves destination memory for them by creating temporary destination allocations
   2017      that you can query for their `ID3D12Heap` + offset using methods like D3D12MA::Allocation::GetHeap().
   2018 2. Inside the pass, **you should**:
   2019    - Inspect the returned list of allocations to be moved.
   2020    - Create new buffers/textures as placed at the returned destination temporary allocations.
   2021    - Copy data from source to destination resources if necessary.
   2022    - Store the pointer to the new resource in the temporary destination allocation.
   2023 3. D3D12MA::DefragmentationContext::EndPass() function call:
   2024    - Frees the source memory reserved for the allocations that are moved.
   2025    - Modifies source D3D12MA::Allocation objects that are moved to point to the destination reserved memory
   2026      and destination resource, while source resource is released.
   2027    - Frees `ID3D12Heap` blocks that became empty.
   2028 
   2029 Defragmentation algorithm tries to move all suitable allocations.
   2030 You can, however, refuse to move some of them inside a defragmentation pass, by setting
   2031 `pass.pMoves[i].Operation` to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_IGNORE.
   2032 This is not recommended and may result in suboptimal packing of the allocations after defragmentation.
   2033 If you cannot ensure any allocation can be moved, it is better to keep movable allocations separate in a custom pool.
   2034 
   2035 Inside a pass, for each allocation that should be moved:
   2036 
   2037 - You should copy its data from the source to the destination place by calling e.g. `CopyResource()`.
   2038   - You need to make sure these commands finished executing before the source buffers/textures are released by D3D12MA::DefragmentationContext::EndPass().
   2039 - If a resource doesn't contain any meaningful data, e.g. it is a transient render-target texture to be cleared,
   2040   filled, and used temporarily in each rendering frame, you can just recreate this texture
   2041   without copying its data.
   2042 - If the resource is in `D3D12_HEAP_TYPE_READBACK` memory, you can copy its data on the CPU
   2043   using `memcpy()`.
   2044 - If you cannot move the allocation, you can set `pass.pMoves[i].Operation` to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_IGNORE.
   2045   This will cancel the move.
   2046   - D3D12MA::DefragmentationContext::EndPass() will then free the destination memory
   2047     not the source memory of the allocation, leaving it unchanged.
   2048 - If you decide the allocation is unimportant and can be destroyed instead of moved (e.g. it wasn't used for long time),
   2049   you can set `pass.pMoves[i].Operation` to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_DESTROY.
   2050   - D3D12MA::DefragmentationContext::EndPass() will then free both source and destination memory, and will destroy the source D3D12MA::Allocation object.
   2051 
   2052 You can defragment a specific custom pool by calling D3D12MA::Pool::BeginDefragmentation
   2053 or all the default pools by calling D3D12MA::Allocator::BeginDefragmentation (like in the example above).
   2054 
   2055 Defragmentation is always performed in each pool separately.
   2056 Allocations are never moved between different heap types.
   2057 The size of the destination memory reserved for a moved allocation is the same as the original one.
   2058 Alignment of an allocation as it was determined using `GetResourceAllocationInfo()` is also respected after defragmentation.
   2059 Buffers/textures should be recreated with the same `D3D12_RESOURCE_DESC` parameters as the original ones.
   2060 
   2061 You can perform the defragmentation incrementally to limit the number of allocations and bytes to be moved
   2062 in each pass, e.g. to call it in sync with render frames and not to experience too big hitches.
   2063 See members: D3D12MA::DEFRAGMENTATION_DESC::MaxBytesPerPass, D3D12MA::DEFRAGMENTATION_DESC::MaxAllocationsPerPass.
   2064 
   2065 <b>Thread safety:</b>
   2066 It is safe to perform the defragmentation asynchronously to render frames and other Direct3D 12 and %D3D12MA
   2067 usage, possibly from multiple threads, with the exception that allocations
   2068 returned in D3D12MA::DEFRAGMENTATION_PASS_MOVE_INFO::pMoves shouldn't be released until the defragmentation pass is ended.
   2069 During the call to D3D12MA::DefragmentationContext::BeginPass(), any operations on the memory pool
   2070 affected by the defragmentation are blocked by a mutex.
   2071 
   2072 What it means in practice is that you shouldn't free any allocations from the defragmented pool
   2073 since the moment a call to `BeginPass` begins. Otherwise, a thread performing the `allocation->Release()`
   2074 would block for the time `BeginPass` executes and then free the allocation when it finishes, while the allocation
   2075 could have ended up on the list of allocations to move.
   2076 A solution to freeing allocations during defragmentation is to find such allocation on the list
   2077 `pass.pMoves[i]` and set its operation to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_DESTROY instead of
   2078 calling `allocation->Release()`, or simply deferring the release to the time after defragmentation finished.
   2079 
   2080 <b>Mapping</b> is out of scope of this library and so it is not preserved after an allocation is moved during defragmentation.
   2081 You need to map the new resource yourself if needed.
   2082 
   2083 \note Defragmentation is not supported in custom pools created with D3D12MA::POOL_FLAG_ALGORITHM_LINEAR.
   2084 
   2085 
   2086 \page statistics Statistics
   2087 
   2088 This library contains several functions that return information about its internal state,
   2089 especially the amount of memory allocated from D3D12.
   2090 
   2091 \section statistics_numeric_statistics Numeric statistics
   2092 
   2093 If you need to obtain basic statistics about memory usage per memory segment group, together with current budget,
   2094 you can call function D3D12MA::Allocator::GetBudget() and inspect structure D3D12MA::Budget.
   2095 This is useful to keep track of memory usage and stay withing budget.
   2096 Example:
   2097 
   2098 \code
   2099 D3D12MA::Budget localBudget;
   2100 allocator->GetBudget(&localBudget, NULL);
   2101 
   2102 printf("My GPU memory currently has %u allocations taking %llu B,\n",
   2103     localBudget.Statistics.AllocationCount,
   2104     localBudget.Statistics.AllocationBytes);
   2105 printf("allocated out of %u D3D12 memory heaps taking %llu B,\n",
   2106     localBudget.Statistics.BlockCount,
   2107     localBudget.Statistics.BlockBytes);
   2108 printf("D3D12 reports total usage %llu B with budget %llu B.\n",
   2109     localBudget.UsageBytes,
   2110     localBudget.BudgetBytes);
   2111 \endcode
   2112 
   2113 You can query for more detailed statistics per heap type, memory segment group, and totals,
   2114 including minimum and maximum allocation size and unused range size,
   2115 by calling function D3D12MA::Allocator::CalculateStatistics() and inspecting structure D3D12MA::TotalStatistics.
   2116 This function is slower though, as it has to traverse all the internal data structures,
   2117 so it should be used only for debugging purposes.
   2118 
   2119 You can query for statistics of a custom pool using function D3D12MA::Pool::GetStatistics()
   2120 or D3D12MA::Pool::CalculateStatistics().
   2121 
   2122 You can query for information about a specific allocation using functions of the D3D12MA::Allocation class,
   2123 e.g. `GetSize()`, `GetOffset()`, `GetHeap()`.
   2124 
   2125 \section statistics_json_dump JSON dump
   2126 
   2127 You can dump internal state of the allocator to a string in JSON format using function D3D12MA::Allocator::BuildStatsString().
   2128 The result is guaranteed to be correct JSON.
   2129 It uses Windows Unicode (UTF-16) encoding.
   2130 Any strings provided by user (see D3D12MA::Allocation::SetName())
   2131 are copied as-is and properly escaped for JSON.
   2132 It must be freed using function D3D12MA::Allocator::FreeStatsString().
   2133 
   2134 The format of this JSON string is not part of official documentation of the library,
   2135 but it will not change in backward-incompatible way without increasing library major version number
   2136 and appropriate mention in changelog.
   2137 
   2138 The JSON string contains all the data that can be obtained using D3D12MA::Allocator::CalculateStatistics().
   2139 It can also contain detailed map of allocated memory blocks and their regions -
   2140 free and occupied by allocations.
   2141 This allows e.g. to visualize the memory or assess fragmentation.
   2142 
   2143 
   2144 \page resource_aliasing Resource aliasing (overlap)
   2145 
   2146 New explicit graphics APIs (Vulkan and Direct3D 12), thanks to manual memory
   2147 management, give an opportunity to alias (overlap) multiple resources in the
   2148 same region of memory - a feature not available in the old APIs (Direct3D 11, OpenGL).
   2149 It can be useful to save video memory, but it must be used with caution.
   2150 
   2151 For example, if you know the flow of your whole render frame in advance, you
   2152 are going to use some intermediate textures or buffers only during a small range of render passes,
   2153 and you know these ranges don't overlap in time, you can create these resources in
   2154 the same place in memory, even if they have completely different parameters (width, height, format etc.).
   2155 
   2156 ![Resource aliasing (overlap)](../gfx/Aliasing.png)
   2157 
   2158 Such scenario is possible using D3D12MA, but you need to create your resources
   2159 using special function D3D12MA::Allocator::CreateAliasingResource.
   2160 Before that, you need to allocate memory with parameters calculated using formula:
   2161 
   2162 - allocation size = max(size of each resource)
   2163 - allocation alignment = max(alignment of each resource)
   2164 
   2165 Following example shows two different textures created in the same place in memory,
   2166 allocated to fit largest of them.
   2167 
   2168 \code
   2169 D3D12_RESOURCE_DESC resDesc1 = {};
   2170 resDesc1.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
   2171 resDesc1.Alignment = 0;
   2172 resDesc1.Width = 1920;
   2173 resDesc1.Height = 1080;
   2174 resDesc1.DepthOrArraySize = 1;
   2175 resDesc1.MipLevels = 1;
   2176 resDesc1.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
   2177 resDesc1.SampleDesc.Count = 1;
   2178 resDesc1.SampleDesc.Quality = 0;
   2179 resDesc1.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
   2180 resDesc1.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
   2181 
   2182 D3D12_RESOURCE_DESC resDesc2 = {};
   2183 resDesc2.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
   2184 resDesc2.Alignment = 0;
   2185 resDesc2.Width = 1024;
   2186 resDesc2.Height = 1024;
   2187 resDesc2.DepthOrArraySize = 1;
   2188 resDesc2.MipLevels = 0;
   2189 resDesc2.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
   2190 resDesc2.SampleDesc.Count = 1;
   2191 resDesc2.SampleDesc.Quality = 0;
   2192 resDesc2.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
   2193 resDesc2.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
   2194 
   2195 const D3D12_RESOURCE_ALLOCATION_INFO allocInfo1 =
   2196     device->GetResourceAllocationInfo(0, 1, &resDesc1);
   2197 const D3D12_RESOURCE_ALLOCATION_INFO allocInfo2 =
   2198     device->GetResourceAllocationInfo(0, 1, &resDesc2);
   2199 
   2200 D3D12_RESOURCE_ALLOCATION_INFO finalAllocInfo = {};
   2201 finalAllocInfo.Alignment = std::max(allocInfo1.Alignment, allocInfo2.Alignment);
   2202 finalAllocInfo.SizeInBytes = std::max(allocInfo1.SizeInBytes, allocInfo2.SizeInBytes);
   2203 
   2204 D3D12MA::ALLOCATION_DESC allocDesc = {};
   2205 allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
   2206 allocDesc.ExtraHeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES;
   2207 
   2208 D3D12MA::Allocation* alloc;
   2209 hr = allocator->AllocateMemory(&allocDesc, &finalAllocInfo, &alloc);
   2210 assert(alloc != NULL && alloc->GetHeap() != NULL);
   2211 
   2212 ID3D12Resource* res1;
   2213 hr = allocator->CreateAliasingResource(
   2214     alloc,
   2215     0, // AllocationLocalOffset
   2216     &resDesc1,
   2217     D3D12_RESOURCE_STATE_COMMON,
   2218     NULL, // pOptimizedClearValue
   2219     IID_PPV_ARGS(&res1));
   2220 
   2221 ID3D12Resource* res2;
   2222 hr = allocator->CreateAliasingResource(
   2223     alloc,
   2224     0, // AllocationLocalOffset
   2225     &resDesc2,
   2226     D3D12_RESOURCE_STATE_COMMON,
   2227     NULL, // pOptimizedClearValue
   2228     IID_PPV_ARGS(&res2));
   2229 
   2230 // You can use res1 and res2, but not at the same time!
   2231 
   2232 res2->Release();
   2233 res1->Release();
   2234 alloc->Release();
   2235 \endcode
   2236 
   2237 Remember that using resouces that alias in memory requires proper synchronization.
   2238 You need to issue a special barrier of type `D3D12_RESOURCE_BARRIER_TYPE_ALIASING`.
   2239 You also need to treat a resource after aliasing as uninitialized - containing garbage data.
   2240 For example, if you use `res1` and then want to use `res2`, you need to first initialize `res2`
   2241 using either Clear, Discard, or Copy to the entire resource.
   2242 
   2243 Additional considerations:
   2244 
   2245 - D3D12 also allows to interpret contents of memory between aliasing resources consistently in some cases,
   2246   which is called "data inheritance". For details, see
   2247   Microsoft documentation chapter "Memory Aliasing and Data Inheritance".
   2248 - You can create more complex layout where different textures and buffers are bound
   2249   at different offsets inside one large allocation. For example, one can imagine
   2250   a big texture used in some render passes, aliasing with a set of many small buffers
   2251   used in some further passes. To bind a resource at non-zero offset of an allocation,
   2252   call D3D12MA::Allocator::CreateAliasingResource with appropriate value of `AllocationLocalOffset` parameter.
   2253 - Resources of the three categories: buffers, textures with `RENDER_TARGET` or `DEPTH_STENCIL` flags, and all other textures,
   2254   can be placed in the same memory only when `allocator->GetD3D12Options().ResourceHeapTier >= D3D12_RESOURCE_HEAP_TIER_2`.
   2255   Otherwise they must be placed in different memory heap types, and thus aliasing them is not possible.
   2256 
   2257 
   2258 \page linear_algorithm Linear allocation algorithm
   2259 
   2260 Each D3D12 memory block managed by this library has accompanying metadata that
   2261 keeps track of used and unused regions. By default, the metadata structure and
   2262 algorithm tries to find best place for new allocations among free regions to
   2263 optimize memory usage. This way you can allocate and free objects in any order.
   2264 
   2265 ![Default allocation algorithm](../gfx/Linear_allocator_1_algo_default.png)
   2266 
   2267 Sometimes there is a need to use simpler, linear allocation algorithm. You can
   2268 create custom pool that uses such algorithm by adding flag
   2269 D3D12MA::POOL_FLAG_ALGORITHM_LINEAR to D3D12MA::POOL_DESC::Flags while creating
   2270 D3D12MA::Pool object. Then an alternative metadata management is used. It always
   2271 creates new allocations after last one and doesn't reuse free regions after
   2272 allocations freed in the middle. It results in better allocation performance and
   2273 less memory consumed by metadata.
   2274 
   2275 ![Linear allocation algorithm](../gfx/Linear_allocator_2_algo_linear.png)
   2276 
   2277 With this one flag, you can create a custom pool that can be used in many ways:
   2278 free-at-once, stack, double stack, and ring buffer. See below for details.
   2279 You don't need to specify explicitly which of these options you are going to use - it is detected automatically.
   2280 
   2281 \section linear_algorithm_free_at_once Free-at-once
   2282 
   2283 In a pool that uses linear algorithm, you still need to free all the allocations
   2284 individually by calling `allocation->Release()`. You can free
   2285 them in any order. New allocations are always made after last one - free space
   2286 in the middle is not reused. However, when you release all the allocation and
   2287 the pool becomes empty, allocation starts from the beginning again. This way you
   2288 can use linear algorithm to speed up creation of allocations that you are going
   2289 to release all at once.
   2290 
   2291 ![Free-at-once](../gfx/Linear_allocator_3_free_at_once.png)
   2292 
   2293 This mode is also available for pools created with D3D12MA::POOL_DESC::MaxBlockCount
   2294 value that allows multiple memory blocks.
   2295 
   2296 \section linear_algorithm_stack Stack
   2297 
   2298 When you free an allocation that was created last, its space can be reused.
   2299 Thanks to this, if you always release allocations in the order opposite to their
   2300 creation (LIFO - Last In First Out), you can achieve behavior of a stack.
   2301 
   2302 ![Stack](../gfx/Linear_allocator_4_stack.png)
   2303 
   2304 This mode is also available for pools created with D3D12MA::POOL_DESC::MaxBlockCount
   2305 value that allows multiple memory blocks.
   2306 
   2307 \section linear_algorithm_double_stack Double stack
   2308 
   2309 The space reserved by a custom pool with linear algorithm may be used by two
   2310 stacks:
   2311 
   2312 - First, default one, growing up from offset 0.
   2313 - Second, "upper" one, growing down from the end towards lower offsets.
   2314 
   2315 To make allocation from the upper stack, add flag D3D12MA::ALLOCATION_FLAG_UPPER_ADDRESS
   2316 to D3D12MA::ALLOCATION_DESC::Flags.
   2317 
   2318 ![Double stack](../gfx/Linear_allocator_7_double_stack.png)
   2319 
   2320 Double stack is available only in pools with one memory block -
   2321 D3D12MA::POOL_DESC::MaxBlockCount must be 1. Otherwise behavior is undefined.
   2322 
   2323 When the two stacks' ends meet so there is not enough space between them for a
   2324 new allocation, such allocation fails with usual `E_OUTOFMEMORY` error.
   2325 
   2326 \section linear_algorithm_ring_buffer Ring buffer
   2327 
   2328 When you free some allocations from the beginning and there is not enough free space
   2329 for a new one at the end of a pool, allocator's "cursor" wraps around to the
   2330 beginning and starts allocation there. Thanks to this, if you always release
   2331 allocations in the same order as you created them (FIFO - First In First Out),
   2332 you can achieve behavior of a ring buffer / queue.
   2333 
   2334 ![Ring buffer](../gfx/Linear_allocator_5_ring_buffer.png)
   2335 
   2336 Ring buffer is available only in pools with one memory block -
   2337 D3D12MA::POOL_DESC::MaxBlockCount must be 1. Otherwise behavior is undefined.
   2338 
   2339 \section linear_algorithm_additional_considerations Additional considerations
   2340 
   2341 Linear algorithm can also be used with \ref virtual_allocator.
   2342 See flag D3D12MA::VIRTUAL_BLOCK_FLAG_ALGORITHM_LINEAR.
   2343 
   2344 
   2345 \page virtual_allocator Virtual allocator
   2346 
   2347 As an extra feature, the core allocation algorithm of the library is exposed through a simple and convenient API of "virtual allocator".
   2348 It doesn't allocate any real GPU memory. It just keeps track of used and free regions of a "virtual block".
   2349 You can use it to allocate your own memory or other objects, even completely unrelated to D3D12.
   2350 A common use case is sub-allocation of pieces of one large GPU buffer.
   2351 
   2352 \section virtual_allocator_creating_virtual_block Creating virtual block
   2353 
   2354 To use this functionality, there is no main "allocator" object.
   2355 You don't need to have D3D12MA::Allocator object created.
   2356 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:
   2357 
   2358 -# Fill in D3D12MA::ALLOCATOR_DESC structure.
   2359 -# Call D3D12MA::CreateVirtualBlock. Get new D3D12MA::VirtualBlock object.
   2360 
   2361 Example:
   2362 
   2363 \code
   2364 D3D12MA::VIRTUAL_BLOCK_DESC blockDesc = {};
   2365 blockDesc.Size = 1048576; // 1 MB
   2366 
   2367 D3D12MA::VirtualBlock *block;
   2368 HRESULT hr = CreateVirtualBlock(&blockDesc, &block);
   2369 \endcode
   2370 
   2371 \section virtual_allocator_making_virtual_allocations Making virtual allocations
   2372 
   2373 D3D12MA::VirtualBlock object contains internal data structure that keeps track of free and occupied regions
   2374 using the same code as the main D3D12 memory allocator.
   2375 A single allocation is identified by a lightweight structure D3D12MA::VirtualAllocation.
   2376 You will also likely want to know the offset at which the allocation was made in the block.
   2377 
   2378 In order to make an allocation:
   2379 
   2380 -# Fill in D3D12MA::VIRTUAL_ALLOCATION_DESC structure.
   2381 -# Call D3D12MA::VirtualBlock::Allocate. Get new D3D12MA::VirtualAllocation value that identifies the allocation.
   2382 
   2383 Example:
   2384 
   2385 \code
   2386 D3D12MA::VIRTUAL_ALLOCATION_DESC allocDesc = {};
   2387 allocDesc.Size = 4096; // 4 KB
   2388 
   2389 D3D12MA::VirtualAllocation alloc;
   2390 UINT64 allocOffset;
   2391 hr = block->Allocate(&allocDesc, &alloc, &allocOffset);
   2392 if(SUCCEEDED(hr))
   2393 {
   2394     // Use the 4 KB of your memory starting at allocOffset.
   2395 }
   2396 else
   2397 {
   2398     // Allocation failed - no space for it could be found. Handle this error!
   2399 }
   2400 \endcode
   2401 
   2402 \section virtual_allocator_deallocation Deallocation
   2403 
   2404 When no longer needed, an allocation can be freed by calling D3D12MA::VirtualBlock::FreeAllocation.
   2405 
   2406 When whole block is no longer needed, the block object can be released by calling `block->Release()`.
   2407 All allocations must be freed before the block is destroyed, which is checked internally by an assert.
   2408 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 -
   2409 a feature not available in normal D3D12 memory allocator.
   2410 
   2411 Example:
   2412 
   2413 \code
   2414 block->FreeAllocation(alloc);
   2415 block->Release();
   2416 \endcode
   2417 
   2418 \section virtual_allocator_allocation_parameters Allocation parameters
   2419 
   2420 You can attach a custom pointer to each allocation by using D3D12MA::VirtualBlock::SetAllocationPrivateData.
   2421 Its default value is `NULL`.
   2422 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
   2423 larger data structure containing more information. Example:
   2424 
   2425 \code
   2426 struct CustomAllocData
   2427 {
   2428     std::string m_AllocName;
   2429 };
   2430 CustomAllocData* allocData = new CustomAllocData();
   2431 allocData->m_AllocName = "My allocation 1";
   2432 block->SetAllocationPrivateData(alloc, allocData);
   2433 \endcode
   2434 
   2435 The pointer can later be fetched, along with allocation offset and size, by passing the allocation handle to function
   2436 D3D12MA::VirtualBlock::GetAllocationInfo and inspecting returned structure D3D12MA::VIRTUAL_ALLOCATION_INFO.
   2437 If you allocated a new object to be used as the custom pointer, don't forget to delete that object before freeing the allocation!
   2438 Example:
   2439 
   2440 \code
   2441 VIRTUAL_ALLOCATION_INFO allocInfo;
   2442 block->GetAllocationInfo(alloc, &allocInfo);
   2443 delete (CustomAllocData*)allocInfo.pPrivateData;
   2444 
   2445 block->FreeAllocation(alloc);
   2446 \endcode
   2447 
   2448 \section virtual_allocator_alignment_and_units Alignment and units
   2449 
   2450 It feels natural to express sizes and offsets in bytes.
   2451 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
   2452 D3D12MA::VIRTUAL_ALLOCATION_DESC::Alignment to request it. Example:
   2453 
   2454 \code
   2455 D3D12MA::VIRTUAL_ALLOCATION_DESC allocDesc = {};
   2456 allocDesc.Size = 4096; // 4 KB
   2457 allocDesc.Alignment = 4; // Returned offset must be a multiply of 4 B
   2458 
   2459 D3D12MA::VirtualAllocation alloc;
   2460 UINT64 allocOffset;
   2461 hr = block->Allocate(&allocDesc, &alloc, &allocOffset);
   2462 \endcode
   2463 
   2464 Alignments of different allocations made from one block may vary.
   2465 However, if all alignments and sizes are always multiply of some size e.g. 4 B or `sizeof(MyDataStruct)`,
   2466 you can express all sizes, alignments, and offsets in multiples of that size instead of individual bytes.
   2467 It might be more convenient, but you need to make sure to use this new unit consistently in all the places:
   2468 
   2469 - D3D12MA::VIRTUAL_BLOCK_DESC::Size
   2470 - D3D12MA::VIRTUAL_ALLOCATION_DESC::Size and D3D12MA::VIRTUAL_ALLOCATION_DESC::Alignment
   2471 - Using offset returned by D3D12MA::VirtualBlock::Allocate and D3D12MA::VIRTUAL_ALLOCATION_INFO::Offset
   2472 
   2473 \section virtual_allocator_statistics Statistics
   2474 
   2475 You can obtain brief statistics of a virtual block using D3D12MA::VirtualBlock::GetStatistics().
   2476 The function fills structure D3D12MA::Statistics - same as used by the normal D3D12 memory allocator.
   2477 Example:
   2478 
   2479 \code
   2480 D3D12MA::Statistics stats;
   2481 block->GetStatistics(&stats);
   2482 printf("My virtual block has %llu bytes used by %u virtual allocations\n",
   2483     stats.AllocationBytes, stats.AllocationCount);
   2484 \endcode
   2485 
   2486 More detailed statistics can be obtained using function D3D12MA::VirtualBlock::CalculateStatistics(),
   2487 but they are slower to calculate.
   2488 
   2489 You can also request a full list of allocations and free regions as a string in JSON format by calling
   2490 D3D12MA::VirtualBlock::BuildStatsString.
   2491 Returned string must be later freed using D3D12MA::VirtualBlock::FreeStatsString.
   2492 The format of this string may differ from the one returned by the main D3D12 allocator, but it is similar.
   2493 
   2494 \section virtual_allocator_additional_considerations Additional considerations
   2495 
   2496 Alternative, linear algorithm can be used with virtual allocator - see flag
   2497 D3D12MA::VIRTUAL_BLOCK_FLAG_ALGORITHM_LINEAR and documentation: \ref linear_algorithm.
   2498 
   2499 Note that the "virtual allocator" functionality is implemented on a level of individual memory blocks.
   2500 Keeping track of a whole collection of blocks, allocating new ones when out of free space,
   2501 deleting empty ones, and deciding which one to try first for a new allocation must be implemented by the user.
   2502 
   2503 
   2504 \page configuration Configuration
   2505 
   2506 Please check file `D3D12MemAlloc.cpp` lines between "Configuration Begin" and
   2507 "Configuration End" to find macros that you can define to change the behavior of
   2508 the library, primarily for debugging purposes.
   2509 
   2510 \section custom_memory_allocator Custom CPU memory allocator
   2511 
   2512 If you use custom allocator for CPU memory rather than default C++ operator `new`
   2513 and `delete` or `malloc` and `free` functions, you can make this library using
   2514 your allocator as well by filling structure D3D12MA::ALLOCATION_CALLBACKS and
   2515 passing it as optional member D3D12MA::ALLOCATOR_DESC::pAllocationCallbacks.
   2516 Functions pointed there will be used by the library to make any CPU-side
   2517 allocations. Example:
   2518 
   2519 \code
   2520 #include <malloc.h>
   2521 
   2522 void* CustomAllocate(size_t Size, size_t Alignment, void* pPrivateData)
   2523 {
   2524     void* memory = _aligned_malloc(Size, Alignment);
   2525     // Your extra bookkeeping here...
   2526     return memory;
   2527 }
   2528 
   2529 void CustomFree(void* pMemory, void* pPrivateData)
   2530 {
   2531     // Your extra bookkeeping here...
   2532     _aligned_free(pMemory);
   2533 }
   2534 
   2535 (...)
   2536 
   2537 D3D12MA::ALLOCATION_CALLBACKS allocationCallbacks = {};
   2538 allocationCallbacks.pAllocate = &CustomAllocate;
   2539 allocationCallbacks.pFree = &CustomFree;
   2540 
   2541 D3D12MA::ALLOCATOR_DESC allocatorDesc = {};
   2542 allocatorDesc.pDevice = device;
   2543 allocatorDesc.pAdapter = adapter;
   2544 allocatorDesc.pAllocationCallbacks = &allocationCallbacks;
   2545 
   2546 D3D12MA::Allocator* allocator;
   2547 HRESULT hr = D3D12MA::CreateAllocator(&allocatorDesc, &allocator);
   2548 \endcode
   2549 
   2550 
   2551 \section debug_margins Debug margins
   2552 
   2553 By default, allocations are laid out in memory blocks next to each other if possible
   2554 (considering required alignment returned by `ID3D12Device::GetResourceAllocationInfo`).
   2555 
   2556 ![Allocations without margin](../gfx/Margins_1.png)
   2557 
   2558 Define macro `D3D12MA_DEBUG_MARGIN` to some non-zero value (e.g. 16) inside "D3D12MemAlloc.cpp"
   2559 to enforce specified number of bytes as a margin after every allocation.
   2560 
   2561 ![Allocations with margin](../gfx/Margins_2.png)
   2562 
   2563 If your bug goes away after enabling margins, it means it may be caused by memory
   2564 being overwritten outside of allocation boundaries. It is not 100% certain though.
   2565 Change in application behavior may also be caused by different order and distribution
   2566 of allocations across memory blocks after margins are applied.
   2567 
   2568 Margins work with all memory heap types.
   2569 
   2570 Margin is applied only to placed allocations made out of memory heaps and not to committed
   2571 allocations, which have their own, implicit memory heap of specific size.
   2572 It is thus not applied to allocations made using D3D12MA::ALLOCATION_FLAG_COMMITTED flag
   2573 or those automatically decided to put into committed allocations, e.g. due to its large size.
   2574 
   2575 Margins appear in [JSON dump](@ref statistics_json_dump) as part of free space.
   2576 
   2577 Note that enabling margins increases memory usage and fragmentation.
   2578 
   2579 Margins do not apply to \ref virtual_allocator.
   2580 
   2581 
   2582 \page general_considerations General considerations
   2583 
   2584 \section general_considerations_thread_safety Thread safety
   2585 
   2586 - The library has no global state, so separate D3D12MA::Allocator objects can be used independently.
   2587   In typical applications there should be no need to create multiple such objects though - one per `ID3D12Device` is enough.
   2588 - All calls to methods of D3D12MA::Allocator class are safe to be made from multiple
   2589   threads simultaneously because they are synchronized internally when needed.
   2590 - When the allocator is created with D3D12MA::ALLOCATOR_FLAG_SINGLETHREADED,
   2591   calls to methods of D3D12MA::Allocator class must be made from a single thread or synchronized by the user.
   2592   Using this flag may improve performance.
   2593 - D3D12MA::VirtualBlock is not safe to be used from multiple threads simultaneously.
   2594 
   2595 \section general_considerations_versioning_and_compatibility Versioning and compatibility
   2596 
   2597 The library uses [**Semantic Versioning**](https://semver.org/),
   2598 which means version numbers follow convention: Major.Minor.Patch (e.g. 2.3.0), where:
   2599 
   2600 - Incremented Patch version means a release is backward- and forward-compatible,
   2601   introducing only some internal improvements, bug fixes, optimizations etc.
   2602   or changes that are out of scope of the official API described in this documentation.
   2603 - Incremented Minor version means a release is backward-compatible,
   2604   so existing code that uses the library should continue to work, while some new
   2605   symbols could have been added: new structures, functions, new values in existing
   2606   enums and bit flags, new structure members, but not new function parameters.
   2607 - Incrementing Major version means a release could break some backward compatibility.
   2608 
   2609 All changes between official releases are documented in file "CHANGELOG.md".
   2610 
   2611 \warning Backward compatiblity is considered on the level of C++ source code, not binary linkage.
   2612 Adding new members to existing structures is treated as backward compatible if initializing
   2613 the new members to binary zero results in the old behavior.
   2614 You should always fully initialize all library structures to zeros and not rely on their
   2615 exact binary size.
   2616 
   2617 \section general_considerations_features_not_supported Features not supported
   2618 
   2619 Features deliberately excluded from the scope of this library:
   2620 
   2621 - **Descriptor allocation.** Although also called "heaps", objects that represent
   2622   descriptors are separate part of the D3D12 API from buffers and textures.
   2623   You can still use \ref virtual_allocator to manage descriptors and their ranges inside a descriptor heap.
   2624 - **Support for reserved (tiled) resources.** We don't recommend using them.
   2625 - Support for `ID3D12Device::Evict` and `MakeResident`. We don't recommend using them.
   2626   You can call them on the D3D12 objects manually.
   2627   Plese keep in mind, however, that eviction happens on the level of entire `ID3D12Heap` memory blocks
   2628   and not individual buffers or textures which may be placed inside them.
   2629 - **Handling CPU memory allocation failures.** When dynamically creating small C++
   2630   objects in CPU memory (not the GPU memory), allocation failures are not
   2631   handled gracefully, because that would complicate code significantly and
   2632   is usually not needed in desktop PC applications anyway.
   2633   Success of an allocation is just checked with an assert.
   2634 - **Code free of any compiler warnings.**
   2635   There are many preprocessor macros that make some variables unused, function parameters unreferenced,
   2636   or conditional expressions constant in some configurations.
   2637   The code of this library should not be bigger or more complicated just to silence these warnings.
   2638   It is recommended to disable such warnings instead.
   2639 - This is a C++ library. **Bindings or ports to any other programming languages** are welcome as external projects but
   2640   are not going to be included into this repository.
   2641 */