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:
parent
e06f01be71
commit
e6b93e8706
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue