Add missing reporting from custom pools in Allocator::CalculateStats

This commit is contained in:
Adam Sawicki 2020-04-02 17:34:33 +02:00
parent f2bea63545
commit 07cf40a2b8
2 changed files with 106 additions and 25 deletions

View File

@ -2510,6 +2510,7 @@ public:
private:
friend class Allocator;
friend class Pool;
/*
Heuristics that decides whether a resource should better be placed in its own,
@ -2535,6 +2536,10 @@ private:
AllocationVectorType* m_pCommittedAllocations[HEAP_TYPE_COUNT];
D3D12MA_RW_MUTEX m_CommittedAllocationsMutex[HEAP_TYPE_COUNT];
typedef Vector<Pool*> PoolVectorType;
PoolVectorType* m_pPools[HEAP_TYPE_COUNT];
D3D12MA_RW_MUTEX m_PoolsMutex[HEAP_TYPE_COUNT];
// Default pools.
BlockVector* m_BlockVectors[DEFAULT_POOL_MAX_COUNT];
@ -2584,6 +2589,11 @@ private:
// Unregisters Allocation object from m_pCommittedAllocations.
void UnregisterCommittedAllocation(Allocation* alloc, D3D12_HEAP_TYPE heapType);
// Registers Pool object in m_pPools.
void RegisterPool(Pool* pool, D3D12_HEAP_TYPE heapType);
// Unregisters Pool object from m_pPools.
void UnregisterPool(Pool* pool, D3D12_HEAP_TYPE heapType);
HRESULT UpdateD3D12Budget();
D3D12_RESOURCE_ALLOCATION_INFO GetResourceAllocationInfo(D3D12_RESOURCE_DESC& inOutResourceDesc) const;
@ -3812,6 +3822,8 @@ Pool::Pool(Allocator* allocator, const POOL_DESC &desc) :
Pool::~Pool()
{
m_Pimpl->GetAllocator()->UnregisterPool(this, m_Pimpl->GetDesc().HeapType);
D3D12MA_DELETE(m_Pimpl->GetAllocator()->GetAllocs(), m_Pimpl);
}
@ -3836,11 +3848,13 @@ AllocatorPimpl::AllocatorPimpl(const ALLOCATION_CALLBACKS& allocationCallbacks,
ZeroMemory(&m_D3D12Options, sizeof(m_D3D12Options));
ZeroMemory(m_pCommittedAllocations, sizeof(m_pCommittedAllocations));
ZeroMemory(m_pPools, sizeof(m_pPools));
ZeroMemory(m_BlockVectors, sizeof(m_BlockVectors));
for(UINT heapTypeIndex = 0; heapTypeIndex < HEAP_TYPE_COUNT; ++heapTypeIndex)
{
m_pCommittedAllocations[heapTypeIndex] = D3D12MA_NEW(GetAllocs(), AllocationVectorType)(GetAllocs());
m_pPools[heapTypeIndex] = D3D12MA_NEW(GetAllocs(), PoolVectorType)(GetAllocs());
}
m_Device->AddRef();
@ -3906,6 +3920,16 @@ AllocatorPimpl::~AllocatorPimpl()
D3D12MA_DELETE(GetAllocs(), m_BlockVectors[i]);
}
for(UINT i = HEAP_TYPE_COUNT; i--; )
{
if(m_pPools[i] && !m_pPools[i]->empty())
{
D3D12MA_ASSERT(0 && "Unfreed pools found!");
}
D3D12MA_DELETE(GetAllocs(), m_pPools[i]);
}
for(UINT i = HEAP_TYPE_COUNT; i--; )
{
if(m_pCommittedAllocations[i] && !m_pCommittedAllocations[i]->empty())
@ -4447,6 +4471,27 @@ void AllocatorPimpl::UnregisterCommittedAllocation(Allocation* alloc, D3D12_HEAP
D3D12MA_ASSERT(success);
}
void AllocatorPimpl::RegisterPool(Pool* pool, D3D12_HEAP_TYPE heapType)
{
const UINT heapTypeIndex = HeapTypeToIndex(heapType);
MutexLockWrite lock(m_PoolsMutex[heapTypeIndex], m_UseMutex);
PoolVectorType* const pools = m_pPools[heapTypeIndex];
D3D12MA_ASSERT(pools);
pools->InsertSorted(pool, PointerLess());
}
void AllocatorPimpl::UnregisterPool(Pool* pool, D3D12_HEAP_TYPE heapType)
{
const UINT heapTypeIndex = HeapTypeToIndex(heapType);
MutexLockWrite lock(m_PoolsMutex[heapTypeIndex], m_UseMutex);
PoolVectorType* const pools = m_pPools[heapTypeIndex];
D3D12MA_ASSERT(pools);
bool success = pools->RemoveSorted(pool, PointerLess());
D3D12MA_ASSERT(success);
}
void AllocatorPimpl::FreeCommittedMemory(Allocation* allocation)
{
D3D12MA_ASSERT(allocation && allocation->m_PackedData.GetType() == Allocation::TYPE_COMMITTED);
@ -4514,16 +4559,30 @@ void AllocatorPimpl::CalculateStats(Stats& outStats)
pBlockVector->AddStats(outStats);
}
// Process committed allocations.
for(size_t i = 0; i < HEAP_TYPE_COUNT; ++i)
// Process custom pools
for(size_t heapTypeIndex = 0; heapTypeIndex < HEAP_TYPE_COUNT; ++heapTypeIndex)
{
StatInfo& heapStatInfo = outStats.HeapType[i];
MutexLockRead lock(m_CommittedAllocationsMutex[i], m_UseMutex);
const AllocationVectorType* const allocationVector = m_pCommittedAllocations[i];
D3D12MA_ASSERT(allocationVector);
for(size_t j = 0, count = allocationVector->size(); j < count; ++j)
StatInfo& heapStatInfo = outStats.HeapType[heapTypeIndex];
MutexLockRead lock(m_PoolsMutex[heapTypeIndex], m_UseMutex);
const PoolVectorType* const poolVector = m_pPools[heapTypeIndex];
D3D12MA_ASSERT(poolVector);
for(size_t poolIndex = 0, count = poolVector->size(); poolIndex < count; ++poolIndex)
{
UINT64 size = (*allocationVector)[j]->GetSize();
Pool* pool = (*poolVector)[poolIndex];
pool->m_Pimpl->GetBlockVector()->AddStats(outStats);
}
}
// Process committed allocations.
for(size_t heapTypeIndex = 0; heapTypeIndex < HEAP_TYPE_COUNT; ++heapTypeIndex)
{
StatInfo& heapStatInfo = outStats.HeapType[heapTypeIndex];
MutexLockRead lock(m_CommittedAllocationsMutex[heapTypeIndex], m_UseMutex);
const AllocationVectorType* const allocationVector = m_pCommittedAllocations[heapTypeIndex];
D3D12MA_ASSERT(allocationVector);
for(size_t allocIndex = 0, count = allocationVector->size(); allocIndex < count; ++allocIndex)
{
UINT64 size = (*allocationVector)[allocIndex]->GetSize();
StatInfo statInfo = {};
statInfo.BlockCount = 1;
statInfo.AllocationCount = 1;
@ -5175,7 +5234,11 @@ HRESULT Allocator::CreatePool(
D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK
*ppPool = D3D12MA_NEW(m_Pimpl->GetAllocs(), Pool)(this, *pPoolDesc);
HRESULT hr = (*ppPool)->m_Pimpl->Init();
if(FAILED(hr))
if(SUCCEEDED(hr))
{
m_Pimpl->RegisterPool(*ppPool, pPoolDesc->HeapType);
}
else
{
D3D12MA_DELETE(m_Pimpl->GetAllocs(), *ppPool);
*ppPool = NULL;

View File

@ -407,6 +407,11 @@ static void TestCustomPools(const TestContext& ctx)
{
wprintf(L"Test custom pools\n");
// # Fetch global stats 1
D3D12MA::Stats globalStatsBeg = {};
ctx.allocator->CalculateStats(&globalStatsBeg);
// # Create pool, 1..2 blocks of 11 MB
D3D12MA::POOL_DESC poolDesc = {};
@ -422,12 +427,14 @@ static void TestCustomPools(const TestContext& ctx)
D3D12MA::Allocation* allocPtr;
D3D12MA::StatInfo stats = {};
pool->CalculateStats(&stats);
CHECK_BOOL( stats.BlockCount == 1 );
CHECK_BOOL( stats.AllocationCount == 0 );
CHECK_BOOL( stats.UsedBytes == 0 );
CHECK_BOOL( stats.UnusedBytes == poolDesc.BlockSize );
// # Validate stats for empty pool
D3D12MA::StatInfo poolStats = {};
pool->CalculateStats(&poolStats);
CHECK_BOOL( poolStats.BlockCount == 1 );
CHECK_BOOL( poolStats.AllocationCount == 0 );
CHECK_BOOL( poolStats.UsedBytes == 0 );
CHECK_BOOL( poolStats.UnusedBytes == poolDesc.BlockSize );
// # Create buffers 2x 5 MB
@ -451,11 +458,22 @@ static void TestCustomPools(const TestContext& ctx)
allocs[i].reset(allocPtr);
}
pool->CalculateStats(&stats);
CHECK_BOOL( stats.BlockCount == 1 );
CHECK_BOOL( stats.AllocationCount == 2 );
CHECK_BOOL( stats.UsedBytes == 2 * BUFFER_SIZE );
CHECK_BOOL( stats.UnusedBytes == poolDesc.BlockSize - stats.UsedBytes );
// # Validate pool stats now
pool->CalculateStats(&poolStats);
CHECK_BOOL( poolStats.BlockCount == 1 );
CHECK_BOOL( poolStats.AllocationCount == 2 );
CHECK_BOOL( poolStats.UsedBytes == 2 * BUFFER_SIZE );
CHECK_BOOL( poolStats.UnusedBytes == poolDesc.BlockSize - poolStats.UsedBytes );
// # Check that global stats are updated as well
D3D12MA::Stats globalStatsCurr = {};
ctx.allocator->CalculateStats(&globalStatsCurr);
CHECK_BOOL( globalStatsCurr.Total.AllocationCount == globalStatsBeg.Total.AllocationCount + poolStats.AllocationCount );
CHECK_BOOL( globalStatsCurr.Total.BlockCount == globalStatsBeg.Total.BlockCount + poolStats.BlockCount );
CHECK_BOOL( globalStatsCurr.Total.UsedBytes == globalStatsBeg.Total.UsedBytes + poolStats.UsedBytes );
// # NEVER_ALLOCATE and COMMITTED should fail
@ -493,11 +511,11 @@ static void TestCustomPools(const TestContext& ctx)
}
}
pool->CalculateStats(&stats);
CHECK_BOOL( stats.BlockCount == 2 );
CHECK_BOOL( stats.AllocationCount == 4 );
CHECK_BOOL( stats.UsedBytes == 4 * BUFFER_SIZE );
CHECK_BOOL( stats.UnusedBytes == stats.BlockCount * poolDesc.BlockSize - stats.UsedBytes );
pool->CalculateStats(&poolStats);
CHECK_BOOL( poolStats.BlockCount == 2 );
CHECK_BOOL( poolStats.AllocationCount == 4 );
CHECK_BOOL( poolStats.UsedBytes == 4 * BUFFER_SIZE );
CHECK_BOOL( poolStats.UnusedBytes == poolStats.BlockCount * poolDesc.BlockSize - poolStats.UsedBytes );
// # Make room, AllocateMemory, CreateAliasingResource