Render graph integration and resource management refactor
Introduces a full-featured render graph system with pass culling, resource aliasing, and automatic barrier generation. Refactors resource and barrier APIs, improves error handling, and unifies result types. Renderer and render passes now use the new graph-based workflow. Updates shader includes, adds a blit shader, and improves HLSL parsing. Removes dynamic descriptor heaps in favor of persistent ones. Project file now includes the render graph module. Lays the foundation for advanced rendering features and improved memory efficiency.
This commit is contained in:
@@ -5,7 +5,6 @@ using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
@@ -115,7 +114,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
#if DEBUG
|
||||
[DoesNotReturn]
|
||||
[System.Diagnostics.CodeAnalysis.DoesNotReturn]
|
||||
private static void RecordError(string cmdName, ErrorStatus status)
|
||||
#else
|
||||
private void RecordError(string cmdName, ErrorStatus status)
|
||||
@@ -206,51 +205,82 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
#endif
|
||||
IncrementCommandCount();
|
||||
|
||||
if (barrierDescs.IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var count = 0u;
|
||||
var pBarriers = stackalloc D3D12_RESOURCE_BARRIER[barrierDescs.Length];
|
||||
|
||||
for (var i = 0; i < barrierDescs.Length; i++)
|
||||
{
|
||||
var desc = barrierDescs[i];
|
||||
if (desc.StateBefore == desc.StateAfter)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
D3D12_RESOURCE_BARRIER barrier = default;
|
||||
|
||||
if (!desc.Resource.IsValid)
|
||||
switch (desc.type)
|
||||
{
|
||||
RecordError(nameof(ResourceBarrier), ErrorStatus.InvalidArgument);
|
||||
continue;
|
||||
}
|
||||
case BarrierType.Transition:
|
||||
if (desc.transition.stateBefore == desc.transition.stateAfter)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var recordResult = _resourceDatabase.GetResourceRecord(desc.Resource);
|
||||
if (recordResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(ResourceBarrier), recordResult.Error);
|
||||
continue;
|
||||
}
|
||||
var recordResult = _resourceDatabase.GetResourceRecord(desc.transition.resource);
|
||||
if (recordResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(TransitionBarrier), recordResult.Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
ref var record = ref recordResult.Value;
|
||||
if (record.state != desc.StateBefore)
|
||||
{
|
||||
RecordError(nameof(ResourceBarrier), ErrorStatus.InvalidState);
|
||||
continue;
|
||||
}
|
||||
ref var record = ref recordResult.Value;
|
||||
var stateBefore = desc.transition.stateBefore == ResourceState.Auto ? record.state : desc.transition.stateBefore;
|
||||
|
||||
barrier = D3D12_RESOURCE_BARRIER.InitTransition(record.ResourcePtr,
|
||||
stateBefore.ToD3D12States(), desc.transition.stateAfter.ToD3D12States());
|
||||
|
||||
var barrier = D3D12_RESOURCE_BARRIER.InitTransition(record.ResourcePtr,
|
||||
desc.StateBefore.ToD3D12States(), desc.StateAfter.ToD3D12States());
|
||||
record.state = desc.transition.stateAfter;
|
||||
break;
|
||||
|
||||
case BarrierType.Aliasing:
|
||||
var recordBeforeResult = _resourceDatabase.GetResourceRecord(desc.aliasing.resourceBefore);
|
||||
if (recordBeforeResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(TransitionBarrier), recordBeforeResult.Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
var recordAfterResult = _resourceDatabase.GetResourceRecord(desc.aliasing.resourceAfter);
|
||||
if (recordAfterResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(TransitionBarrier), recordAfterResult.Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
barrier = D3D12_RESOURCE_BARRIER.InitAliasing(
|
||||
recordBeforeResult.Value.ResourcePtr,
|
||||
recordAfterResult.Value.ResourcePtr);
|
||||
break;
|
||||
case BarrierType.UAV:
|
||||
var recordUavResult = _resourceDatabase.GetResourceRecord(desc.uav.resource);
|
||||
if (recordUavResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(TransitionBarrier), recordUavResult.Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
barrier = D3D12_RESOURCE_BARRIER.InitUAV(recordUavResult.Value.ResourcePtr);
|
||||
break;
|
||||
}
|
||||
|
||||
pBarriers[count] = barrier;
|
||||
count++;
|
||||
|
||||
// Update the resource state in the database
|
||||
record.state = desc.StateAfter;
|
||||
}
|
||||
|
||||
|
||||
_commandList.Get()->ResourceBarrier(count, pBarriers);
|
||||
}
|
||||
|
||||
public void ResourceBarrier(Handle<GPUResource> resource, ResourceState stateBefore, ResourceState stateAfter)
|
||||
public void TransitionBarrier(Handle<GPUResource> resource, ResourceState stateBefore, ResourceState stateAfter)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
ThrowIfNotRecording();
|
||||
@@ -270,7 +300,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
var recordResult = _resourceDatabase.GetResourceRecord(resource);
|
||||
if (recordResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(ResourceBarrier), recordResult.Error);
|
||||
RecordError(nameof(TransitionBarrier), recordResult.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -282,7 +312,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
record.state = stateAfter;
|
||||
}
|
||||
|
||||
public void ResourceBarrier(Handle<GPUResource> resource, ResourceState stateAfter)
|
||||
public void TransitionBarrier(Handle<GPUResource> resource, ResourceState stateAfter)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
ThrowIfNotRecording();
|
||||
@@ -297,7 +327,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
var recordResult = _resourceDatabase.GetResourceRecord(resource);
|
||||
if (recordResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(ResourceBarrier), recordResult.Error);
|
||||
RecordError(nameof(TransitionBarrier), recordResult.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -314,6 +344,38 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
record.state = stateAfter;
|
||||
}
|
||||
|
||||
public void AliasBarrier(Handle<GPUResource> resourceBefore, Handle<GPUResource> resourceAfter)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
ThrowIfNotRecording();
|
||||
#if !DEBUG
|
||||
if (_lastError.Status != ErrorStatus.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
IncrementCommandCount();
|
||||
|
||||
var recordBeforeResult = _resourceDatabase.GetResourceRecord(resourceBefore);
|
||||
if (recordBeforeResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(AliasBarrier), recordBeforeResult.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
var recordAfterResult = _resourceDatabase.GetResourceRecord(resourceAfter);
|
||||
if (recordAfterResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(AliasBarrier), recordAfterResult.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
var barrier = D3D12_RESOURCE_BARRIER.InitAliasing(
|
||||
recordBeforeResult.Value.ResourcePtr,
|
||||
recordAfterResult.Value.ResourcePtr);
|
||||
_commandList.Get()->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
public void SetRenderTargets(ReadOnlySpan<Handle<Texture>> renderTargets, Handle<Texture> depthTarget)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
@@ -367,6 +429,69 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
_commandList.Get()->OMSetRenderTargets(rtvCount, pRtvHandles, FALSE, pDsvHandle);
|
||||
}
|
||||
|
||||
public void ClearRenderTargetView(Handle<Texture> renderTarget, Color128 clearColor)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
ThrowIfNotRecording();
|
||||
#if !DEBUG
|
||||
if (_lastError.Status != ErrorStatus.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
IncrementCommandCount();
|
||||
|
||||
var recordResult = _resourceDatabase.GetResourceRecord(renderTarget.AsResource());
|
||||
if (recordResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(ClearRenderTargetView), recordResult.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
ref var record = ref recordResult.Value;
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(record.viewGroup.rtv);
|
||||
var color = stackalloc float[4]
|
||||
{
|
||||
clearColor.r,
|
||||
clearColor.g,
|
||||
clearColor.b,
|
||||
clearColor.a
|
||||
};
|
||||
|
||||
_commandList.Get()->ClearRenderTargetView(cpuHandle, color, 0, null);
|
||||
}
|
||||
|
||||
public void ClearDepthStencilView(Handle<Texture> depthStencil, bool inlcudeDepth, bool includeStencil, float clearDepth = 1.0f, byte clearStencil = 0)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
ThrowIfNotRecording();
|
||||
#if !DEBUG
|
||||
if (_lastError.Status != ErrorStatus.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
IncrementCommandCount();
|
||||
|
||||
var recordResult = _resourceDatabase.GetResourceRecord(depthStencil.AsResource());
|
||||
if (recordResult.Error != ErrorStatus.None)
|
||||
{
|
||||
RecordError(nameof(ClearDepthStencilView), recordResult.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
ref var record = ref recordResult.Value;
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(record.viewGroup.dsv);
|
||||
var flag = (inlcudeDepth ? D3D12_CLEAR_FLAG_DEPTH : 0) | (includeStencil ? D3D12_CLEAR_FLAG_STENCIL : 0);
|
||||
|
||||
_commandList.Get()->ClearDepthStencilView(cpuHandle,
|
||||
flag,
|
||||
clearDepth,
|
||||
clearStencil,
|
||||
0,
|
||||
null);
|
||||
}
|
||||
|
||||
public void BeginRenderPass(ReadOnlySpan<PassRenderTargetDesc> rtDescs, PassDepthStencilDesc depthDesc, bool allowUAVWrites = false)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
@@ -18,12 +18,12 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public D3D12DescriptorAllocator(D3D12RenderDevice device, int initialRtvCount = 256, int initialDsvCount = 256, int initialSrvCount = 200_000, int initialSamplerCount = 256)
|
||||
public D3D12DescriptorAllocator(D3D12RenderDevice device, int initialRtvCount = 512, int initialDsvCount = 512, int initialSrvCount = 200_000, int initialSamplerCount = 256)
|
||||
{
|
||||
_rtvHeap = new D3D12DescriptorHeap("rtv", device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, initialRtvCount, initialRtvCount / 2);
|
||||
_dsvHeap = new D3D12DescriptorHeap("dsv", device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, initialDsvCount, initialDsvCount / 2);
|
||||
_cbvSrvUavHeap = new D3D12DescriptorHeap("srv", device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, initialSrvCount, initialSrvCount / 2);
|
||||
_samplerHeap = new D3D12DescriptorHeap("sampler", device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, initialSamplerCount, initialSamplerCount);
|
||||
_rtvHeap = new D3D12DescriptorHeap("rtv", device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, initialRtvCount);
|
||||
_dsvHeap = new D3D12DescriptorHeap("dsv", device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, initialDsvCount);
|
||||
_cbvSrvUavHeap = new D3D12DescriptorHeap("srv", device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, initialSrvCount);
|
||||
_samplerHeap = new D3D12DescriptorHeap("sampler", device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, initialSamplerCount);
|
||||
}
|
||||
|
||||
~D3D12DescriptorAllocator()
|
||||
@@ -33,11 +33,11 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
|
||||
#region RTV Methods
|
||||
|
||||
public Identifier<RTVDescriptor> AllocateRTV(bool dynamic = false)
|
||||
public Identifier<RTVDescriptor> AllocateRTV()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var index = dynamic ? _rtvHeap.AllocateDescriptorDynamic() : _rtvHeap.AllocateDescriptor();
|
||||
var index = _rtvHeap.AllocateDescriptor();
|
||||
if (index == -1)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to allocate RTV descriptor");
|
||||
@@ -46,11 +46,11 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
return new Identifier<RTVDescriptor>(index);
|
||||
}
|
||||
|
||||
public Identifier<RTVDescriptor>[] AllocateRTVs(int count, bool dynamic = false)
|
||||
public Identifier<RTVDescriptor>[] AllocateRTVs(int count)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var baseIndex = dynamic ? _rtvHeap.AllocateDescriptorsDynamic(count) : _rtvHeap.AllocateDescriptors(count);
|
||||
var baseIndex = _rtvHeap.AllocateDescriptors(count);
|
||||
if (baseIndex == -1)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to allocate {count} RTV descriptors");
|
||||
@@ -91,39 +91,15 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void MakePersistent(Identifier<RTVDescriptor> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
_rtvHeap.CopyToPersistentHeap(descriptor.Value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void MakePersistent(ReadOnlySpan<Identifier<RTVDescriptor>> descriptors)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
foreach (var descriptor in descriptors)
|
||||
{
|
||||
MakePersistent(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ResetRTVDynamicHeap()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
_rtvHeap.ResetDynamicHeap();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DSV Methods
|
||||
|
||||
public Identifier<DSVDescriptor> AllocateDSV(bool dynamic = false)
|
||||
public Identifier<DSVDescriptor> AllocateDSV()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var index = dynamic ? _dsvHeap.AllocateDescriptorDynamic() : _dsvHeap.AllocateDescriptor();
|
||||
var index = _dsvHeap.AllocateDescriptor();
|
||||
if (index == -1)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to allocate DSV descriptor");
|
||||
@@ -132,11 +108,11 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
return new Identifier<DSVDescriptor>(index);
|
||||
}
|
||||
|
||||
public Identifier<DSVDescriptor>[] AllocateDSVs(int count, bool dynamic = false)
|
||||
public Identifier<DSVDescriptor>[] AllocateDSVs(int count)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var baseIndex = dynamic ? _dsvHeap.AllocateDescriptorsDynamic(count) : _dsvHeap.AllocateDescriptors(count);
|
||||
var baseIndex = _dsvHeap.AllocateDescriptors(count);
|
||||
if (baseIndex == -1)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to allocate {count} DSV descriptors");
|
||||
@@ -174,53 +150,28 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void MakePersistent(Identifier<DSVDescriptor> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
_dsvHeap.CopyToPersistentHeap(descriptor.Value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void MakePersistent(ReadOnlySpan<Identifier<DSVDescriptor>> descriptors)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
foreach (var descriptor in descriptors)
|
||||
{
|
||||
MakePersistent(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ResetDSVDynamicHeap()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
_dsvHeap.ResetDynamicHeap();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CBV_SRV_UAV Methods
|
||||
|
||||
public Identifier<CbvSrvUavDescriptor> AllocateCbvSrvUav(bool dynamic = false)
|
||||
public Identifier<CbvSrvUavDescriptor> AllocateCbvSrvUav()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var index = dynamic ? _cbvSrvUavHeap.AllocateDescriptorDynamic() : _cbvSrvUavHeap.AllocateDescriptor();
|
||||
var index = _cbvSrvUavHeap.AllocateDescriptor();
|
||||
if (index == -1)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to allocate CBV/SRV/UAV descriptor");
|
||||
}
|
||||
|
||||
_cbvSrvUavHeap.CopyToShaderVisibleHeap(index);
|
||||
return new Identifier<CbvSrvUavDescriptor>(index);
|
||||
}
|
||||
|
||||
public Identifier<CbvSrvUavDescriptor>[] AllocateSRVs(int count, bool dynamic = false)
|
||||
public Identifier<CbvSrvUavDescriptor>[] AllocateSRVs(int count)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var baseIndex = dynamic ? _cbvSrvUavHeap.AllocateDescriptorsDynamic(count) : _cbvSrvUavHeap.AllocateDescriptors(count);
|
||||
var baseIndex = _cbvSrvUavHeap.AllocateDescriptors(count);
|
||||
if (baseIndex == -1)
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to allocate {count} CBV/SRV/UAV descriptors");
|
||||
@@ -233,10 +184,15 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
descriptors[i] = new Identifier<CbvSrvUavDescriptor>(index);
|
||||
}
|
||||
|
||||
_cbvSrvUavHeap.CopyToShaderVisibleHeap(baseIndex, count);
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
public void CopyToShaderVisible(Identifier<CbvSrvUavDescriptor> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
_cbvSrvUavHeap.CopyToShaderVisibleHeap(descriptor.Value);
|
||||
}
|
||||
|
||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<CbvSrvUavDescriptor> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
@@ -271,30 +227,6 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void MakePersistent(Identifier<CbvSrvUavDescriptor> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
_cbvSrvUavHeap.CopyToPersistentHeap(descriptor.Value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void MakePersistent(ReadOnlySpan<Identifier<CbvSrvUavDescriptor>> descriptors)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
foreach (var descriptor in descriptors)
|
||||
{
|
||||
MakePersistent(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ResetCbvSrvUavDynamicHeap()
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
_cbvSrvUavHeap.ResetDynamicHeap();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sampler Methods
|
||||
@@ -309,7 +241,6 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
throw new InvalidOperationException("Failed to allocate Sampler descriptor");
|
||||
}
|
||||
|
||||
_samplerHeap.CopyToShaderVisibleHeap(index);
|
||||
return new Identifier<SamplerDescriptor>(index);
|
||||
}
|
||||
|
||||
@@ -330,10 +261,15 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
descriptors[i] = new Identifier<SamplerDescriptor>(index);
|
||||
}
|
||||
|
||||
_samplerHeap.CopyToShaderVisibleHeap(baseIndex, count);
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
public void CopyToShaderVisible(Identifier<SamplerDescriptor> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
_samplerHeap.CopyToShaderVisibleHeap(descriptor.Value);
|
||||
}
|
||||
|
||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<SamplerDescriptor> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Ghost.Core.Utilities;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Misaki.HighPerformance.LowLevel;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using TerraFX.Interop.DirectX;
|
||||
@@ -22,10 +22,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
private D3D12_CPU_DESCRIPTOR_HANDLE _startCpuHandleShaderVisible;
|
||||
private D3D12_GPU_DESCRIPTOR_HANDLE _startGpuHandleShaderVisible;
|
||||
private int _searchStart;
|
||||
private UnsafeArray<bool> _allocatedDescriptors;
|
||||
|
||||
private readonly int _dynamicHeapStart;
|
||||
private int _currentDynamicOffset;
|
||||
private UnsafeBitSet _allocatedDescriptors;
|
||||
|
||||
private readonly Lock _lock = new();
|
||||
|
||||
@@ -57,7 +54,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
public readonly ID3D12DescriptorHeap* Heap => _heap.Get();
|
||||
public readonly ID3D12DescriptorHeap* ShaderVisibleHeap => _shaderVisibleHeap.Get();
|
||||
|
||||
public D3D12DescriptorHeap(string name, D3D12RenderDevice device, D3D12_DESCRIPTOR_HEAP_TYPE type, int numDescriptors, int dynamicHeapStart)
|
||||
public D3D12DescriptorHeap(string name, D3D12RenderDevice device, D3D12_DESCRIPTOR_HEAP_TYPE type, int numDescriptors)
|
||||
{
|
||||
numDescriptors = Math.Max(64, numDescriptors);
|
||||
|
||||
@@ -68,16 +65,13 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
ShaderVisible = type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
Stride = device.NativeDevice.Get()->GetDescriptorHandleIncrementSize(type);
|
||||
|
||||
_dynamicHeapStart = Math.Clamp(dynamicHeapStart, 0, numDescriptors);
|
||||
_currentDynamicOffset = 0;
|
||||
|
||||
var success = AllocateResources(numDescriptors);
|
||||
Debug.Assert(success);
|
||||
|
||||
_heap.Get()->SetName(name.AsSpan().GetUnsafePtr());
|
||||
_heap.Get()->SetName(name);
|
||||
if (ShaderVisible)
|
||||
{
|
||||
_shaderVisibleHeap.Get()->SetName($"{name} Shader Visible".AsSpan().GetUnsafePtr());
|
||||
_shaderVisibleHeap.Get()->SetName($"{name} Shader Visible");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +88,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
// Find a contiguous range of 'count' indices for which _allocatedDescriptors[index] is false
|
||||
for (var index = _searchStart; index < NumDescriptors; index++)
|
||||
{
|
||||
if (_allocatedDescriptors[index])
|
||||
if (_allocatedDescriptors.IsSet(index))
|
||||
{
|
||||
freeCount = 0;
|
||||
}
|
||||
@@ -111,15 +105,20 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
if (!found || foundIndex >= _dynamicHeapStart)
|
||||
if (!found)
|
||||
{
|
||||
Debug.Assert(false, "ERROR: Descriptor heap is full!");
|
||||
return _INVALID_DESCRIPTOR_INDEX;
|
||||
foundIndex = NumDescriptors;
|
||||
|
||||
if (!Grow(NumDescriptors + count))
|
||||
{
|
||||
Debug.WriteLine("Error: Failed to grow descriptor heap.");
|
||||
return _INVALID_DESCRIPTOR_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
for (var index = foundIndex; index < foundIndex + count; index++)
|
||||
{
|
||||
_allocatedDescriptors[index] = true;
|
||||
_allocatedDescriptors.SetBit(index);
|
||||
}
|
||||
|
||||
NumAllocatedDescriptors += count;
|
||||
@@ -128,38 +127,6 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public int AllocateDescriptorDynamic() => AllocateDescriptorsDynamic(1);
|
||||
|
||||
public int AllocateDescriptorsDynamic(int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(count), "Count must be greater than zero.");
|
||||
}
|
||||
|
||||
// NOTE: In dynamic allocation, we use arena-style allocation without freeing.
|
||||
// We reset the Offset at the beginning of each frame instead.
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
var baseIndex = _currentDynamicOffset + _dynamicHeapStart;
|
||||
_currentDynamicOffset += count;
|
||||
|
||||
var requiredSize = baseIndex + count;
|
||||
if (requiredSize > NumDescriptors)
|
||||
{
|
||||
if (!Grow(requiredSize))
|
||||
{
|
||||
Debug.Assert(false, "ERROR: Failed to grow a descriptor heap!");
|
||||
return _INVALID_DESCRIPTOR_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
NumAllocatedDescriptors += count;
|
||||
return baseIndex;
|
||||
}
|
||||
}
|
||||
|
||||
public void ReleaseDescriptor(int index) => ReleaseDescriptors(index, 1);
|
||||
|
||||
public void ReleaseDescriptors(int baseIndex, int count = 1)
|
||||
@@ -174,24 +141,18 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
return;
|
||||
}
|
||||
|
||||
if (baseIndex >= _dynamicHeapStart)
|
||||
{
|
||||
// Dynamic allocations are not released individually.
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
for (var index = baseIndex; index < baseIndex + count; index++)
|
||||
{
|
||||
#if DEBUG || GHOST_EDITOR
|
||||
if (!_allocatedDescriptors[index])
|
||||
if (!_allocatedDescriptors.IsSet(index))
|
||||
{
|
||||
Debug.WriteLine("Error: Attempted to release an un-allocated descriptor");
|
||||
}
|
||||
#endif
|
||||
|
||||
_allocatedDescriptors[index] = false;
|
||||
_allocatedDescriptors.ClearBit(index);
|
||||
}
|
||||
|
||||
NumAllocatedDescriptors -= count;
|
||||
@@ -203,14 +164,6 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetDynamicHeap()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_currentDynamicOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public readonly D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(int index)
|
||||
{
|
||||
if (index < 0 || index >= NumDescriptors)
|
||||
@@ -251,19 +204,6 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
return _startGpuHandleShaderVisible.Offset(index, Stride);
|
||||
}
|
||||
|
||||
public int CopyToPersistentHeap(int index, int count = 1)
|
||||
{
|
||||
if (index < _dynamicHeapStart)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
var newLocation = AllocateDescriptors(count);
|
||||
_device.NativeDevice.Get()->CopyDescriptorsSimple((uint)count, GetCpuHandle(index), GetCpuHandle(newLocation), HeapType);
|
||||
|
||||
return newLocation;
|
||||
}
|
||||
|
||||
public readonly void CopyToShaderVisibleHeap(int index, int count = 1)
|
||||
{
|
||||
_device.NativeDevice.Get()->CopyDescriptorsSimple((uint)count, GetCpuHandleShaderVisible(index), GetCpuHandle(index), HeapType);
|
||||
@@ -296,7 +236,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
|
||||
if (!_allocatedDescriptors.IsCreated)
|
||||
{
|
||||
_allocatedDescriptors = new UnsafeArray<bool>(numDescriptors, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent, Misaki.HighPerformance.LowLevel.Buffer.AllocationOption.Clear);
|
||||
_allocatedDescriptors = new UnsafeBitSet(numDescriptors, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent, Misaki.HighPerformance.LowLevel.Buffer.AllocationOption.Clear);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -128,9 +128,6 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
}
|
||||
|
||||
_resourceAllocator.ReleaseTempResources();
|
||||
_descriptorAllocator.ResetCbvSrvUavDynamicHeap();
|
||||
_descriptorAllocator.ResetDSVDynamicHeap();
|
||||
_descriptorAllocator.ResetRTVDynamicHeap();
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -142,6 +139,11 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var renderer in _renderers)
|
||||
{
|
||||
renderer.Dispose();
|
||||
}
|
||||
|
||||
_resourceAllocator.Dispose();
|
||||
_pipelineLibrary.Dispose();
|
||||
_resourceDatabase.Dispose();
|
||||
|
||||
@@ -59,35 +59,6 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary
|
||||
// NOTE: Since we are targeting SM 6.6, we can use ResourceDescriptorHeap and SamplerDescriptorHeap directly without needing to set up viewGroup tables.
|
||||
var rootParameters = stackalloc D3D12_ROOT_PARAMETER1[RootSignatureLayout.ROOT_PARAMETER_COUNT];
|
||||
|
||||
#if false
|
||||
rootParameters[0] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
|
||||
Descriptor = new D3D12_ROOT_DESCRIPTOR1(RootSignatureLayout.GLOBAL_BUFFER_SLOT, 0), // b0
|
||||
};
|
||||
|
||||
rootParameters[1] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
|
||||
Descriptor = new D3D12_ROOT_DESCRIPTOR1(RootSignatureLayout.PER_VIEW_BUFFER_SLOT, 0), // b1
|
||||
};
|
||||
|
||||
rootParameters[2] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
|
||||
Descriptor = new D3D12_ROOT_DESCRIPTOR1(RootSignatureLayout.PER_OBJECT_BUFFER_SLOT, 0), // b2
|
||||
};
|
||||
|
||||
rootParameters[3] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
|
||||
Descriptor = new D3D12_ROOT_DESCRIPTOR1(RootSignatureLayout.PER_MATERIAL_BUFFER_SLOT, 0), // b3
|
||||
};
|
||||
#else
|
||||
rootParameters[0] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS,
|
||||
@@ -99,7 +70,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary
|
||||
Num32BitValues = 4 // Global, View, Object, Material indices
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC1
|
||||
{
|
||||
NumParameters = RootSignatureLayout.ROOT_PARAMETER_COUNT,
|
||||
@@ -175,9 +146,14 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary
|
||||
|
||||
private static Result<CBufferInfo> ValidateReflectionData(ShaderReflectionData reflectionData)
|
||||
{
|
||||
if (reflectionData.ResourcesBindings.Count != RootSignatureLayout.ROOT_PARAMETER_COUNT)
|
||||
if (reflectionData.ResourcesBindings.Count > RootSignatureLayout.ROOT_PARAMETER_COUNT)
|
||||
{
|
||||
return Result.Failure($"Shader must use all {RootSignatureLayout.ROOT_PARAMETER_COUNT} constant buffer slots defined in the root signature.");
|
||||
return Result.Failure($"Shader uses more root parameters than supported ({RootSignatureLayout.ROOT_PARAMETER_COUNT}).");
|
||||
}
|
||||
|
||||
if (reflectionData.ResourcesBindings.Count == 0)
|
||||
{
|
||||
return Result.Success(default(CBufferInfo));
|
||||
}
|
||||
|
||||
var rootConstant = reflectionData.ResourcesBindings[0];
|
||||
@@ -275,11 +251,11 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary
|
||||
|
||||
if (!_pipelineCache.ContainsKey(pipelineKey))
|
||||
{
|
||||
var result = ValidatePassReflectionData(in compiled);
|
||||
if (result.IsFailure)
|
||||
{
|
||||
return Result.Failure(result.Message);
|
||||
}
|
||||
//var result = ValidatePassReflectionData(in compiled);
|
||||
//if (result.IsFailure)
|
||||
//{
|
||||
// return Result.Failure(result.Message);
|
||||
//}
|
||||
|
||||
var desc = new D3DX12_MESH_SHADER_PIPELINE_STATE_DESC
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using Ghost.Graphics.RHI;
|
||||
using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.RenderPasses;
|
||||
using Ghost.Graphics.Contracts;
|
||||
using Ghost.Graphics.RenderGraphModule;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -15,6 +16,7 @@ internal class D3D12Renderer : IRenderer
|
||||
private readonly D3D12ResourceDatabase _resourceDatabase;
|
||||
|
||||
private readonly ICommandBuffer _commandBuffer;
|
||||
private readonly RenderGraph _renderGraph;
|
||||
|
||||
private uint _frameIndex;
|
||||
private bool _disposed;
|
||||
@@ -35,6 +37,7 @@ internal class D3D12Renderer : IRenderer
|
||||
_resourceDatabase = resourceDatabase;
|
||||
|
||||
_commandBuffer = _graphicsEngine.CreateCommandBuffer(CommandBufferType.Graphics);
|
||||
_renderGraph = new RenderGraph(_graphicsEngine);
|
||||
|
||||
// NOTE: Testing only.
|
||||
_pass = new();
|
||||
@@ -61,7 +64,7 @@ internal class D3D12Renderer : IRenderer
|
||||
_commandBuffer.Begin(commandAllocator);
|
||||
RenderOutput.BeginRender(_commandBuffer);
|
||||
|
||||
// NOTE: Temperary solution: render directly to the swap chain back buffer if available.
|
||||
// NOTE: Temporary solution: render directly to the swap chain back buffer if available.
|
||||
// HACK: This is hard coded for testing purposes only.
|
||||
|
||||
var error = RenderScene(target, RenderOutput.Viewport, RenderOutput.Scissor);
|
||||
@@ -87,30 +90,6 @@ internal class D3D12Renderer : IRenderer
|
||||
// TODO: A proper render graph integration.
|
||||
private ErrorStatus RenderScene(Handle<Texture> target, ViewportDesc viewport, RectDesc rect)
|
||||
{
|
||||
var clearColor = new Color128 { r = 1.0f, g = 0.0f, b = 1.0f, a = 1.0f };
|
||||
|
||||
Span<PassRenderTargetDesc> rtDesc =
|
||||
[
|
||||
new PassRenderTargetDesc
|
||||
{
|
||||
Texture = target,
|
||||
ClearColor = clearColor,
|
||||
LoadOp = AttachmentLoadOp.Clear,
|
||||
StoreOp = AttachmentStoreOp.Store,
|
||||
},
|
||||
];
|
||||
|
||||
var depthDesc = new PassDepthStencilDesc
|
||||
{
|
||||
Texture = Handle<Texture>.Invalid,
|
||||
ClearDepth = 1.0f,
|
||||
ClearStencil = 0,
|
||||
DepthLoadOp = AttachmentLoadOp.Clear,
|
||||
StencilLoadOp = AttachmentLoadOp.Clear,
|
||||
DepthStoreOp = AttachmentStoreOp.Store,
|
||||
StencilStoreOp = AttachmentStoreOp.Store,
|
||||
};
|
||||
|
||||
// NOTE: Testing only.
|
||||
var ctx = new RenderingContext(_graphicsEngine, _commandBuffer);
|
||||
if (_frameIndex == 0)
|
||||
@@ -118,14 +97,23 @@ internal class D3D12Renderer : IRenderer
|
||||
_pass.Initialize(ref ctx);
|
||||
}
|
||||
|
||||
_commandBuffer.BeginRenderPass(rtDesc, depthDesc, false);
|
||||
//_commandBuffer.BeginRenderPass(rtDesc, depthDesc, false);
|
||||
_commandBuffer.SetViewport(viewport);
|
||||
_commandBuffer.SetScissorRect(rect);
|
||||
|
||||
// NOTE: Testing only.
|
||||
_pass.Execute(ref ctx);
|
||||
_renderGraph.Reset();
|
||||
|
||||
_commandBuffer.EndRenderPass();
|
||||
var backBuffer = _renderGraph.ImportTexture(target, "Back Buffer");
|
||||
_pass.Build(_renderGraph, backBuffer);
|
||||
|
||||
// Create view state from viewport
|
||||
var viewState = new ViewState((uint)viewport.Width, (uint)viewport.Height);
|
||||
|
||||
// Compile with view state
|
||||
_renderGraph.Compile(in viewState);
|
||||
_renderGraph.Execute(_commandBuffer);
|
||||
|
||||
//_commandBuffer.EndRenderPass();
|
||||
_frameIndex++;
|
||||
|
||||
return ErrorStatus.None;
|
||||
@@ -140,6 +128,7 @@ internal class D3D12Renderer : IRenderer
|
||||
|
||||
// NOTE: Testing only.
|
||||
_pass.Cleanup(_resourceDatabase);
|
||||
_renderGraph.Dispose();
|
||||
|
||||
_commandBuffer.Dispose();
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml.Linq;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
@@ -623,9 +624,9 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private Handle<GPUResource> TrackResource(D3D12MA_Allocation* allocation, D3D12_RESOURCE_STATES state, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string name, bool isTemp)
|
||||
private Handle<GPUResource> TrackAllocation(D3D12MA_Allocation* allocation, D3D12_RESOURCE_STATES state, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string name, bool isTemp)
|
||||
{
|
||||
var handle = _resourceDatabase.AddAllocation(allocation, _fenceSynchronizer.CPUFenceValue, D3D12Utility.ToResourceState(state), resourceDescriptor, desc, name);
|
||||
var handle = _resourceDatabase.AddAllocation(allocation, _fenceSynchronizer.CPUFenceValue, state.ToResourceState(), resourceDescriptor, desc, name);
|
||||
|
||||
if (isTemp)
|
||||
{
|
||||
@@ -635,12 +636,11 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
return handle;
|
||||
}
|
||||
|
||||
private HRESULT CreateResource(D3D12MA_ALLOCATION_DESC* pAllocationDesc, D3D12_RESOURCE_DESC* pResourceDesc, D3D12_RESOURCE_STATES initialState, CreationOptions options, void** ppv)
|
||||
private HRESULT CreateResource(D3D12MA_ALLOCATION_DESC* pAllocationDesc, D3D12_RESOURCE_DESC* pResourceDesc, D3D12_RESOURCE_STATES initialState, CreationOptions options, Guid* riid, void** ppv)
|
||||
{
|
||||
var hr = S.S_OK;
|
||||
var iid = IID.IID_NULL;
|
||||
|
||||
if (options.AllocationType == ResourceAllocationType.RenderGraphTransient)
|
||||
if (options.AllocationType == ResourceAllocationType.Suballocation)
|
||||
{
|
||||
// pAllocation should be the render graph Heap. ppvResource should be the out resource.
|
||||
var result = _resourceDatabase.GetResourceRecord(options.Heap);
|
||||
@@ -649,11 +649,12 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
return E.E_NOTFOUND;
|
||||
}
|
||||
|
||||
hr = _d3d12MA.Get()->CreateAliasingResource(result.Value.resource.allocation.Get(), options.Offset, pResourceDesc, initialState, null, &iid, ppv);
|
||||
hr = _d3d12MA.Get()->CreateAliasingResource(result.Value.resource.allocation.Get(), options.Offset, pResourceDesc, initialState, null, riid, ppv);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = _d3d12MA.Get()->CreateResource(pAllocationDesc, pResourceDesc, initialState, null, (D3D12MA_Allocation**)ppv, &iid, null);
|
||||
var nuliid = IID.IID_NULL;
|
||||
hr = _d3d12MA.Get()->CreateResource(pAllocationDesc, pResourceDesc, initialState, null, (D3D12MA_Allocation**)ppv, &nuliid, null);
|
||||
}
|
||||
|
||||
return hr;
|
||||
@@ -695,7 +696,7 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
return Handle<GPUResource>.Invalid;
|
||||
}
|
||||
|
||||
return TrackResource(alloc, D3D12_RESOURCE_STATE_COMMON, ResourceViewGroup.Invalid, default, name, false);
|
||||
return TrackAllocation(alloc, D3D12_RESOURCE_STATE_COMMON, ResourceViewGroup.Invalid, default, name, false);
|
||||
}
|
||||
|
||||
public Handle<Texture> CreateTexture(ref readonly TextureDesc desc, string name, CreationOptions options = default)
|
||||
@@ -756,10 +757,26 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
};
|
||||
|
||||
var initialState = DetermineInitialTextureState(desc.Usage);
|
||||
|
||||
var isSubAllocation = options.AllocationType == ResourceAllocationType.Suballocation;
|
||||
D3D12MA_Allocation* pAllocation = default;
|
||||
if (CreateResource(&allocationDesc, &resourceDesc, initialState, options, (void**)&pAllocation).FAILED)
|
||||
ID3D12Resource* pResource = default;
|
||||
HRESULT hr;
|
||||
|
||||
if (isSubAllocation)
|
||||
{
|
||||
hr = CreateResource(&allocationDesc, &resourceDesc, initialState, options, __uuidof(pResource), (void**)&pResource);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = CreateResource(&allocationDesc, &resourceDesc, initialState, options, null, (void**)&pAllocation);
|
||||
pResource = pAllocation->GetResource();
|
||||
}
|
||||
|
||||
if (hr.FAILED)
|
||||
{
|
||||
#if DEBUG
|
||||
Marshal.ThrowExceptionForHR(hr);
|
||||
#endif
|
||||
return Handle<Texture>.Invalid;
|
||||
}
|
||||
|
||||
@@ -767,46 +784,55 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
var resourceDescriptor = ResourceViewGroup.Invalid;
|
||||
if (desc.Usage.HasFlag(TextureUsage.ShaderResource))
|
||||
{
|
||||
resourceDescriptor.srv = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
// TODO: Maybe use non-shader-visible descriptor first then batch copy to shader-visible Heap later?
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandleShaderVisible(resourceDescriptor.srv);
|
||||
resourceDescriptor.srv = _descriptorAllocator.AllocateCbvSrvUav();
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv);
|
||||
|
||||
var isCubeMap = desc.Dimension == TextureDimension.TextureCube || desc.Dimension == TextureDimension.TextureCubeArray;
|
||||
var srvDesc = CreateTextureSrvDesc(pAllocation->GetResource(), mipLevels, desc.Slice, isCubeMap);
|
||||
var srvDesc = CreateTextureSrvDesc(pResource, mipLevels, desc.Slice, isCubeMap);
|
||||
|
||||
_device.NativeDevice.Get()->CreateShaderResourceView(pAllocation->GetResource(), &srvDesc, cpuHandle);
|
||||
_device.NativeDevice.Get()->CreateShaderResourceView(pResource, &srvDesc, cpuHandle);
|
||||
_descriptorAllocator.CopyToShaderVisible(resourceDescriptor.srv);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(TextureUsage.RenderTarget))
|
||||
{
|
||||
resourceDescriptor.rtv = _descriptorAllocator.AllocateRTV(isTemp);
|
||||
resourceDescriptor.rtv = _descriptorAllocator.AllocateRTV();
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.rtv);
|
||||
var rtvDesc = CreateRtvDesc(pAllocation->GetResource());
|
||||
var rtvDesc = CreateRtvDesc(pResource);
|
||||
|
||||
_device.NativeDevice.Get()->CreateRenderTargetView(pAllocation->GetResource(), &rtvDesc, cpuHandle);
|
||||
_device.NativeDevice.Get()->CreateRenderTargetView(pResource, &rtvDesc, cpuHandle);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(TextureUsage.DepthStencil))
|
||||
{
|
||||
resourceDescriptor.dsv = _descriptorAllocator.AllocateDSV(isTemp);
|
||||
resourceDescriptor.dsv = _descriptorAllocator.AllocateDSV();
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.dsv);
|
||||
var dsvDesc = CreateDsvDesc(pAllocation->GetResource());
|
||||
var dsvDesc = CreateDsvDesc(pResource);
|
||||
|
||||
_device.NativeDevice.Get()->CreateDepthStencilView(pAllocation->GetResource(), &dsvDesc, cpuHandle);
|
||||
_device.NativeDevice.Get()->CreateDepthStencilView(pResource, &dsvDesc, cpuHandle);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(TextureUsage.UnorderedAccess))
|
||||
{
|
||||
resourceDescriptor.uav = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandleShaderVisible(resourceDescriptor.uav);
|
||||
var uavDesc = CreateTextureUavDesc(pAllocation->GetResource());
|
||||
resourceDescriptor.uav = _descriptorAllocator.AllocateCbvSrvUav();
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.uav);
|
||||
var uavDesc = CreateTextureUavDesc(pResource);
|
||||
|
||||
_device.NativeDevice.Get()->CreateUnorderedAccessView(pAllocation->GetResource(), null, &uavDesc, cpuHandle);
|
||||
_device.NativeDevice.Get()->CreateUnorderedAccessView(pResource, null, &uavDesc, cpuHandle);
|
||||
_descriptorAllocator.CopyToShaderVisible(resourceDescriptor.uav);
|
||||
}
|
||||
|
||||
var handle = TrackResource(pAllocation, initialState, resourceDescriptor, ResourceDesc.Texture(desc), name, isTemp);
|
||||
Handle<GPUResource> resource;
|
||||
if (isSubAllocation)
|
||||
{
|
||||
resource = _resourceDatabase.ImportExternalResource(pResource, initialState.ToResourceState(), resourceDescriptor, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
resource = TrackAllocation(pAllocation, initialState, resourceDescriptor, ResourceDesc.Texture(desc), name, isTemp);
|
||||
}
|
||||
|
||||
return handle.AsTexture();
|
||||
return resource.AsTexture();
|
||||
}
|
||||
|
||||
public Handle<Texture> CreateRenderTarget(ref readonly RenderTargetDesc desc, string name, CreationOptions options = default)
|
||||
@@ -839,21 +865,33 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
};
|
||||
|
||||
var initialState = DetermineInitialBufferState(desc.Usage, desc.MemoryType);
|
||||
|
||||
var isSubAllocation = options.Heap.IsValid;
|
||||
D3D12MA_Allocation* pAllocation = default;
|
||||
if (CreateResource(&allocationDesc, &resourceDesc, initialState, options, (void**)&pAllocation).FAILED)
|
||||
ID3D12Resource* pResource = default;
|
||||
HRESULT hr;
|
||||
|
||||
if (isSubAllocation)
|
||||
{
|
||||
hr = CreateResource(&allocationDesc, &resourceDesc, initialState, options, __uuidof(pResource), (void**)&pResource);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = CreateResource(&allocationDesc, &resourceDesc, initialState, options, null, (void**)&pAllocation);
|
||||
pResource = pAllocation->GetResource();
|
||||
}
|
||||
|
||||
if (hr.FAILED)
|
||||
{
|
||||
return Handle<GraphicsBuffer>.Invalid;
|
||||
}
|
||||
|
||||
var isTemp = options.AllocationType == ResourceAllocationType.Temporary;
|
||||
var resourceDescriptor = ResourceViewGroup.Invalid;
|
||||
var pResource = pAllocation->GetResource();
|
||||
|
||||
if (desc.Usage.HasFlag(BufferUsage.Constant))
|
||||
{
|
||||
resourceDescriptor.cbv = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandleShaderVisible(resourceDescriptor.cbv);
|
||||
resourceDescriptor.cbv = _descriptorAllocator.AllocateCbvSrvUav();
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.cbv);
|
||||
var cbvDesc = new D3D12_CONSTANT_BUFFER_VIEW_DESC
|
||||
{
|
||||
BufferLocation = pResource->GetGPUVirtualAddress(),
|
||||
@@ -861,28 +899,40 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
};
|
||||
|
||||
_device.NativeDevice.Get()->CreateConstantBufferView(&cbvDesc, cpuHandle);
|
||||
_descriptorAllocator.CopyToShaderVisible(resourceDescriptor.cbv);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(BufferUsage.ShaderResource))
|
||||
{
|
||||
resourceDescriptor.srv = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandleShaderVisible(resourceDescriptor.srv);
|
||||
var srvDesc = CreateBufferSrvDesc(pAllocation->GetResource(), desc.Stride, isRaw);
|
||||
resourceDescriptor.srv = _descriptorAllocator.AllocateCbvSrvUav();
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv);
|
||||
var srvDesc = CreateBufferSrvDesc(pResource, desc.Stride, isRaw);
|
||||
|
||||
_device.NativeDevice.Get()->CreateShaderResourceView(pResource, &srvDesc, cpuHandle);
|
||||
_descriptorAllocator.CopyToShaderVisible(resourceDescriptor.srv);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(BufferUsage.UnorderedAccess))
|
||||
{
|
||||
resourceDescriptor.uav = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandleShaderVisible(resourceDescriptor.uav);
|
||||
var uavDesc = CreateBufferUavDesc(pAllocation->GetResource(), desc.Stride, isRaw);
|
||||
resourceDescriptor.uav = _descriptorAllocator.AllocateCbvSrvUav();
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.uav);
|
||||
var uavDesc = CreateBufferUavDesc(pResource, desc.Stride, isRaw);
|
||||
|
||||
_device.NativeDevice.Get()->CreateUnorderedAccessView(pResource, null, &uavDesc, cpuHandle);
|
||||
_descriptorAllocator.CopyToShaderVisible(resourceDescriptor.uav);
|
||||
}
|
||||
|
||||
var handle = TrackResource(pAllocation, initialState, resourceDescriptor, ResourceDesc.Buffer(desc), name, isTemp);
|
||||
return handle.AsGraphicsBuffer();
|
||||
Handle<GPUResource> resource;
|
||||
if (isSubAllocation)
|
||||
{
|
||||
resource = _resourceDatabase.ImportExternalResource(pResource, initialState.ToResourceState(), resourceDescriptor, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
resource = TrackAllocation(pAllocation, initialState, resourceDescriptor, ResourceDesc.Buffer(desc), name, isTemp);
|
||||
}
|
||||
|
||||
return resource.AsGraphicsBuffer();
|
||||
}
|
||||
|
||||
public Handle<GraphicsBuffer> CreateTempUploadBuffer(ulong sizeInBytes, out ulong offset)
|
||||
@@ -935,8 +985,9 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
};
|
||||
|
||||
var samplerDescriptor = _descriptorAllocator.AllocateSampler();
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandleShaderVisible(samplerDescriptor);
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(samplerDescriptor);
|
||||
_device.NativeDevice.Get()->CreateSampler(&samplerDesc, cpuHandle);
|
||||
_descriptorAllocator.CopyToShaderVisible(samplerDescriptor);
|
||||
|
||||
return _resourceDatabase.CreateSampler(in desc, samplerDescriptor.Value);
|
||||
}
|
||||
@@ -1013,15 +1064,15 @@ internal sealed unsafe partial class D3D12ResourceAllocator : IResourceAllocator
|
||||
while (_tempResources.Count > 0)
|
||||
{
|
||||
var handle = _tempResources.Peek();
|
||||
ref var info = ref _resourceDatabase.GetResourceRecord(handle, out var exist);
|
||||
if (!exist || !info.Allocated)
|
||||
var r = _resourceDatabase.GetResourceRecord(handle);
|
||||
if (r.IsFailure || !r.Value.Allocated)
|
||||
{
|
||||
// Resource already released or invalid, just dequeue
|
||||
_tempResources.Dequeue();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info.cpuFenceValue > _fenceSynchronizer.GPUFenceValue)
|
||||
if (r.Value.cpuFenceValue > _fenceSynchronizer.GPUFenceValue)
|
||||
{
|
||||
// Resource still in use by GPU, stop processing.
|
||||
// Since resources are enqueued in order, we can break here.
|
||||
|
||||
@@ -133,6 +133,13 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
public unsafe Handle<GPUResource> ImportExternalResource(ID3D12Resource* pResource, ResourceState initialState, ResourceViewGroup viewGroup, string? name = null)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
if (pResource == null)
|
||||
{
|
||||
#if DEBUG
|
||||
System.Diagnostics.Debugger.Break();
|
||||
#endif
|
||||
return Handle<GPUResource>.Invalid;
|
||||
}
|
||||
|
||||
var id = _resources.Add(new ResourceRecord(pResource, initialState, viewGroup), out var generation);
|
||||
var handle = new Handle<GPUResource>(id, generation);
|
||||
@@ -151,6 +158,13 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
public unsafe Handle<GPUResource> AddAllocation(D3D12MA_Allocation* allocation, uint cpuFenceValue, ResourceState initialState, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string? name = null)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
if (allocation == null)
|
||||
{
|
||||
#if DEBUG
|
||||
System.Diagnostics.Debugger.Break();
|
||||
#endif
|
||||
return Handle<GPUResource>.Invalid;
|
||||
}
|
||||
|
||||
var id = _resources.Add(new ResourceRecord(allocation, cpuFenceValue, initialState, resourceDescriptor, desc), out var generation);
|
||||
var handle = new Handle<GPUResource>(id, generation);
|
||||
@@ -159,7 +173,11 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
allocation->SetName(name);
|
||||
allocation->GetResource()->SetName(name);
|
||||
var pResource = allocation->GetResource();
|
||||
if (pResource != null)
|
||||
{
|
||||
pResource->SetName(name);
|
||||
}
|
||||
_resourceName[handle] = name;
|
||||
}
|
||||
#endif
|
||||
@@ -186,18 +204,10 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
return RefResult<ResourceRecord, ErrorStatus>.Success(ref info);
|
||||
}
|
||||
|
||||
public ref ResourceRecord GetResourceRecord(Handle<GPUResource> handle, out bool exist)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return ref _resources.GetElementReferenceAt(handle.ID, handle.Generation, out exist);
|
||||
}
|
||||
|
||||
public SharedPtr<ID3D12Resource> GetResource(Handle<GPUResource> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var r = GetResourceRecord(handle);
|
||||
if (r.Error != ErrorStatus.None)
|
||||
if (r.IsFailure)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -207,10 +217,8 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
|
||||
public Result<ResourceState, ErrorStatus> GetResourceState(Handle<GPUResource> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var r = GetResourceRecord(handle);
|
||||
if (!r)
|
||||
if (r.IsFailure)
|
||||
{
|
||||
return r.Error;
|
||||
}
|
||||
@@ -218,25 +226,22 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
return r.Value.state;
|
||||
}
|
||||
|
||||
public void SetResourceState(Handle<GPUResource> handle, ResourceState state)
|
||||
public ErrorStatus SetResourceState(Handle<GPUResource> handle, ResourceState state)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
ref var info = ref _resources.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
|
||||
if (!exist || !info.Allocated)
|
||||
var r = GetResourceRecord(handle);
|
||||
if (r.IsFailure)
|
||||
{
|
||||
throw new KeyNotFoundException($"Resource with handle {handle} not found.");
|
||||
return r.Error;
|
||||
}
|
||||
|
||||
info.state = state;
|
||||
r.Value.state = state;
|
||||
return ErrorStatus.None;
|
||||
}
|
||||
|
||||
public Result<ResourceDesc, ErrorStatus> GetResourceDescription(Handle<GPUResource> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var r = GetResourceRecord(handle);
|
||||
if (!r)
|
||||
if (r.IsFailure)
|
||||
{
|
||||
return r.Error;
|
||||
}
|
||||
@@ -246,15 +251,13 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
|
||||
public uint GetBindlessIndex(Handle<GPUResource> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
ref var info = ref GetResourceRecord(handle, out var exist);
|
||||
if (!exist || !info.Allocated)
|
||||
var r = GetResourceRecord(handle);
|
||||
if (r.IsFailure || !r.Value.Allocated)
|
||||
{
|
||||
return ~0u;
|
||||
}
|
||||
|
||||
return (uint)info.viewGroup.srv.Value;
|
||||
return (uint)r.Value.viewGroup.srv.Value;
|
||||
}
|
||||
|
||||
public string? GetResourceName(Handle<GPUResource> handle)
|
||||
@@ -329,17 +332,15 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
return _meshes.Contains(handle.ID, handle.Generation);
|
||||
}
|
||||
|
||||
public ref Mesh GetMeshReference(Handle<Mesh> handle)
|
||||
public RefResult<Mesh, ErrorStatus> GetMeshReference(Handle<Mesh> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
ref var mesh = ref _meshes.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
|
||||
if (!exist)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(handle), $"Mesh {handle} is invalid.");
|
||||
return ErrorStatus.NotFound;
|
||||
}
|
||||
|
||||
return ref mesh;
|
||||
return RefResult<Mesh, ErrorStatus>.Success(ref mesh);
|
||||
}
|
||||
|
||||
public void ReleaseMesh(Handle<Mesh> handle)
|
||||
@@ -370,17 +371,15 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
return _materials.Contains(handle.ID, handle.Generation);
|
||||
}
|
||||
|
||||
public ref Material GetMaterialReference(Handle<Material> handle)
|
||||
public RefResult<Material, ErrorStatus> GetMaterialReference(Handle<Material> handle)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
ref var material = ref _materials.GetElementReferenceAt(handle.ID, handle.Generation, out var exist);
|
||||
if (!exist)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(handle), $"Material handle {handle} is invalid.");
|
||||
return ErrorStatus.NotFound;
|
||||
}
|
||||
|
||||
return ref material;
|
||||
return RefResult<Material, ErrorStatus>.Success(ref material);
|
||||
}
|
||||
|
||||
public void ReleaseMaterial(Handle<Material> handle)
|
||||
@@ -412,16 +411,14 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
return id.Value >= 0 && id.Value < _shaders.Count;
|
||||
}
|
||||
|
||||
public ref Shader GetShaderReference(Identifier<Shader> id)
|
||||
public RefResult<Shader, ErrorStatus> GetShaderReference(Identifier<Shader> id)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
if (!HasShader(id))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(id), $"Shader id {id} is invalid.");
|
||||
return ErrorStatus.NotFound;
|
||||
}
|
||||
|
||||
return ref _shaders[id.Value];
|
||||
return RefResult<Shader, ErrorStatus>.Success(ref _shaders[id.Value]);
|
||||
}
|
||||
|
||||
public void ReleaseShader(Identifier<Shader> id)
|
||||
|
||||
@@ -7,11 +7,11 @@ namespace Ghost.Graphics.D3D12.Utilities;
|
||||
internal unsafe static class D3D12PipelineResource
|
||||
{
|
||||
private readonly static D3D12_INPUT_ELEMENT_DESC[] s_inputElementDescs = [
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.position.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 0u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.normal.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 16u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.tangent.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 32u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.uv.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 48u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.color.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 64u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Position.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 0u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Normal.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 16u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Tangent.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 32u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Uv.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 48u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
new D3D12_INPUT_ELEMENT_DESC{ SemanticName = (sbyte*)Vertex.Semantic.Color.GetUnsafePointer(), SemanticIndex = 0u, Format = Vertex.Semantic.ALIGNED_FORMAT, InputSlot = 0u, AlignedByteOffset = 64u, InputSlotClass = D3D12_INPUT_CLASSIFICATION.D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, InstanceDataStepRate = 0 },
|
||||
];
|
||||
|
||||
public const DXGI_FORMAT SWAP_CHAIN_BACK_BUFFER_FORMAT = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
@@ -42,7 +42,7 @@ internal unsafe static class D3D12Utility
|
||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE1D => TextureDimension.Texture2D,
|
||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE2D => TextureDimension.Texture2D,
|
||||
D3D12_RESOURCE_DIMENSION.D3D12_RESOURCE_DIMENSION_TEXTURE3D => TextureDimension.Texture3D,
|
||||
_ => TextureDimension.Unknown,
|
||||
_ => throw new NotSupportedException($"Resource dimension {dimension} is not supported."),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ internal unsafe static class D3D12Utility
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT => TextureFormat.R32G32B32A32_Float,
|
||||
DXGI_FORMAT_D24_UNORM_S8_UINT => TextureFormat.D24_UNorm_S8_UInt,
|
||||
DXGI_FORMAT_D32_FLOAT => TextureFormat.D32_Float,
|
||||
_ => TextureFormat.Unknown,
|
||||
_ => throw new NotSupportedException($"DXGI format {format} is not supported.")
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user