From cdf948baa433bab65a3b60f6edd394e7637d8ec6 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Fri, 31 Jan 2025 18:00:36 +0100 Subject: [PATCH 01/10] Added support for resource tight alignment Added macro D3D12MA_TIGHT_ALIGNMENT_SUPPORTED, flag ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT, function Allocator::IsTightAlignmentSupported. --- include/D3D12MemAlloc.h | 11 ++++++++ src/CMakeLists.txt | 8 ++++++ src/D3D12MemAlloc.cpp | 48 +++++++++++++++++++++++++++++--- src/D3D12Sample.cpp | 10 +++++-- src/Tests.cpp | 61 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+), 7 deletions(-) diff --git a/include/D3D12MemAlloc.h b/include/D3D12MemAlloc.h index 2dc31c7..737e6ae 100644 --- a/include/D3D12MemAlloc.h +++ b/include/D3D12MemAlloc.h @@ -1053,6 +1053,8 @@ enum ALLOCATOR_FLAGS It can also be disabled for a single allocation by using #ALLOCATION_FLAG_STRATEGY_MIN_TIME. */ ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED = 0x10, + /** TODO document... */ + ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT = 0x20, }; /// \brief Parameters of created Allocator object. To be used with CreateAllocator(). @@ -1127,6 +1129,15 @@ class D3D12MA_API Allocator : public IUnknownImpl `#define D3D12MA_OPTIONS16_SUPPORTED 1` is needed for the compilation of this library. Otherwise the flag is always false. */ BOOL IsGPUUploadHeapSupported() const; + /** \brief Returns true if resource tight alignment is supported on the current system. + When supported, it is automatically used by the library, unless + #ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT flag was specified on allocator creation. + + This flag is fetched from `D3D12_FEATURE_DATA_TIGHT_ALIGNMENT::SupportTier`. + + `#define D3D12MA_TIGHT_ALIGNMENT_SUPPORTED 1` is needed for the compilation of this library. Otherwise the flag is always false. + */ + BOOL IsTightAlignmentSupported() const; /** \brief Returns total amount of memory of specific segment group, in bytes. \param memorySegmentGroup use `DXGI_MEMORY_SEGMENT_GROUP_LOCAL` or DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL`. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 23e0941..6134ea3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -198,3 +198,11 @@ if(D3D12MA_OPTIONS16_SUPPORTED) target_compile_definitions(D3D12Sample PRIVATE D3D12MA_OPTIONS16_SUPPORTED=1) endif() endif() + +option(D3D12MA_TIGHT_ALIGNMENT_SUPPORTED "Set if using Agility SDK 1.716.0-preview or newer that defines D3D12_FEATURE_DATA_TIGHT_ALIGNMENT." OFF) +if(D3D12MA_TIGHT_ALIGNMENT_SUPPORTED) + target_compile_definitions(D3D12MemoryAllocator PRIVATE D3D12MA_TIGHT_ALIGNMENT_SUPPORTED=1) + if(${D3D12MA_BUILD_SAMPLE} AND ${WIN32}) + target_compile_definitions(D3D12Sample PRIVATE D3D12MA_TIGHT_ALIGNMENT_SUPPORTED=1) + endif() +endif() diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp index 6962f0b..7eb79f0 100644 --- a/src/D3D12MemAlloc.cpp +++ b/src/D3D12MemAlloc.cpp @@ -5911,6 +5911,8 @@ class AllocatorPimpl BOOL IsCacheCoherentUMA() const { return m_D3D12Architecture.CacheCoherentUMA; } bool SupportsResourceHeapTier2() const { return m_D3D12Options.ResourceHeapTier >= D3D12_RESOURCE_HEAP_TIER_2; } bool IsGPUUploadHeapSupported() const { return m_GPUUploadHeapSupported != FALSE; } + bool IsTightAlignmentSupported() const { return m_TightAlignmentSupported != FALSE; } + bool IsTightAlignmentEnabled() const { return IsTightAlignmentSupported() && m_UseTightAlignment; } bool UseMutex() const { return m_UseMutex; } AllocationObjectAllocator& GetAllocationObjectAllocator() { return m_AllocationObjectAllocator; } UINT GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); } @@ -5998,6 +6000,7 @@ class AllocatorPimpl const bool m_AlwaysCommitted; const bool m_MsaaAlwaysCommitted; const bool m_PreferSmallBuffersCommitted; + const bool m_UseTightAlignment; bool m_DefaultPoolsNotZeroed = false; ID3D12Device* m_Device; // AddRef #ifdef __ID3D12Device1_INTERFACE_DEFINED__ @@ -6022,6 +6025,7 @@ class AllocatorPimpl DXGI_ADAPTER_DESC m_AdapterDesc; D3D12_FEATURE_DATA_D3D12_OPTIONS m_D3D12Options; BOOL m_GPUUploadHeapSupported = FALSE; + BOOL m_TightAlignmentSupported = FALSE; D3D12_FEATURE_DATA_ARCHITECTURE m_D3D12Architecture; AllocationObjectAllocator m_AllocationObjectAllocator; @@ -6089,7 +6093,8 @@ AllocatorPimpl::AllocatorPimpl(const ALLOCATION_CALLBACKS& allocationCallbacks, : m_UseMutex((desc.Flags & ALLOCATOR_FLAG_SINGLETHREADED) == 0), m_AlwaysCommitted((desc.Flags & ALLOCATOR_FLAG_ALWAYS_COMMITTED) != 0), m_MsaaAlwaysCommitted((desc.Flags & ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED) != 0), - m_PreferSmallBuffersCommitted((desc.Flags & ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED) == 0), + m_PreferSmallBuffersCommitted((desc.Flags& ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED) == 0), + m_UseTightAlignment((desc.Flags & ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT) == 0), m_Device(desc.pDevice), m_Adapter(desc.pAdapter), m_PreferredBlockSize(desc.PreferredBlockSize != 0 ? desc.PreferredBlockSize : D3D12MA_DEFAULT_BLOCK_SIZE), @@ -6177,6 +6182,20 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc) } #endif + // You must define macro `#define D3D12MA_TIGHT_ALIGNMENT_SUPPORTED 1` to enable resource tight alignment! + // Unfortunately there is no way to programmatically check if the included defines D3D12_FEATURE_DATA_TIGHT_ALIGNMENT or not. + // Main interfaces have respective macros like __ID3D12Device4_INTERFACE_DEFINED__, but structures like this do not. +#if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED + { + D3D12_FEATURE_DATA_TIGHT_ALIGNMENT tightAlignment = {}; + hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_TIGHT_ALIGNMENT, &tightAlignment, sizeof(tightAlignment)); + if (SUCCEEDED(hr)) + { + m_TightAlignmentSupported = tightAlignment.SupportTier >= D3D12_TIGHT_ALIGNMENT_TIER_1; + } + } +#endif + hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &m_D3D12Architecture, sizeof(m_D3D12Architecture)); if (FAILED(hr)) { @@ -6861,6 +6880,9 @@ void AllocatorPimpl::BuildStatsString(WCHAR** ppStatsString, BOOL detailedMap) json.WriteString(L"GPUUploadHeapSupported"); json.WriteBool(m_GPUUploadHeapSupported != FALSE); + + json.WriteString(L"TightAlignmentSupported"); + json.WriteBool(m_TightAlignmentSupported != FALSE); } json.EndObject(); } @@ -7623,8 +7645,19 @@ template D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfo(D3D12_RESOURCE_DESC_T& inOutResourceDesc) const { #ifdef __ID3D12Device1_INTERFACE_DEFINED__ - /* Optional optimization: Microsoft documentation says: - https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-getresourceallocationinfo + +#if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED + if (IsTightAlignmentEnabled() && + // Don't allow USE_TIGHT_ALIGNMENT together with ALLOW_CROSS_ADAPTER as there is a D3D Debug Layer error: + // D3D12 ERROR: ID3D12Device::GetResourceAllocationInfo: D3D12_RESOURCE_DESC::Flag D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT will be ignored since D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER is set. [ STATE_CREATION ERROR #599: CREATERESOURCE_INVALIDMISCFLAGS] + (inOutResourceDesc.Flags & D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER) == 0) + { + inOutResourceDesc.Flags |= D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT; + } +#endif // #if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED + + /* Optional optimization: Microsoft documentation of the ID3D12Device:: + GetResourceAllocationInfo function says: Your application can forgo using GetResourceAllocationInfo for buffer resources (D3D12_RESOURCE_DIMENSION_BUFFER). Buffers have the same size on all adapters, @@ -7632,12 +7665,14 @@ D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfo(D3D12_R D3D12_RESOURCE_DESC::Width. */ if (inOutResourceDesc.Alignment == 0 && - inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && + !IsTightAlignmentEnabled()) { return { AlignUp(inOutResourceDesc.Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT), // SizeInBytes D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT }; // Alignment } + #endif // #ifdef __ID3D12Device1_INTERFACE_DEFINED__ #if D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT @@ -9552,6 +9587,11 @@ BOOL Allocator::IsGPUUploadHeapSupported() const return m_Pimpl->IsGPUUploadHeapSupported(); } +BOOL Allocator::IsTightAlignmentSupported() const +{ + return m_Pimpl->IsTightAlignmentSupported(); +} + UINT64 Allocator::GetMemoryCapacity(UINT memorySegmentGroup) const { return m_Pimpl->GetMemoryCapacity(memorySegmentGroup); diff --git a/src/D3D12Sample.cpp b/src/D3D12Sample.cpp index e39e3fe..ea88ee9 100644 --- a/src/D3D12Sample.cpp +++ b/src/D3D12Sample.cpp @@ -438,6 +438,11 @@ inline UINT64 UpdateSubresources( UINT* pNumRows = reinterpret_cast(pRowSizesInBytes + NumSubresources); D3D12_RESOURCE_DESC Desc = pDestinationResource->GetDesc(); + + // Needed because of the D3D Debug Layer error: + // D3D12 ERROR: ID3D12Device::GetCopyableFootprints: D3D12_RESOURCE_DESC::Alignment is invalid. The value is 16. When D3D12_RESOURCE_DESC::Flag bit for D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT is set, Alignment must be 0. [ STATE_CREATION ERROR #721: CREATERESOURCE_INVALIDALIGNMENT] + Desc.Alignment = 0; + ID3D12Device* pDevice; pDestinationResource->GetDevice(__uuidof(*pDevice), reinterpret_cast(&pDevice)); pDevice->GetCopyableFootprints(&Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize); @@ -1052,8 +1057,7 @@ static void InitD3D() // initializes direct3d 12 CHECK_HR( g_Allocator->CreateResource( &vertexBufferAllocDesc, &vertexBufferResourceDesc, // resource description for a buffer - D3D12_RESOURCE_STATE_COPY_DEST, // we will start this heap in the copy destination state since we will copy data - // from the upload heap to this heap + D3D12_RESOURCE_STATE_COMMON, nullptr, // optimized clear value must be null for this type of resource. used for render targets and depth/stencil buffers &g_VertexBufferAllocation, IID_PPV_ARGS(&vertexBufferPtr)) ); @@ -1165,7 +1169,7 @@ static void InitD3D() // initializes direct3d 12 CHECK_HR( g_Allocator->CreateResource( &indexBufferAllocDesc, &indexBufferResourceDesc, // resource description for a buffer - D3D12_RESOURCE_STATE_COPY_DEST, // start in the copy destination state + D3D12_RESOURCE_STATE_COMMON, nullptr, // optimized clear value must be null for this type of resource &g_IndexBufferAllocation, IID_PPV_ARGS(&g_IndexBuffer)) ); diff --git a/src/Tests.cpp b/src/Tests.cpp index bd065eb..40388f9 100644 --- a/src/Tests.cpp +++ b/src/Tests.cpp @@ -51,6 +51,17 @@ static constexpr UINT64 MEGABYTE = 1024 * KILOBYTE; static constexpr CONFIG_TYPE ConfigType = CONFIG_TYPE_AVERAGE; static const char* FREE_ORDER_NAMES[] = { "FORWARD", "BACKWARD", "RANDOM", }; +// Indexes match enum D3D12_HEAP_TYPE. +static const WCHAR* const HEAP_TYPE_NAMES[] = +{ + L"", + L"DEFAULT", + L"UPLOAD", + L"READBACK", + L"CUSTOM", + L"GPU_UPLOAD", +}; + static void CurrentTimeToStr(std::string& out) { time_t rawTime; time(&rawTime); @@ -2990,6 +3001,55 @@ static void TestGPUUploadHeap(const TestContext& ctx) #endif } +static void TestTightAlignment(const TestContext& ctx) +{ +#if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED + using namespace D3D12MA; + + wprintf(L"Test resource tight alignment\n"); + + if(!ctx.allocator->IsTightAlignmentSupported()) + { + wprintf(L" Skipped due to tight alignment not supported.\n"); + return; + } + + // Use a custom heap to make sure our small buffers are not created as committed. + POOL_DESC poolDesc = {}; + poolDesc.BlockSize = 1024 * 1024; + poolDesc.MinBlockCount = poolDesc.MaxBlockCount = 1; + + D3D12_RESOURCE_DESC resDesc; + FillResourceDescForBuffer(resDesc, 16); + + const D3D12_HEAP_TYPE heapTypes[] = { D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_TYPE_UPLOAD }; + for (auto heapType : heapTypes) + { + poolDesc.HeapProperties.Type = heapType; + ComPtr pool; + CHECK_HR(ctx.allocator->CreatePool(&poolDesc, &pool)); + + ALLOCATION_DESC allocDesc = {}; + allocDesc.CustomPool = pool.Get(); + + ComPtr allocs[2] = {}; + + for (size_t i = 0; i < _countof(allocs); ++i) + { + CHECK_HR(ctx.allocator->CreateResource(&allocDesc, &resDesc, + D3D12_RESOURCE_STATE_COMMON, NULL, &allocs[i], IID_NULL, NULL)); + CHECK_BOOL(allocs[i] && allocs[i]->GetResource()); + } + + // Print the offset of the 2nd buffer. + wprintf(L" In D3D12_HEAP_TYPE_%s, a %llu B buffer was aligned to %llu B.\n", + HEAP_TYPE_NAMES[(size_t)heapType], + resDesc.Width, + allocs[1]->GetOffset()); + } +#endif +} + static void TestVirtualBlocks(const TestContext& ctx) { wprintf(L"Test virtual blocks\n"); @@ -4257,6 +4317,7 @@ static void TestGroupBasics(const TestContext& ctx) #endif TestGPUUploadHeap(ctx); + TestTightAlignment(ctx); FILE* file; fopen_s(&file, "Results.csv", "w"); From 1063339a51139ee321d9c4136d8ce44a1af05068 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Sun, 2 Feb 2025 17:03:12 +0100 Subject: [PATCH 02/10] Disabled preference for creating small buffers as committed when tight alignment is used --- include/D3D12MemAlloc.h | 5 +++++ src/D3D12MemAlloc.cpp | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/D3D12MemAlloc.h b/include/D3D12MemAlloc.h index 737e6ae..bb102da 100644 --- a/include/D3D12MemAlloc.h +++ b/include/D3D12MemAlloc.h @@ -1051,6 +1051,11 @@ enum ALLOCATOR_FLAGS which may take longer than creating placed resources in existing heaps. Passing this flag will disable this committed preference globally for the allocator. It can also be disabled for a single allocation by using #ALLOCATION_FLAG_STRATEGY_MIN_TIME. + + If the tight resource alignment feature is used by the library (which happens automatically whenever supported, + unless you use flag #ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT), then small buffers are not preferred as committed. + Long story short, you don't need to specify any of these flags. + The library chooses the most optimal method automatically. */ ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED = 0x10, /** TODO document... */ diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp index 7eb79f0..d67ac34 100644 --- a/src/D3D12MemAlloc.cpp +++ b/src/D3D12MemAlloc.cpp @@ -5999,7 +5999,7 @@ class AllocatorPimpl const bool m_UseMutex; const bool m_AlwaysCommitted; const bool m_MsaaAlwaysCommitted; - const bool m_PreferSmallBuffersCommitted; + bool m_PreferSmallBuffersCommitted; const bool m_UseTightAlignment; bool m_DefaultPoolsNotZeroed = false; ID3D12Device* m_Device; // AddRef @@ -6192,6 +6192,14 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc) if (SUCCEEDED(hr)) { m_TightAlignmentSupported = tightAlignment.SupportTier >= D3D12_TIGHT_ALIGNMENT_TIER_1; + + // If tight alignment is supported (checked by the code above) and wasn't disabled by the developer + // (with ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT), disable the preference for creating small buffers as committed, + // as if ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED was specified. + if (IsTightAlignmentEnabled()) + { + m_PreferSmallBuffersCommitted = false; + } } } #endif From 42bfb6b6fb7caf1a0c37196caa1e357f8b138af1 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Wed, 26 Feb 2025 13:07:53 +0100 Subject: [PATCH 03/10] Align buffers to 256 B at least Because this is the alignment required for constant buffers. --- src/D3D12MemAlloc.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp index d67ac34..976e872 100644 --- a/src/D3D12MemAlloc.cpp +++ b/src/D3D12MemAlloc.cpp @@ -7710,7 +7710,15 @@ D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfo(D3D12_R } #endif // #if D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT - return GetResourceAllocationInfoNative(inOutResourceDesc); + D3D12_RESOURCE_ALLOCATION_INFO resAllocInfo = GetResourceAllocationInfoNative(inOutResourceDesc); + + // Align up to 256 B because this is the alignment required for constant buffers. + if (inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) + { + resAllocInfo.Alignment = D3D12MA_MAX(resAllocInfo.Alignment, (UINT64)D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); + } + + return resAllocInfo; } bool AllocatorPimpl::NewAllocationWithinBudget(D3D12_HEAP_TYPE heapType, UINT64 size) From 619c795fba2e5c53506d51a20b4e4d2b10f62298 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Wed, 26 Feb 2025 14:04:10 +0100 Subject: [PATCH 04/10] Removed macros D3D12MA_OPTIONS16_SUPPORTED, D3D12MA_TIGHT_ALIGNMENT_SUPPORTED from the public interface Also removed them from the Cmake script. They are now automatically determined based on D3D12_PREVIEW_SDK_VERSION, D3D12_SDK_VERSION macro. Also made fixes in tests. --- include/D3D12MemAlloc.h | 4 ---- src/CMakeLists.txt | 16 ---------------- src/D3D12MemAlloc.cpp | 28 +++++++++++++++++++--------- src/Doxyfile | 4 +++- src/Tests.cpp | 27 +++++++++++++++++++++++---- 5 files changed, 45 insertions(+), 34 deletions(-) diff --git a/include/D3D12MemAlloc.h b/include/D3D12MemAlloc.h index bb102da..23c8f70 100644 --- a/include/D3D12MemAlloc.h +++ b/include/D3D12MemAlloc.h @@ -1130,8 +1130,6 @@ class D3D12MA_API Allocator : public IUnknownImpl When true, you can use `D3D12_HEAP_TYPE_GPU_UPLOAD`. This flag is fetched from `D3D12_FEATURE_D3D12_OPTIONS16::GPUUploadHeapSupported`. - - `#define D3D12MA_OPTIONS16_SUPPORTED 1` is needed for the compilation of this library. Otherwise the flag is always false. */ BOOL IsGPUUploadHeapSupported() const; /** \brief Returns true if resource tight alignment is supported on the current system. @@ -1139,8 +1137,6 @@ class D3D12MA_API Allocator : public IUnknownImpl #ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT flag was specified on allocator creation. This flag is fetched from `D3D12_FEATURE_DATA_TIGHT_ALIGNMENT::SupportTier`. - - `#define D3D12MA_TIGHT_ALIGNMENT_SUPPORTED 1` is needed for the compilation of this library. Otherwise the flag is always false. */ BOOL IsTightAlignmentSupported() const; /** \brief Returns total amount of memory of specific segment group, in bytes. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6134ea3..327ec7c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -190,19 +190,3 @@ if(D3D12MA_AGILITY_SDK_DIRECTORY) else() message(STATUS "DX12 Agility SDK not used.") endif() - -option(D3D12MA_OPTIONS16_SUPPORTED "Set if using Agility SDK 1.710.0-preview or newer that defines D3D12_FEATURE_DATA_D3D12_OPTIONS16." OFF) -if(D3D12MA_OPTIONS16_SUPPORTED) - target_compile_definitions(D3D12MemoryAllocator PRIVATE D3D12MA_OPTIONS16_SUPPORTED=1) - if(${D3D12MA_BUILD_SAMPLE} AND ${WIN32}) - target_compile_definitions(D3D12Sample PRIVATE D3D12MA_OPTIONS16_SUPPORTED=1) - endif() -endif() - -option(D3D12MA_TIGHT_ALIGNMENT_SUPPORTED "Set if using Agility SDK 1.716.0-preview or newer that defines D3D12_FEATURE_DATA_TIGHT_ALIGNMENT." OFF) -if(D3D12MA_TIGHT_ALIGNMENT_SUPPORTED) - target_compile_definitions(D3D12MemoryAllocator PRIVATE D3D12MA_TIGHT_ALIGNMENT_SUPPORTED=1) - if(${D3D12MA_BUILD_SAMPLE} AND ${WIN32}) - target_compile_definitions(D3D12Sample PRIVATE D3D12MA_TIGHT_ALIGNMENT_SUPPORTED=1) - endif() -endif() diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp index 976e872..0d358ea 100644 --- a/src/D3D12MemAlloc.cpp +++ b/src/D3D12MemAlloc.cpp @@ -107,6 +107,22 @@ especially to test compatibility with D3D12_RESOURCE_HEAP_TIER_1 on modern GPUs. #define D3D12MA_DEFAULT_BLOCK_SIZE (64ull * 1024 * 1024) #endif +#ifndef D3D12MA_TIGHT_ALIGNMENT_SUPPORTED + #if D3D12_PREVIEW_SDK_VERSION >= 716 + #define D3D12MA_TIGHT_ALIGNMENT_SUPPORTED 1 + #else + #define D3D12MA_TIGHT_ALIGNMENT_SUPPORTED 0 + #endif +#endif + +#ifndef D3D12MA_OPTIONS16_SUPPORTED + #if D3D12_SDK_VERSION >= 610 + #define D3D12MA_OPTIONS16_SUPPORTED 1 + #else + #define D3D12MA_OPTIONS16_SUPPORTED 0 + #endif +#endif + #ifndef D3D12MA_DEBUG_LOG #define D3D12MA_DEBUG_LOG(format, ...) /* @@ -6168,9 +6184,6 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc) m_D3D12Options.ResourceHeapTier = (D3D12MA_FORCE_RESOURCE_HEAP_TIER); #endif -// You must define this macro to like `#define D3D12MA_OPTIONS16_SUPPORTED 1` to enable GPU Upload Heaps! -// Unfortunately there is no way to programmatically check if the included defines D3D12_FEATURE_DATA_D3D12_OPTIONS16 or not. -// Main interfaces have respective macros like __ID3D12Device4_INTERFACE_DEFINED__, but structures like this do not. #if D3D12MA_OPTIONS16_SUPPORTED { D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16 = {}; @@ -6180,11 +6193,8 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc) m_GPUUploadHeapSupported = options16.GPUUploadHeapSupported; } } -#endif +#endif // #if D3D12MA_OPTIONS16_SUPPORTED - // You must define macro `#define D3D12MA_TIGHT_ALIGNMENT_SUPPORTED 1` to enable resource tight alignment! - // Unfortunately there is no way to programmatically check if the included defines D3D12_FEATURE_DATA_TIGHT_ALIGNMENT or not. - // Main interfaces have respective macros like __ID3D12Device4_INTERFACE_DEFINED__, but structures like this do not. #if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED { D3D12_FEATURE_DATA_TIGHT_ALIGNMENT tightAlignment = {}; @@ -6202,7 +6212,7 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc) } } } -#endif +#endif // #if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_ARCHITECTURE, &m_D3D12Architecture, sizeof(m_D3D12Architecture)); if (FAILED(hr)) @@ -7427,7 +7437,7 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U outPreferCommitted = false; D3D12MA_ASSERT((allocDesc.HeapType != D3D12_HEAP_TYPE_GPU_UPLOAD_COPY || IsGPUUploadHeapSupported()) && - "Trying to allocate from D3D12_HEAP_TYPE_GPU_UPLOAD while GPUUploadHeapSupported == FALSE or D3D12MA_OPTIONS16_SUPPORTED macro was not defined when compiling D3D12MA library."); + "Trying to allocate from D3D12_HEAP_TYPE_GPU_UPLOAD while GPUUploadHeapSupported == FALSE."); bool msaaAlwaysCommitted; if (allocDesc.CustomPool != NULL) diff --git a/src/Doxyfile b/src/Doxyfile index a93bdbb..e9cc11b 100644 --- a/src/Doxyfile +++ b/src/Doxyfile @@ -42,7 +42,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "Direct3D 12 Memory Allocator" +PROJECT_NAME = "D3D12 Memory Allocator" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -2372,6 +2372,8 @@ PREDEFINED = __ID3D12Device1_INTERFACE_DEFINED__ \ __ID3D12Device4_INTERFACE_DEFINED__ \ __ID3D12Device8_INTERFACE_DEFINED__ \ __ID3D12Device10_INTERFACE_DEFINED__ \ + D3D12_PREVIEW_SDK_VERSION=716 \ + D3D12_SDK_VERSION=716 \ protected=private # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this diff --git a/src/Tests.cpp b/src/Tests.cpp index 40388f9..f52419a 100644 --- a/src/Tests.cpp +++ b/src/Tests.cpp @@ -51,6 +51,8 @@ static constexpr UINT64 MEGABYTE = 1024 * KILOBYTE; static constexpr CONFIG_TYPE ConfigType = CONFIG_TYPE_AVERAGE; static const char* FREE_ORDER_NAMES[] = { "FORWARD", "BACKWARD", "RANDOM", }; +constexpr D3D12_RESOURCE_FLAGS D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT_COPY = (D3D12_RESOURCE_FLAGS)0x400; + // Indexes match enum D3D12_HEAP_TYPE. static const WCHAR* const HEAP_TYPE_NAMES[] = { @@ -204,6 +206,10 @@ static void FillAllocationsDataGPU(const TestContext& ctx, const ComPtrGetResource()->GetDesc(); if (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { + // Fix for D3D12 ERROR: ID3D12Device::CreatePlacedResource: D3D12_RESOURCE_DESC::Alignment is invalid. The value is 8. When D3D12_RESOURCE_DESC::Flag bit for D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT is set, Alignment must be 0. [ STATE_CREATION ERROR #721: CREATERESOURCE_INVALIDALIGNMENT] + if ((resDesc.Flags & D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT_COPY) != 0) + resDesc.Alignment = 0; + ComPtr uploadAlloc; CHECK_HR(ctx.allocator->CreateResource(&allocDesc, &resDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, &uploadAlloc, IID_NULL, nullptr)); @@ -296,6 +302,10 @@ static void ValidateAllocationsDataGPU(const TestContext& ctx, const ComPtrGetResource()->GetDesc(); if (resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { + // Fix for D3D12 ERROR: ID3D12Device::CreatePlacedResource: D3D12_RESOURCE_DESC::Alignment is invalid. The value is 8. When D3D12_RESOURCE_DESC::Flag bit for D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT is set, Alignment must be 0. [ STATE_CREATION ERROR #721: CREATERESOURCE_INVALIDALIGNMENT] + if ((resDesc.Flags & D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT_COPY) != 0) + resDesc.Alignment = 0; + ComPtr downloadAlloc; CHECK_HR(ctx.allocator->CreateResource(&allocDesc, &resDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, &downloadAlloc, IID_NULL, nullptr)); @@ -762,7 +772,13 @@ static void TestSmallBuffers(const TestContext& ctx) CHECK_HR(ctx.allocator->CreateResource(&allocDesc, &resDesc, D3D12_RESOURCE_STATE_COMMON, nullptr, &resWithAlloc.allocation, IID_PPV_ARGS(&resWithAlloc.resource))); CHECK_BOOL(resWithAlloc.allocation && resWithAlloc.allocation->GetResource()); - CHECK_BOOL(!resWithAlloc.allocation->GetHeap()); // Expected to be committed. + // May or may not be committed, depending on the PREFER_SMALL_BUFFERS_COMMITTED + // and TIGHT_ALIGNMENT settings. + const bool isCommitted = resWithAlloc.allocation->GetHeap() == NULL; + if (isCommitted) + wprintf(L" Small buffer %llu B inside a custom pool was created as committed.\n", resDesc.Width); + else + wprintf(L" Small buffer %llu B inside a custom pool was created as placed.\n", resDesc.Width); } // Test 3: NEVER_ALLOCATE. @@ -2857,7 +2873,7 @@ static void TestDevice10(const TestContext& ctx) static void TestGPUUploadHeap(const TestContext& ctx) { -#if D3D12MA_OPTIONS16_SUPPORTED +#if D3D12_SDK_VERSION >= 610 using namespace D3D12MA; wprintf(L"Test GPU Upload Heap\n"); @@ -3003,7 +3019,6 @@ static void TestGPUUploadHeap(const TestContext& ctx) static void TestTightAlignment(const TestContext& ctx) { -#if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED using namespace D3D12MA; wprintf(L"Test resource tight alignment\n"); @@ -3047,7 +3062,6 @@ static void TestTightAlignment(const TestContext& ctx) resDesc.Width, allocs[1]->GetOffset()); } -#endif } static void TestVirtualBlocks(const TestContext& ctx) @@ -3418,6 +3432,11 @@ static void ProcessDefragmentationPass(const TestContext& ctx, D3D12MA::DEFRAGME const bool isDefaultHeap = stepInfo.pMoves[i].pSrcAllocation->GetHeap()->GetDesc().Properties.Type == D3D12_HEAP_TYPE_DEFAULT; // Create new resource D3D12_RESOURCE_DESC desc = stepInfo.pMoves[i].pSrcAllocation->GetResource()->GetDesc(); + + // Fix for D3D12 ERROR: ID3D12Device::CreatePlacedResource: D3D12_RESOURCE_DESC::Alignment is invalid. The value is 8. When D3D12_RESOURCE_DESC::Flag bit for D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT is set, Alignment must be 0. [ STATE_CREATION ERROR #721: CREATERESOURCE_INVALIDALIGNMENT] + if ((desc.Flags & D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT_COPY) != 0) + desc.Alignment = 0; + ComPtr dstRes; CHECK_HR(ctx.device->CreatePlacedResource(stepInfo.pMoves[i].pDstTmpAllocation->GetHeap(), stepInfo.pMoves[i].pDstTmpAllocation->GetOffset(), &desc, From 3ca443a8ae328391099b8e5d7b5c1c3759e2a676 Mon Sep 17 00:00:00 2001 From: Adam Sawicki Date: Fri, 28 Feb 2025 13:47:16 +0100 Subject: [PATCH 05/10] Added documentation chapter "Optimal resource allocation" Also other fixes in the documentation. Updated Doxyfile to the new Doxygen version. Regenerated the docs. --- docs/html/_d3_d12_mem_alloc_8h.html | 13 +- docs/html/annotated.html | 4 +- ...ass_d3_d12_m_a_1_1_allocation-members.html | 4 +- .../html/class_d3_d12_m_a_1_1_allocation.html | 4 +- ...lass_d3_d12_m_a_1_1_allocator-members.html | 9 +- docs/html/class_d3_d12_m_a_1_1_allocator.html | 32 +- ...a_1_1_defragmentation_context-members.html | 4 +- ...3_d12_m_a_1_1_defragmentation_context.html | 4 +- .../class_d3_d12_m_a_1_1_pool-members.html | 4 +- docs/html/class_d3_d12_m_a_1_1_pool.html | 4 +- ..._d3_d12_m_a_1_1_virtual_block-members.html | 4 +- .../class_d3_d12_m_a_1_1_virtual_block.html | 4 +- docs/html/classes.html | 4 +- docs/html/configuration.html | 20 +- docs/html/custom_pools.html | 8 +- docs/html/defragmentation.html | 26 +- .../dir_d44c64559bbebec7f509842c48db8b23.html | 4 +- docs/html/doxygen_crawl.html | 10 + docs/html/files.html | 4 +- docs/html/functions.html | 5 +- docs/html/functions_func.html | 5 +- docs/html/functions_rela.html | 4 +- docs/html/functions_vars.html | 4 +- docs/html/general_considerations.html | 4 +- docs/html/globals.html | 4 +- docs/html/globals_defs.html | 4 +- docs/html/hierarchy.html | 4 +- docs/html/index.html | 20 +- docs/html/linear_algorithm.html | 4 +- docs/html/namespace_d3_d12_m_a.html | 11 +- docs/html/namespacemembers.html | 5 +- docs/html/namespacemembers_enum.html | 4 +- docs/html/namespacemembers_eval.html | 5 +- docs/html/namespacemembers_func.html | 4 +- docs/html/namespacemembers_type.html | 4 +- docs/html/namespaces.html | 4 +- docs/html/optimal_allocation.html | 343 ++++++++ docs/html/quick_start.html | 41 +- docs/html/resource_aliasing.html | 14 +- docs/html/search/all_0.js | 99 +-- docs/html/search/all_1.js | 7 +- docs/html/search/all_10.js | 14 +- docs/html/search/all_11.js | 28 +- docs/html/search/all_13.js | 5 +- docs/html/search/all_14.js | 39 +- docs/html/search/all_15.js | 2 +- docs/html/search/all_2.js | 41 +- docs/html/search/all_3.js | 2 +- docs/html/search/all_6.js | 3 +- docs/html/search/all_7.js | 2 +- docs/html/search/all_8.js | 3 +- docs/html/search/all_a.js | 3 +- docs/html/search/all_b.js | 4 +- docs/html/search/all_d.js | 11 +- docs/html/search/all_e.js | 35 +- docs/html/search/enumvalues_0.js | 7 +- docs/html/search/functions_6.js | 3 +- docs/html/search/pages_0.js | 9 +- docs/html/search/pages_1.js | 2 +- docs/html/search/pages_2.js | 2 +- docs/html/search/pages_5.js | 2 +- docs/html/search/pages_6.js | 3 +- docs/html/search/pages_7.js | 2 +- docs/html/search/pages_9.js | 3 +- docs/html/search/pages_a.js | 2 +- docs/html/search/pages_b.js | 2 +- docs/html/search/searchdata.js | 2 +- docs/html/statistics.html | 12 +- ...a_t_i_o_n___c_a_l_l_b_a_c_k_s-members.html | 4 +- ...l_l_o_c_a_t_i_o_n___c_a_l_l_b_a_c_k_s.html | 4 +- ...a_l_l_o_c_a_t_i_o_n___d_e_s_c-members.html | 4 +- ...m_a_1_1_a_l_l_o_c_a_t_i_o_n___d_e_s_c.html | 4 +- ...1_a_l_l_o_c_a_t_o_r___d_e_s_c-members.html | 4 +- ...2_m_a_1_1_a_l_l_o_c_a_t_o_r___d_e_s_c.html | 4 +- .../struct_d3_d12_m_a_1_1_budget-members.html | 4 +- docs/html/struct_d3_d12_m_a_1_1_budget.html | 4 +- ...g_m_e_n_t_a_t_i_o_n___d_e_s_c-members.html | 4 +- ...e_f_r_a_g_m_e_n_t_a_t_i_o_n___d_e_s_c.html | 4 +- ...g_m_e_n_t_a_t_i_o_n___m_o_v_e-members.html | 4 +- ...e_f_r_a_g_m_e_n_t_a_t_i_o_n___m_o_v_e.html | 4 +- ...__p_a_s_s___m_o_v_e___i_n_f_o-members.html | 4 +- ...t_i_o_n___p_a_s_s___m_o_v_e___i_n_f_o.html | 4 +- ...m_e_n_t_a_t_i_o_n___s_t_a_t_s-members.html | 4 +- ...f_r_a_g_m_e_n_t_a_t_i_o_n___s_t_a_t_s.html | 4 +- ...2_m_a_1_1_detailed_statistics-members.html | 4 +- ...ct_d3_d12_m_a_1_1_detailed_statistics.html | 4 +- ...d12_m_a_1_1_p_o_o_l___d_e_s_c-members.html | 4 +- ...ruct_d3_d12_m_a_1_1_p_o_o_l___d_e_s_c.html | 4 +- ...uct_d3_d12_m_a_1_1_statistics-members.html | 4 +- .../struct_d3_d12_m_a_1_1_statistics.html | 4 +- ..._d12_m_a_1_1_total_statistics-members.html | 4 +- ...truct_d3_d12_m_a_1_1_total_statistics.html | 4 +- ...a_l_l_o_c_a_t_i_o_n___d_e_s_c-members.html | 4 +- ...u_a_l___a_l_l_o_c_a_t_i_o_n___d_e_s_c.html | 4 +- ...a_l_l_o_c_a_t_i_o_n___i_n_f_o-members.html | 4 +- ...u_a_l___a_l_l_o_c_a_t_i_o_n___i_n_f_o.html | 4 +- ...t_u_a_l___b_l_o_c_k___d_e_s_c-members.html | 4 +- ...1_v_i_r_t_u_a_l___b_l_o_c_k___d_e_s_c.html | 4 +- ...12_m_a_1_1_virtual_allocation-members.html | 4 +- ...uct_d3_d12_m_a_1_1_virtual_allocation.html | 4 +- docs/html/virtual_allocator.html | 28 +- include/D3D12MemAlloc.h | 558 ++++++++++++- src/D3D12MemAlloc.cpp | 2 +- src/Doxyfile | 730 +++++++++++------- 104 files changed, 1778 insertions(+), 676 deletions(-) create mode 100644 docs/html/optimal_allocation.html diff --git a/docs/html/_d3_d12_mem_alloc_8h.html b/docs/html/_d3_d12_mem_alloc_8h.html index 05320f0..6df7c0d 100644 --- a/docs/html/_d3_d12_mem_alloc_8h.html +++ b/docs/html/_d3_d12_mem_alloc_8h.html @@ -5,7 +5,7 @@ -Direct3D 12 Memory Allocator: D:/PROJECTS/D3D12 Memory Allocator/REPO/include/D3D12MemAlloc.h File Reference +D3D12 Memory Allocator: D:/PROJECTS/D3D12 Memory Allocator/REPO/include/D3D12MemAlloc.h File Reference @@ -25,7 +25,7 @@ -
Direct3D 12 Memory Allocator +
D3D12 Memory Allocator
@@ -177,6 +177,7 @@ #define D3D12MA_DXGI_1_4   0   #define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT   1 + When defined to value other than 0, the library will try to use D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT or D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT for created textures when possible, which can save memory because some small textures may get their alignment 4 KB and their size a multiply of 4 KB instead of 64 KB.
  @@ -299,6 +301,13 @@

