Skip to content

Commit

Permalink
Supported nested resource allocators. (#965)
Browse files Browse the repository at this point in the history
Adds support to create new resource allocator from another resource allocator.
  • Loading branch information
bbernhar authored Jan 9, 2024
1 parent baf9a57 commit 1a421f4
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 5 deletions.
19 changes: 19 additions & 0 deletions include/gpgmm_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -1454,6 +1454,25 @@ namespace gpgmm::d3d12 {
IResidencyManager* pResidencyManager,
IResourceAllocator** ppResourceAllocatorOut);

/** \brief Create a resource allocator from an existing resource allocator.
Creating a resource allocator from another resource allocator allows resources heaps to be
re-used between allocators that have seperate configurations. For example, the application
developer may want a global resource allocator to service large requests using dedication
allocations but still prefer smaller requests to use sub-allocation. By creating a resource
allocator from another, the same pool can be re-used instead of managing multiple pools.
@param allocatorDescriptor A reference to RESOURCE_ALLOCATOR_DESC structure that describes the
allocator.
@param pResourceAllocator allocator used to create the allocator. Required parameter.
@param[out] ppResourceAllocatorOut Pointer to a memory block that receives a pointer to the
resource allocator. Pass NULL to test if allocator creation would succeed, but not actually
create the allocator.
*/
GPGMM_EXPORT HRESULT CreateResourceAllocator(const RESOURCE_ALLOCATOR_DESC& allocatorDescriptor,
IResourceAllocator* pResourceAllocator,
IResourceAllocator** ppResourceAllocatorOut);

} // namespace gpgmm::d3d12

#endif // INCLUDE_GPGMM_D3D12_H_
62 changes: 57 additions & 5 deletions src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,18 @@ namespace gpgmm::d3d12 {
IDXGIAdapter* pAdapter,
IResidencyManager* pResidencyManager,
IResourceAllocator** ppResourceAllocatorOut) {
return ResourceAllocator::CreateResourceAllocator(allocatorDescriptor, pDevice, pAdapter,
pResidencyManager, nullptr,
ppResourceAllocatorOut);
}

HRESULT CreateResourceAllocator(const RESOURCE_ALLOCATOR_DESC& allocatorDescriptor,
IResourceAllocator* pResourceAllocator,
IResourceAllocator** ppResourceAllocatorOut) {
ResourceAllocator* resourceAllocator = static_cast<ResourceAllocator*>(pResourceAllocator);
return ResourceAllocator::CreateResourceAllocator(
allocatorDescriptor, pDevice, pAdapter, pResidencyManager, ppResourceAllocatorOut);
allocatorDescriptor, resourceAllocator->GetDevice(), resourceAllocator->GetAdapter(),
resourceAllocator->GetResidencyManager(), pResourceAllocator, ppResourceAllocatorOut);
}

// static
Expand Down Expand Up @@ -423,7 +433,8 @@ namespace gpgmm::d3d12 {

ComPtr<IResourceAllocator> resourceAllocator;
GPGMM_RETURN_IF_FAILED(CreateResourceAllocator(allocatorDescriptor, pDevice, pAdapter,
residencyManager.Get(), &resourceAllocator));
residencyManager.Get(), nullptr,
&resourceAllocator));

