D3D12: Use ringbuffer allocator for descriptor heaps.

Enable descriptor heap re-use by using ringbuffer.

BUG=dawn:155

Change-Id: I72e3fb98a64dc1af671e185e2114868a577a0554
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9460
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Bryan Bernhart <bryan.bernhart@intel.com>
This commit is contained in:
Bryan Bernhart 2019-10-01 02:19:02 +00:00 committed by Commit Bot service account
parent e06f01be71
commit e6b93e8706
4 changed files with 40 additions and 48 deletions

View File

@ -25,6 +25,7 @@ namespace dawn_native {
class RingBufferAllocator { class RingBufferAllocator {
public: public:
RingBufferAllocator() = default;
RingBufferAllocator(size_t maxSize); RingBufferAllocator(size_t maxSize);
~RingBufferAllocator() = default; ~RingBufferAllocator() = default;

View File

@ -67,24 +67,12 @@ namespace dawn_native { namespace d3d12 {
uint32_t allocationSize, uint32_t allocationSize,
DescriptorHeapInfo* heapInfo, DescriptorHeapInfo* heapInfo,
D3D12_DESCRIPTOR_HEAP_FLAGS flags) { D3D12_DESCRIPTOR_HEAP_FLAGS flags) {
// TODO(enga@google.com): This is just a linear allocator so the heap will quickly run out const Serial pendingSerial = mDevice->GetPendingCommandSerial();
// of space causing a new one to be allocated We should reuse heap subranges that have been size_t startOffset = (heapInfo->heap == nullptr)
// released ? RingBufferAllocator::kInvalidOffset
if (count == 0) { : heapInfo->allocator.Allocate(count, pendingSerial);
return DescriptorHeapHandle(); if (startOffset != RingBufferAllocator::kInvalidOffset) {
} return DescriptorHeapHandle{heapInfo->heap, mSizeIncrements[type], startOffset};
{
// 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;
}
} }
// If the pool has no more space, replace the pool with a new one of the specified size // 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"); return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate heap");
} }
AllocationInfo allocationInfo = {allocationSize, allocationSize - count}; mDevice->ReferenceUntilUnused(heap);
*heapInfo = std::make_pair(heap, allocationInfo);
DescriptorHeapHandle handle(heap, mSizeIncrements[type], 0); *heapInfo = {heap, RingBufferAllocator(allocationSize)};
Release(handle);
return handle; startOffset = heapInfo->allocator.Allocate(count, pendingSerial);
ASSERT(startOffset != RingBufferAllocator::kInvalidOffset);
return DescriptorHeapHandle(heap, mSizeIncrements[type], startOffset);
} }
ResultOrError<DescriptorHeapHandle> DescriptorHeapAllocator::AllocateCPUHeap( ResultOrError<DescriptorHeapHandle> DescriptorHeapAllocator::AllocateCPUHeap(
@ -120,18 +111,24 @@ namespace dawn_native { namespace d3d12 {
uint32_t count) { uint32_t count) {
ASSERT(type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || ASSERT(type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ||
type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
unsigned int heapSize = unsigned int heapSize = (type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV
(type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ? kMaxCbvUavSrvHeapSize ? D3D12_MAX_SHADER_VISIBLE_DESCRIPTOR_HEAP_SIZE_TIER_1
: kMaxSamplerHeapSize); : D3D12_MAX_SHADER_VISIBLE_SAMPLER_HEAP_SIZE);
return Allocate(type, count, heapSize, &mGpuDescriptorHeapInfos[type], return Allocate(type, count, heapSize, &mGpuDescriptorHeapInfos[type],
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE); D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE);
} }
void DescriptorHeapAllocator::Tick(uint64_t lastCompletedSerial) { void DescriptorHeapAllocator::Deallocate(uint64_t lastCompletedSerial) {
mReleasedHandles.ClearUpTo(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) { for (uint32_t i = 0; i < mGpuDescriptorHeapInfos.size(); i++) {
mReleasedHandles.Enqueue(handle, mDevice->GetPendingCommandSerial()); if (mGpuDescriptorHeapInfos[i].heap != nullptr) {
mGpuDescriptorHeapInfos[i].allocator.Deallocate(lastCompletedSerial);
}
}
} }
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -22,6 +22,7 @@
#include "common/SerialQueue.h" #include "common/SerialQueue.h"
#include "dawn_native/Error.h" #include "dawn_native/Error.h"
#include "dawn_native/RingBufferAllocator.h"
namespace dawn_native { namespace d3d12 { namespace dawn_native { namespace d3d12 {
@ -52,34 +53,27 @@ namespace dawn_native { namespace d3d12 {
uint32_t count); uint32_t count);
ResultOrError<DescriptorHeapHandle> AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, ResultOrError<DescriptorHeapHandle> AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE type,
uint32_t count); uint32_t count);
void Tick(uint64_t lastCompletedSerial); void Deallocate(uint64_t lastCompletedSerial);
private: private:
static constexpr unsigned int kMaxCbvUavSrvHeapSize = 1000000; struct DescriptorHeapInfo {
static constexpr unsigned int kMaxSamplerHeapSize = 2048; ComPtr<ID3D12DescriptorHeap> heap;
static constexpr unsigned int kDescriptorHeapTypes = RingBufferAllocator allocator;
D3D12_DESCRIPTOR_HEAP_TYPE::D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
struct AllocationInfo {
uint32_t size = 0;
uint32_t remaining = 0;
}; };
using DescriptorHeapInfo = std::pair<ComPtr<ID3D12DescriptorHeap>, AllocationInfo>;
ResultOrError<DescriptorHeapHandle> Allocate(D3D12_DESCRIPTOR_HEAP_TYPE type, ResultOrError<DescriptorHeapHandle> Allocate(D3D12_DESCRIPTOR_HEAP_TYPE type,
uint32_t count, uint32_t count,
uint32_t allocationSize, uint32_t allocationSize,
DescriptorHeapInfo* heapInfo, DescriptorHeapInfo* heapInfo,
D3D12_DESCRIPTOR_HEAP_FLAGS flags); D3D12_DESCRIPTOR_HEAP_FLAGS flags);
void Release(DescriptorHeapHandle handle);
Device* mDevice; Device* mDevice;
std::array<uint32_t, kDescriptorHeapTypes> mSizeIncrements; std::array<uint32_t, D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES> mSizeIncrements;
std::array<DescriptorHeapInfo, kDescriptorHeapTypes> mCpuDescriptorHeapInfos; std::array<DescriptorHeapInfo, D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES>
std::array<DescriptorHeapInfo, kDescriptorHeapTypes> mGpuDescriptorHeapInfos; mCpuDescriptorHeapInfos;
SerialQueue<DescriptorHeapHandle> mReleasedHandles; std::array<DescriptorHeapInfo, D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES>
mGpuDescriptorHeapInfos;
}; };
}} // namespace dawn_native::d3d12 }} // namespace dawn_native::d3d12

View File

@ -221,7 +221,7 @@ namespace dawn_native { namespace d3d12 {
mResourceAllocator->Tick(mCompletedSerial); mResourceAllocator->Tick(mCompletedSerial);
mCommandAllocatorManager->Tick(mCompletedSerial); mCommandAllocatorManager->Tick(mCompletedSerial);
mDescriptorHeapAllocator->Tick(mCompletedSerial); mDescriptorHeapAllocator->Deallocate(mCompletedSerial);
mMapRequestTracker->Tick(mCompletedSerial); mMapRequestTracker->Tick(mCompletedSerial);
mUsedComObjectRefs.ClearUpTo(mCompletedSerial); mUsedComObjectRefs.ClearUpTo(mCompletedSerial);
ExecuteCommandList(nullptr); ExecuteCommandList(nullptr);