244 lines
6.9 KiB
C++
244 lines
6.9 KiB
C++
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
|
|
|
#if GRAPHICS_API_DIRECTX12
|
|
|
|
#include "DescriptorHeapDX12.h"
|
|
#include "GPUDeviceDX12.h"
|
|
#include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h"
|
|
|
|
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorHeapWithSlotsDX12::Slot::CPU() const
|
|
{
|
|
ASSERT_LOW_LAYER(Heap);
|
|
return Heap->CPU(Index);
|
|
}
|
|
|
|
D3D12_GPU_DESCRIPTOR_HANDLE DescriptorHeapWithSlotsDX12::Slot::GPU() const
|
|
{
|
|
ASSERT_LOW_LAYER(Heap);
|
|
return Heap->GPU(Index);
|
|
}
|
|
|
|
void DescriptorHeapWithSlotsDX12::Slot::CreateSRV(GPUDeviceDX12* device, ID3D12Resource* resource, D3D12_SHADER_RESOURCE_VIEW_DESC* desc)
|
|
{
|
|
if (Heap == nullptr)
|
|
device->Heap_CBV_SRV_UAV.AllocateSlot(Heap, Index);
|
|
device->GetDevice()->CreateShaderResourceView(resource, desc, CPU());
|
|
}
|
|
|
|
void DescriptorHeapWithSlotsDX12::Slot::CreateRTV(GPUDeviceDX12* device, ID3D12Resource* resource, D3D12_RENDER_TARGET_VIEW_DESC* desc)
|
|
{
|
|
if (Heap == nullptr)
|
|
device->Heap_RTV.AllocateSlot(Heap, Index);
|
|
device->GetDevice()->CreateRenderTargetView(resource, desc, CPU());
|
|
}
|
|
|
|
void DescriptorHeapWithSlotsDX12::Slot::CreateDSV(GPUDeviceDX12* device, ID3D12Resource* resource, D3D12_DEPTH_STENCIL_VIEW_DESC* desc)
|
|
{
|
|
if (Heap == nullptr)
|
|
device->Heap_DSV.AllocateSlot(Heap, Index);
|
|
device->GetDevice()->CreateDepthStencilView(resource, desc, CPU());
|
|
}
|
|
|
|
void DescriptorHeapWithSlotsDX12::Slot::CreateUAV(GPUDeviceDX12* device, ID3D12Resource* resource, D3D12_UNORDERED_ACCESS_VIEW_DESC* desc, ID3D12Resource* counterResource)
|
|
{
|
|
if (Heap == nullptr)
|
|
device->Heap_CBV_SRV_UAV.AllocateSlot(Heap, Index);
|
|
device->GetDevice()->CreateUnorderedAccessView(resource, counterResource, desc, CPU());
|
|
}
|
|
|
|
void DescriptorHeapWithSlotsDX12::Slot::Release()
|
|
{
|
|
if (Heap)
|
|
{
|
|
Heap->ReleaseSlot(Index);
|
|
Heap = nullptr;
|
|
}
|
|
}
|
|
|
|
DescriptorHeapWithSlotsDX12::DescriptorHeapWithSlotsDX12(GPUDeviceDX12* device)
|
|
: _device(device)
|
|
, _heap(nullptr)
|
|
, _descriptorsCount(0)
|
|
{
|
|
}
|
|
|
|
bool DescriptorHeapWithSlotsDX12::Create(D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCount, bool shaderVisible)
|
|
{
|
|
// Create description
|
|
D3D12_DESCRIPTOR_HEAP_DESC desc;
|
|
desc.Type = type;
|
|
desc.NumDescriptors = descriptorsCount;
|
|
desc.Flags = shaderVisible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
|
desc.NodeMask = 0;
|
|
|
|
// Create heap
|
|
const HRESULT result = _device->GetDevice()->CreateDescriptorHeap(&desc, __uuidof(ID3D12DescriptorHeap), reinterpret_cast<void**>(&_heap));
|
|
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
|
|
|
// Setup
|
|
_type = type;
|
|
_shaderVisible = shaderVisible;
|
|
_descriptorsCount = descriptorsCount;
|
|
_beginCPU = _heap->GetCPUDescriptorHandleForHeapStart();
|
|
if (shaderVisible)
|
|
_beginGPU = _heap->GetGPUDescriptorHandleForHeapStart();
|
|
else
|
|
_beginGPU.ptr = 0;
|
|
_incrementSize = _device->GetDevice()->GetDescriptorHandleIncrementSize(desc.Type);
|
|
|
|
// Setup usage cache
|
|
_usage.Resize(static_cast<int32>(_descriptorsCount / 32), false);
|
|
Platform::MemorySet(_usage.Get(), _usage.Count() * sizeof(uint32), 0);
|
|
|
|
_memoryUsage = 1;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool DescriptorHeapWithSlotsDX12::TryToGetUnusedSlot(uint32& index)
|
|
{
|
|
for (int32 i = 0; i < _usage.Count(); i++)
|
|
{
|
|
uint32& value = _usage[i];
|
|
if (value != MAX_uint32)
|
|
{
|
|
// TODO: make it better?
|
|
for (int32 bit = 0; bit < 32; bit++)
|
|
{
|
|
const uint32 mask = 1 << bit;
|
|
if ((value & mask) == 0)
|
|
{
|
|
// Found
|
|
index = i * 32 + bit;
|
|
value |= mask;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void DescriptorHeapWithSlotsDX12::ReleaseSlot(uint32 index)
|
|
{
|
|
uint32& value = _usage[index / 32];
|
|
const uint32 mask = 1 << (index & 31);
|
|
ASSERT_LOW_LAYER((value & mask) == mask);
|
|
value &= ~mask;
|
|
}
|
|
|
|
GPUResourceType DescriptorHeapWithSlotsDX12::GetResourceType() const
|
|
{
|
|
return GPUResourceType::Descriptor;
|
|
}
|
|
|
|
DescriptorHeapPoolDX12::DescriptorHeapPoolDX12(GPUDeviceDX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCountPerHeap, bool shaderVisible)
|
|
: _device(device)
|
|
, _type(type)
|
|
, _descriptorsCountPerHeap(descriptorsCountPerHeap)
|
|
, _shaderVisible(shaderVisible)
|
|
{
|
|
}
|
|
|
|
void DescriptorHeapPoolDX12::AllocateSlot(DescriptorHeapWithSlotsDX12*& heap, uint32& slot)
|
|
{
|
|
for (int32 i = 0; i < _heaps.Count(); i++)
|
|
{
|
|
if (_heaps[i]->TryToGetUnusedSlot(slot))
|
|
{
|
|
heap = _heaps[i];
|
|
return;
|
|
}
|
|
}
|
|
|
|
heap = New<DescriptorHeapWithSlotsDX12>(_device);
|
|
if (heap->Create(_type, _descriptorsCountPerHeap, _shaderVisible))
|
|
{
|
|
Platform::Fatal(TEXT("Failed to allocate descriptor heap."));
|
|
}
|
|
_heaps.Add(heap);
|
|
heap->TryToGetUnusedSlot(slot);
|
|
}
|
|
|
|
void DescriptorHeapPoolDX12::ReleaseGPU()
|
|
{
|
|
for (auto heap : _heaps)
|
|
{
|
|
heap->ReleaseGPU();
|
|
Delete(heap);
|
|
}
|
|
_heaps.Clear();
|
|
}
|
|
|
|
void DescriptorHeapWithSlotsDX12::OnReleaseGPU()
|
|
{
|
|
_usage.SetCapacity(0, false);
|
|
DX_SAFE_RELEASE_CHECK(_heap, 0);
|
|
_descriptorsCount = 0;
|
|
}
|
|
|
|
DescriptorHeapRingBufferDX12::DescriptorHeapRingBufferDX12(GPUDeviceDX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCount, bool shaderVisible)
|
|
: _device(device)
|
|
, _heap(nullptr)
|
|
, _type(type)
|
|
, _descriptorsCount(descriptorsCount)
|
|
, _shaderVisible(shaderVisible)
|
|
{
|
|
}
|
|
|
|
bool DescriptorHeapRingBufferDX12::Init()
|
|
{
|
|
// Create heap
|
|
D3D12_DESCRIPTOR_HEAP_DESC desc;
|
|
desc.Type = _type;
|
|
desc.NumDescriptors = _descriptorsCount;
|
|
desc.Flags = _shaderVisible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
|
desc.NodeMask = 0;
|
|
const HRESULT result = _device->GetDevice()->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&_heap));
|
|
LOG_DIRECTX_RESULT_WITH_RETURN(result, true);
|
|
|
|
// Setup
|
|
_firstFree = 0;
|
|
_beginCPU = _heap->GetCPUDescriptorHandleForHeapStart();
|
|
if (_shaderVisible)
|
|
_beginGPU = _heap->GetGPUDescriptorHandleForHeapStart();
|
|
else
|
|
_beginGPU.ptr = 0;
|
|
_incrementSize = _device->GetDevice()->GetDescriptorHandleIncrementSize(desc.Type);
|
|
_memoryUsage = 1;
|
|
|
|
return false;
|
|
}
|
|
|
|
DescriptorHeapRingBufferDX12::Allocation DescriptorHeapRingBufferDX12::AllocateTable(uint32 numDesc)
|
|
{
|
|
Allocation result;
|
|
|
|
// Move the ring buffer pointer
|
|
uint32 index = _firstFree;
|
|
_firstFree += numDesc;
|
|
|
|
// Check for overflow
|
|
if (_firstFree >= _descriptorsCount)
|
|
{
|
|
// Move to the begin
|
|
index = 0;
|
|
_firstFree = numDesc;
|
|
}
|
|
|
|
// Set pointers
|
|
result.CPU.ptr = _beginCPU.ptr + static_cast<SIZE_T>(index * _incrementSize);
|
|
result.GPU.ptr = _shaderVisible ? _beginGPU.ptr + index * _incrementSize : 0;
|
|
|
|
return result;
|
|
}
|
|
|
|
void DescriptorHeapRingBufferDX12::OnReleaseGPU()
|
|
{
|
|
DX_SAFE_RELEASE_CHECK(_heap, 0);
|
|
_firstFree = 0;
|
|
}
|
|
|
|
#endif
|