From 9052833c4aa1ba7f669ec3b80ff5e3440940c175 Mon Sep 17 00:00:00 2001 From: Bryan Bernhart Date: Tue, 30 Aug 2022 14:52:25 -0700 Subject: [PATCH] Make ALLOCATION_DESC::HeapType optional. --- src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp | 39 ++++++++++++++----- src/gpgmm/d3d12/ResourceAllocatorD3D12.h | 3 +- .../end2end/D3D12ResourceAllocatorTests.cpp | 22 +++++++++++ 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp b/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp index dd72e5f14..e9cb85354 100644 --- a/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp +++ b/src/gpgmm/d3d12/ResourceAllocatorD3D12.cpp @@ -224,6 +224,22 @@ namespace gpgmm::d3d12 { } } + HRESULT GetHeapType(D3D12_RESOURCE_STATES initialResourceState, D3D12_HEAP_TYPE* heapType) { + if (HasAllFlags(GetInitialResourceState(D3D12_HEAP_TYPE_UPLOAD), + initialResourceState)) { + *heapType = D3D12_HEAP_TYPE_UPLOAD; + return S_OK; + } + + if (HasAllFlags(GetInitialResourceState(D3D12_HEAP_TYPE_READBACK), + initialResourceState)) { + *heapType = D3D12_HEAP_TYPE_READBACK; + return S_OK; + } + + return E_UNEXPECTED; + } + // RAII wrapper to lock/unlock heap from the residency cache. class ScopedResidencyLock final : public NonCopyable { public: @@ -761,9 +777,14 @@ namespace gpgmm::d3d12 { return E_OUTOFMEMORY; } - const RESOURCE_HEAP_TYPE resourceHeapType = - GetResourceHeapType(newResourceDesc.Dimension, allocationDescriptor.HeapType, - newResourceDesc.Flags, mResourceHeapTier); + // If the heap type was not specified, infer it using the initial resource state. + D3D12_HEAP_TYPE heapType = allocationDescriptor.HeapType; + if (heapType == 0) { + ReturnIfFailed(GetHeapType(initialResourceState, &heapType)); + } + + const RESOURCE_HEAP_TYPE resourceHeapType = GetResourceHeapType( + newResourceDesc.Dimension, heapType, newResourceDesc.Flags, mResourceHeapTier); if (resourceHeapType == RESOURCE_HEAP_TYPE_INVALID) { return E_INVALIDARG; } @@ -824,7 +845,7 @@ namespace gpgmm::d3d12 { // Limit available memory to unused budget when residency is enabled. if (mResidencyManager != nullptr) { const DXGI_MEMORY_SEGMENT_GROUP segment = - mResidencyManager->GetMemorySegmentGroup(allocationDescriptor.HeapType); + mResidencyManager->GetMemorySegmentGroup(heapType); DXGI_QUERY_VIDEO_MEMORY_INFO* currentVideoInfo = mResidencyManager->GetVideoMemoryInfo(segment); @@ -853,8 +874,8 @@ namespace gpgmm::d3d12 { if (allocationDescriptor.Flags & ALLOCATION_FLAG_ALLOW_SUBALLOCATE_WITHIN_RESOURCE && resourceInfo.Alignment > newResourceDesc.Width && newResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER && - GetInitialResourceState(allocationDescriptor.HeapType) == initialResourceState && - !isAlwaysCommitted && !neverSubAllocate) { + GetInitialResourceState(heapType) == initialResourceState && !isAlwaysCommitted && + !neverSubAllocate) { allocator = mSmallBufferAllocatorOfType[static_cast(resourceHeapType)].get(); // GetResourceAllocationInfo() always rejects alignments smaller than 64KB. So if the @@ -995,9 +1016,9 @@ namespace gpgmm::d3d12 { ComPtr committedResource; Heap* resourceHeap = nullptr; - ReturnIfFailed(CreateCommittedResource( - allocationDescriptor.HeapType, heapFlags, resourceInfo, &newResourceDesc, clearValue, - initialResourceState, &committedResource, &resourceHeap)); + ReturnIfFailed(CreateCommittedResource(heapType, heapFlags, resourceInfo, &newResourceDesc, + clearValue, initialResourceState, &committedResource, + &resourceHeap)); // Using committed resources will create a tightly allocated resource allocations. // This means the block and heap size should be equal (modulo driver padding). diff --git a/src/gpgmm/d3d12/ResourceAllocatorD3D12.h b/src/gpgmm/d3d12/ResourceAllocatorD3D12.h index 03792b59c..e47edabb8 100644 --- a/src/gpgmm/d3d12/ResourceAllocatorD3D12.h +++ b/src/gpgmm/d3d12/ResourceAllocatorD3D12.h @@ -315,7 +315,8 @@ namespace gpgmm::d3d12 { /** \brief Heap type that the resource to be allocated requires. - Required parameter. + Optional parameter. If the heap type is not provided, the heap type will be inferred by the + parameters used to call CreateResource. */ D3D12_HEAP_TYPE HeapType; diff --git a/src/tests/end2end/D3D12ResourceAllocatorTests.cpp b/src/tests/end2end/D3D12ResourceAllocatorTests.cpp index 8985691b1..061b9c82b 100644 --- a/src/tests/end2end/D3D12ResourceAllocatorTests.cpp +++ b/src/tests/end2end/D3D12ResourceAllocatorTests.cpp @@ -405,6 +405,28 @@ TEST_F(D3D12ResourceAllocatorTests, CreateBuffer) { ASSERT_NE(allocation, nullptr); EXPECT_EQ(allocation->GetDebugName(), allocationDesc.DebugName); } + + // Creating a buffer without a heap type should be inferred based on the resource state. + { + ComPtr allocation; + ASSERT_SUCCEEDED(resourceAllocator->CreateResource( + {}, CreateBasicBufferDesc(kDefaultBufferSize), D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + &allocation)); + ASSERT_NE(allocation, nullptr); + } + { + ComPtr allocation; + ASSERT_SUCCEEDED(resourceAllocator->CreateResource( + {}, CreateBasicBufferDesc(kDefaultBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, &allocation)); + ASSERT_NE(allocation, nullptr); + } + { + ComPtr allocation; + ASSERT_FAILED(resourceAllocator->CreateResource( + {}, CreateBasicBufferDesc(kDefaultBufferSize), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + nullptr, &allocation)); + } } TEST_F(D3D12ResourceAllocatorTests, CreateSmallTexture) {