+

When defined to value other than 0, the library will try to use D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT or D3D12_SMALL_MSAA_RESOURCE_PLACEMENT_ALIGNMENT for created textures when possible, which can save memory because some small textures may get their alignment 4 KB and their size a multiply of 4 KB instead of 64 KB.

+
    +
  • #define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 0 - Disables small texture alignment.
  • +
  • #define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 1 (the default) - Enables conservative algorithm that will use small alignment only for some textures that are surely known to support it.
  • +
  • #define D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT 2 - Enables query for small alignment to D3D12 (based on Microsoft sample) which will enable small alignment for more textures, but will also generate D3D Debug Layer error #721 on call to ID3D12Device::GetResourceAllocationInfo, which you should just ignore.
  • +
+ diff --git a/docs/html/annotated.html b/docs/html/annotated.html index 7e00073..6810191 100644 --- a/docs/html/annotated.html +++ b/docs/html/annotated.html @@ -5,7 +5,7 @@ -Direct3D 12 Memory Allocator: Class List +D3D12 Memory Allocator: Class List @@ -25,7 +25,7 @@

diff --git a/docs/html/class_d3_d12_m_a_1_1_allocation-members.html b/docs/html/class_d3_d12_m_a_1_1_allocation-members.html index 95e5051..65c9dc6 100644 --- a/docs/html/class_d3_d12_m_a_1_1_allocation-members.html +++ b/docs/html/class_d3_d12_m_a_1_1_allocation-members.html @@ -5,7 +5,7 @@ -Direct3D 12 Memory Allocator: Member List +D3D12 Memory Allocator: Member List @@ -25,7 +25,7 @@ diff --git a/docs/html/class_d3_d12_m_a_1_1_allocation.html b/docs/html/class_d3_d12_m_a_1_1_allocation.html index 7e17b43..33f9020 100644 --- a/docs/html/class_d3_d12_m_a_1_1_allocation.html +++ b/docs/html/class_d3_d12_m_a_1_1_allocation.html @@ -5,7 +5,7 @@ -Direct3D 12 Memory Allocator: D3D12MA::Allocation Class Reference +D3D12 Memory Allocator: D3D12MA::Allocation Class Reference @@ -25,7 +25,7 @@ diff --git a/docs/html/class_d3_d12_m_a_1_1_allocator-members.html b/docs/html/class_d3_d12_m_a_1_1_allocator-members.html index 423ebc5..7edcd19 100644 --- a/docs/html/class_d3_d12_m_a_1_1_allocator-members.html +++ b/docs/html/class_d3_d12_m_a_1_1_allocator-members.html @@ -5,7 +5,7 @@ -Direct3D 12 Memory Allocator: Member List +D3D12 Memory Allocator: Member List @@ -25,7 +25,7 @@ @@ -113,8 +113,9 @@ - - + + +

@@ -240,6 +241,7 @@ ,
  D3D12MA::ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED = 0x8 , D3D12MA::ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED = 0x10 +, D3D12MA::ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT = 0x20
}

 Bit flags to be used with ALLOCATOR_DESC::Flags. More...
-
Direct3D 12 Memory Allocator +
D3D12 Memory Allocator
-
Direct3D 12 Memory Allocator +
D3D12 Memory Allocator
-
Direct3D 12 Memory Allocator +
D3D12 Memory Allocator
-
Direct3D 12 Memory Allocator +
D3D12 Memory Allocator
GetMemoryCapacity(UINT memorySegmentGroup) constD3D12MA::Allocator
IsCacheCoherentUMA() constD3D12MA::Allocator
IsGPUUploadHeapSupported() constD3D12MA::Allocator
IsUMA() constD3D12MA::Allocator
SetCurrentFrameIndex(UINT frameIndex)D3D12MA::Allocator
IsTightAlignmentSupported() constD3D12MA::Allocator
IsUMA() constD3D12MA::Allocator
SetCurrentFrameIndex(UINT frameIndex)D3D12MA::Allocator