Refactor graphics architecture and resource management

Added DescriptorAllocator.cs to manage descriptor allocations for Direct3D 12.
Added Texture2D.cs to handle 2D textures and GPU resource creation.
Added DescriptorAllocatorExample.cs to demonstrate the new descriptor allocator interface.

Changed project files to reference Misaki.HighPerformance.LowLevel instead of Misaki.HighPerformance.Unsafe.
Changed _renderView type from IRenderer? to Renderer? in ScenePage.xaml.cs.
Changed EngineCore.cs to remove explicit graphics API specification during initialization.
Changed Logger.cs to enhance the Assert method with a DoesNotReturnIf attribute.
Changed resource types in Mesh.cs from IResource to GraphicsResource.

Removed multiple interfaces including ICommandBuffer, IDebugLayer, IGraphicsDevice, IPipelineResource, IRenderPass, IRenderer, IResource, and IResourceAllocator to simplify the graphics architecture.
Removed D3D12DebugLayer class from DebugLayer.cs to streamline the debug layer implementation.

Updated CommandList.cs and D3D12CommandBuffer.cs to implement a new command list structure for Direct3D 12.
Updated Material.cs to improve handling of constant buffers and textures.
Updated Shader.cs to include new structures for texture and property information.
Updated GraphicsPipeline.cs to support the new graphics device and resource management system.
Updated UnitTestAppWindow.xaml.cs to reflect changes in the renderer type and ensure proper resource management.
Updated BindlessMeshRenderPass.cs and MeshRenderPass.cs to implement modern rendering techniques, including bindless textures and improved shader management.
Updated CBufferCache.cs to align with the new resource management system and improve memory handling.
This commit is contained in:
2025-07-12 01:20:04 +09:00
parent eed1b9d3d0
commit 1284bb17de
38 changed files with 2831 additions and 517 deletions

View File

