diff --git a/src/dawn_native/RingBufferAllocator.h b/src/dawn_native/RingBufferAllocator.h index 82241b3d8d..60ee6395c4 100644 --- a/src/dawn_native/RingBufferAllocator.h +++ b/src/dawn_native/RingBufferAllocator.h @@ -25,6 +25,7 @@ namespace dawn_native { class RingBufferAllocator { public: + RingBufferAllocator() = default; RingBufferAllocator(size_t maxSize); ~RingBufferAllocator() = default; diff --git a/src/dawn_native/d3d12/DescriptorHeapAllocator.cpp b/src/dawn_native/d3d12/DescriptorHeapAllocator.cpp index 3f28e5a201..29ccab7ddb 100644 --- a/src/dawn_native/d3d12/DescriptorHeapAllocator.cpp +++ b/src/dawn_native/d3d12/DescriptorHeapAllocator.cpp @@ -67,24 +67,12 @@ namespace dawn_native { namespace d3d12 { uint32_t allocationSize, DescriptorHeapInfo* heapInfo, D3D12_DESCRIPTOR_HEAP_FLAGS flags) { - // TODO(enga@google.com): This is just a linear allocator so the heap will quickly run out - // of space causing a new one to be allocated We should reuse heap subranges that have been - // released - if (count == 0) { - return DescriptorHeapHandle(); - } - - { - // If the current pool for this type has space, linearly allocate count bytes in the - // pool - auto& allocationInfo = heapInfo->second; - if (allocationInfo.remaining >= count) { - DescriptorHeapHandle handle(heapInfo->first, mSizeIncrements[type], - allocationInfo.size - allocationInfo.remaining); - allocationInfo.remaining -= count; - Release(handle); - return handle; - } + const Serial pendingSerial = mDevice->GetPendingCommandSerial(); + size_t startOffset = (heapInfo->heap == nullptr) + ? RingBufferAllocator::kInvalidOffset + : heapInfo->allocator.Allocate(count, pendingSerial); + if (startOffset != RingBufferAllocator::kInvalidOffset) { + return DescriptorHeapHandle{heapInfo->heap, mSizeIncrements[type], startOffset}; } // If the pool has no more space, replace the pool with a new one of the specified size @@ -100,12 +88,15 @@ namespace dawn_native { namespace d3d12 { return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate heap"); } - AllocationInfo allocationInfo = {allocationSize, allocationSize - count}; - *heapInfo = std::make_pair(heap, allocationInfo); + mDevice->ReferenceUntilUnused(heap); - DescriptorHeapHandle handle(heap, mSizeIncrements[type], 0); - Release(handle); - return handle; + *heapInfo = {heap, RingBufferAllocator(allocationSize)}; + + startOffset = heapInfo->allocator.Allocate(count, pendingSerial); + + ASSERT(startOffset != RingBufferAllocator::kInvalidOffset); + + return DescriptorHeapHandle(heap, mSizeIncrements[type], startOffset); } ResultOrError DescriptorHeapAllocator::AllocateCPUHeap( @@ -120,18 +111,24 @@ namespace dawn_native { namespace d3d12 { uint32_t count) { ASSERT(type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); - unsigned int heapSize = - (type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ? kMaxCbvUavSrvHeapSize - : kMaxSamplerHeapSize); + unsigned int heapSize = (type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV + ? D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1 + : D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE); return Allocate(type, count, heapSize, &mGpuDescriptorHeapInfos[type], D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); } - void DescriptorHeapAllocator::Tick(uint64_t lastCompletedSerial) { - mReleasedHandles.ClearUpTo(lastCompletedSerial); - } + void DescriptorHeapAllocator::Deallocate(uint64_t lastCompletedSerial) { + for (uint32_t i = 0; i < mCpuDescriptorHeapInfos.size(); i++) { + if (mCpuDescriptorHeapInfos[i].heap != nullptr) { + mCpuDescriptorHeapInfos[i].allocator.Deallocate(lastCompletedSerial); + } + } - void DescriptorHeapAllocator::Release(DescriptorHeapHandle handle) { - mReleasedHandles.Enqueue(handle, mDevice->GetPendingCommandSerial()); + for (uint32_t i = 0; i < mGpuDescriptorHeapInfos.size(); i++) { + if (mGpuDescriptorHeapInfos[i].heap != nullptr) { + mGpuDescriptorHeapInfos[i].allocator.Deallocate(lastCompletedSerial); + } + } } }} // namespace dawn_native::d3d12 diff --git a/src/dawn_native/d3d12/DescriptorHeapAllocator.h b/src/dawn_native/d3d12/DescriptorHeapAllocator.h index d98b7a8fe3..e4949a68cd 100644 --- a/src/dawn_native/d3d12/DescriptorHeapAllocator.h +++ b/src/dawn_native/d3d12/DescriptorHeapAllocator.h @@ -22,6 +22,7 @@ #include "common/SerialQueue.h" #include "dawn_native/Error.h" +#include "dawn_native/RingBufferAllocator.h" namespace dawn_native { namespace d3d12 { @@ -52,34 +53,27 @@ namespace dawn_native { namespace d3d12 { uint32_t count); ResultOrError AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count); - void Tick(uint64_t lastCompletedSerial); + void Deallocate(uint64_t lastCompletedSerial); private: - static constexpr unsigned int kMaxCbvUavSrvHeapSize = 1000000; - static constexpr unsigned int kMaxSamplerHeapSize = 2048; - static constexpr unsigned int kDescriptorHeapTypes = - D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; - - struct AllocationInfo { - uint32_t size = 0; - uint32_t remaining = 0; + struct DescriptorHeapInfo { + ComPtr heap; + RingBufferAllocator allocator; }; - using DescriptorHeapInfo = std::pair, AllocationInfo>; - ResultOrError Allocate(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32_t count, uint32_t allocationSize, DescriptorHeapInfo* heapInfo, D3D12_DESCRIPTOR_HEAP_FLAGS flags); - void Release(DescriptorHeapHandle handle); Device* mDevice; - std::array mSizeIncrements; - std::array mCpuDescriptorHeapInfos; - std::array mGpuDescriptorHeapInfos; - SerialQueue mReleasedHandles; + std::array mSizeIncrements; + std::array + mCpuDescriptorHeapInfos; + std::array + mGpuDescriptorHeapInfos; }; }} // namespace dawn_native::d3d12 diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp index ffc5a7ed33..2f535ee6ec 100644 --- a/src/dawn_native/d3d12/DeviceD3D12.cpp +++ b/src/dawn_native/d3d12/DeviceD3D12.cpp @@ -221,7 +221,7 @@ namespace dawn_native { namespace d3d12 { mResourceAllocator->Tick(mCompletedSerial); mCommandAllocatorManager->Tick(mCompletedSerial); - mDescriptorHeapAllocator->Tick(mCompletedSerial); + mDescriptorHeapAllocator->Deallocate(mCompletedSerial); mMapRequestTracker->Tick(mCompletedSerial); mUsedComObjectRefs.ClearUpTo(mCompletedSerial); ExecuteCommandList(nullptr);