Merge branch 'master' into WasZeroInitialized
diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp
index 6c55b6e..7e8b2a4 100644
--- a/src/D3D12MemAlloc.cpp
+++ b/src/D3D12MemAlloc.cpp
@@ -86,14 +86,15 @@
#define D3D12MA_DEFAULT_BLOCK_SIZE (256ull * 1024 * 1024)
#endif
-#ifndef D3D12MA_EXTRA_DEFAULT_TYPE_HEAP_FLAGS
+#ifndef D3D12MA_ALLOW_SHADER_ATOMICS
/*
- Here you can control additional heap flags added to heaps/resources created in DEFAULT heap type.
- It's mostly for automatic usage of the cryptic, undocumented flag D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS.
- Its absence doesn't seem to change anything but better to use it always, just in case.
+ Set this to 1 to make the library automatically adding flag
+ D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS to any allocated heap that might contain a
+ buffer or a texture used as a UAV. You can change it to 0 if you are sure your
+ program doesn't use atomic functions in its shaders. In practice this flag
+ doesn't seem to change anything.
*/
- //#define D3D12MA_EXTRA_DEFAULT_TYPE_HEAP_FLAGS (D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS)
- #define D3D12MA_EXTRA_DEFAULT_TYPE_HEAP_FLAGS (D3D12_HEAP_FLAG_NONE)
+ #define D3D12MA_ALLOW_SHADER_ATOMICS (1)
#endif
////////////////////////////////////////////////////////////////////////////////
@@ -730,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
@@ -1610,9 +1621,9 @@
private:
List<T>* m_pList;
- List<T>::Item* m_pItem;
+ Item* m_pItem;
- iterator(List<T>* pList, List<T>::Item* pItem) :
+ iterator(List<T>* pList, Item* pItem) :
m_pList(pList),
m_pItem(pItem)
{
@@ -1692,14 +1703,14 @@
}
private:
- const_iterator(const List<T>* pList, const List<T>::Item* pItem) :
+ const_iterator(const List<T>* pList, const Item* pItem) :
m_pList(pList),
m_pItem(pItem)
{
}
const List<T>* m_pList;
- const List<T>::Item* m_pItem;
+ const Item* m_pItem;
friend class List<T>;
};
@@ -1936,7 +1947,7 @@
}
template<typename T>
-typename List<T>::Item* List<T>::InsertBefore(List<T>::Item* pItem, const T& value)
+typename List<T>::Item* List<T>::InsertBefore(Item* pItem, const T& value)
{
Item* const newItem = InsertBefore(pItem);
newItem->Value = value;
@@ -1944,7 +1955,7 @@
}
template<typename T>
-typename List<T>::Item* List<T>::InsertAfter(List<T>::Item* pItem, const T& value)
+typename List<T>::Item* List<T>::InsertAfter(Item* pItem, const T& value)
{
Item* const newItem = InsertAfter(pItem);
newItem->Value = value;
@@ -2442,7 +2453,6 @@
HRESULT AllocateMemory(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation);
@@ -2515,7 +2525,6 @@
// Creates and returns Allocation object.
HRESULT AllocateHeap(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo,
Allocation** ppAllocation);
@@ -2538,7 +2547,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.
@@ -3317,7 +3326,7 @@
{
Budget budget = {};
m_hAllocator->GetBudgetForHeapType(budget, m_HeapType);
- freeMemory = (budget.Usage < budget.Budget) ? (budget.Budget - budget.Usage) : 0;
+ freeMemory = (budget.UsageBytes < budget.BudgetBytes) ? (budget.BudgetBytes - budget.UsageBytes) : 0;
}
const bool canCreateNewBlock =
@@ -3436,7 +3445,7 @@
{
Budget budget = {};
m_hAllocator->GetBudgetForHeapType(budget, m_HeapType);
- budgetExceeded = budget.Usage >= budget.Budget;
+ budgetExceeded = budget.UsageBytes >= budget.BudgetBytes;
}
// Scope for lock.
@@ -3754,6 +3763,20 @@
D3D12MA_ASSERT(resAllocInfo.SizeInBytes > 0);
const UINT defaultPoolIndex = CalcDefaultPoolIndex(*pAllocDesc, resourceDesc2);
+ 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);
@@ -3831,7 +3854,6 @@
HRESULT AllocatorPimpl::AllocateMemory(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation)
{
@@ -3844,16 +3866,18 @@
ALLOCATION_DESC finalAllocDesc = *pAllocDesc;
- const UINT defaultPoolIndex = CalcDefaultPoolIndex(*pAllocDesc, heapFlags);
- if(defaultPoolIndex == UINT32_MAX)
+ const UINT defaultPoolIndex = CalcDefaultPoolIndex(*pAllocDesc);
+ bool requireCommittedMemory = (defaultPoolIndex == UINT32_MAX);
+ if(requireCommittedMemory)
{
- return E_INVALIDARG;
+ return AllocateHeap(&finalAllocDesc, *pAllocInfo, ppAllocation);
}
+
BlockVector* blockVector = m_BlockVectors[defaultPoolIndex];
D3D12MA_ASSERT(blockVector);
const UINT64 preferredBlockSize = blockVector->GetPreferredBlockSize();
- bool preferCommittedMemory =
+ const bool preferCommittedMemory =
m_AlwaysCommitted ||
// Heuristics: Allocate committed memory if requested size if greater than half of preferred block size.
pAllocInfo->SizeInBytes > preferredBlockSize / 2;
@@ -3865,7 +3889,7 @@
if((finalAllocDesc.Flags & ALLOCATION_FLAG_COMMITTED) != 0)
{
- return AllocateHeap(&finalAllocDesc, heapFlags, *pAllocInfo, ppAllocation);
+ return AllocateHeap(&finalAllocDesc, *pAllocInfo, ppAllocation);
}
else
{
@@ -3880,7 +3904,7 @@
return hr;
}
- return AllocateHeap(&finalAllocDesc, heapFlags, *pAllocInfo, ppAllocation);
+ return AllocateHeap(&finalAllocDesc, *pAllocInfo, ppAllocation);
}
}
@@ -3909,7 +3933,7 @@
{
Budget budget = {};
GetBudgetForHeapType(budget, pAllocDesc->HeapType);
- if(budget.Usage + resAllocInfo.SizeInBytes > budget.Budget)
+ if(budget.UsageBytes + resAllocInfo.SizeInBytes > budget.BudgetBytes)
{
return E_OUTOFMEMORY;
}
@@ -3918,8 +3942,14 @@
D3D12_HEAP_PROPERTIES heapProps = {};
heapProps.Type = pAllocDesc->HeapType;
- const D3D12_HEAP_FLAGS heapFlags = pAllocDesc->HeapType == D3D12_HEAP_TYPE_DEFAULT ?
- D3D12MA_EXTRA_DEFAULT_TYPE_HEAP_FLAGS : 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)
+ {
+ D3D12MA_ASSERT(pAllocDesc->HeapType == D3D12_HEAP_TYPE_DEFAULT);
+ heapFlags = D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS;
+ }
+#endif
ID3D12Resource* res = NULL;
HRESULT hr = m_Device->CreateCommittedResource(
@@ -3950,7 +3980,6 @@
HRESULT AllocatorPimpl::AllocateHeap(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo,
Allocation** ppAllocation)
{
@@ -3965,16 +3994,19 @@
{
Budget budget = {};
GetBudgetForHeapType(budget, pAllocDesc->HeapType);
- if(budget.Usage + allocInfo.SizeInBytes > budget.Budget)
+ if(budget.UsageBytes + allocInfo.SizeInBytes > budget.BudgetBytes)
{
return E_OUTOFMEMORY;
}
}
+ D3D12_HEAP_FLAGS heapFlags = pAllocDesc->ExtraHeapFlags;
+#if D3D12MA_ALLOW_SHADER_ATOMICS
if(pAllocDesc->HeapType == D3D12_HEAP_TYPE_DEFAULT)
{
- heapFlags |= D3D12MA_EXTRA_DEFAULT_TYPE_HEAP_FLAGS;
+ heapFlags |= D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS;
}
+#endif
D3D12_HEAP_DESC heapDesc = {};
heapDesc.SizeInBytes = allocInfo.SizeInBytes;
@@ -4012,6 +4044,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)
{
@@ -4039,8 +4077,14 @@
return poolIndex;
}
-UINT AllocatorPimpl::CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, const D3D12_HEAP_FLAGS heapFlags) const
+UINT AllocatorPimpl::CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc) const
{
+ const D3D12_HEAP_FLAGS extraHeapFlags = allocDesc.ExtraHeapFlags & ~GetExtraHeapFlagsToIgnore();
+ if(extraHeapFlags != 0)
+ {
+ return UINT32_MAX;
+ }
+
UINT poolIndex = UINT_MAX;
switch(allocDesc.HeapType)
{
@@ -4054,9 +4098,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)
@@ -4115,10 +4159,12 @@
D3D12MA_ASSERT(0);
}
+#if D3D12MA_ALLOW_SHADER_ATOMICS
if(outHeapType == D3D12_HEAP_TYPE_DEFAULT)
{
- outHeapFlags |= D3D12MA_EXTRA_DEFAULT_TYPE_HEAP_FLAGS;
+ outHeapFlags |= D3D12_HEAP_FLAG_ALLOW_SHADER_ATOMICS;
}
+#endif
}
void AllocatorPimpl::RegisterCommittedAllocation(Allocation* alloc, D3D12_HEAP_TYPE heapType)
@@ -4266,27 +4312,27 @@
if(m_Budget.m_D3D12UsageLocal + outGpuBudget->BlockBytes > m_Budget.m_BlockBytesAtBudgetFetch[0])
{
- outGpuBudget->Usage = m_Budget.m_D3D12UsageLocal +
+ outGpuBudget->UsageBytes = m_Budget.m_D3D12UsageLocal +
outGpuBudget->BlockBytes - m_Budget.m_BlockBytesAtBudgetFetch[0];
}
else
{
- outGpuBudget->Usage = 0;
+ outGpuBudget->UsageBytes = 0;
}
- outGpuBudget->Budget = m_Budget.m_D3D12BudgetLocal;
+ outGpuBudget->BudgetBytes = m_Budget.m_D3D12BudgetLocal;
}
if(outCpuBudget)
{
if(m_Budget.m_D3D12UsageNonLocal + outCpuBudget->BlockBytes > m_Budget.m_BlockBytesAtBudgetFetch[1] + m_Budget.m_BlockBytesAtBudgetFetch[2])
{
- outCpuBudget->Usage = m_Budget.m_D3D12UsageNonLocal +
+ outCpuBudget->UsageBytes = m_Budget.m_D3D12UsageNonLocal +
outCpuBudget->BlockBytes - (m_Budget.m_BlockBytesAtBudgetFetch[1] + m_Budget.m_BlockBytesAtBudgetFetch[2]);
}
else
{
- outCpuBudget->Usage = 0;
+ outCpuBudget->UsageBytes = 0;
}
- outCpuBudget->Budget = m_Budget.m_D3D12BudgetNonLocal;
+ outCpuBudget->BudgetBytes = m_Budget.m_D3D12BudgetNonLocal;
}
}
else
@@ -4301,14 +4347,14 @@
if(outGpuBudget)
{
const UINT64 gpuMemorySize = m_AdapterDesc.DedicatedVideoMemory + m_AdapterDesc.DedicatedSystemMemory; // TODO: Is this right?
- outGpuBudget->Usage = outGpuBudget->BlockBytes;
- outGpuBudget->Budget = gpuMemorySize * 8 / 10; // 80% heuristics.
+ outGpuBudget->UsageBytes = outGpuBudget->BlockBytes;
+ outGpuBudget->BudgetBytes = gpuMemorySize * 8 / 10; // 80% heuristics.
}
if(outCpuBudget)
{
const UINT64 cpuMemorySize = m_AdapterDesc.SharedSystemMemory; // TODO: Is this right?
- outCpuBudget->Usage = outCpuBudget->BlockBytes;
- outCpuBudget->Budget = cpuMemorySize * 8 / 10; // 80% heuristics.
+ outCpuBudget->UsageBytes = outCpuBudget->BlockBytes;
+ outCpuBudget->BudgetBytes = cpuMemorySize * 8 / 10; // 80% heuristics.
}
}
}
@@ -4573,10 +4619,10 @@
json.WriteNumber(budget.BlockBytes);
json.WriteString(L"AllocationBytes");
json.WriteNumber(budget.AllocationBytes);
- json.WriteString(L"Usage");
- json.WriteNumber(budget.Usage);
- json.WriteString(L"Budget");
- json.WriteNumber(budget.Budget);
+ json.WriteString(L"UsageBytes");
+ json.WriteNumber(budget.UsageBytes);
+ json.WriteString(L"BudgetBytes");
+ json.WriteNumber(budget.BudgetBytes);
}
json.EndObject();
}
@@ -4814,7 +4860,6 @@
HRESULT Allocator::AllocateMemory(
const ALLOCATION_DESC* pAllocDesc,
- D3D12_HEAP_FLAGS heapFlags,
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
Allocation** ppAllocation)
{
@@ -4825,14 +4870,13 @@
pAllocInfo->Alignment == D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ||
pAllocInfo->Alignment == D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT) ||
pAllocInfo->SizeInBytes == 0 ||
- pAllocInfo->SizeInBytes % (64ull * 1024) != 0 ||
- (heapFlags & ~(D3D12_HEAP_FLAG_DENY_BUFFERS | D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES | D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES)) != 0)
+ pAllocInfo->SizeInBytes % (64ull * 1024) != 0)
{
D3D12MA_ASSERT(0 && "Invalid arguments passed to Allocator::AllocateMemory.");
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 2f0870d..4898e38 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.
@@ -722,7 +739,7 @@
also occupying the memory, like swapchain, pipeline state objects, descriptor heaps, command lists, or
memory blocks allocated outside of this library, if any.
*/
- UINT64 Usage;
+ UINT64 UsageBytes;
/** \brief Estimated amount of memory available to the program, in bytes.
@@ -730,10 +747,10 @@
It might be different (most probably smaller) than memory sizes reported in `DXGI_ADAPTER_DESC` due to factors
external to the program, like other programs also consuming system resources.
- Difference `Budget - Usage` is the amount of additional memory that can probably
+ Difference `BudgetBytes - UsageBytes` is the amount of additional memory that can probably
be allocated without problems. Exceeding the budget may result in various problems.
*/
- UINT64 Budget;
+ UINT64 BudgetBytes;
};
/**
@@ -796,12 +813,13 @@
This function is similar to `ID3D12Device::CreateHeap`, but it may really assign
part of a larger, existing heap to the allocation.
- If ResourceHeapTier = 1, `heapFlags` must be one of these values, depending on type
+ If ResourceHeapTier = 1, `heapFlags` must contain one of these values, depending on type
of resources you are going to create in this memory:
`D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS`,
`D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES`,
`D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES`.
- If ResourceHeapTier = 2, `heapFlags` may be `D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES`.
+ If ResourceHeapTier = 2, `heapFlags` may be `D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES` = 0.
+ Additional flags in `heapFlags` are allowed as well.
`pAllocInfo->SizeInBytes` must be multiply of 64KB.
`pAllocInfo->Alignment` must be one of the legal values as described in documentation of `D3D12_HEAP_DESC`.
@@ -811,7 +829,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 113c64a..2c1bfb3 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -178,7 +178,7 @@
ResourceWithAllocation resources[count];
D3D12MA::ALLOCATION_DESC allocDesc = {};
- allocDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD;
+ allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_COMMITTED;
D3D12_RESOURCE_DESC resourceDesc;
@@ -192,7 +192,7 @@
CHECK_HR( ctx.allocator->CreateResource(
&allocDesc,
&resourceDesc,
- D3D12_RESOURCE_STATE_GENERIC_READ,
+ D3D12_RESOURCE_STATE_COPY_DEST,
NULL,
&alloc,
__uuidof(ID3D12Resource),
@@ -236,6 +236,65 @@
ctx.allocator->FreeStatsString(jsonString);
}
+static void TestCustomHeapFlags(const TestContext& ctx)
+{
+ wprintf(L"Test custom heap flags\n");
+
+ // 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.
+
+ 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);
+
+ // 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)
{
wprintf(L"Test placed resources\n");
@@ -346,6 +405,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 +443,6 @@
D3D12MA::Allocation* allocPtr = NULL;
CHECK_HR( ctx.allocator->AllocateMemory(
&allocDesc,
- D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES,
&allocInfo,
&allocPtr) );
AllocationUniquePtr alloc(allocPtr);
@@ -941,6 +1000,7 @@
{
TestFrameIndexAndJson(ctx);
TestCommittedResourcesAndJson(ctx);
+ TestCustomHeapFlags(ctx);
TestPlacedResources(ctx);
TestAliasingMemory(ctx);
TestMapping(ctx);