mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git
synced 2024-11-21 19:50:05 +00:00
Removed Pool::SetMinBytes, Allocator::SetDefaultHeapMinBytes (compatibility breaking!)
More refactoring. Added private enum ResourceClass.
This commit is contained in:
parent
b2c5183078
commit
49fb8acf85
@ -687,6 +687,42 @@ static UINT GetBitsPerPixel(DXGI_FORMAT format)
|
||||
}
|
||||
}
|
||||
|
||||
static const D3D12_HEAP_FLAGS RESOURCE_CLASS_HEAP_FLAGS =
|
||||
D3D12_HEAP_FLAG_DENY_BUFFERS | D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES | D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES;
|
||||
|
||||
enum class ResourceClass
|
||||
{
|
||||
Unknown, Buffer, Non_RT_DS_Texture, RT_DS_Texture
|
||||
};
|
||||
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
static inline ResourceClass ResourceDescToResourceClass(const D3D12_RESOURCE_DESC_T& resDesc)
|
||||
{
|
||||
if(resDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
return ResourceClass::Buffer;
|
||||
// Else: it's surely a texture.
|
||||
const bool isRenderTargetOrDepthStencil =
|
||||
(resDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0;
|
||||
return isRenderTargetOrDepthStencil ? ResourceClass::RT_DS_Texture : ResourceClass::Non_RT_DS_Texture;
|
||||
}
|
||||
|
||||
static inline ResourceClass HeapFlagsToResourceClass(D3D12_HEAP_FLAGS heapFlags)
|
||||
{
|
||||
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 uint8_t allowedGroupCount = (allowBuffers ? 1 : 0) + (allowRtDsTextures ? 1 : 0) + (allowNonRtDsTextures ? 1 : 0);
|
||||
if(allowedGroupCount != 1)
|
||||
return ResourceClass::Unknown;
|
||||
|
||||
if(allowRtDsTextures)
|
||||
return ResourceClass::RT_DS_Texture;
|
||||
if(allowNonRtDsTextures)
|
||||
return ResourceClass::Non_RT_DS_Texture;
|
||||
return ResourceClass::Buffer;
|
||||
}
|
||||
|
||||
// This algorithm is overly conservative.
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
static bool CanUseSmallAlignment(const D3D12_RESOURCE_DESC_T& resourceDesc)
|
||||
@ -728,13 +764,6 @@ static bool CanUseSmallAlignment(const D3D12_RESOURCE_DESC_T& resourceDesc)
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline bool IsHeapTypeStandard(D3D12_HEAP_TYPE type)
|
||||
{
|
||||
return type == D3D12_HEAP_TYPE_DEFAULT ||
|
||||
@ -2644,8 +2673,6 @@ public:
|
||||
void** ppvResource);
|
||||
#endif // #ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
|
||||
HRESULT SetMinBytes(UINT64 minBytes);
|
||||
|
||||
void AddStats(StatInfo& outStats);
|
||||
void AddStats(Stats& outStats);
|
||||
|
||||
@ -2659,7 +2686,6 @@ private:
|
||||
const size_t m_MinBlockCount;
|
||||
const size_t m_MaxBlockCount;
|
||||
const bool m_ExplicitBlockSize;
|
||||
UINT64 m_MinBytes;
|
||||
/* There can be at most one allocation that is completely empty - a
|
||||
hysteresis to avoid pessimistic case of alternating creation and destruction
|
||||
of a VkDeviceMemory. */
|
||||
@ -2754,8 +2780,6 @@ public:
|
||||
const POOL_DESC& GetDesc() const { return m_Desc; }
|
||||
BlockVector* GetBlockVector() { return m_BlockVector; }
|
||||
|
||||
HRESULT SetMinBytes(UINT64 minBytes) { return m_BlockVector->SetMinBytes(minBytes); }
|
||||
|
||||
void CalculateStats(StatInfo& outStats);
|
||||
|
||||
void SetName(LPCWSTR Name);
|
||||
@ -2865,11 +2889,6 @@ public:
|
||||
REFIID riidResource,
|
||||
void** ppvResource);
|
||||
|
||||
HRESULT SetDefaultHeapMinBytes(
|
||||
D3D12_HEAP_TYPE heapType,
|
||||
D3D12_HEAP_FLAGS heapFlags,
|
||||
UINT64 minBytes);
|
||||
|
||||
// Unregisters allocation from the collection of dedicated allocations.
|
||||
// Allocation object must be deleted externally afterwards.
|
||||
void FreeCommittedMemory(Allocation* allocation);
|
||||
@ -2934,11 +2953,6 @@ private:
|
||||
|
||||
CommittedAllocationList m_CommittedAllocations[STANDARD_HEAP_TYPE_COUNT];
|
||||
|
||||
// # Used only when ResourceHeapTier = 1
|
||||
UINT64 m_DefaultPoolTier1MinBytes[DEFAULT_POOL_MAX_COUNT]; // Default 0
|
||||
UINT64 m_DefaultPoolHeapTypeMinBytes[HEAP_TYPE_COUNT]; // Default UINT64_MAX, meaning not set
|
||||
D3D12MA_RW_MUTEX m_DefaultPoolMinBytesMutex;
|
||||
|
||||
// Allocates and registers new committed resource with implicit heap, as dedicated allocation.
|
||||
// Creates and returns Allocation object.
|
||||
HRESULT AllocateCommittedResource(
|
||||
@ -3027,18 +3041,8 @@ private:
|
||||
8: D3D12_HEAP_TYPE_READBACK + texture RT or DS
|
||||
*/
|
||||
UINT CalcDefaultPoolCount() const;
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
UINT CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, const D3D12_RESOURCE_DESC_T& resourceDesc) const;
|
||||
// This one returns UINT32_MAX if nonstandard heap flags are used and index cannot be calculcated.
|
||||
static UINT CalcDefaultPoolIndex(D3D12_HEAP_TYPE heapType, D3D12_HEAP_FLAGS heapFlags, bool supportsResourceHeapTier2);
|
||||
UINT CalcDefaultPoolIndex(D3D12_HEAP_TYPE heapType, D3D12_HEAP_FLAGS heapFlags) const
|
||||
{
|
||||
return CalcDefaultPoolIndex(heapType, heapFlags, SupportsResourceHeapTier2());
|
||||
}
|
||||
UINT CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc) const
|
||||
{
|
||||
return CalcDefaultPoolIndex(allocDesc.HeapType, allocDesc.ExtraHeapFlags);
|
||||
}
|
||||
// Returns UINT32_MAX if index cannot be calculcated.
|
||||
UINT CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, ResourceClass resourceClass) const;
|
||||
void CalcDefaultPoolParams(D3D12_HEAP_TYPE& outHeapType, D3D12_HEAP_FLAGS& outHeapFlags, UINT index) const;
|
||||
|
||||
// Registers Pool object in m_Pools.
|
||||
@ -3860,7 +3864,6 @@ BlockVector::BlockVector(
|
||||
m_MinBlockCount(minBlockCount),
|
||||
m_MaxBlockCount(maxBlockCount),
|
||||
m_ExplicitBlockSize(explicitBlockSize),
|
||||
m_MinBytes(0),
|
||||
m_HasEmptyBlock(false),
|
||||
m_Blocks(hAllocator->GetAllocs()),
|
||||
m_NextBlockId(0)
|
||||
@ -4084,8 +4087,7 @@ void BlockVector::Free(Allocation* hAllocation)
|
||||
{
|
||||
// Already has empty Allocation. We don't want to have two, so delete this one.
|
||||
if((m_HasEmptyBlock || budgetExceeded) &&
|
||||
blockCount > m_MinBlockCount &&
|
||||
sumBlockSize - pBlock->m_pMetadata->GetSize() >= m_MinBytes)
|
||||
blockCount > m_MinBlockCount)
|
||||
{
|
||||
pBlockToDelete = pBlock;
|
||||
Remove(pBlock);
|
||||
@ -4101,8 +4103,7 @@ void BlockVector::Free(Allocation* hAllocation)
|
||||
else if(m_HasEmptyBlock && blockCount > m_MinBlockCount)
|
||||
{
|
||||
NormalBlock* pLastBlock = m_Blocks.back();
|
||||
if(pLastBlock->m_pMetadata->IsEmpty() &&
|
||||
sumBlockSize - pLastBlock->m_pMetadata->GetSize() >= m_MinBytes)
|
||||
if(pLastBlock->m_pMetadata->IsEmpty())
|
||||
{
|
||||
pBlockToDelete = pLastBlock;
|
||||
m_Blocks.pop_back();
|
||||
@ -4328,89 +4329,6 @@ HRESULT BlockVector::CreateBlock(UINT64 blockSize, size_t* pNewBlockIndex)
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT BlockVector::SetMinBytes(UINT64 minBytes)
|
||||
{
|
||||
MutexLockWrite lock(m_Mutex, m_hAllocator->UseMutex());
|
||||
|
||||
if(minBytes == m_MinBytes)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
UINT64 sumBlockSize = CalcSumBlockSize();
|
||||
size_t blockCount = m_Blocks.size();
|
||||
|
||||
// New minBytes is smaller - may be able to free some blocks.
|
||||
if(minBytes < m_MinBytes)
|
||||
{
|
||||
m_HasEmptyBlock = false; // Will recalculate this value from scratch.
|
||||
for(size_t blockIndex = blockCount; blockIndex--; )
|
||||
{
|
||||
NormalBlock* const block = m_Blocks[blockIndex];
|
||||
const UINT64 size = block->m_pMetadata->GetSize();
|
||||
const bool isEmpty = block->m_pMetadata->IsEmpty();
|
||||
if(isEmpty &&
|
||||
sumBlockSize - size >= minBytes &&
|
||||
blockCount - 1 >= m_MinBlockCount)
|
||||
{
|
||||
D3D12MA_DELETE(m_hAllocator->GetAllocs(), block);
|
||||
m_Blocks.remove(blockIndex);
|
||||
sumBlockSize -= size;
|
||||
--blockCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isEmpty)
|
||||
{
|
||||
m_HasEmptyBlock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// New minBytes is larger - may need to allocate some blocks.
|
||||
else
|
||||
{
|
||||
const UINT64 minBlockSize = m_PreferredBlockSize >> NEW_BLOCK_SIZE_SHIFT_MAX;
|
||||
while(SUCCEEDED(hr) && sumBlockSize < minBytes)
|
||||
{
|
||||
if(blockCount < m_MaxBlockCount)
|
||||
{
|
||||
UINT64 newBlockSize = m_PreferredBlockSize;
|
||||
if(!m_ExplicitBlockSize)
|
||||
{
|
||||
if(sumBlockSize + newBlockSize > minBytes)
|
||||
{
|
||||
newBlockSize = minBytes - sumBlockSize;
|
||||
}
|
||||
// Next one would be the last block to create and its size would be smaller than
|
||||
// the smallest block size we want to use here, so make this one smaller.
|
||||
else if(blockCount + 1 < m_MaxBlockCount &&
|
||||
sumBlockSize + newBlockSize + minBlockSize > minBytes)
|
||||
{
|
||||
newBlockSize -= minBlockSize + sumBlockSize + m_PreferredBlockSize - minBytes;
|
||||
}
|
||||
}
|
||||
|
||||
hr = CreateBlock(newBlockSize, NULL);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
m_HasEmptyBlock = true;
|
||||
sumBlockSize += newBlockSize;
|
||||
++blockCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_MinBytes = minBytes;
|
||||
return hr;
|
||||
}
|
||||
|
||||
void BlockVector::AddStats(StatInfo& outStats)
|
||||
{
|
||||
MutexLockRead lock(m_Mutex, m_hAllocator->UseMutex());
|
||||
@ -4561,11 +4479,6 @@ POOL_DESC Pool::GetDesc() const
|
||||
return m_Pimpl->GetDesc();
|
||||
}
|
||||
|
||||
HRESULT Pool::SetMinBytes(UINT64 minBytes)
|
||||
{
|
||||
return m_Pimpl->SetMinBytes(minBytes);
|
||||
}
|
||||
|
||||
void Pool::CalculateStats(StatInfo* pStats)
|
||||
{
|
||||
D3D12MA_ASSERT(pStats);
|
||||
@ -4615,12 +4528,6 @@ AllocatorPimpl::AllocatorPimpl(const ALLOCATION_CALLBACKS& allocationCallbacks,
|
||||
ZeroMemory(&m_D3D12Architecture, sizeof(m_D3D12Architecture));
|
||||
|
||||
ZeroMemory(m_BlockVectors, sizeof(m_BlockVectors));
|
||||
ZeroMemory(m_DefaultPoolTier1MinBytes, sizeof(m_DefaultPoolTier1MinBytes));
|
||||
|
||||
for(UINT i = 0; i < HEAP_TYPE_COUNT; ++i)
|
||||
{
|
||||
m_DefaultPoolHeapTypeMinBytes[i] = UINT64_MAX;
|
||||
}
|
||||
|
||||
for(UINT i = 0; i < STANDARD_HEAP_TYPE_COUNT; ++i)
|
||||
{
|
||||
@ -4790,7 +4697,8 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
}
|
||||
else
|
||||
{
|
||||
const UINT defaultPoolIndex = CalcDefaultPoolIndex(*pAllocDesc, finalResourceDesc);
|
||||
const ResourceClass resourceClass = ResourceDescToResourceClass(finalResourceDesc);
|
||||
const UINT defaultPoolIndex = CalcDefaultPoolIndex(*pAllocDesc, resourceClass);
|
||||
const bool requireCommittedMemory = defaultPoolIndex == UINT32_MAX;
|
||||
if(requireCommittedMemory)
|
||||
{
|
||||
@ -4969,7 +4877,8 @@ HRESULT AllocatorPimpl::CreateResource2(
|
||||
}
|
||||
else
|
||||
{
|
||||
const UINT defaultPoolIndex = CalcDefaultPoolIndex(*pAllocDesc, finalResourceDesc);
|
||||
const ResourceClass resourceClass = ResourceDescToResourceClass(finalResourceDesc);
|
||||
const UINT defaultPoolIndex = CalcDefaultPoolIndex(*pAllocDesc, resourceClass);
|
||||
requireCommittedMemory = requireCommittedMemory || defaultPoolIndex == UINT32_MAX;
|
||||
if(requireCommittedMemory)
|
||||
{
|
||||
@ -5154,71 +5063,6 @@ HRESULT AllocatorPimpl::CreateAliasingResource(
|
||||
ppvResource);
|
||||
}
|
||||
|
||||
HRESULT AllocatorPimpl::SetDefaultHeapMinBytes(
|
||||
D3D12_HEAP_TYPE heapType,
|
||||
D3D12_HEAP_FLAGS heapFlags,
|
||||
UINT64 minBytes)
|
||||
{
|
||||
if(!IsHeapTypeStandard(heapType))
|
||||
{
|
||||
D3D12MA_ASSERT(0 && "Allocator::SetDefaultHeapMinBytes: Invalid heapType passed.");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if(SupportsResourceHeapTier2())
|
||||
{
|
||||
if(heapFlags != D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES &&
|
||||
heapFlags != D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS &&
|
||||
heapFlags != D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES &&
|
||||
heapFlags != D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES)
|
||||
{
|
||||
D3D12MA_ASSERT(0 && "Allocator::SetDefaultHeapMinBytes: Invalid heapFlags passed.");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
UINT64 newMinBytes = UINT64_MAX;
|
||||
|
||||
{
|
||||
MutexLockWrite lock(m_DefaultPoolMinBytesMutex, m_UseMutex);
|
||||
|
||||
if(heapFlags == D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES)
|
||||
{
|
||||
m_DefaultPoolHeapTypeMinBytes[HeapTypeToIndex(heapType)] = minBytes;
|
||||
newMinBytes = minBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
const UINT defaultPoolTier1Index = CalcDefaultPoolIndex(heapType, heapFlags, false);
|
||||
m_DefaultPoolTier1MinBytes[defaultPoolTier1Index] = minBytes;
|
||||
|
||||
newMinBytes = m_DefaultPoolHeapTypeMinBytes[HeapTypeToIndex(heapType)];
|
||||
if(newMinBytes == UINT64_MAX)
|
||||
{
|
||||
newMinBytes = m_DefaultPoolTier1MinBytes[CalcDefaultPoolIndex(heapType, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS, false)] +
|
||||
m_DefaultPoolTier1MinBytes[CalcDefaultPoolIndex(heapType, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES, false)] +
|
||||
m_DefaultPoolTier1MinBytes[CalcDefaultPoolIndex(heapType, D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES, false)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const UINT defaultPoolIndex = CalcDefaultPoolIndex(heapType, D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES);
|
||||
return m_BlockVectors[defaultPoolIndex]->SetMinBytes(newMinBytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(heapFlags != D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS &&
|
||||
heapFlags != D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES &&
|
||||
heapFlags != D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES)
|
||||
{
|
||||
D3D12MA_ASSERT(0 && "Allocator::SetDefaultHeapMinBytes: Invalid heapFlags passed.");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
const UINT defaultPoolIndex = CalcDefaultPoolIndex(heapType, heapFlags);
|
||||
return m_BlockVectors[defaultPoolIndex]->SetMinBytes(minBytes);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
bool AllocatorPimpl::PrefersCommittedAllocation(const D3D12_RESOURCE_DESC_T& resourceDesc)
|
||||
{
|
||||
@ -5553,10 +5397,9 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
|
||||
|
||||
if(allocDesc.CustomPool != NULL)
|
||||
{
|
||||
if((allocDesc.Flags & ALLOCATION_FLAG_COMMITTED) == 0)
|
||||
{
|
||||
outBlockVector = allocDesc.CustomPool->m_Pimpl->GetBlockVector();
|
||||
}
|
||||
PoolPimpl* const pool = allocDesc.CustomPool->m_Pimpl;
|
||||
outBlockVector = pool->GetBlockVector();
|
||||
outCommittedAllocationList = &pool->m_CommittedAllocations;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -5564,14 +5407,12 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if((allocDesc.Flags & ALLOCATION_FLAG_NEVER_ALLOCATE) == 0)
|
||||
{
|
||||
|
||||
outCommittedAllocationList = &m_CommittedAllocations[HeapTypeToIndex(allocDesc.HeapType)];
|
||||
}
|
||||
if(!m_AlwaysCommitted &&
|
||||
(allocDesc.Flags & ALLOCATION_FLAG_COMMITTED) == 0)
|
||||
{
|
||||
const UINT defaultPoolIndex = CalcDefaultPoolIndex(allocDesc);
|
||||
|
||||
const ResourceClass resourceClass = (resDesc != NULL) ?
|
||||
ResourceDescToResourceClass(*resDesc) : HeapFlagsToResourceClass(allocDesc.ExtraHeapFlags);
|
||||
const UINT defaultPoolIndex = CalcDefaultPoolIndex(allocDesc, resourceClass);
|
||||
if(defaultPoolIndex != UINT32_MAX)
|
||||
{
|
||||
outBlockVector = m_BlockVectors[defaultPoolIndex];
|
||||
@ -5586,10 +5427,29 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
|
||||
outPreferCommitted = true;
|
||||
}
|
||||
}
|
||||
|
||||
const D3D12_HEAP_FLAGS extraHeapFlags = allocDesc.ExtraHeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS;
|
||||
if(outBlockVector != NULL && extraHeapFlags != 0)
|
||||
{
|
||||
outBlockVector = NULL;
|
||||
}
|
||||
}
|
||||
if(resDesc != NULL && PrefersCommittedAllocation(*resDesc))
|
||||
|
||||
if((allocDesc.Flags & ALLOCATION_FLAG_COMMITTED) != 0 ||
|
||||
m_AlwaysCommitted)
|
||||
{
|
||||
outBlockVector = NULL;
|
||||
}
|
||||
if((allocDesc.Flags & ALLOCATION_FLAG_NEVER_ALLOCATE) != 0)
|
||||
{
|
||||
outCommittedAllocationList = NULL;
|
||||
}
|
||||
|
||||
if(resDesc != NULL && !outPreferCommitted && PrefersCommittedAllocation(*resDesc))
|
||||
{
|
||||
outPreferCommitted = true;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -5605,10 +5465,9 @@ UINT AllocatorPimpl::CalcDefaultPoolCount() const
|
||||
}
|
||||
}
|
||||
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
UINT AllocatorPimpl::CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, const D3D12_RESOURCE_DESC_T& resourceDesc) const
|
||||
UINT AllocatorPimpl::CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, ResourceClass resourceClass) const
|
||||
{
|
||||
const D3D12_HEAP_FLAGS extraHeapFlags = allocDesc.ExtraHeapFlags & ~GetExtraHeapFlagsToIgnore();
|
||||
const D3D12_HEAP_FLAGS extraHeapFlags = allocDesc.ExtraHeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS;
|
||||
if(extraHeapFlags != 0)
|
||||
{
|
||||
return UINT32_MAX;
|
||||
@ -5623,66 +5482,22 @@ UINT AllocatorPimpl::CalcDefaultPoolIndex(const ALLOCATION_DESC& allocDesc, cons
|
||||
default: D3D12MA_ASSERT(0);
|
||||
}
|
||||
|
||||
if(!SupportsResourceHeapTier2())
|
||||
{
|
||||
poolIndex *= 3;
|
||||
if(resourceDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER)
|
||||
{
|
||||
++poolIndex;
|
||||
const bool isRenderTargetOrDepthStencil =
|
||||
(resourceDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0;
|
||||
if(isRenderTargetOrDepthStencil)
|
||||
{
|
||||
++poolIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(SupportsResourceHeapTier2())
|
||||
return poolIndex;
|
||||
}
|
||||
|
||||
UINT AllocatorPimpl::CalcDefaultPoolIndex(D3D12_HEAP_TYPE heapType, D3D12_HEAP_FLAGS heapFlags, bool supportsResourceHeapTier2)
|
||||
{
|
||||
const D3D12_HEAP_FLAGS extraHeapFlags = heapFlags & ~GetExtraHeapFlagsToIgnore();
|
||||
if(extraHeapFlags != 0)
|
||||
else
|
||||
{
|
||||
switch(resourceClass)
|
||||
{
|
||||
case ResourceClass::Buffer:
|
||||
return poolIndex * 3;
|
||||
case ResourceClass::Non_RT_DS_Texture:
|
||||
return poolIndex * 3 + 1;
|
||||
case ResourceClass::RT_DS_Texture:
|
||||
return poolIndex * 3 + 2;
|
||||
default:
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
UINT poolIndex = UINT_MAX;
|
||||
switch(heapType)
|
||||
{
|
||||
case D3D12_HEAP_TYPE_DEFAULT: poolIndex = 0; break;
|
||||
case D3D12_HEAP_TYPE_UPLOAD: poolIndex = 1; break;
|
||||
case D3D12_HEAP_TYPE_READBACK: poolIndex = 2; break;
|
||||
default: D3D12MA_ASSERT(0);
|
||||
}
|
||||
|
||||
if(!supportsResourceHeapTier2)
|
||||
{
|
||||
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 uint8_t allowedGroupCount = (allowBuffers ? 1 : 0) + (allowRtDsTextures ? 1 : 0) + (allowNonRtDsTextures ? 1 : 0);
|
||||
if(allowedGroupCount != 1)
|
||||
{
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
if(!allowBuffers)
|
||||
{
|
||||
++poolIndex;
|
||||
if(allowRtDsTextures)
|
||||
{
|
||||
++poolIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return poolIndex;
|
||||
}
|
||||
|
||||
void AllocatorPimpl::CalcDefaultPoolParams(D3D12_HEAP_TYPE& outHeapType, D3D12_HEAP_FLAGS& outHeapFlags, UINT index) const
|
||||
@ -6597,15 +6412,6 @@ HRESULT Allocator::CreatePool(
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Allocator::SetDefaultHeapMinBytes(
|
||||
D3D12_HEAP_TYPE heapType,
|
||||
D3D12_HEAP_FLAGS heapFlags,
|
||||
UINT64 minBytes)
|
||||
{
|
||||
D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK
|
||||
return m_Pimpl->SetDefaultHeapMinBytes(heapType, heapFlags, minBytes);
|
||||
}
|
||||
|
||||
void Allocator::SetCurrentFrameIndex(UINT frameIndex)
|
||||
{
|
||||
D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK
|
||||
|
@ -40,7 +40,6 @@ Documentation of all members: D3D12MemAlloc.h
|
||||
- [Mapping memory](@ref quick_start_mapping_memory)
|
||||
- \subpage custom_pools
|
||||
- \subpage resource_aliasing
|
||||
- \subpage reserving_memory
|
||||
- \subpage virtual_allocator
|
||||
- \subpage configuration
|
||||
- [Custom CPU memory allocator](@ref custom_memory_allocator)
|
||||
@ -413,43 +412,6 @@ Additional considerations:
|
||||
Otherwise they must be placed in different memory heap types, and thus aliasing them is not possible.
|
||||
|
||||
|
||||
\page reserving_memory Reserving minimum amount of memory
|
||||
|
||||
The library automatically allocates and frees memory heaps.
|
||||
It also applies some hysteresis so that it doesn't allocate and free entire heap
|
||||
when you repeatedly create and release a single resource.
|
||||
However, if you want to make sure certain number of bytes is always allocated as heaps in a specific pool,
|
||||
you can use functions designed for this purpose:
|
||||
|
||||
- For default heaps use D3D12MA::Allocator::SetDefaultHeapMinBytes.
|
||||
- For custom heaps use D3D12MA::Pool::SetMinBytes.
|
||||
|
||||
Default is 0. You can change this parameter any time.
|
||||
Setting it to higher value may cause new heaps to be allocated.
|
||||
If this allocation fails, the function returns appropriate error code, but the parameter remains set to the new value.
|
||||
Setting it to lower value may cause some empty heaps to be released.
|
||||
|
||||
You can always call D3D12MA::Allocator::SetDefaultHeapMinBytes for 3 sets of heap flags separately:
|
||||
`D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS`, `D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES`, `D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES`.
|
||||
When ResourceHeapTier = 2, so that all types of resourced are kept together,
|
||||
these 3 values as simply summed up to calculate minimum amount of bytes for default pool with certain heap type.
|
||||
Alternatively, when ResourceHeapTier = 2, you can call this function with
|
||||
`D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES` = 0. This will set a single value for the default pool and
|
||||
will override the sum of those three.
|
||||
|
||||
Reservation of minimum number of bytes interacts correctly with
|
||||
D3D12MA::POOL_DESC::MinBlockCount and D3D12MA::POOL_DESC::MaxBlockCount.
|
||||
For example, free blocks (heaps) of a custom pool will be released only when
|
||||
their number doesn't fall below `MinBlockCount` and their sum size doesn't fall below `MinBytes`.
|
||||
|
||||
Some restrictions apply:
|
||||
|
||||
- Setting `MinBytes` doesn't interact with memory budget. The allocator tries
|
||||
to create additional heaps when necessary without checking if they will exceed the budget.
|
||||
- Resources created as committed don't count into the number of bytes compared with `MinBytes` set.
|
||||
Only placed resources are considered.
|
||||
|
||||
|
||||
\page virtual_allocator Virtual allocator
|
||||
|
||||
As an extra feature, the core allocation algorithm of the library is exposed through a simple and convenient API of "virtual allocator".
|
||||
@ -1096,12 +1058,6 @@ public:
|
||||
*/
|
||||
POOL_DESC GetDesc() const;
|
||||
|
||||
/** \brief Sets the minimum number of bytes that should always be allocated (reserved) in this pool.
|
||||
|
||||
See also: \subpage reserving_memory.
|
||||
*/
|
||||
HRESULT SetMinBytes(UINT64 minBytes);
|
||||
|
||||
/** \brief Retrieves statistics from the current state of this pool.
|
||||
*/
|
||||
void CalculateStats(StatInfo* pStats);
|
||||
@ -1457,20 +1413,6 @@ public:
|
||||
const POOL_DESC* pPoolDesc,
|
||||
Pool** ppPool);
|
||||
|
||||
/** \brief Sets the minimum number of bytes that should always be allocated (reserved) in a specific default pool.
|
||||
|
||||
\param heapType Must be one of: `D3D12_HEAP_TYPE_DEFAULT`, `D3D12_HEAP_TYPE_UPLOAD`, `D3D12_HEAP_TYPE_READBACK`.
|
||||
\param heapFlags Must be one of: `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, it can also be `D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES`.
|
||||
\param minBytes Minimum number of bytes to keep allocated.
|
||||
|
||||
See also: \subpage reserving_memory.
|
||||
*/
|
||||
HRESULT SetDefaultHeapMinBytes(
|
||||
D3D12_HEAP_TYPE heapType,
|
||||
D3D12_HEAP_FLAGS heapFlags,
|
||||
UINT64 minBytes);
|
||||
|
||||
/** \brief Sets the index of the current frame.
|
||||
|
||||
This function is used to set the frame index in the allocator when a new game frame begins.
|
||||
|
@ -606,22 +606,6 @@ static void TestCustomPools(const TestContext& ctx)
|
||||
pool->SetName(NAME);
|
||||
CHECK_BOOL( wcscmp(pool->GetName(), NAME) == 0 );
|
||||
|
||||
// # SetMinBytes
|
||||
|
||||
CHECK_HR( pool->SetMinBytes(15 * MEGABYTE) );
|
||||
pool->CalculateStats(&poolStats);
|
||||
CHECK_BOOL( poolStats.BlockCount == 2 );
|
||||
CHECK_BOOL( poolStats.AllocationCount == 0 );
|
||||
CHECK_BOOL( poolStats.UsedBytes == 0 );
|
||||
CHECK_BOOL( poolStats.UnusedBytes == poolStats.BlockCount * poolDesc.BlockSize );
|
||||
|
||||
CHECK_HR( pool->SetMinBytes(0) );
|
||||
pool->CalculateStats(&poolStats);
|
||||
CHECK_BOOL( poolStats.BlockCount == 1 );
|
||||
CHECK_BOOL( poolStats.AllocationCount == 0 );
|
||||
CHECK_BOOL( poolStats.UsedBytes == 0 );
|
||||
CHECK_BOOL( poolStats.UnusedBytes == poolStats.BlockCount * poolDesc.BlockSize );
|
||||
|
||||
// # Create buffers 2x 5 MB
|
||||
|
||||
D3D12MA::ALLOCATION_DESC allocDesc = {};
|
||||
@ -806,26 +790,6 @@ static void TestCustomHeaps(const TestContext& ctx)
|
||||
CHECK_HR(hr);
|
||||
}
|
||||
|
||||
static void TestDefaultPoolMinBytes(const TestContext& ctx)
|
||||
{
|
||||
D3D12MA::Stats stats;
|
||||
ctx.allocator->CalculateStats(&stats);
|
||||
const UINT64 gpuAllocatedBefore = stats.HeapType[0].UsedBytes + stats.HeapType[0].UnusedBytes;
|
||||
|
||||
const UINT64 gpuAllocatedMin = gpuAllocatedBefore * 105 / 100;
|
||||
CHECK_HR( ctx.allocator->SetDefaultHeapMinBytes(D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS, CeilDiv(gpuAllocatedMin, 3ull)) );
|
||||
CHECK_HR( ctx.allocator->SetDefaultHeapMinBytes(D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES, CeilDiv(gpuAllocatedMin, 3ull)) );
|
||||
CHECK_HR( ctx.allocator->SetDefaultHeapMinBytes(D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES, CeilDiv(gpuAllocatedMin, 3ull)) );
|
||||
|
||||
ctx.allocator->CalculateStats(&stats);
|
||||
const UINT64 gpuAllocatedAfter = stats.HeapType[0].UsedBytes + stats.HeapType[0].UnusedBytes;
|
||||
CHECK_BOOL(gpuAllocatedAfter >= gpuAllocatedMin);
|
||||
|
||||
CHECK_HR( ctx.allocator->SetDefaultHeapMinBytes(D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS, 0) );
|
||||
CHECK_HR( ctx.allocator->SetDefaultHeapMinBytes(D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES, 0) );
|
||||
CHECK_HR( ctx.allocator->SetDefaultHeapMinBytes(D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES, 0) );
|
||||
}
|
||||
|
||||
static void TestAliasingMemory(const TestContext& ctx)
|
||||
{
|
||||
wprintf(L"Test aliasing memory\n");
|
||||
@ -1526,7 +1490,6 @@ static void TestGroupBasics(const TestContext& ctx)
|
||||
TestOtherComInterface(ctx);
|
||||
TestCustomPools(ctx);
|
||||
TestCustomHeaps(ctx);
|
||||
TestDefaultPoolMinBytes(ctx);
|
||||
TestAliasingMemory(ctx);
|
||||
TestMapping(ctx);
|
||||
TestStats(ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user