Add member ALLOCATION_DESC::ExtraHeapFlags, remove parameter Allocator::AllocateMemory heapFlags (compatibility breaking!)
Makes it possible to specify custom HeapFlags when allocating memory or creating resources. These are always created as separate allocations / committed resources.
Also added tests for it.
diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp
index 4eef684..cfe1616 100644
--- a/src/D3D12MemAlloc.cpp
+++ b/src/D3D12MemAlloc.cpp
@@ -731,6 +731,16 @@
return tileCount <= 16;
}
+static D3D12_HEAP_FLAGS GetExtraHeapFlagsToIgnore()
+{
+ D3D12_HEAP_FLAGS result =
+ D3D12_HEAP_FLAG_DENY_BUFFERS | D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES | D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES;
+#if D3D12MA_ALLOW_SHADER_ATOMICS
+ result |= D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS;
+#endif
+ return result;
+}
+
////////////////////////////////////////////////////////////////////////////////
// Private class Vector
@@ -2383,7 +2393,6 @@
HRESULT AllocateMemory(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation);
@@ -2456,7 +2465,6 @@
// Creates and returns Allocation object.
HRESULT AllocateHeap(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo,
Allocation** ppAllocation);
@@ -2479,7 +2487,7 @@
UINT CalcDefaultPoolCount() const;
UINT CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, const D3D12_RESOURCE_DESC& resourceDesc) const;
// This one returns UINT32_MAX if nonstandard heap flags are used and index cannot be calculcated.
- UINT CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, const D3D12_HEAP_FLAGS heapFlags) const;
+ UINT CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc) const;
void CalcDefaultPoolParams(D3D12_HEAP_TYPE& outHeapType, D3D12_HEAP_FLAGS& outHeapFlags, UINT index) const;
// Registers Allocation object in m_pCommittedAllocations.
@@ -3688,7 +3696,20 @@
D3D12MA_ASSERT(resAllocInfo.SizeInBytes > 0);
const UINT defaultPoolIndex = CalcDefaultPoolIndex(*pAllocDesc, resourceDesc2);
- D3D12MA_ASSERT(defaultPoolIndex != UINT32_MAX);
+ const bool requireCommittedMemory = defaultPoolIndex == UINT32_MAX;
+ if(requireCommittedMemory)
+ {
+ return AllocateCommittedResource(
+ &finalAllocDesc,
+ &resourceDesc2,
+ resAllocInfo,
+ InitialResourceState,
+ pOptimizedClearValue,
+ ppAllocation,
+ riidResource,
+ ppvResource);
+ }
+
BlockVector* blockVector = m_BlockVectors[defaultPoolIndex];
D3D12MA_ASSERT(blockVector);
@@ -3766,7 +3787,6 @@
HRESULT AllocatorPimpl::AllocateMemory(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation)
{
@@ -3779,11 +3799,11 @@
ALLOCATION_DESC finalAllocDesc = *pAllocDesc;
- const UINT defaultPoolIndex = CalcDefaultPoolIndex(*pAllocDesc, heapFlags);
+ const UINT defaultPoolIndex = CalcDefaultPoolIndex(*pAllocDesc);
bool requireCommittedMemory = (defaultPoolIndex == UINT32_MAX);
if(requireCommittedMemory)
{
- return AllocateHeap(&finalAllocDesc, heapFlags, *pAllocInfo, ppAllocation);
+ return AllocateHeap(&finalAllocDesc, *pAllocInfo, ppAllocation);
}
BlockVector* blockVector = m_BlockVectors[defaultPoolIndex];
@@ -3802,7 +3822,7 @@
if((finalAllocDesc.Flags & ALLOCATION_FLAG_COMMITTED) != 0)
{
- return AllocateHeap(&finalAllocDesc, heapFlags, *pAllocInfo, ppAllocation);
+ return AllocateHeap(&finalAllocDesc, *pAllocInfo, ppAllocation);
}
else
{
@@ -3817,7 +3837,7 @@
return hr;
}
- return AllocateHeap(&finalAllocDesc, heapFlags, *pAllocInfo, ppAllocation);
+ return AllocateHeap(&finalAllocDesc, *pAllocInfo, ppAllocation);
}
}
@@ -3855,7 +3875,7 @@
D3D12_HEAP_PROPERTIES heapProps = {};
heapProps.Type = pAllocDesc->HeapType;
- D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_NONE;
+ D3D12_HEAP_FLAGS heapFlags = pAllocDesc->ExtraHeapFlags;
#if D3D12MA_ALLOW_SHADER_ATOMICS
if((pResourceDesc->Flags & D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS) != 0)
{
@@ -3892,7 +3912,6 @@
HRESULT AllocatorPimpl::AllocateHeap(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo,
Allocation** ppAllocation)
{
@@ -3913,6 +3932,7 @@
}
}
+ D3D12_HEAP_FLAGS heapFlags = pAllocDesc->ExtraHeapFlags;
#if D3D12MA_ALLOW_SHADER_ATOMICS
if(pAllocDesc->HeapType == D3D12_HEAP_TYPE_DEFAULT)
{
@@ -3955,6 +3975,12 @@
UINT AllocatorPimpl::CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, const D3D12_RESOURCE_DESC& resourceDesc) const
{
+ const D3D12_HEAP_FLAGS extraHeapFlags = allocDesc.ExtraHeapFlags & ~GetExtraHeapFlagsToIgnore();
+ if(extraHeapFlags != 0)
+ {
+ return UINT32_MAX;
+ }
+
UINT poolIndex = UINT_MAX;
switch(allocDesc.HeapType)
{
@@ -3982,15 +4008,10 @@
return poolIndex;
}
-UINT AllocatorPimpl::CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, const D3D12_HEAP_FLAGS heapFlags) const
+UINT AllocatorPimpl::CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc) const
{
- D3D12_HEAP_FLAGS heapFlagsToIgnore =
- D3D12_HEAP_FLAG_DENY_BUFFERS | D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES | D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES;
-#if D3D12MA_ALLOW_SHADER_ATOMICS
- heapFlagsToIgnore |= D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS;
-#endif
- const D3D12_HEAP_FLAGS additionalHeapFlags = heapFlags & ~heapFlagsToIgnore;
- if(additionalHeapFlags != 0)
+ const D3D12_HEAP_FLAGS extraHeapFlags = allocDesc.ExtraHeapFlags & ~GetExtraHeapFlagsToIgnore();
+ if(extraHeapFlags != 0)
{
return UINT32_MAX;
}
@@ -4008,9 +4029,9 @@
{
poolIndex *= 3;
- const bool allowBuffers = (heapFlags & D3D12_HEAP_FLAG_DENY_BUFFERS) == 0;
- const bool allowRtDsTextures = (heapFlags & D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES) == 0;
- const bool allowNonRtDsTextures = (heapFlags & D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES) == 0;
+ const bool allowBuffers = (allocDesc.ExtraHeapFlags & D3D12_HEAP_FLAG_DENY_BUFFERS) == 0;
+ const bool allowRtDsTextures = (allocDesc.ExtraHeapFlags & D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES) == 0;
+ const bool allowNonRtDsTextures = (allocDesc.ExtraHeapFlags & D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES) == 0;
const uint8_t allowedGroupCount = (allowBuffers ? 1 : 0) + (allowRtDsTextures ? 1 : 0) + (allowNonRtDsTextures ? 1 : 0);
if(allowedGroupCount != 1)
@@ -4765,7 +4786,6 @@
HRESULT Allocator::AllocateMemory(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation)
{
@@ -4782,7 +4802,7 @@
return E_INVALIDARG;
}
D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK
- return m_Pimpl->AllocateMemory(pAllocDesc, heapFlags, pAllocInfo, ppAllocation);
+ return m_Pimpl->AllocateMemory(pAllocDesc, pAllocInfo, ppAllocation);
}
void Allocator::SetCurrentFrameIndex(UINT frameIndex)
diff --git a/src/D3D12MemAlloc.h b/src/D3D12MemAlloc.h
index df1c0d1..56bab99 100644
--- a/src/D3D12MemAlloc.h
+++ b/src/D3D12MemAlloc.h
@@ -440,6 +440,23 @@
It must be one of: `D3D12_HEAP_TYPE_DEFAULT`, `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`.
*/
D3D12_HEAP_TYPE HeapType;
+ /** \brief Additional heap flags to be used when allocating memory.
+
+ In most cases it can be 0.
+
+ - If you use D3D12MA::Allocator::CreateResource(), you don't need to care.
+ In case of D3D12MA::Allocator::GetD3D12Options()`.ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1`,
+ necessary flag `D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS`, `D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES`,
+ or `D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES` is added automatically.
+ - If you use D3D12MA::Allocator::AllocateMemory() and
+ D3D12MA::Allocator::GetD3D12Options()`.ResourceHeapTier == D3D12_RESOURCE_HEAP_TIER_1`,
+ you must specify one of those `ALLOW_ONLY` flags. When it's `TIER_2`, you can leave it 0.
+ - If configuration macro `D3D12MA_ALLOW_SHADER_ATOMICS` is set to 1 (which is the default),
+ `D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS` is added automatically wherever it might be needed.
+ - You can specify additional flags if needed. Then the memory will always be allocated as
+ separate block using `D3D12Device::CreateCommittedResource` or `CreateHeap`, not as part of an existing larget block.
+ */
+ D3D12_HEAP_FLAGS ExtraHeapFlags;
};
/** \brief Represents single memory allocation.
@@ -793,7 +810,6 @@
*/
HRESULT AllocateMemory(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation);
diff --git a/src/Tests.cpp b/src/Tests.cpp
index 817aea0..7d189de 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -217,23 +217,59 @@
{
wprintf(L"Test custom heap flags\n");
- D3D12MA::ALLOCATION_DESC allocDesc = {};
- allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
+ // 1. Just memory heap with custom flags
+ {
+ D3D12MA::ALLOCATION_DESC allocDesc = {};
+ allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
+ allocDesc.ExtraHeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES |
+ D3D12_HEAP_FLAG_SHARED; // Extra flag.
- const D3D12_HEAP_FLAGS heapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES |
- D3D12_HEAP_FLAG_SHARED; // Extra flag.
+ D3D12_RESOURCE_ALLOCATION_INFO resAllocInfo = {};
+ resAllocInfo.SizeInBytes = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+ resAllocInfo.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
- D3D12_RESOURCE_ALLOCATION_INFO resAllocInfo = {};
- resAllocInfo.SizeInBytes = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
- resAllocInfo.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+ D3D12MA::Allocation* alloc = nullptr;
+ CHECK_HR( ctx.allocator->AllocateMemory(&allocDesc, &resAllocInfo, &alloc) );
+ ResourceWithAllocation res;
+ res.allocation.reset(alloc);
- D3D12MA::Allocation* alloc = nullptr;
- CHECK_HR( ctx.allocator->AllocateMemory(&allocDesc, heapFlags, &resAllocInfo, &alloc) );
- ResourceWithAllocation res;
- res.allocation.reset(alloc);
+ // Must be created as separate allocation.
+ CHECK_BOOL( res.allocation->GetOffset() == 0 );
+ }
- // Must be created as separate allocation.
- CHECK_BOOL( res.allocation->GetOffset() == 0 );
+ // 2. Committed resource with custom flags
+ {
+ D3D12_RESOURCE_DESC resourceDesc = {};
+ resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ resourceDesc.Alignment = 0;
+ resourceDesc.Width = 1920;
+ resourceDesc.Height = 1080;
+ resourceDesc.DepthOrArraySize = 1;
+ resourceDesc.MipLevels = 1;
+ resourceDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ resourceDesc.SampleDesc.Count = 1;
+ resourceDesc.SampleDesc.Quality = 0;
+ resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ resourceDesc.Flags = D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER;
+
+ D3D12MA::ALLOCATION_DESC allocDesc = {};
+ allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
+ allocDesc.ExtraHeapFlags = D3D12_HEAP_FLAG_SHARED | D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER; // Extra flags.
+
+ ResourceWithAllocation res;
+ D3D12MA::Allocation* alloc = nullptr;
+ CHECK_HR( ctx.allocator->CreateResource(
+ &allocDesc,
+ &resourceDesc,
+ D3D12_RESOURCE_STATE_COMMON,
+ NULL,
+ &alloc,
+ IID_PPV_ARGS(&res.resource)) );
+ res.allocation.reset(alloc);
+
+ // Must be created as committed.
+ CHECK_BOOL( res.allocation->GetHeap() == NULL );
+ }
}
static void TestPlacedResources(const TestContext& ctx)
@@ -346,6 +382,7 @@
D3D12MA::ALLOCATION_DESC allocDesc = {};
allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
+ allocDesc.ExtraHeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES;
D3D12_RESOURCE_DESC resourceDesc1 = {};
resourceDesc1.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
@@ -383,7 +420,6 @@
D3D12MA::Allocation* allocPtr = NULL;
CHECK_HR( ctx.allocator->AllocateMemory(
&allocDesc,
- D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES,
&allocInfo,
&allocPtr) );
AllocationUniquePtr alloc(allocPtr);