From cf21bf5aaa169d4e0c65b3dd5a7b91ba91c87836 Mon Sep 17 00:00:00 2001 From: "Bernhart, Bryan" Date: Tue, 9 Jan 2024 15:32:02 -0800 Subject: [PATCH] Allow SUBALLOCATED_WITHIN to share only pools. Fixes a possible issue when nested allocators could override the allocation type. --- src/gpgmm/common/MemoryAllocator.cpp | 4 ++ src/gpgmm/common/MemoryAllocator.h | 1 + src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp | 6 ++- .../end2end/D3D12ResourceAllocatorTests.cpp | 40 +++++++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/gpgmm/common/MemoryAllocator.cpp b/src/gpgmm/common/MemoryAllocator.cpp index 9321b110..a103a7eb 100644 --- a/src/gpgmm/common/MemoryAllocator.cpp +++ b/src/gpgmm/common/MemoryAllocator.cpp @@ -201,6 +201,10 @@ namespace gpgmm { std::lock_guard lock(mMutex); ASSERT(next != nullptr); next->mParent = this->value(); + SetNextInChain(std::move(next)); + } + + void MemoryAllocatorBase::SetNextInChain(ScopedRef next) { mNext = next; } diff --git a/src/gpgmm/common/MemoryAllocator.h b/src/gpgmm/common/MemoryAllocator.h index 81836e3f..93247691 100644 --- a/src/gpgmm/common/MemoryAllocator.h +++ b/src/gpgmm/common/MemoryAllocator.h @@ -208,6 +208,7 @@ namespace gpgmm { // Return the next MemoryAllocatorBase. MemoryAllocatorBase* GetNextInChain() const; + void SetNextInChain(ScopedRef next); // Return the previous MemoryAllocatorBase. MemoryAllocatorBase* GetParent() const; diff --git a/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp b/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp index 0f317cf3..b5ae6955 100644 --- a/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp +++ b/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp @@ -621,8 +621,10 @@ namespace gpgmm::d3d12 { allocator->mPooledOrNonPooledHeapAllocator[resourceHeapTypeIndex]; mMSAAPooledOrNonPooledHeapAllocator[resourceHeapTypeIndex] = allocator->mMSAAPooledOrNonPooledHeapAllocator[resourceHeapTypeIndex]; - mSmallBufferAllocatorOfType[resourceHeapTypeIndex] = - allocator->mSmallBufferAllocatorOfType[resourceHeapTypeIndex]; + + // Small buffers have seperate pools within because they cannot use managed heaps. + mSmallBufferAllocatorOfType[resourceHeapTypeIndex]->SetNextInChain( + allocator->mSmallBufferAllocatorOfType[resourceHeapTypeIndex]->GetNextInChain()); } } diff --git a/src/tests/end2end/D3D12ResourceAllocatorTests.cpp b/src/tests/end2end/D3D12ResourceAllocatorTests.cpp index ad8aaf5c..d4f57a79 100644 --- a/src/tests/end2end/D3D12ResourceAllocatorTests.cpp +++ b/src/tests/end2end/D3D12ResourceAllocatorTests.cpp @@ -2102,3 +2102,43 @@ TEST_F(D3D12ResourceAllocatorTests, NestedAllocators) { RESOURCE_ALLOCATOR_STATS afterStats = GetStats(parentAllocator); EXPECT_EQ(beforeStats.FreeHeapUsage, afterStats.FreeHeapUsage); } + +// Create two resource allocations using different methods using the same heaps. +TEST_F(D3D12ResourceAllocatorTests, NestedAllocatorsWithin) { + RESOURCE_ALLOCATOR_DESC desc = CreateBasicAllocatorDesc(); + desc.SubAllocationAlgorithm = RESOURCE_ALLOCATION_ALGORITHM_BUDDY_SYSTEM; + + RESOURCE_ALLOCATION_DESC allocationDesc = {}; + allocationDesc.Flags |= RESOURCE_ALLOCATION_FLAG_ALLOW_SUBALLOCATE_WITHIN_RESOURCE; + + ComPtr parentAllocator; + ASSERT_SUCCEEDED( + CreateResourceAllocator(desc, mDevice.Get(), mAdapter.Get(), &parentAllocator, nullptr)); + + { + ComPtr subAllocation; + ASSERT_SUCCEEDED(parentAllocator->CreateResource(allocationDesc, CreateBasicBufferDesc(1), + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + &subAllocation)); + EXPECT_EQ(subAllocation->GetInfo().Type, RESOURCE_ALLOCATION_TYPE_SUBALLOCATED_WITHIN); + } + + RESOURCE_ALLOCATOR_STATS beforeStats = GetStats(parentAllocator); + EXPECT_GT(beforeStats.FreeHeapUsage, 0u); + + desc.SubAllocationAlgorithm = RESOURCE_ALLOCATION_ALGORITHM_SLAB; + + ComPtr childAllocator; + ASSERT_SUCCEEDED(CreateResourceAllocator(desc, parentAllocator.Get(), &childAllocator)); + + { + ComPtr subAllocation; + ASSERT_SUCCEEDED(childAllocator->CreateResource(allocationDesc, CreateBasicBufferDesc(1), + D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + &subAllocation)); + EXPECT_EQ(subAllocation->GetInfo().Type, RESOURCE_ALLOCATION_TYPE_SUBALLOCATED_WITHIN); + } + + RESOURCE_ALLOCATOR_STATS afterStats = GetStats(parentAllocator); + EXPECT_EQ(beforeStats.FreeHeapUsage, afterStats.FreeHeapUsage); +}