if (ppResourceAllocatorOut != nullptr) {
*ppResourceAllocatorOut = resourceAllocator.Detach();
Expand All @@ -442,6 +453,7 @@ namespace gpgmm::d3d12 {
ID3D12Device* pDevice,
IDXGIAdapter* pAdapter,
IResidencyManager* pResidencyManager,
IResourceAllocator* pResourceAllocator,
IResourceAllocator** ppResourceAllocatorOut) {
GPGMM_RETURN_IF_NULL(pDevice);

Expand Down Expand Up @@ -571,10 +583,16 @@ namespace gpgmm::d3d12 {
}
#endif

std::unique_ptr<ResourceAllocator> resourceAllocator =
std::unique_ptr<ResourceAllocator>(new ResourceAllocator(
newDescriptor, pDevice, static_cast<ResidencyManager*>(pResidencyManager),
std::unique_ptr<ResourceAllocator> resourceAllocator;
if (pResourceAllocator == nullptr) {
resourceAllocator = std::unique_ptr<ResourceAllocator>(new ResourceAllocator(
newDescriptor, pDevice, pAdapter, static_cast<ResidencyManager*>(pResidencyManager),
std::move(caps)));
} else {
resourceAllocator = std::unique_ptr<ResourceAllocator>(new ResourceAllocator(
newDescriptor, static_cast<ResourceAllocator*>(pResourceAllocator),
std::move(caps)));
}

GPGMM_TRACE_EVENT_OBJECT_SNAPSHOT(resourceAllocator.get(), newDescriptor);

Expand All @@ -588,11 +606,33 @@ namespace gpgmm::d3d12 {
return S_OK;
}

ResourceAllocator::ResourceAllocator(const RESOURCE_ALLOCATOR_DESC& descriptor,
ResourceAllocator* allocator,
std::unique_ptr<Caps> caps)
: ResourceAllocator(descriptor,
allocator->mDevice,
allocator->mAdapter,
allocator->mResidencyManager.Get(),
std::move(caps)) {
// Use the existing pooled allocators allocator.
for (uint32_t resourceHeapTypeIndex = 0; resourceHeapTypeIndex < kNumOfResourceHeapTypes;
resourceHeapTypeIndex++) {
mPooledOrNonPooledHeapAllocator[resourceHeapTypeIndex] =
allocator->mPooledOrNonPooledHeapAllocator[resourceHeapTypeIndex];
mMSAAPooledOrNonPooledHeapAllocator[resourceHeapTypeIndex] =
allocator->mMSAAPooledOrNonPooledHeapAllocator[resourceHeapTypeIndex];
mSmallBufferAllocatorOfType[resourceHeapTypeIndex] =
allocator->mSmallBufferAllocatorOfType[resourceHeapTypeIndex];
}
}

ResourceAllocator::ResourceAllocator(const RESOURCE_ALLOCATOR_DESC& descriptor,
ID3D12Device* pDevice,
IDXGIAdapter* pAdapter,
ResidencyManager* pResidencyManager,
std::unique_ptr<Caps> caps)
: mDevice(pDevice),
mAdapter(pAdapter),
mResidencyManager(pResidencyManager),
mCaps(std::move(caps)),
mResourceHeapTier(descriptor.ResourceHeapTier),
Expand Down Expand Up @@ -1837,6 +1877,18 @@ namespace gpgmm::d3d12 {
return DebugObject::SetDebugNameImpl(Name);
}

ID3D12Device* ResourceAllocator::GetDevice() const {
return mDevice;
}

IDXGIAdapter* ResourceAllocator::GetAdapter() const {
return mAdapter;
}

IResidencyManager* ResourceAllocator::GetResidencyManager() const {
return mResidencyManager.Get();
}

ImportResourceCallbackContext::ImportResourceCallbackContext(ID3D12Resource* resource)
: mResource(resource) {
}
Expand Down
15 changes: 15 additions & 0 deletions src/gpgmm/d3d12/ResourceAllocatorD3D12.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ namespace gpgmm::d3d12 {
ID3D12Device* pDevice,
IDXGIAdapter* pAdapter,
IResidencyManager* pResidencyManager,
IResourceAllocator* pResourceAllocator,
IResourceAllocator** ppResourceAllocatorOut);

static HRESULT CreateResourceAllocator(const RESOURCE_ALLOCATOR_DESC& allocatorDescriptor,
IResourceAllocator* pResourceAllocator,
IResourceAllocator** ppResourceAllocatorOut);

~ResourceAllocator() override;
Expand All @@ -74,15 +79,24 @@ namespace gpgmm::d3d12 {
LPCWSTR GetDebugName() const override;
HRESULT SetDebugName(LPCWSTR Name) override;

ID3D12Device* GetDevice() const;
IDXGIAdapter* GetAdapter() const;
IResidencyManager* GetResidencyManager() const;

private:
friend BufferAllocator;
friend ResourceAllocation;

ResourceAllocator(const RESOURCE_ALLOCATOR_DESC& descriptor,
ID3D12Device* pDevice,
IDXGIAdapter* pAdapter,
ResidencyManager* pResidencyManager,
std::unique_ptr<Caps> caps);

ResourceAllocator(const RESOURCE_ALLOCATOR_DESC& descriptor,
ResourceAllocator* allocator,
std::unique_ptr<Caps> caps);

void DeleteThis() override;

template <typename CreateResourceFn>
Expand Down Expand Up @@ -153,6 +167,7 @@ namespace gpgmm::d3d12 {
DEFINE_OBJECT_BASE_OVERRIDES(IResourceAllocator)

ID3D12Device* mDevice = nullptr;
IDXGIAdapter* mAdapter = nullptr;
ComPtr<ResidencyManager> mResidencyManager;

std::unique_ptr<Caps> mCaps;
Expand Down
37 changes: 37 additions & 0 deletions src/tests/end2end/D3D12ResourceAllocatorTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2065,3 +2065,40 @@ TEST_F(D3D12ResourceAllocatorTests, AllocatorFeatures) {
RESOURCE_ALLOCATOR_FEATURE_RESOURCE_ALLOCATION_SUPPORT, &data, sizeof(data)));
}
}

// Create two resource allocations using different methods using the same heaps.
TEST_F(D3D12ResourceAllocatorTests, NestedAllocators) {
RESOURCE_ALLOCATOR_DESC desc = CreateBasicAllocatorDesc();
desc.SubAllocationAlgorithm = RESOURCE_ALLOCATION_ALGORITHM_BUDDY_SYSTEM;

ComPtr<IResourceAllocator> parentAllocator;
ASSERT_SUCCEEDED(
CreateResourceAllocator(desc, mDevice.Get(), mAdapter.Get(), &parentAllocator, nullptr));

{
ComPtr<IResourceAllocation> subAllocation;
ASSERT_SUCCEEDED(parentAllocator->CreateResource({}, CreateBasicBufferDesc(1),
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
&subAllocation));
EXPECT_EQ(subAllocation->GetInfo().Type, RESOURCE_ALLOCATION_TYPE_SUBALLOCATED);
}

RESOURCE_ALLOCATOR_STATS beforeStats = GetStats(parentAllocator);
EXPECT_GT(beforeStats.FreeHeapUsage, 0u);

desc.SubAllocationAlgorithm = RESOURCE_ALLOCATION_ALGORITHM_DEDICATED;

ComPtr<IResourceAllocator> childAllocator;
ASSERT_SUCCEEDED(CreateResourceAllocator(desc, parentAllocator.Get(), &childAllocator));

{
ComPtr<IResourceAllocation> dedicatedAllocation;
ASSERT_SUCCEEDED(childAllocator->CreateResource({}, CreateBasicBufferDesc(1),
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
&dedicatedAllocation));
EXPECT_EQ(dedicatedAllocation->GetInfo().Type, RESOURCE_ALLOCATION_TYPE_STANDALONE);
}

RESOURCE_ALLOCATOR_STATS afterStats = GetStats(parentAllocator);
EXPECT_EQ(beforeStats.FreeHeapUsage, afterStats.FreeHeapUsage);
}

0 comments on commit 1a421f4

Please sign in to comment.