Refactor Vector3Field and update project structure
Changed Vector3Field.cs to derive from ValueControl<Vector3> and use NumberBox controls for better UI handling. Changed EditorControls.xaml to update resource paths for new controls. Changed InternalControls.xaml to simplify the resource dictionary by removing unnecessary references. Changed IComponentEditor.cs to reflect updates in the component editor's lifecycle methods. Changed project files for Ghost.Editor and Ghost.Core to include new dependencies and project references. Changed FileExtensions.cs and IInspectorService.cs to align with the new namespace structure. Changed Result.cs to enhance error handling and success checking methods. Changed TypeHandle.cs to improve type handling compatibility. Changed AssemblyInfo.cs files to include new assembly visibility attributes for better encapsulation. Added new graphics-related classes and interfaces in the Ghost.Engine project, including IGraphicsDevice and DX12GraphicsDevice. Added a new Mesh class to handle 3D mesh data and provide methods for creating geometric shapes. Added GraphicsPipeline.cs to manage the graphics rendering loop and device initialization. Added ScenePage.xaml and ScenePage.xaml.cs to create a new page for rendering scenes. Updated HierarchyPage.xaml.cs and InspectorPage.xaml.cs to use the new service locator pattern for service retrieval. Updated LandingWindow.xaml.cs and EngineEditorWindow.xaml.cs to utilize the new service locator pattern for better service access. Updated Logger.cs to enhance logging capabilities with optional stack traces and assertion logging. Updated QueryFilter.cs and QueryEnumerable.cs to use the new TypeHandle structure for improved efficiency. Updated WorldNode.cs and WorldNodeSerializer.cs to enhance serialization and management of world nodes. Updated AssetDatabase and related classes to improve asset management and metadata generation. Updated Ghost.UnitTest.csproj to include new project references and package dependencies for unit tests.
This commit is contained in:
36
Ghost.Graphics/DX12/DX12DebugLayer.cs
Normal file
36
Ghost.Graphics/DX12/DX12DebugLayer.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Ghost.Graphics.Contracts;
|
||||
using Vortice.Direct3D12;
|
||||
using Vortice.Direct3D12.Debug;
|
||||
using Vortice.DXGI;
|
||||
using Vortice.DXGI.Debug;
|
||||
|
||||
namespace Ghost.Graphics.DX12;
|
||||
|
||||
internal class DX12DebugLayer : IDebugLayer
|
||||
{
|
||||
#if DEBUG
|
||||
private readonly ID3D12Debug6 _d3d12Debug;
|
||||
private readonly IDXGIDebug1 _dxgiDebug;
|
||||
#endif
|
||||
|
||||
public DX12DebugLayer()
|
||||
{
|
||||
#if DEBUG
|
||||
_d3d12Debug = D3D12.D3D12GetDebugInterface<ID3D12Debug6>();
|
||||
_d3d12Debug.EnableDebugLayer();
|
||||
|
||||
_dxgiDebug = DXGI.DXGIGetDebugInterface1<IDXGIDebug1>();
|
||||
_dxgiDebug.EnableLeakTrackingForThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
#if DEBUG
|
||||
_dxgiDebug.ReportLiveObjects(DXGI.DebugAll, ReportLiveObjectFlags.Detail | ReportLiveObjectFlags.IgnoreInternal);
|
||||
|
||||
_d3d12Debug?.Dispose();
|
||||
_dxgiDebug?.Dispose();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
117
Ghost.Graphics/DX12/DX12GraphicsDevice.cs
Normal file
117
Ghost.Graphics/DX12/DX12GraphicsDevice.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using Ghost.Graphics.Contracts;
|
||||
using Ghost.Graphics.Data;
|
||||
using Vortice.Direct3D;
|
||||
using Vortice.Direct3D12;
|
||||
using Vortice.DXGI;
|
||||
|
||||
namespace Ghost.Graphics.DX12;
|
||||
|
||||
internal class DX12GraphicsDevice : IGraphicsDevice
|
||||
{
|
||||
private readonly IDXGIFactory7 _dxgiFactory;
|
||||
private readonly ID3D12Device14 _device;
|
||||
private readonly ID3D12CommandQueue _commandQueue;
|
||||
|
||||
private readonly List<IRenderView> _renderViews = new();
|
||||
|
||||
#if DEBUG
|
||||
private readonly IDebugLayer _debugLayer;
|
||||
#endif
|
||||
|
||||
public ID3D12Device14 Device => _device;
|
||||
public IDXGIFactory7 DXGIFactory => _dxgiFactory;
|
||||
public ID3D12CommandQueue CommandQueue => _commandQueue;
|
||||
|
||||
public static IGraphicsDevice Create() => new DX12GraphicsDevice();
|
||||
|
||||
private DX12GraphicsDevice()
|
||||
{
|
||||
#if DEBUG
|
||||
_debugLayer = new DX12DebugLayer();
|
||||
#endif
|
||||
|
||||
InitializeDevice(out _dxgiFactory, out _device);
|
||||
InitializeCommandQueue(out _commandQueue);
|
||||
}
|
||||
|
||||
private void InitializeDevice(out IDXGIFactory7 factory, out ID3D12Device14 device)
|
||||
{
|
||||
#if DEBUG
|
||||
factory = DXGI.CreateDXGIFactory2<IDXGIFactory7>(true);
|
||||
#else
|
||||
factory = DXGI.CreateDXGIFactory2<IDXGIFactory7>(false);
|
||||
#endif
|
||||
|
||||
ID3D12Device14? d3d12Device = default;
|
||||
for (uint adapterIndex = 0;
|
||||
factory.EnumAdapters1(adapterIndex, out var adapter).Success;
|
||||
adapterIndex++)
|
||||
{
|
||||
var desc = adapter.Description1;
|
||||
|
||||
// Don't select the Basic Render Driver adapter.
|
||||
if ((desc.Flags & AdapterFlags.Software) != AdapterFlags.None)
|
||||
{
|
||||
adapter.Dispose();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (D3D12.D3D12CreateDevice(adapter, FeatureLevel.Level_11_0, out d3d12Device).Success)
|
||||
{
|
||||
adapter.Dispose();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (d3d12Device == null)
|
||||
{
|
||||
throw new PlatformNotSupportedException("Cannot create ID3D12Device");
|
||||
}
|
||||
|
||||
device = d3d12Device;
|
||||
}
|
||||
|
||||
private void InitializeCommandQueue(out ID3D12CommandQueue queue)
|
||||
{
|
||||
var queueDesc = new CommandQueueDescription
|
||||
{
|
||||
Type = CommandListType.Direct,
|
||||
Priority = (int)CommandQueuePriority.High,
|
||||
Flags = CommandQueueFlags.None,
|
||||
};
|
||||
|
||||
queue = _device.CreateCommandQueue(queueDesc);
|
||||
}
|
||||
|
||||
public IRenderView CreateRenderView(in SwapChainSurface swapChainSurface)
|
||||
{
|
||||
var renderView = new DX12RenderView(this, swapChainSurface);
|
||||
_renderViews.Add(renderView);
|
||||
return renderView;
|
||||
}
|
||||
|
||||
public void OnRender()
|
||||
{
|
||||
foreach (var renderView in _renderViews)
|
||||
{
|
||||
renderView.Render();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var renderView in _renderViews)
|
||||
{
|
||||
renderView.Dispose();
|
||||
}
|
||||
_renderViews.Clear();
|
||||
|
||||
_commandQueue?.Dispose();
|
||||
_device?.Dispose();
|
||||
_dxgiFactory?.Dispose();
|
||||
|
||||
#if DEBUG
|
||||
_debugLayer.Dispose();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
219
Ghost.Graphics/DX12/DX12RenderView.cs
Normal file
219
Ghost.Graphics/DX12/DX12RenderView.cs
Normal file
@@ -0,0 +1,219 @@
|
||||
using Ghost.Graphics.Contracts;
|
||||
using Ghost.Graphics.Data;
|
||||
using Ghost.Graphics.DX12.Utilities;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Vortice.Direct3D12;
|
||||
using Vortice.DXGI;
|
||||
|
||||
namespace Ghost.Graphics.DX12;
|
||||
|
||||
internal class DX12RenderView : IRenderView
|
||||
{
|
||||
private const int _RENDER_TARGET_VIEW_HEAP_SIZE = 1024;
|
||||
private const int _DEPTH_STENCIL_VIEW_HEAP_SIZE = 256;
|
||||
|
||||
private readonly DX12GraphicsDevice _graphicsDevice;
|
||||
|
||||
private readonly IDXGISwapChain4 _swapChain;
|
||||
private readonly ID3D12Resource[] _renderTargets;
|
||||
private readonly uint[] _renderTargetDescriptorIndexes;
|
||||
private uint _backBufferIndex;
|
||||
|
||||
private readonly ID3D12CommandAllocator[] _commandAllocators;
|
||||
private readonly ID3D12GraphicsCommandList7 _commandList;
|
||||
|
||||
private readonly ID3D12Fence1 _fence;
|
||||
private readonly AutoResetEvent _fenceEvent;
|
||||
private readonly ulong[] _fenceValues;
|
||||
|
||||
private readonly D3D12DescriptorAllocator _rtvHeap;
|
||||
|
||||
public DX12RenderView(DX12GraphicsDevice pipelineContext, in SwapChainSurface swapChainSurface)
|
||||
{
|
||||
_graphicsDevice = pipelineContext;
|
||||
|
||||
_rtvHeap = new(_graphicsDevice.Device, DescriptorHeapType.RenderTargetView, _RENDER_TARGET_VIEW_HEAP_SIZE);
|
||||
|
||||
_fenceEvent = new AutoResetEvent(false);
|
||||
_renderTargets = new ID3D12Resource[GraphicsPipeline.FRAME_COUNT];
|
||||
_fenceValues = new ulong[GraphicsPipeline.FRAME_COUNT];
|
||||
_renderTargetDescriptorIndexes = new uint[GraphicsPipeline.FRAME_COUNT];
|
||||
|
||||
InitializeSwapChain(swapChainSurface, out _swapChain);
|
||||
InitializeCommandObjects(out _commandAllocators, out _commandList, out _fence);
|
||||
CreateRenderTargets();
|
||||
}
|
||||
|
||||
private void InitializeSwapChain(in SwapChainSurface swapChainSurface, out IDXGISwapChain4 swapChain)
|
||||
{
|
||||
var swapChainDesc = new SwapChainDescription1
|
||||
{
|
||||
Width = swapChainSurface.Width,
|
||||
Height = swapChainSurface.Height,
|
||||
Format = Format.B8G8R8A8_UNorm,
|
||||
Stereo = false,
|
||||
SampleDescription = new SampleDescription(1, 0),
|
||||
BufferUsage = Usage.RenderTargetOutput,
|
||||
BufferCount = GraphicsPipeline.FRAME_COUNT,
|
||||
Scaling = Scaling.Stretch,
|
||||
SwapEffect = SwapEffect.FlipDiscard,
|
||||
AlphaMode = AlphaMode.Ignore,
|
||||
Flags = SwapChainFlags.AllowTearing
|
||||
};
|
||||
|
||||
// NOTE: Not going to need it for now, this is for standalone applications.
|
||||
var swapChainFullscreenDesc = new SwapChainFullscreenDescription
|
||||
{
|
||||
Windowed = true,
|
||||
};
|
||||
|
||||
switch (swapChainSurface.Type)
|
||||
{
|
||||
case SwapChainSurface.TargetType.Composition:
|
||||
var swapChain1 = _graphicsDevice.DXGIFactory.CreateSwapChainForComposition(_graphicsDevice.CommandQueue, swapChainDesc);
|
||||
swapChain = swapChain1.QueryInterface<IDXGISwapChain4>();
|
||||
|
||||
_backBufferIndex = swapChain.CurrentBackBufferIndex;
|
||||
swapChainSurface.SwapChainPanelNative!.SetSwapChain(swapChain);
|
||||
break;
|
||||
case SwapChainSurface.TargetType.Hwnd:
|
||||
var swapChain2 = _graphicsDevice.DXGIFactory.CreateSwapChainForHwnd(
|
||||
_graphicsDevice.CommandQueue,
|
||||
swapChainSurface.Hwnd,
|
||||
swapChainDesc,
|
||||
swapChainFullscreenDesc,
|
||||
null);
|
||||
swapChain = swapChain2.QueryInterface<IDXGISwapChain4>();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Unsupported swap chain surface type.");
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeCommandObjects(out ID3D12CommandAllocator[] commandAllocator, out ID3D12GraphicsCommandList7 commandList, out ID3D12Fence1 fence)
|
||||
{
|
||||
commandAllocator = new ID3D12CommandAllocator[GraphicsPipeline.FRAME_COUNT];
|
||||
for (var i = 0; i < GraphicsPipeline.FRAME_COUNT; i++)
|
||||
{
|
||||
commandAllocator[i] = _graphicsDevice.Device.CreateCommandAllocator(CommandListType.Direct);
|
||||
}
|
||||
|
||||
commandList = _graphicsDevice.Device.CreateCommandList<ID3D12GraphicsCommandList7>(CommandListType.Direct, commandAllocator[0], null!);
|
||||
fence = _graphicsDevice.Device.CreateFence<ID3D12Fence1>(_fenceValues[_backBufferIndex], FenceFlags.None);
|
||||
|
||||
_commandList.Close();
|
||||
_fenceValues[_backBufferIndex]++;
|
||||
}
|
||||
|
||||
private void CreateRenderTargets()
|
||||
{
|
||||
for (var i = 0u; i < GraphicsPipeline.FRAME_COUNT; i++)
|
||||
{
|
||||
_renderTargets[i] = _swapChain.GetBuffer<ID3D12Resource>(i);
|
||||
_renderTargets[i].Name = $"RenderTarget_{i}";
|
||||
_renderTargetDescriptorIndexes[i] = _rtvHeap.AllocateDescriptor();
|
||||
|
||||
var rtvHandle = _rtvHeap.GetCpuHandle(_renderTargetDescriptorIndexes[i]);
|
||||
_graphicsDevice.Device.CreateRenderTargetView(_renderTargets[i], null, rtvHandle);
|
||||
}
|
||||
}
|
||||
|
||||
public void Resize(uint width, uint height)
|
||||
{
|
||||
WaitIdle();
|
||||
|
||||
for (var i = 0; i < GraphicsPipeline.FRAME_COUNT; i++)
|
||||
{
|
||||
_renderTargets[i].Dispose();
|
||||
_rtvHeap.ReleaseDescriptor(_renderTargetDescriptorIndexes[i]);
|
||||
|
||||
_fenceValues[i] = _fenceValues[_backBufferIndex];
|
||||
}
|
||||
|
||||
_swapChain.ResizeBuffers(GraphicsPipeline.FRAME_COUNT, width, height, Format.B8G8R8A8_UNorm, SwapChainFlags.AllowTearing).CheckError();
|
||||
|
||||
CreateRenderTargets();
|
||||
_backBufferIndex = _swapChain.CurrentBackBufferIndex;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
var commandAllocator = _commandAllocators[_backBufferIndex];
|
||||
commandAllocator.Reset();
|
||||
_commandList.Reset(commandAllocator, null);
|
||||
|
||||
_commandList.Close();
|
||||
_graphicsDevice.CommandQueue.ExecuteCommandLists([_commandList]);
|
||||
|
||||
_swapChain.Present(1, PresentFlags.None).CheckError();
|
||||
|
||||
WaitNextFrame();
|
||||
}
|
||||
|
||||
public void WaitNextFrame()
|
||||
{
|
||||
var fenceValue = _fenceValues[_backBufferIndex];
|
||||
|
||||
if (_graphicsDevice.CommandQueue.Signal(_fence, fenceValue).Failure)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_backBufferIndex = _swapChain.CurrentBackBufferIndex;
|
||||
if (_fence.CompletedValue < _fenceValues[_backBufferIndex]
|
||||
&& _fence.SetEventOnCompletion(_fenceValues[_backBufferIndex], _fenceEvent.SafeWaitHandle.DangerousGetHandle()).Success)
|
||||
{
|
||||
_fenceEvent.WaitOne();
|
||||
}
|
||||
|
||||
_fenceValues[_backBufferIndex]++;
|
||||
}
|
||||
|
||||
public void WaitIdle()
|
||||
{
|
||||
var fenceValue = _fenceValues[_backBufferIndex];
|
||||
if (_graphicsDevice.CommandQueue.Signal(_fence, fenceValue).Failure
|
||||
|| _fence.SetEventOnCompletion(fenceValue, _fenceEvent.SafeWaitHandle.DangerousGetHandle()).Failure)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_fenceEvent.WaitOne();
|
||||
_fenceValues[_backBufferIndex]++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Flush()
|
||||
{
|
||||
for (var i = 0; i < GraphicsPipeline.FRAME_COUNT; i++)
|
||||
{
|
||||
WaitIdle();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Flush();
|
||||
|
||||
foreach (var commandAllocator in _commandAllocators)
|
||||
{
|
||||
commandAllocator.Dispose();
|
||||
}
|
||||
|
||||
foreach (var renderTarget in _renderTargets)
|
||||
{
|
||||
renderTarget.Dispose();
|
||||
}
|
||||
|
||||
_swapChain.Dispose();
|
||||
_commandList.Dispose();
|
||||
|
||||
_fence.Dispose();
|
||||
_fenceEvent.Dispose();
|
||||
|
||||
_rtvHeap.Dispose();
|
||||
|
||||
_backBufferIndex = 0;
|
||||
_fenceValues.AsSpan().Clear();
|
||||
}
|
||||
}
|
||||
238
Ghost.Graphics/DX12/Utilities/D3D12DescriptorAllocator.cs
Normal file
238
Ghost.Graphics/DX12/Utilities/D3D12DescriptorAllocator.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using Vortice.Direct3D12;
|
||||
using DescriptorIndex = System.UInt32;
|
||||
|
||||
namespace Ghost.Graphics.DX12.Utilities;
|
||||
|
||||
internal class D3D12DescriptorAllocator : IDisposable
|
||||
{
|
||||
private const DescriptorIndex _INVALID_DESCRIPTOR_INDEX = ~0u;
|
||||
|
||||
private readonly ID3D12Device _device;
|
||||
private readonly Lock _mutex = new();
|
||||
|
||||
private ID3D12DescriptorHeap? _heap;
|
||||
private ID3D12DescriptorHeap? _shaderVisibleHeap;
|
||||
private CpuDescriptorHandle _startCpuHandle = default;
|
||||
private CpuDescriptorHandle _startCpuHandleShaderVisible = default;
|
||||
private GpuDescriptorHandle _startGpuHandleShaderVisible = default;
|
||||
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 ID3D12DescriptorHeap Heap => _heap!;
|
||||
public ID3D12DescriptorHeap? ShaderVisibleHeap => _shaderVisibleHeap;
|
||||
|
||||
public D3D12DescriptorAllocator(ID3D12Device device, DescriptorHeapType type, uint numDescriptors)
|
||||
{
|
||||
_device = device;
|
||||
HeapType = type;
|
||||
NumDescriptors = numDescriptors;
|
||||
ShaderVisible = type == DescriptorHeapType.ConstantBufferViewShaderResourceViewUnorderedAccessView || type == DescriptorHeapType.Sampler;
|
||||
Stride = device.GetDescriptorHandleIncrementSize(type);
|
||||
|
||||
Debug.Assert(AllocateResources(numDescriptors));
|
||||
}
|
||||
|
||||
public DescriptorIndex AllocateDescriptor() => AllocateDescriptors(1);
|
||||
|
||||
public DescriptorIndex AllocateDescriptors(uint count)
|
||||
{
|
||||
lock (_mutex)
|
||||
{
|
||||
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 (_mutex)
|
||||
{
|
||||
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.CopyDescriptorsSimple(count, GetCpuHandleShaderVisible(index), GetCpuHandle(index), HeapType);
|
||||
}
|
||||
|
||||
private bool AllocateResources(uint numDescriptors)
|
||||
{
|
||||
NumDescriptors = numDescriptors;
|
||||
_heap?.Dispose();
|
||||
_shaderVisibleHeap?.Dispose();
|
||||
|
||||
DescriptorHeapDescription heapDesc = new()
|
||||
{
|
||||
Type = HeapType,
|
||||
DescriptorCount = numDescriptors,
|
||||
Flags = DescriptorHeapFlags.None,
|
||||
NodeMask = 0
|
||||
};
|
||||
|
||||
var hr = _device.CreateDescriptorHeap(in heapDesc, out _heap);
|
||||
if (hr.Failure)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_startCpuHandle = _heap!.GetCPUDescriptorHandleForHeapStart();
|
||||
Array.Resize(ref _allocatedDescriptors, (int)numDescriptors);
|
||||
|
||||
if (ShaderVisible)
|
||||
{
|
||||
heapDesc.Flags = DescriptorHeapFlags.ShaderVisible;
|
||||
|
||||
hr = _device.CreateDescriptorHeap(in heapDesc, out _shaderVisibleHeap);
|
||||
|
||||
if (hr.Failure)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_startCpuHandleShaderVisible = _shaderVisibleHeap!.GetCPUDescriptorHandleForHeapStart();
|
||||
_startGpuHandleShaderVisible = _shaderVisibleHeap!.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.CopyDescriptorsSimple(oldSize, _startCpuHandle, oldHeap!.GetCPUDescriptorHandleForHeapStart(), HeapType);
|
||||
|
||||
if (_shaderVisibleHeap is not null)
|
||||
{
|
||||
_device.CopyDescriptorsSimple(oldSize, _startCpuHandleShaderVisible, oldHeap.GetCPUDescriptorHandleForHeapStart(), HeapType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
_heap?.Dispose();
|
||||
_shaderVisibleHeap?.Dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user