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 {
public:
RingBufferAllocator() = default;
RingBufferAllocator(size_t maxSize);
~RingBufferAllocator() = default;

View File

@ -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<DescriptorHeapHandle> 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

View File

@ -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<DescriptorHeapHandle> 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<ID3D12DescriptorHeap> heap;
RingBufferAllocator allocator;
};
using DescriptorHeapInfo = std::pair<ComPtr<ID3D12DescriptorHeap>, AllocationInfo>;
ResultOrError<DescriptorHeapHandle> 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<uint32_t, kDescriptorHeapTypes> mSizeIncrements;
std::array<DescriptorHeapInfo, kDescriptorHeapTypes> mCpuDescriptorHeapInfos;
std::array<DescriptorHeapInfo, kDescriptorHeapTypes> mGpuDescriptorHeapInfos;
SerialQueue<DescriptorHeapHandle> mReleasedHandles;
std::array<uint32_t, D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES> mSizeIncrements;
std::array<DescriptorHeapInfo, D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES>
mCpuDescriptorHeapInfos;
std::array<DescriptorHeapInfo, D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES>
mGpuDescriptorHeapInfos;
};
}} // namespace dawn_native::d3d12

View File

@ -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);