Files
UnrealEngine/Engine/Source/Runtime/D3D12RHI/Private/D3D12Descriptors.cpp
2025-05-18 13:04:45 +08:00

630 lines
21 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "D3D12Descriptors.h"
#include "D3D12RHIPrivate.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UE::D3D12Descriptors::CopyDescriptor(FD3D12Device* Device, FD3D12DescriptorHeap* TargetHeap, FRHIDescriptorHandle DstHandle, D3D12_CPU_DESCRIPTOR_HANDLE SrcCpuHandle)
{
if (DstHandle.IsValid())
{
const D3D12_CPU_DESCRIPTOR_HANDLE DestCpuHandle = TargetHeap->GetCPUSlotHandle(DstHandle.GetIndex());
const D3D12_DESCRIPTOR_HEAP_TYPE D3DHeapType = Translate(DstHandle.GetType());
Device->GetDevice()->CopyDescriptorsSimple(1, DestCpuHandle, SrcCpuHandle, D3DHeapType);
}
}
void UE::D3D12Descriptors::CopyDescriptors(FD3D12Device* Device, FD3D12DescriptorHeap* TargetHeap, FD3D12DescriptorHeap* SourceHeap, uint32 FirstDescriptor, uint32 NumDescriptors)
{
// Use regular CPU Profile without dynamic value - almost same overhead for string formatting as actual Copy
TRACE_CPUPROFILER_EVENT_SCOPE_STR("CopyDescriptors HeapToHeap");
//SCOPED_NAMED_EVENT_F(TEXT("CopyDescriptors HeapToHeap (%d)"), FColor::Turquoise, NumDescriptors);
const D3D12_CPU_DESCRIPTOR_HANDLE TargetStart = TargetHeap->GetCPUSlotHandle(FirstDescriptor);
const D3D12_CPU_DESCRIPTOR_HANDLE SourceStart = SourceHeap->GetCPUSlotHandle(FirstDescriptor);
const D3D12_DESCRIPTOR_HEAP_TYPE D3DHeapType = Translate(TargetHeap->GetType());
Device->GetDevice()->CopyDescriptorsSimple(
NumDescriptors,
TargetStart,
SourceStart,
D3DHeapType
);
}
void UE::D3D12Descriptors::CopyDescriptors(FD3D12Device* Device, FD3D12DescriptorHeap* TargetHeap, FD3D12DescriptorHeap* SourceHeap, TConstArrayView<FRHIDescriptorHandle> Handles)
{
// Use regular CPU Profile without dynamic value - almost same overhead for string formatting as actual Copy
TRACE_CPUPROFILER_EVENT_SCOPE_STR("CopyDescriptors HeapToHeap Scattered");
//SCOPED_NAMED_EVENT_F(TEXT("CopyDescriptors HeapToHeap Scattered (%d)"), FColor::Turquoise, Handles.Num());
const int32 NumDescriptors = Handles.Num();
const D3D12_DESCRIPTOR_HEAP_TYPE D3DHeapType = Translate(TargetHeap->GetType());
TArray<D3D12_CPU_DESCRIPTOR_HANDLE> DstDescriptors;
TArray<D3D12_CPU_DESCRIPTOR_HANDLE> SrcDescriptors;
TArray<UINT> CopyCounts;
DstDescriptors.SetNumUninitialized(NumDescriptors);
SrcDescriptors.SetNumUninitialized(NumDescriptors);
CopyCounts.SetNumUninitialized(NumDescriptors);
for (int32 Index = 0; Index < NumDescriptors; Index++)
{
DstDescriptors[Index] = TargetHeap->GetCPUSlotHandle(Handles[Index].GetIndex());
SrcDescriptors[Index] = SourceHeap->GetCPUSlotHandle(Handles[Index].GetIndex());
CopyCounts[Index] = 1;
}
Device->GetDevice()->CopyDescriptors(
NumDescriptors, DstDescriptors.GetData(), CopyCounts.GetData(),
NumDescriptors, SrcDescriptors.GetData(), CopyCounts.GetData(),
D3DHeapType
);
}
void UE::D3D12Descriptors::CopyDescriptors(FD3D12Device* Device, FD3D12DescriptorHeap* TargetHeap, TConstArrayView<FRHIDescriptorHandle> DstHandles, TConstArrayView<FD3D12OfflineDescriptor> SrcOfflineDescriptors)
{
// Use regular CPU Profile without dynamic value - almost same overhead for string formatting as actual Copy
TRACE_CPUPROFILER_EVENT_SCOPE_STR("CopyDescriptors Scattered");
//SCOPED_NAMED_EVENT_F(TEXT("CopyDescriptors Scattered (%d)"), FColor::Turquoise, DstHandles.Num());
check(DstHandles.Num() == SrcOfflineDescriptors.Num());
const int32 NumDescriptors = DstHandles.Num();
const D3D12_DESCRIPTOR_HEAP_TYPE D3DHeapType = Translate(TargetHeap->GetType());
TArray<D3D12_CPU_DESCRIPTOR_HANDLE> DstDescriptors;
TArray<D3D12_CPU_DESCRIPTOR_HANDLE> SrcDescriptors;
TArray<UINT> CopyCounts;
DstDescriptors.SetNumUninitialized(NumDescriptors);
SrcDescriptors.SetNumUninitialized(NumDescriptors);
CopyCounts.SetNumUninitialized(NumDescriptors);
for (int32 Index = 0; Index < NumDescriptors; Index++)
{
DstDescriptors[Index] = TargetHeap->GetCPUSlotHandle(DstHandles[Index].GetIndex());
SrcDescriptors[Index] = SrcOfflineDescriptors[Index];
CopyCounts[Index] = 1;
}
Device->GetDevice()->CopyDescriptors(
NumDescriptors, DstDescriptors.GetData(), CopyCounts.GetData(),
NumDescriptors, SrcDescriptors.GetData(), CopyCounts.GetData(),
D3DHeapType
);
}
FD3D12OfflineDescriptor UE::D3D12Descriptors::CreateOfflineCopy(FD3D12Device* Device, D3D12_CPU_DESCRIPTOR_HANDLE InDescriptor, ERHIDescriptorHeapType InType)
{
FD3D12OfflineDescriptor NewDescriptor = Device->GetOfflineDescriptorManager(InType).AllocateHeapSlot();
Device->GetDevice()->CopyDescriptorsSimple(1, NewDescriptor, InDescriptor, Translate(InType));
NewDescriptor.IncrementVersion();
return NewDescriptor;
}
FD3D12OfflineDescriptor UE::D3D12Descriptors::CreateOfflineCopy(FD3D12Device* Device, FD3D12DescriptorHeap* InHeap, FRHIDescriptorHandle InHandle)
{
D3D12_CPU_DESCRIPTOR_HANDLE SourceDescriptor = InHeap->GetCPUSlotHandle(InHandle.GetIndex());
return UE::D3D12Descriptors::CreateOfflineCopy(Device, SourceDescriptor, InHeap->GetType());
}
void UE::D3D12Descriptors::FreeOfflineCopy(FD3D12Device* Device, FD3D12OfflineDescriptor& InDescriptor, ERHIDescriptorHeapType InType)
{
Device->GetOfflineDescriptorManager(InType).FreeHeapSlot(InDescriptor);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FD3D12DescriptorHeap
FD3D12DescriptorHeap::FD3D12DescriptorHeap(FD3D12Device* InDevice, TRefCountPtr<ID3D12DescriptorHeap>&& InHeap, uint32 InNumDescriptors, ERHIDescriptorHeapType InType, ED3D12DescriptorHeapFlags InFlags, bool bInIsGlobal)
: FD3D12DeviceChild(InDevice)
, Heap(Forward<TRefCountPtr<ID3D12DescriptorHeap>>(InHeap))
, CpuBase(Heap->GetCPUDescriptorHandleForHeapStart())
, GpuBase(EnumHasAnyFlags(InFlags, ED3D12DescriptorHeapFlags::GpuVisible) ? Heap->GetGPUDescriptorHandleForHeapStart() : D3D12_GPU_DESCRIPTOR_HANDLE{})
, Offset(0)
, NumDescriptors(InNumDescriptors)
, DescriptorSize(InDevice->GetDevice()->GetDescriptorHandleIncrementSize(Translate(InType)))
, Type(InType)
, Flags(InFlags)
, bIsGlobal(bInIsGlobal)
, bIsSuballocation(false)
{
#if STATS
const size_t MemorySize = DescriptorSize * NumDescriptors;
if (Type == ERHIDescriptorHeapType::Standard)
{
INC_MEMORY_STAT_BY(STAT_BindlessResourceHeapMemory, MemorySize);
}
else if (Type == ERHIDescriptorHeapType::Sampler)
{
INC_MEMORY_STAT_BY(STAT_BindlessSamplerHeapMemory, MemorySize);
}
#endif
}
FD3D12DescriptorHeap::FD3D12DescriptorHeap(FD3D12DescriptorHeap* SubAllocateSourceHeap, uint32 InOffset, uint32 InNumDescriptors)
: FD3D12DeviceChild(SubAllocateSourceHeap->GetParentDevice())
, Heap(SubAllocateSourceHeap->Heap)
, CpuBase(SubAllocateSourceHeap->CpuBase, InOffset, SubAllocateSourceHeap->DescriptorSize)
, GpuBase(SubAllocateSourceHeap->GpuBase, InOffset, SubAllocateSourceHeap->DescriptorSize)
, Offset(InOffset)
, NumDescriptors(InNumDescriptors)
, DescriptorSize(SubAllocateSourceHeap->DescriptorSize)
, Type(SubAllocateSourceHeap->GetType())
, Flags(SubAllocateSourceHeap->GetFlags())
, bIsGlobal(SubAllocateSourceHeap->IsGlobal())
, bIsSuballocation(true)
{
}
FD3D12DescriptorHeap::~FD3D12DescriptorHeap()
{
if (CanBePooled())
{
GetParentDevice()->GetDescriptorHeapManager().AddHeapToPool(MoveTemp(Heap), GetType(), GetNumDescriptors(), GetFlags());
}
#if STATS
if (!bIsSuballocation)
{
const size_t MemorySize = DescriptorSize * NumDescriptors;
if (Type == ERHIDescriptorHeapType::Standard)
{
DEC_MEMORY_STAT_BY(STAT_BindlessResourceHeapMemory, MemorySize);
}
else if (Type == ERHIDescriptorHeapType::Sampler)
{
DEC_MEMORY_STAT_BY(STAT_BindlessSamplerHeapMemory, MemorySize);
}
}
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FD3D12DescriptorManager
FD3D12DescriptorManager::FD3D12DescriptorManager(FD3D12Device* Device, FD3D12DescriptorHeap* InHeap, TConstArrayView<TStatId> InStats)
: FD3D12DeviceChild(Device)
, FRHIHeapDescriptorAllocator(InHeap->GetType(), InHeap->GetNumDescriptors(), InStats)
, Heap(InHeap)
{
}
FD3D12DescriptorManager::~FD3D12DescriptorManager() = default;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FD3D12OnlineDescriptorManager
FD3D12OnlineDescriptorManager::FD3D12OnlineDescriptorManager(FD3D12Device* Device)
: FD3D12DeviceChild(Device)
{
}
FD3D12OnlineDescriptorManager::~FD3D12OnlineDescriptorManager() = default;
// Allocate and initialize the online heap
void FD3D12OnlineDescriptorManager::Init(uint32 InTotalSize, uint32 InBlockSize, bool bBindlessResources)
{
#if PLATFORM_SUPPORTS_BINDLESS_RENDERING
if (bBindlessResources)
{
#if D3D12RHI_USE_CONSTANT_BUFFER_VIEWS
Heaps = GetParentDevice()->GetBindlessDescriptorManager().AllocateResourceHeapsForAllPipelines(InTotalSize);
for (ERHIPipeline Pipeline : MakeFlagsRange(ERHIPipeline::All))
{
if (Heaps[Pipeline])
{
INC_DWORD_STAT(STAT_NumViewOnlineDescriptorHeaps);
INC_MEMORY_STAT_BY(STAT_ViewOnlineDescriptorHeapMemory, Heaps[Pipeline]->GetMemorySize());
}
}
#else
// We won't need CBVs, so don't allocate the heap for them
return;
#endif
}
else
#endif
{
FD3D12DescriptorHeapPtr Heap = GetParentDevice()->GetDescriptorHeapManager().AllocateHeap(
TEXT("Device Global - Online View Heap"),
ERHIDescriptorHeapType::Standard,
InTotalSize,
ED3D12DescriptorHeapFlags::GpuVisible);
INC_DWORD_STAT(STAT_NumViewOnlineDescriptorHeaps);
INC_MEMORY_STAT_BY(STAT_ViewOnlineDescriptorHeapMemory, Heap->GetMemorySize());
for (ERHIPipeline Pipeline : MakeFlagsRange(ERHIPipeline::All))
{
Heaps[Pipeline] = Heap;
}
}
// Update the stats
INC_DWORD_STAT_BY(STAT_GlobalViewHeapFreeDescriptors, InTotalSize);
// Compute amount of free blocks
uint32 BlockCount = InTotalSize / InBlockSize;
// Allocate the free blocks
uint32 CurrentBaseSlot = 0;
for (uint32 BlockIndex = 0; BlockIndex < BlockCount; ++BlockIndex)
{
// Last entry take the rest
uint32 ActualBlockSize = (BlockIndex == (BlockCount - 1)) ? InTotalSize - CurrentBaseSlot : InBlockSize;
FreeBlocks.Enqueue(new FD3D12OnlineDescriptorBlock(CurrentBaseSlot, ActualBlockSize));
CurrentBaseSlot += ActualBlockSize;
}
}
void FD3D12OnlineDescriptorManager::CleanupResources()
{
for (ERHIPipeline Pipeline : MakeFlagsRange(ERHIPipeline::All))
{
Heaps[Pipeline] = nullptr;
}
}
// Allocate a new heap block
FD3D12OnlineDescriptorBlock* FD3D12OnlineDescriptorManager::AllocateHeapBlock()
{
SCOPED_NAMED_EVENT(FD3D12OnlineViewHeap_AllocateHeapBlock, FColor::Silver);
FScopeLock Lock(&CriticalSection);
// Free block
FD3D12OnlineDescriptorBlock* Result = nullptr;
FreeBlocks.Dequeue(Result);
if (Result)
{
// Update stats
INC_DWORD_STAT(STAT_GlobalViewHeapBlockAllocations);
DEC_DWORD_STAT_BY(STAT_GlobalViewHeapFreeDescriptors, Result->Size);
INC_DWORD_STAT_BY(STAT_GlobalViewHeapReservedDescriptors, Result->Size);
}
return Result;
}
// Free given block - can still be used by the GPU
void FD3D12OnlineDescriptorManager::FreeHeapBlock(FD3D12OnlineDescriptorBlock* InHeapBlock)
{
// Update stats
DEC_DWORD_STAT_BY(STAT_GlobalViewHeapReservedDescriptors, InHeapBlock->Size);
INC_DWORD_STAT_BY(STAT_GlobalViewHeapUsedDescriptors, InHeapBlock->SizeUsed);
INC_DWORD_STAT_BY(STAT_GlobalViewHeapWastedDescriptors, InHeapBlock->Size - InHeapBlock->SizeUsed);
FD3D12DynamicRHI::GetD3DRHI()->DeferredDelete(InHeapBlock, this);
}
// Called by the EOP task to recycle blocks
void FD3D12OnlineDescriptorManager::Recycle(FD3D12OnlineDescriptorBlock* Block)
{
FScopeLock Lock(&CriticalSection);
// Update stats
DEC_DWORD_STAT_BY(STAT_GlobalViewHeapUsedDescriptors, Block->SizeUsed);
DEC_DWORD_STAT_BY(STAT_GlobalViewHeapWastedDescriptors, Block->Size - Block->SizeUsed);
INC_DWORD_STAT_BY(STAT_GlobalViewHeapFreeDescriptors, Block->Size);
Block->SizeUsed = 0;
FreeBlocks.Enqueue(Block);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FD3D12OfflineDescriptorManager
static uint32 GetOfflineDescriptorHeapDefaultSize(ERHIDescriptorHeapType InHeapType)
{
switch (InHeapType)
{
default: checkNoEntry();
#if D3D12RHI_USE_CONSTANT_BUFFER_VIEWS
case ERHIDescriptorHeapType::Standard: return 4096;
#else
case ERHIDescriptorHeapType::Standard: return 2048;
#endif
case ERHIDescriptorHeapType::RenderTarget: return 256;
case ERHIDescriptorHeapType::DepthStencil: return 256;
case ERHIDescriptorHeapType::Sampler: return 128;
}
}
FD3D12OfflineDescriptorManager::FD3D12OfflineDescriptorManager(FD3D12Device* InDevice, ERHIDescriptorHeapType InHeapType)
: FD3D12DeviceChild(InDevice)
, HeapType(InHeapType)
{
DescriptorSize = GetParentDevice()->GetDevice()->GetDescriptorHandleIncrementSize(Translate(InHeapType));
NumDescriptorsPerHeap = GetOfflineDescriptorHeapDefaultSize(InHeapType);
}
FD3D12OfflineDescriptorManager::~FD3D12OfflineDescriptorManager() = default;
void FD3D12OfflineDescriptorManager::AllocateHeap()
{
checkf(NumDescriptorsPerHeap != 0, TEXT("Init() needs to be called before allocating heaps."));
TRefCountPtr<FD3D12DescriptorHeap> Heap = GetParentDevice()->GetDescriptorHeapManager().AllocateHeap(
TEXT("FD3D12OfflineDescriptorManager"),
HeapType,
NumDescriptorsPerHeap,
ED3D12DescriptorHeapFlags::None
);
D3D12_CPU_DESCRIPTOR_HANDLE HeapBase = Heap->GetCPUSlotHandle(0);
check(HeapBase.ptr != 0);
// Allocate and initialize a single new entry in the map
const uint32 NewHeapIndex = Heaps.Num();
Heaps.Emplace(Heap, HeapBase, NumDescriptorsPerHeap * DescriptorSize);
FreeHeaps.AddTail(NewHeapIndex);
}
FD3D12OfflineDescriptor FD3D12OfflineDescriptorManager::AllocateHeapSlot()
{
FScopeLock Lock(&CriticalSection);
FD3D12OfflineDescriptor Result;
if (FreeHeaps.Num() == 0)
{
AllocateHeap();
}
check(FreeHeaps.Num() != 0);
auto Head = FreeHeaps.GetHead();
Result.HeapIndex = Head->GetValue();
FD3D12OfflineHeapEntry& HeapEntry = Heaps[Result.HeapIndex];
check(0 != HeapEntry.FreeList.Num());
FD3D12OfflineHeapFreeRange& Range = HeapEntry.FreeList.GetHead()->GetValue();
Result.ptr = Range.Start;
Range.Start += DescriptorSize;
if (Range.Start == Range.End)
{
HeapEntry.FreeList.RemoveNode(HeapEntry.FreeList.GetHead());
if (HeapEntry.FreeList.Num() == 0)
{
FreeHeaps.RemoveNode(Head);
}
}
return Result;
}
void FD3D12OfflineDescriptorManager::FreeHeapSlot(FD3D12OfflineDescriptor& Descriptor)
{
FScopeLock Lock(&CriticalSection);
FD3D12OfflineHeapEntry& HeapEntry = Heaps[Descriptor.HeapIndex];
const FD3D12OfflineHeapFreeRange NewRange{ Descriptor.ptr, Descriptor.ptr + DescriptorSize };
bool bFound = false;
for (auto Node = HeapEntry.FreeList.GetHead();
Node != nullptr && !bFound;
Node = Node->GetNextNode())
{
FD3D12OfflineHeapFreeRange& Range = Node->GetValue();
check(Range.Start < Range.End);
if (Range.Start == Descriptor.ptr + DescriptorSize)
{
Range.Start = Descriptor.ptr;
bFound = true;
}
else if (Range.End == Descriptor.ptr)
{
Range.End += DescriptorSize;
bFound = true;
}
else
{
check(Range.End < Descriptor.ptr || Range.Start > Descriptor.ptr);
if (Range.Start > Descriptor.ptr)
{
HeapEntry.FreeList.InsertNode(NewRange, Node);
bFound = true;
}
}
}
if (!bFound)
{
if (HeapEntry.FreeList.Num() == 0)
{
FreeHeaps.AddTail(Descriptor.HeapIndex);
}
HeapEntry.FreeList.AddTail(NewRange);
}
Descriptor = {};
}
void FD3D12OfflineDescriptorManager::CleanupResources()
{
for (FD3D12OfflineHeapEntry& HeapEntry : Heaps)
{
HeapEntry.Heap = nullptr;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FD3D12DescriptorHeapManager
FD3D12DescriptorHeapManager::FD3D12DescriptorHeapManager(FD3D12Device* InDevice)
: FD3D12DeviceChild(InDevice)
{
}
FD3D12DescriptorHeapManager::~FD3D12DescriptorHeapManager()
{
Destroy();
}
static FD3D12DescriptorHeap* CreateDescriptorHeap(FD3D12Device* Device, const TCHAR* DebugName, ERHIDescriptorHeapType HeapType, uint32 NumDescriptors, ED3D12DescriptorHeapFlags Flags, bool bIsGlobal)
{
SCOPED_NAMED_EVENT_F(TEXT("D3D12Device::CreateDescriptorHeap(%s, %d)"), FColor::Turquoise, DebugName, NumDescriptors);
D3D12_DESCRIPTOR_HEAP_DESC Desc{};
Desc.Type = Translate(HeapType);
Desc.NumDescriptors = NumDescriptors;
Desc.Flags = Translate(Flags);
Desc.NodeMask = Device->GetGPUMask().GetNative();
TRefCountPtr<ID3D12DescriptorHeap> Heap;
VERIFYD3D12RESULT(Device->GetDevice()->CreateDescriptorHeap(&Desc, IID_PPV_ARGS(Heap.GetInitReference())));
SetD3D12ObjectName(Heap, DebugName);
return new FD3D12DescriptorHeap(Device, MoveTemp(Heap), NumDescriptors, HeapType, Flags, bIsGlobal);
}
void FD3D12DescriptorHeapManager::Init(uint32 InNumGlobalResourceDescriptors, uint32 InNumGlobalSamplerDescriptors)
{
if (InNumGlobalResourceDescriptors > 0)
{
FD3D12DescriptorHeap* Heap = CreateDescriptorHeap(
GetParentDevice(),
TEXT("GlobalResourceHeap"),
ERHIDescriptorHeapType::Standard,
InNumGlobalResourceDescriptors,
ED3D12DescriptorHeapFlags::GpuVisible,
true /* bIsGlobal */
);
const TStatId Stats[] = {GET_STATID(STAT_ResourceDescriptorsAllocated)};
GlobalHeaps.Emplace(GetParentDevice(), Heap, Stats);
}
if (InNumGlobalSamplerDescriptors > 0)
{
FD3D12DescriptorHeap* Heap = CreateDescriptorHeap(
GetParentDevice(),
TEXT("GlobalSamplerHeap"),
ERHIDescriptorHeapType::Sampler,
InNumGlobalSamplerDescriptors,
ED3D12DescriptorHeapFlags::GpuVisible,
true /* bIsGlobal */
);
const TStatId Stats[] = { GET_STATID(STAT_SamplerDescriptorsAllocated) };
GlobalHeaps.Emplace(GetParentDevice(), Heap, Stats);
}
}
void FD3D12DescriptorHeapManager::Destroy()
{
}
TRefCountPtr<ID3D12DescriptorHeap> FD3D12DescriptorHeapManager::AcquirePooledHeap(ERHIDescriptorHeapType InType, uint32 InNumDescriptors, ED3D12DescriptorHeapFlags InFlags)
{
FScopeLock Lock(&PooledHeapsCS);
const int32 Index = PooledHeaps.IndexOfByPredicate([InType, InNumDescriptors, InFlags](const FPooledHeap& PooledHeap) -> bool
{
return PooledHeap.Type == InType
&& PooledHeap.NumDescriptors == InNumDescriptors
&& PooledHeap.Flags == InFlags;
});
if (Index != INDEX_NONE)
{
TRefCountPtr<ID3D12DescriptorHeap> Result;
PooledHeaps[Index].Heap.Swap(Result);
PooledHeaps.RemoveAt(Index);
return Result;
}
return nullptr;
}
FD3D12DescriptorHeap* FD3D12DescriptorHeapManager::AllocateIndependentHeap(const TCHAR* InDebugName, ERHIDescriptorHeapType InHeapType, uint32 InNumDescriptors, ED3D12DescriptorHeapFlags InHeapFlags)
{
if (EnumHasAnyFlags(InHeapFlags, ED3D12DescriptorHeapFlags::Poolable))
{
TRefCountPtr<ID3D12DescriptorHeap> PooledHeap = AcquirePooledHeap(InHeapType, InNumDescriptors, InHeapFlags);
if (PooledHeap.GetReference())
{
return new FD3D12DescriptorHeap(GetParentDevice(), MoveTemp(PooledHeap), InNumDescriptors, InHeapType, InHeapFlags, false);
}
}
return CreateDescriptorHeap(GetParentDevice(), InDebugName, InHeapType, InNumDescriptors, InHeapFlags, false);
}
FD3D12DescriptorHeap* FD3D12DescriptorHeapManager::AllocateHeap(const TCHAR* InDebugName, ERHIDescriptorHeapType InHeapType, uint32 InNumDescriptors, ED3D12DescriptorHeapFlags InHeapFlags)
{
for (FD3D12DescriptorManager& GlobalHeap : GlobalHeaps)
{
if (GlobalHeap.HandlesAllocationWithFlags(InHeapType, InHeapFlags))
{
uint32 Offset = 0;
if (GlobalHeap.Allocate(InNumDescriptors, Offset))
{
return new FD3D12DescriptorHeap(GlobalHeap.GetHeap(), Offset, InNumDescriptors);
}
// TODO: handle running out of space
//checkNoEntry();
}
}
return AllocateIndependentHeap(InDebugName, InHeapType, InNumDescriptors, InHeapFlags);
}
void FD3D12DescriptorHeapManager::DeferredFreeHeap(FD3D12DescriptorHeap* InHeap)
{
if (InHeap->IsGlobal())
{
for (FD3D12DescriptorManager& GlobalHeap : GlobalHeaps)
{
if (GlobalHeap.IsHeapAChild(InHeap))
{
InHeap->AddRef();
FD3D12DynamicRHI::GetD3DRHI()->DeferredDelete(InHeap, FD3D12DeferredDeleteObject::EType::DescriptorHeap);
return;
}
}
}
else
{
InHeap->AddRef();
FD3D12DynamicRHI::GetD3DRHI()->DeferredDelete(InHeap, FD3D12DeferredDeleteObject::EType::DescriptorHeap);
}
}
void FD3D12DescriptorHeapManager::ImmediateFreeHeap(FD3D12DescriptorHeap* InHeap)
{
if (InHeap->IsGlobal())
{
for (FD3D12DescriptorManager& GlobalHeap : GlobalHeaps)
{
if (GlobalHeap.IsHeapAChild(InHeap))
{
GlobalHeap.Free(InHeap->GetOffset(), InHeap->GetNumDescriptors());
InHeap->Release();
return;
}
}
}
else
{
InHeap->Release();
}
}
void FD3D12DescriptorHeapManager::AddHeapToPool(TRefCountPtr<ID3D12DescriptorHeap>&& InHeap, ERHIDescriptorHeapType InType, uint32 InNumDescriptors, ED3D12DescriptorHeapFlags InFlags)
{
FScopeLock Lock(&PooledHeapsCS);
PooledHeaps.Emplace(Forward<TRefCountPtr<ID3D12DescriptorHeap>>(InHeap), InType, InNumDescriptors, InFlags);
}