Skip to content

Commit 0c573d8

Browse files
Improved TestStats
Based on TestStatistics function in VMA.
1 parent 8ebd258 commit 0c573d8

File tree

1 file changed

+288
-65
lines changed

1 file changed

+288
-65
lines changed

src/Tests.cpp

Lines changed: 288 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,11 @@ static inline bool StatisticsEqual(const D3D12MA::DetailedStatistics& lhs, const
16991699
return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
17001700
}
17011701

1702+
static inline bool StatisticsEqual(const D3D12MA::Statistics& lhs, const D3D12MA::Statistics& rhs)
1703+
{
1704+
return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
1705+
}
1706+
17021707
static void CheckStatistics(const D3D12MA::DetailedStatistics& stats)
17031708
{
17041709
CHECK_BOOL(stats.Stats.AllocationBytes <= stats.Stats.BlockBytes);
@@ -1714,86 +1719,304 @@ static void CheckStatistics(const D3D12MA::DetailedStatistics& stats)
17141719
}
17151720
}
17161721

1717-
static void TestStats(const TestContext& ctx)
1722+
static void CheckBudgetBasics(const TestContext& ctx,
1723+
const D3D12MA::Budget& localBudget, const D3D12MA::Budget& nonLocalBudget)
17181724
{
1719-
wprintf(L"Test stats\n");
1725+
CHECK_BOOL(localBudget.BudgetBytes > 0);
1726+
CHECK_BOOL(localBudget.BudgetBytes <= ctx.allocator->GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_LOCAL));
1727+
CHECK_BOOL(localBudget.Stats.AllocationBytes <= localBudget.Stats.BlockBytes);
17201728

1721-
D3D12MA::TotalStatistics begStats = {};
1722-
ctx.allocator->CalculateStatistics(&begStats);
1729+
// Discrete graphics card with separate video memory.
1730+
if (!ctx.allocator->IsUMA())
1731+
{
1732+
CHECK_BOOL(nonLocalBudget.BudgetBytes > 0);
1733+
CHECK_BOOL(nonLocalBudget.BudgetBytes <= ctx.allocator->GetMemoryCapacity(DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL));
1734+
CHECK_BOOL(nonLocalBudget.Stats.AllocationBytes <= nonLocalBudget.Stats.BlockBytes);
1735+
}
1736+
}
17231737

1724-
const UINT count = 10;
1725-
const UINT64 bufSize = 64ull * 1024;
1726-
ResourceWithAllocation resources[count];
1738+
static D3D12MA::DetailedStatistics GetEmptyDetailedStatistics()
1739+
{
1740+
D3D12MA::DetailedStatistics out = {};
1741+
out.AllocationSizeMin = UINT64_MAX;
1742+
out.UnusedRangeSizeMin = UINT64_MAX;
1743+
return out;
1744+
}
17271745

1728-
D3D12MA::CALLOCATION_DESC allocDesc = D3D12MA::CALLOCATION_DESC{ D3D12_HEAP_TYPE_UPLOAD };
1746+
static void AddDetailedStatistics(D3D12MA::DetailedStatistics& inoutSum, const D3D12MA::DetailedStatistics& stats)
1747+
{
1748+
inoutSum.Stats.AllocationBytes += stats.Stats.AllocationBytes;
1749+
inoutSum.Stats.AllocationCount += stats.Stats.AllocationCount;
1750+
inoutSum.Stats.BlockBytes += stats.Stats.BlockBytes;
1751+
inoutSum.Stats.BlockCount += stats.Stats.BlockCount;
1752+
inoutSum.UnusedRangeCount += stats.UnusedRangeCount;
1753+
inoutSum.AllocationSizeMax = std::max(inoutSum.AllocationSizeMax, stats.AllocationSizeMax);
1754+
inoutSum.AllocationSizeMin = std::min(inoutSum.AllocationSizeMin, stats.AllocationSizeMin);
1755+
inoutSum.UnusedRangeSizeMax = std::max(inoutSum.UnusedRangeSizeMax, stats.UnusedRangeSizeMax);
1756+
inoutSum.UnusedRangeSizeMin = std::min(inoutSum.UnusedRangeSizeMin, stats.UnusedRangeSizeMin);
1757+
}
17291758

1730-
D3D12_RESOURCE_DESC resourceDesc;
1731-
FillResourceDescForBuffer(resourceDesc, bufSize);
1759+
static void CheckTotalStatistics(const D3D12MA::TotalStatistics& stats)
1760+
{
1761+
D3D12MA::DetailedStatistics sum = GetEmptyDetailedStatistics();
1762+
for (size_t i = 0; i < _countof(stats.HeapType); ++i)
1763+
{
1764+
AddDetailedStatistics(sum, stats.HeapType[i]);
1765+
}
1766+
CHECK_BOOL(StatisticsEqual(sum, stats.Total));
17321767

1733-
for(UINT i = 0; i < count; ++i)
1768+
sum = GetEmptyDetailedStatistics();
1769+
for (size_t i = 0; i < _countof(stats.MemorySegmentGroup); ++i)
17341770
{
1735-
if(i == count / 2)
1736-
allocDesc.Flags |= D3D12MA::ALLOCATION_FLAG_COMMITTED;
1737-
CHECK_HR( ctx.allocator->CreateResource(
1738-
&allocDesc,
1739-
&resourceDesc,
1740-
D3D12_RESOURCE_STATE_GENERIC_READ,
1741-
NULL,
1742-
&resources[i].allocation,
1743-
IID_PPV_ARGS(&resources[i].resource)) );
1771+
AddDetailedStatistics(sum, stats.MemorySegmentGroup[i]);
17441772
}
1773+
CHECK_BOOL(StatisticsEqual(sum, stats.Total));
1774+
}
17451775