@@ -0,0 +1,246 @@
using Ghost.Core;
using System.Diagnostics;
using System.Numerics;
using Win32;
using Win32.Graphics.Direct3D12;
using DescriptorIndex = System.UInt32;
namespace Ghost.Graphics.D3D12.Utilities;
internal unsafe struct DescriptorHeapAllocator : IDisposable
{
private const DescriptorIndex _INVALID_DESCRIPTOR_INDEX = ~0u;
private readonly ConstPtr<ID3D12Device14> _device;
private readonly Lock _lock = new();
private ComPtr<ID3D12DescriptorHeap> _heap;
private ComPtr<ID3D12DescriptorHeap> _shaderVisibleHeap;
private CpuDescriptorHandle _startCpuHandle;
private CpuDescriptorHandle _startCpuHandleShaderVisible;
private GpuDescriptorHandle _startGpuHandleShaderVisible;
private DescriptorIndex _searchStart;
private bool[] _allocatedDescriptors = [];
public DescriptorHeapType HeapType
{
get;
}
public uint NumDescriptors
{
get; private set;
}
public uint NumAllocatedDescriptors
{
get; private set;
}
public bool ShaderVisible
{
get;
}
public uint Stride
{
get;
}
public readonly ConstPtr<ID3D12DescriptorHeap> Heap => new(_heap.Get());
public readonly ConstPtr<ID3D12DescriptorHeap> ShaderVisibleHeap => new(_shaderVisibleHeap.Get());
public DescriptorHeapAllocator(ConstPtr<ID3D12Device14> device, DescriptorHeapType type, uint numDescriptors)
{
_device = device;
HeapType = type;
NumDescriptors = numDescriptors;
ShaderVisible = type == DescriptorHeapType.CbvSrvUav || type == DescriptorHeapType.Sampler;
Stride = device.Ptr->GetDescriptorHandleIncrementSize(type);
var success = AllocateResources(numDescriptors);
Debug.Assert(success);
}
public DescriptorIndex AllocateDescriptor() => AllocateDescriptors(1);
public DescriptorIndex AllocateDescriptors(uint count)
{
lock (_lock)
{
DescriptorIndex foundIndex = 0;
uint freeCount = 0;
var found = false;
// Find a contiguous range of 'count' indices for which _allocatedDescriptors[index] is false
for (var index = _searchStart; index < NumDescriptors; index++)
{
if (_allocatedDescriptors[index])
{
freeCount = 0;
}
else
{
freeCount += 1;
}
if (freeCount >= count)
{
foundIndex = index > 0 ? index - count + 1 : 0;
found = true;
break;
}
}
if (!found)
{
foundIndex = NumDescriptors;
if (!Grow(NumDescriptors + count))
{
Debug.WriteLine("ERROR: Failed to grow a descriptor heap!");
return _INVALID_DESCRIPTOR_INDEX;
}
}
for (var index = foundIndex; index < foundIndex + count; index++)
{
_allocatedDescriptors[index] = true;
}
NumAllocatedDescriptors += count;
_searchStart = foundIndex + count;
return foundIndex;
}
}
public void ReleaseDescriptor(DescriptorIndex index) => ReleaseDescriptors(index, 1);
public void ReleaseDescriptors(DescriptorIndex baseIndex, uint count = 1)
{
if (count == 0)
{
return;
}
lock (_lock)
{
for (var index = baseIndex; index < baseIndex + count; index++)
{
#if DEBUG
if (!_allocatedDescriptors[index])
{
Debug.WriteLine("Error: Attempted to release an un-allocated descriptor");
}
#endif
_allocatedDescriptors[index] = false;
}
NumAllocatedDescriptors -= count;
if (_searchStart > baseIndex)
{
_searchStart = baseIndex;
}
}
}
public CpuDescriptorHandle GetCpuHandle(DescriptorIndex index)
{
var handle = _startCpuHandle;
return handle.Offset((int)index, Stride);
}
public CpuDescriptorHandle GetCpuHandleShaderVisible(DescriptorIndex index)
{
var handle = _startCpuHandleShaderVisible;
return handle.Offset((int)index, Stride);
}
public GpuDescriptorHandle GetGpuHandle(DescriptorIndex index)
{
var handle = _startGpuHandleShaderVisible;
return handle.Offset((int)index, Stride);
}
public void CopyToShaderVisibleHeap(DescriptorIndex index, uint count = 1)
{
_device.Ptr->CopyDescriptorsSimple(count, GetCpuHandleShaderVisible(index), GetCpuHandle(index), HeapType);
}
private bool AllocateResources(uint numDescriptors)
{
NumDescriptors = numDescriptors;
_heap.Dispose();
_shaderVisibleHeap.Dispose();
DescriptorHeapDescription heapDesc = new()
{
Type = HeapType,
NumDescriptors = numDescriptors,
Flags = DescriptorHeapFlags.None,
NodeMask = 0
};
fixed (void* heapPtr = &_heap)
{
var hr = _device.Ptr->CreateDescriptorHeap(&heapDesc, __uuidof<ID3D12DescriptorHeap>(), (void**)heapPtr);
if (hr.Failure)
{
return false;
}
}
_startCpuHandle = _heap.Get()->GetCPUDescriptorHandleForHeapStart();
Array.Resize(ref _allocatedDescriptors, (int)numDescriptors);
if (ShaderVisible)
{
heapDesc.Flags = DescriptorHeapFlags.ShaderVisible;
fixed (void* heapPtr = &_shaderVisibleHeap)
{
var hr = _device.Ptr->CreateDescriptorHeap(&heapDesc, __uuidof<ID3D12DescriptorHeap>(), (void**)heapPtr);
if (hr.Failure)
{
return false;
}
}
_startCpuHandleShaderVisible = _shaderVisibleHeap.Get()->GetCPUDescriptorHandleForHeapStart();
_startGpuHandleShaderVisible = _shaderVisibleHeap.Get()->GetGPUDescriptorHandleForHeapStart();
}
return true;
}
private bool Grow(uint minRequiredSize)
{
var oldSize = NumDescriptors;
var newSize = BitOperations.RoundUpToPowerOf2(minRequiredSize);
var oldHeap = _heap;
if (!AllocateResources(newSize))
{
return false;
}
_device.Ptr->CopyDescriptorsSimple(oldSize, _startCpuHandle, oldHeap.Get()->GetCPUDescriptorHandleForHeapStart(), HeapType);
if (_shaderVisibleHeap.Get() is not null)
{
_device.Ptr->CopyDescriptorsSimple(oldSize, _startCpuHandleShaderVisible, oldHeap.Get()->GetCPUDescriptorHandleForHeapStart(), HeapType);
}
return true;
}
/// <inheritdoc />
public void Dispose()
{
_heap.Dispose();
_shaderVisibleHeap.Dispose();
}
}