Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supported nested resource allocators. #965

Merged
merged 1 commit into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
Loading