1746-
D3D12MA::TotalStatistics endStats = {};
1747-
ctx.allocator->CalculateStatistics(&endStats);
1776+
static void TestStats(const TestContext& ctx)
1777+
{
1778+
using namespace D3D12MA;
17481779

1749-
CHECK_BOOL(endStats.Total.Stats.BlockCount >= begStats.Total.Stats.BlockCount);
1750-
CHECK_BOOL(endStats.Total.Stats.AllocationCount == begStats.Total.Stats.AllocationCount + count);
1751-
CHECK_BOOL(endStats.Total.Stats.AllocationBytes == begStats.Total.Stats.AllocationBytes + count * bufSize);
1752-
CHECK_BOOL(endStats.Total.AllocationSizeMin <= bufSize);
1753-
CHECK_BOOL(endStats.Total.AllocationSizeMax >= bufSize);
1780+
wprintf(L"Test stats\n");
17541781

1755-
CHECK_BOOL(endStats.HeapType[1].Stats.BlockCount >= begStats.HeapType[1].Stats.BlockCount);
1756-
CHECK_BOOL(endStats.HeapType[1].Stats.AllocationCount >= begStats.HeapType[1].Stats.AllocationCount + count);
1757-
CHECK_BOOL(endStats.HeapType[1].Stats.AllocationBytes >= begStats.HeapType[1].Stats.AllocationBytes + count * bufSize);
1758-
CHECK_BOOL(endStats.HeapType[1].AllocationSizeMin <= bufSize);
1759-
CHECK_BOOL(endStats.HeapType[1].AllocationSizeMax >= bufSize);
1782+
constexpr UINT64 BUF_SIZE = 10 * MEGABYTE;
1783+
constexpr UINT32 BUF_COUNT = 4;
1784+
constexpr UINT64 PREALLOCATED_BLOCK_SIZE = BUF_SIZE * (BUF_COUNT + 1);
1785+
1786+
/*
1787+
Test 0: ALLOCATION_FLAG_COMMITTED.
1788+
Test 1: normal allocations.
1789+
Test 2: allocations in a custom pool.
1790+
Test 3: allocations in a custom pool, COMMITTED.
1791+
Test 4: allocations in a custom pool with preallocated memory.
1792+
*/
1793+
for (uint32_t testIndex = 0; testIndex < 5; ++testIndex)
1794+
{
1795+
const bool usePool = testIndex >= 2;
1796+
const bool useCommitted = testIndex == 0 || testIndex == 3;
1797+
const bool usePreallocated = testIndex == 4;
17601798

1761-
CHECK_BOOL(StatisticsEqual(begStats.HeapType[0], endStats.HeapType[0]));
1762-
CHECK_BOOL(StatisticsEqual(begStats.HeapType[2], endStats.HeapType[2]));
1799+
// Get stats "Beg".
1800+
Budget localBudgetBeg = {};
1801+
Budget nonLocalBudgetBeg = {};
1802+
ctx.allocator->GetBudget(&localBudgetBeg, &nonLocalBudgetBeg);
1803+
CheckBudgetBasics(ctx, localBudgetBeg, nonLocalBudgetBeg);
17631804

1764-
CheckStatistics(endStats.Total);
1765-
CheckStatistics(endStats.HeapType[0]);
1766-
CheckStatistics(endStats.HeapType[1]);
1767-
CheckStatistics(endStats.HeapType[2]);
1805+
TotalStatistics statsBeg = {};
1806+
ctx.allocator->CalculateStatistics(&statsBeg);
1807+
CheckTotalStatistics(statsBeg);
17681808

1769-
D3D12MA::Budget localBudget = {}, nonLocalBudget = {};
1770-
ctx.allocator->GetBudget(&localBudget, &nonLocalBudget);
1809+
// Create pool.
1810+
ComPtr<Pool> pool;
1811+
if (usePool)
1812+
{
1813+
POOL_DESC poolDesc = CPOOL_DESC(D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS);
1814+
if (usePreallocated)
1815+
{
1816+
poolDesc.BlockSize = PREALLOCATED_BLOCK_SIZE;
1817+
poolDesc.MinBlockCount = 1;
1818+
poolDesc.MaxBlockCount = 1;
1819+
}
1820+
CHECK_HR(ctx.allocator->CreatePool(&poolDesc, &pool));
1821+
}
17711822

1772-
CHECK_BOOL(localBudget.Stats.AllocationBytes <= localBudget.Stats.BlockBytes);
1773-
CHECK_BOOL(endStats.HeapType[3].Stats.BlockCount == 0); // No allocation from D3D12_HEAP_TYPE_CUSTOM in this test.
1774-
if(!ctx.allocator->IsUMA())
1775-
{
1776-
// Discrete GPU
1777-
CHECK_BOOL(localBudget.Stats.AllocationBytes == endStats.HeapType[0].Stats.AllocationBytes);
1778-
CHECK_BOOL(localBudget.Stats.BlockBytes == endStats.HeapType[0].Stats.BlockBytes);
1779-
1780-
CHECK_BOOL(nonLocalBudget.Stats.AllocationBytes <= nonLocalBudget.Stats.BlockBytes);
1781-
CHECK_BOOL(nonLocalBudget.Stats.AllocationBytes == endStats.HeapType[1].Stats.AllocationBytes + endStats.HeapType[2].Stats.AllocationBytes);
1782-
CHECK_BOOL(nonLocalBudget.Stats.BlockBytes ==
1783-
endStats.HeapType[1].Stats.BlockBytes + endStats.HeapType[2].Stats.BlockBytes);
1784-
}
1785-
else
1786-
{
1787-
// Integrated GPU - all memory is local
1788-
CHECK_BOOL(localBudget.Stats.AllocationBytes == endStats.HeapType[0].Stats.AllocationBytes +
1789-
endStats.HeapType[1].Stats.AllocationBytes +
1790-
endStats.HeapType[2].Stats.AllocationBytes);
1791-
CHECK_BOOL(localBudget.Stats.BlockBytes == endStats.HeapType[0].Stats.BlockBytes +
1792-
endStats.HeapType[1].Stats.BlockBytes +
1793-
endStats.HeapType[2].Stats.BlockBytes);
1794-
1795-
CHECK_BOOL(nonLocalBudget.Stats.AllocationBytes == 0);
1796-
CHECK_BOOL(nonLocalBudget.Stats.BlockBytes == 0);
1823+
// Get pool stats "Beg".
1824+
Statistics poolStatsBeg = {};
1825+
DetailedStatistics detailedPoolStatsBeg = {};
1826+
if (usePool)
1827+
{
1828+
pool->GetStatistics(&poolStatsBeg);
1829+
pool->CalculateStatistics(&detailedPoolStatsBeg);
1830+
CheckStatistics(detailedPoolStatsBeg);
1831+
}
1832+
1833+
// Create buffers.
1834+
D3D12_RESOURCE_DESC resDesc;
1835+
FillResourceDescForBuffer(resDesc, BUF_SIZE);
1836+
1837+
ALLOCATION_DESC allocDesc = {};
1838+
if (usePool)
1839+
allocDesc = CALLOCATION_DESC(pool.Get());
1840+
else
1841+
allocDesc = CALLOCATION_DESC(D3D12_HEAP_TYPE_DEFAULT);
1842+
if (useCommitted)
1843+
allocDesc.Flags |= ALLOCATION_FLAG_COMMITTED;
1844+
1845+
ComPtr<Allocation> allocs[BUF_COUNT];
1846+
for (UINT i = 0; i < BUF_COUNT; ++i)
1847+
{
1848+
CHECK_HR(ctx.allocator->CreateResource(
1849+
&allocDesc, &resDesc, D3D12_RESOURCE_STATE_COMMON,
1850+
NULL, &allocs[i], IID_NULL, NULL));
1851+
}
1852+
1853+
// Get stats "WithBufs".
1854+
Budget localBudgetWithBufs = {};
1855+
Budget nonLocalBudgetWithBufs = {};
1856+
ctx.allocator->GetBudget(&localBudgetWithBufs, &nonLocalBudgetWithBufs);
1857+
CheckBudgetBasics(ctx, localBudgetWithBufs, nonLocalBudgetWithBufs);
1858+
1859+
TotalStatistics statsWithBufs = {};
1860+
ctx.allocator->CalculateStatistics(&statsWithBufs);
1861+
CheckTotalStatistics(statsWithBufs);
1862+
1863+
Statistics poolStatsWithBufs = {};
1864+
DetailedStatistics detailedPoolStatsWithBufs = {};
1865+
if (usePool)
1866+
{
1867+
pool->GetStatistics(&poolStatsWithBufs);
1868+
pool->CalculateStatistics(&detailedPoolStatsWithBufs);
1869+
CheckStatistics(detailedPoolStatsWithBufs);
1870+
}
1871+
1872+
// Destroy buffers.
1873+
for (size_t i = BUF_COUNT; i--; )
1874+
{
1875+
allocs[i].Reset();
1876+
}
1877+
1878+
// Get pool stats "End".
1879+
Statistics poolStatsEnd = {};
1880+
DetailedStatistics detailedPoolStatsEnd = {};
1881+
if (usePool)
1882+
{
1883+
pool->GetStatistics(&poolStatsEnd);
1884+
pool->CalculateStatistics(&detailedPoolStatsEnd);
1885+
CheckStatistics(detailedPoolStatsEnd);
1886+
}
1887+
1888+
// Destroy the pool.
1889+
pool.Reset();
1890+
1891+
// Get stats "End".
1892+
Budget localBudgetEnd = {};
1893+
Budget nonLocalBudgetEnd = {};
1894+
ctx.allocator->GetBudget(&localBudgetEnd, &nonLocalBudgetEnd);
1895+
CheckBudgetBasics(ctx, localBudgetEnd, nonLocalBudgetEnd);
1896+
1897+
TotalStatistics statsEnd = {};
1898+
ctx.allocator->CalculateStatistics(&statsEnd);
1899+
CheckTotalStatistics(statsEnd);
1900+
1901+
// CHECK THE STATS: Local.
1902+
{
1903+
CHECK_BOOL(localBudgetBeg.Stats.AllocationBytes <= localBudgetEnd.Stats.AllocationBytes);
1904+
1905+
// Budget::UsageBytes.
1906+
CHECK_BOOL(localBudgetWithBufs.UsageBytes >= localBudgetBeg.UsageBytes);
1907+
CHECK_BOOL(localBudgetEnd.UsageBytes <= localBudgetWithBufs.UsageBytes);
1908+
1909+
// Budget - Statistics::AllocationBytes.
1910+
CHECK_BOOL(localBudgetEnd.Stats.AllocationBytes == localBudgetBeg.Stats.AllocationBytes);
1911+
CHECK_BOOL(localBudgetWithBufs.Stats.AllocationBytes == localBudgetBeg.Stats.AllocationBytes + BUF_SIZE * BUF_COUNT);
1912+
1913+
// Budget - Statistics::BlockBytes.
1914+
if (usePool)
1915+
{
1916+
CHECK_BOOL(localBudgetEnd.Stats.BlockBytes == localBudgetBeg.Stats.BlockBytes);
1917+
CHECK_BOOL(localBudgetWithBufs.Stats.BlockBytes > localBudgetBeg.Stats.BlockBytes);
1918+
}
1919+
else
1920+
{
1921+
CHECK_BOOL(localBudgetWithBufs.Stats.BlockBytes >= localBudgetBeg.Stats.BlockBytes);
1922+
}
1923+
1924+
// Budget - Statistics::AllocationCount.
1925+
CHECK_BOOL(localBudgetEnd.Stats.AllocationCount == localBudgetBeg.Stats.AllocationCount);
1926+
CHECK_BOOL(localBudgetWithBufs.Stats.AllocationCount == localBudgetBeg.Stats.AllocationCount + BUF_COUNT);
1927+
1928+
// Budget - Statistics::BlockCount.
1929+
if (useCommitted)
1930+
{
1931+
CHECK_BOOL(localBudgetEnd.Stats.BlockCount == localBudgetBeg.Stats.BlockCount);
1932+
CHECK_BOOL(localBudgetWithBufs.Stats.BlockCount == localBudgetBeg.Stats.BlockCount + BUF_COUNT);
1933+
}
1934+
else if (usePool)
1935+
{
1936+
CHECK_BOOL(localBudgetEnd.Stats.BlockCount == localBudgetBeg.Stats.BlockCount);
1937+
if (usePreallocated)
1938+
{
1939+
CHECK_BOOL(localBudgetWithBufs.Stats.BlockCount == localBudgetBeg.Stats.BlockCount + 1);
1940+
}
1941+
else
1942+
{
1943+
CHECK_BOOL(localBudgetWithBufs.Stats.BlockCount > localBudgetBeg.Stats.BlockCount);
1944+
}
1945+
}
1946+
1947+
// Compare CalculateStatistics per memory segment group with GetBudget.
1948+
CHECK_BOOL(StatisticsEqual(statsBeg.MemorySegmentGroup[0].Stats, localBudgetBeg.Stats));
1949+
CHECK_BOOL(StatisticsEqual(statsWithBufs.MemorySegmentGroup[0].Stats, localBudgetWithBufs.Stats));
1950+
CHECK_BOOL(StatisticsEqual(statsEnd.MemorySegmentGroup[0].Stats, localBudgetEnd.Stats));
1951+
}
1952+
1953+
// CHECK THE STATS: Non-local.
1954+
{
1955+
CHECK_BOOL(nonLocalBudgetEnd.Stats.AllocationBytes == nonLocalBudgetBeg.Stats.AllocationBytes &&
1956+
nonLocalBudgetEnd.Stats.AllocationBytes == nonLocalBudgetWithBufs.Stats.AllocationBytes);
1957+
CHECK_BOOL(nonLocalBudgetEnd.Stats.BlockBytes == nonLocalBudgetBeg.Stats.BlockBytes &&
1958+
nonLocalBudgetEnd.Stats.BlockBytes == nonLocalBudgetWithBufs.Stats.BlockBytes);
1959+
CHECK_BOOL(nonLocalBudgetEnd.Stats.AllocationCount == nonLocalBudgetBeg.Stats.AllocationCount &&
1960+
nonLocalBudgetEnd.Stats.AllocationCount == nonLocalBudgetWithBufs.Stats.AllocationCount);
1961+
CHECK_BOOL(nonLocalBudgetEnd.Stats.BlockCount == nonLocalBudgetBeg.Stats.BlockCount &&
1962+
nonLocalBudgetEnd.Stats.BlockCount == nonLocalBudgetWithBufs.Stats.BlockCount);
1963+
1964+
// Compare CalculateStatistics per memory segment group with GetBudget.
1965+
CHECK_BOOL(StatisticsEqual(statsBeg.MemorySegmentGroup[1].Stats, nonLocalBudgetBeg.Stats));
1966+
CHECK_BOOL(StatisticsEqual(statsWithBufs.MemorySegmentGroup[1].Stats, nonLocalBudgetWithBufs.Stats));
1967+
CHECK_BOOL(StatisticsEqual(statsEnd.MemorySegmentGroup[1].Stats, nonLocalBudgetEnd.Stats));
1968+
}
1969+
1970+
if (usePool)
1971+
{
1972+
// Compare simple stats with calculated stats to make sure they are identical.
1973+
CHECK_BOOL(StatisticsEqual(poolStatsBeg, detailedPoolStatsBeg.Stats));
1974+
CHECK_BOOL(StatisticsEqual(poolStatsWithBufs, detailedPoolStatsWithBufs.Stats));
1975+
CHECK_BOOL(StatisticsEqual(poolStatsEnd, detailedPoolStatsEnd.Stats));
1976+
1977+
// Validate stats of an empty pool.
1978+
CHECK_BOOL(detailedPoolStatsBeg.AllocationSizeMax == 0);
1979+
CHECK_BOOL(detailedPoolStatsEnd.AllocationSizeMax == 0);
1980+
CHECK_BOOL(detailedPoolStatsBeg.AllocationSizeMin == UINT64_MAX);
1981+
CHECK_BOOL(detailedPoolStatsEnd.AllocationSizeMin == UINT64_MAX);
1982+
CHECK_BOOL(poolStatsBeg.AllocationCount == 0);
1983+
CHECK_BOOL(poolStatsBeg.AllocationBytes == 0);
1984+
CHECK_BOOL(poolStatsEnd.AllocationCount == 0);
1985+
CHECK_BOOL(poolStatsEnd.AllocationBytes == 0);
1986+
if (usePreallocated)
1987+
{
1988+
CHECK_BOOL(poolStatsBeg.BlockCount == 1);
1989+
CHECK_BOOL(poolStatsEnd.BlockCount == 1);
1990+
CHECK_BOOL(poolStatsBeg.BlockBytes == PREALLOCATED_BLOCK_SIZE);
1991+
CHECK_BOOL(poolStatsEnd.BlockBytes == PREALLOCATED_BLOCK_SIZE);
1992+
}
1993+
else
1994+
{
1995+
CHECK_BOOL(poolStatsBeg.BlockCount == 0);
1996+
CHECK_BOOL(poolStatsBeg.BlockBytes == 0);
1997+
// Not checking poolStatsEnd.blockCount, blockBytes, because an empty block may stay allocated.
1998+
}
1999+
2000+
// Validate stats of a pool with buffers.
2001+
CHECK_BOOL(detailedPoolStatsWithBufs.AllocationSizeMin == BUF_SIZE);
2002+
CHECK_BOOL(detailedPoolStatsWithBufs.AllocationSizeMax == BUF_SIZE);
2003+
CHECK_BOOL(poolStatsWithBufs.AllocationCount == BUF_COUNT);
2004+
CHECK_BOOL(poolStatsWithBufs.AllocationBytes == BUF_COUNT * BUF_SIZE);
2005+
if (usePreallocated)
2006+
{
2007+
CHECK_BOOL(poolStatsWithBufs.BlockCount == 1);
2008+
CHECK_BOOL(poolStatsWithBufs.BlockBytes == PREALLOCATED_BLOCK_SIZE);
2009+
}
2010+
else
2011+
{
2012+
CHECK_BOOL(poolStatsWithBufs.BlockCount > 0);
2013+
CHECK_BOOL(poolStatsWithBufs.BlockBytes >= poolStatsWithBufs.AllocationBytes);
2014+
}
2015+
}
2016+
2017+
// No allocation from D3D12_HEAP_TYPE_CUSTOM or GPU_UPLOAD in this test.
2018+
CHECK_BOOL(statsEnd.HeapType[3].Stats.BlockCount == 0);
2019+
CHECK_BOOL(statsEnd.HeapType[4].Stats.BlockCount == 0);
17972020
}
17982021
}
17992022

0 commit comments

Comments
 (0)