forked from Misaki/GhostEngine
Refactor and enhance graphics and audio systems
Updated target frameworks to .NET 10.0 across multiple projects for compatibility with the latest features. Refactored namespaces and introduced new classes for shader descriptors, FMOD integration, and DirectX 12 utilities using TerraFX. Replaced `Win32` bindings with TerraFX equivalents for DirectX 12. Added a C# wrapper for FMOD Studio API, including DSP and error handling. Enhanced entity queries, component storage, and query filters for better performance and type safety. Introduced new test projects and updated the solution structure. Added `meshoptimizer` bindings and integrated `meshoptimizer_native.dll`. Improved code readability, maintainability, and performance.
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.Data;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
using Win32;
|
||||
using Win32.Graphics.Direct3D;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using Win32.Graphics.Dxgi.Common;
|
||||
using Win32.Numerics;
|
||||
|
||||
using static TerraFX.Aliases.D3D12_Alias;
|
||||
using static TerraFX.Aliases.DXGI_Alias;
|
||||
using static TerraFX.Aliases.D3D_Alias;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -20,7 +20,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
private ComPtr<ID3D12CommandAllocator> _allocator;
|
||||
private ComPtr<ID3D12GraphicsCommandList10> _commandList;
|
||||
|
||||
private readonly D3D12PipelineLibrary _stateController;
|
||||
private readonly D3D12PipelineLibrary _pipelineLibrary;
|
||||
private readonly D3D12ResourceDatabase _resourceDatabase;
|
||||
private readonly D3D12ResourceAllocator _resourceAllocator;
|
||||
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
||||
@@ -48,9 +48,9 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
var commandListType = ConvertCommandBufferType(type);
|
||||
|
||||
device.NativeDevice->CreateCommandAllocator(commandListType, __uuidof<ID3D12CommandAllocator>(), _allocator.GetVoidAddressOf());
|
||||
device.NativeDevice->CreateCommandList1(0u, commandListType, CommandListFlags.None, __uuidof<ID3D12GraphicsCommandList10>(), _commandList.GetVoidAddressOf());
|
||||
device.NativeDevice->CreateCommandList1(0u, commandListType, D3D12_COMMAND_LIST_FLAG_NONE, __uuidof<ID3D12GraphicsCommandList10>(), _commandList.GetVoidAddressOf());
|
||||
|
||||
_stateController = stateController;
|
||||
_pipelineLibrary = stateController;
|
||||
_resourceDatabase = resourceDatabase;
|
||||
_resourceAllocator = resourceAllocator;
|
||||
_descriptorAllocator = descriptorAllocator;
|
||||
@@ -113,7 +113,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
ThrowIfNotRecording();
|
||||
IncrementCommandCount();
|
||||
|
||||
var rtvHandles = stackalloc CpuDescriptorHandle[renderTargets.Length];
|
||||
var rtvHandles = stackalloc D3D12_CPU_DESCRIPTOR_HANDLE[renderTargets.Length];
|
||||
for (var i = 0; i < renderTargets.Length; i++)
|
||||
{
|
||||
var handle = renderTargets[i];
|
||||
@@ -126,13 +126,13 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
rtvHandles[i] = _descriptorAllocator.GetCpuHandle(descriptor.rtv);
|
||||
}
|
||||
|
||||
var dsvHandle = stackalloc CpuDescriptorHandle[depthTarget.IsValid ? 1 : 0];
|
||||
var dsvHandle = stackalloc D3D12_CPU_DESCRIPTOR_HANDLE[depthTarget.IsValid ? 1 : 0];
|
||||
if (dsvHandle != null)
|
||||
{
|
||||
*dsvHandle = _descriptorAllocator.GetCpuHandle(_resourceDatabase.GetResourceInfo(depthTarget.AsResource()).descriptor.dsv);
|
||||
}
|
||||
|
||||
_commandList.Get()->OMSetRenderTargets((uint)renderTargets.Length, rtvHandles, Bool32.False, dsvHandle);
|
||||
_commandList.Get()->OMSetRenderTargets((uint)renderTargets.Length, rtvHandles, FALSE, dsvHandle);
|
||||
}
|
||||
|
||||
public void BeginRenderPass(Handle<Texture> renderTarget, Handle<Texture> depthTarget, Color128 clearColor)
|
||||
@@ -155,7 +155,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
ThrowIfNotRecording();
|
||||
IncrementCommandCount();
|
||||
|
||||
var d3d12Viewport = new Viewport(viewport.width, viewport.height, viewport.x, viewport.y, viewport.minDepth, viewport.maxDepth);
|
||||
var d3d12Viewport = new D3D12_VIEWPORT(viewport.width, viewport.height, viewport.x, viewport.y, viewport.minDepth, viewport.maxDepth);
|
||||
_commandList.Get()->RSSetViewports(1, &d3d12Viewport);
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
ThrowIfNotRecording();
|
||||
IncrementCommandCount();
|
||||
|
||||
var d3d12Rect = new Rect((int)rect.left, (int)rect.top, (int)rect.right, (int)rect.bottom);
|
||||
var d3d12Rect = new RECT((int)rect.left, (int)rect.top, (int)rect.right, (int)rect.bottom);
|
||||
_commandList.Get()->RSSetScissorRects(1, &d3d12Rect);
|
||||
}
|
||||
|
||||
@@ -176,9 +176,10 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
IncrementCommandCount();
|
||||
|
||||
var d3d12Resource = _resourceDatabase.GetResource(resource);
|
||||
|
||||
_commandList.Get()->ResourceBarrierTransition(d3d12Resource,
|
||||
var barrier = D3D12_RESOURCE_BARRIER.InitTransition(d3d12Resource,
|
||||
before.ToD3D12States(), after.ToD3D12States());
|
||||
|
||||
_commandList.Get()->ResourceBarrier(1, &barrier);
|
||||
}
|
||||
|
||||
public void SetRootSignature(IRootSignature rootSignature)
|
||||
@@ -200,7 +201,7 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
IncrementCommandCount();
|
||||
|
||||
var pResource = _resourceDatabase.GetResource(buffer.AsResource());
|
||||
var vbView = new VertexBufferView
|
||||
var vbView = new D3D12_VERTEX_BUFFER_VIEW
|
||||
{
|
||||
BufferLocation = pResource->GetGPUVirtualAddress() + offset,
|
||||
SizeInBytes = (uint)(pResource->GetDesc().Width - offset),
|
||||
@@ -217,11 +218,11 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
IncrementCommandCount();
|
||||
|
||||
var pResource = _resourceDatabase.GetResource(buffer.AsResource());
|
||||
var ibView = new IndexBufferView
|
||||
var ibView = new D3D12_INDEX_BUFFER_VIEW
|
||||
{
|
||||
BufferLocation = pResource->GetGPUVirtualAddress() + offset,
|
||||
SizeInBytes = (uint)(pResource->GetDesc().Width - offset),
|
||||
Format = type == IndexType.UInt16 ? Format.R16Uint : Format.R32Uint
|
||||
Format = type == IndexType.UInt16 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT
|
||||
};
|
||||
|
||||
_commandList.Get()->IASetIndexBuffer(&ibView);
|
||||
@@ -256,36 +257,36 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
ref var materialRef = ref _resourceDatabase.GetMaterialReference(material);
|
||||
ref var shaderRef = ref _resourceDatabase.GetShaderReference(materialRef.Shader);
|
||||
|
||||
var shaderPipeline = _stateController.GetShaderPipeline(materialRef.Shader);
|
||||
var shaderPipeline = _pipelineLibrary.GetShaderPipeline(materialRef.Shader);
|
||||
if (shaderPipeline is not D3D12ShaderPipeline d3d12Pipeline)
|
||||
{
|
||||
throw new InvalidOperationException("Shader pipeline is not compiled or invalid");
|
||||
}
|
||||
|
||||
_commandList.Get()->SetPipelineState(d3d12Pipeline.pipelineState.Get());
|
||||
_commandList.Get()->SetGraphicsRootSignature(d3d12Pipeline.rootSignature.Get());
|
||||
_commandList.Get()->SetGraphicsRootSignature(_pipelineLibrary.DefaultRootSignature);
|
||||
|
||||
// Set descriptor heaps - CRUCIAL: Use the specialized bindless heap for SM 6.6
|
||||
var heaps = stackalloc ID3D12DescriptorHeap*[2];
|
||||
heaps[0] = _descriptorAllocator.GetCbvSrvUavHeap(); // Specialized bindless heap
|
||||
heaps[1] = d3d12Pipeline.samplerHeap.Get(); // Sampler heap from shader
|
||||
heaps[0] = _descriptorAllocator.GetCbvSrvUavHeap(); // Bindless resource heap
|
||||
heaps[1] = _descriptorAllocator.GetSamplerHeap(); // Bindless sampler heap
|
||||
_commandList.Get()->SetDescriptorHeaps(2, heaps);
|
||||
|
||||
var rootParamIndex = 0u;
|
||||
foreach (var cbufferInfo in shaderRef.ConstantBuffers)
|
||||
foreach (var cbufferInfo in shaderRef.PerMaterialBufferInfo)
|
||||
{
|
||||
ref var cache = ref materialRef._cBufferCaches[(int)cbufferInfo.RegisterSlot];
|
||||
ref var cache = ref materialRef._materialPropertiesCache[(int)cbufferInfo.RegisterSlot];
|
||||
var resource = _resourceDatabase.GetResource(cache.GpuResource.AsResource());
|
||||
_commandList.Get()->SetGraphicsRootConstantBufferView(rootParamIndex++, resource->GetGPUVirtualAddress());
|
||||
}
|
||||
|
||||
var samplerGpuHandle = d3d12Pipeline.samplerHeap.Get()->GetGPUDescriptorHandleForHeapStart();
|
||||
var samplerGpuHandle = _descriptorAllocator.GetSamplerHeap()->GetGPUDescriptorHandleForHeapStart();
|
||||
_commandList.Get()->SetGraphicsRootDescriptorTable(rootParamIndex, samplerGpuHandle);
|
||||
|
||||
// For fully bindless rendering, we don't use the Input Assembler stage
|
||||
// Instead, we use instanced drawing where each "instance" represents a triangle
|
||||
// The shader will use SV_InstanceID to index into the index buffer and then into the vertex buffer
|
||||
_commandList.Get()->IASetPrimitiveTopology(PrimitiveTopology.TriangleList);
|
||||
_commandList.Get()->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
// Draw without vertex/index buffers - use instanced drawing
|
||||
// Each instance represents a triangle (3 vertices)
|
||||
@@ -341,10 +342,10 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
var uploadHandle = _resourceAllocator.CreateUploadBuffer(requiredSize);
|
||||
var pUploadResource = _resourceDatabase.GetResource(uploadHandle.AsResource());
|
||||
|
||||
var d3d12Subresources = stackalloc SubresourceData[subresources.Length];
|
||||
var d3d12Subresources = stackalloc D3D12_SUBRESOURCE_DATA[subresources.Length];
|
||||
for (var i = 0; i < subresources.Length; i++)
|
||||
{
|
||||
d3d12Subresources[i] = new SubresourceData
|
||||
d3d12Subresources[i] = new D3D12_SUBRESOURCE_DATA
|
||||
{
|
||||
pData = subresources[i].pData,
|
||||
RowPitch = subresources[i].rowPitch,
|
||||
@@ -385,13 +386,13 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
}
|
||||
}
|
||||
|
||||
private static CommandListType ConvertCommandBufferType(CommandBufferType type)
|
||||
private static D3D12_COMMAND_LIST_TYPE ConvertCommandBufferType(CommandBufferType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
CommandBufferType.Graphics => CommandListType.Direct,
|
||||
CommandBufferType.Compute => CommandListType.Compute,
|
||||
CommandBufferType.Copy => CommandListType.Copy,
|
||||
CommandBufferType.Graphics => D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
CommandBufferType.Compute => D3D12_COMMAND_LIST_TYPE_COMPUTE,
|
||||
CommandBufferType.Copy => D3D12_COMMAND_LIST_TYPE_COPY,
|
||||
_ => throw new ArgumentException($"Unknown command buffer type: {type}")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.RHI;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Win32;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -29,11 +28,11 @@ internal unsafe class D3D12CommandQueue : ICommandQueue
|
||||
_fenceEvent = new AutoResetEvent(false);
|
||||
_fenceValue = 0;
|
||||
|
||||
var queueDesc = new CommandQueueDescription
|
||||
var queueDesc = new D3D12_COMMAND_QUEUE_DESC
|
||||
{
|
||||
Type = ConvertCommandQueueType(type),
|
||||
Priority = (int)CommandQueuePriority.Normal,
|
||||
Flags = CommandQueueFlags.None,
|
||||
Priority = (int)D3D12_COMMAND_QUEUE_PRIORITY.D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
|
||||
Flags = D3D12_COMMAND_QUEUE_FLAGS.D3D12_COMMAND_QUEUE_FLAG_NONE,
|
||||
};
|
||||
|
||||
fixed (void* queuePtr = &_queue)
|
||||
@@ -41,7 +40,7 @@ internal unsafe class D3D12CommandQueue : ICommandQueue
|
||||
pDevice->CreateCommandQueue(&queueDesc, __uuidof<ID3D12CommandQueue>(), (void**)queuePtr);
|
||||
}
|
||||
|
||||
pDevice->CreateFence(0, FenceFlags.None, __uuidof<ID3D12Fence1>(), _fence.GetVoidAddressOf());
|
||||
pDevice->CreateFence(0, D3D12_FENCE_FLAGS.D3D12_FENCE_FLAG_NONE, __uuidof<ID3D12Fence1>(), _fence.GetVoidAddressOf());
|
||||
}
|
||||
|
||||
~D3D12CommandQueue()
|
||||
@@ -120,8 +119,8 @@ internal unsafe class D3D12CommandQueue : ICommandQueue
|
||||
{
|
||||
if (_fence.Get()->GetCompletedValue() < value)
|
||||
{
|
||||
var handle = new Handle((void*)_fenceEvent.SafeWaitHandle.DangerousGetHandle());
|
||||
if (_fence.Get()->SetEventOnCompletion(value, handle).Success)
|
||||
var handle = new HANDLE((void*)_fenceEvent.SafeWaitHandle.DangerousGetHandle());
|
||||
if (_fence.Get()->SetEventOnCompletion(value, handle).SUCCEEDED)
|
||||
{
|
||||
_fenceEvent.WaitOne();
|
||||
}
|
||||
@@ -139,13 +138,13 @@ internal unsafe class D3D12CommandQueue : ICommandQueue
|
||||
WaitForValue(fenceValue);
|
||||
}
|
||||
|
||||
private static CommandListType ConvertCommandQueueType(CommandQueueType type)
|
||||
private static D3D12_COMMAND_LIST_TYPE ConvertCommandQueueType(CommandQueueType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
CommandQueueType.Graphics => CommandListType.Direct,
|
||||
CommandQueueType.Compute => CommandListType.Compute,
|
||||
CommandQueueType.Copy => CommandListType.Copy,
|
||||
CommandQueueType.Graphics => D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_DIRECT,
|
||||
CommandQueueType.Compute => D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_COMPUTE,
|
||||
CommandQueueType.Copy => D3D12_COMMAND_LIST_TYPE.D3D12_COMMAND_LIST_TYPE_COPY,
|
||||
_ => throw new ArgumentException($"Unknown command queue type: {type}")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Win32;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using Win32.Graphics.Dxgi;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
using static TerraFX.Aliases.DXGI_Alias;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -19,13 +21,13 @@ internal unsafe class D3D12DebugLayer
|
||||
_dxgiDebug.Get()->EnableLeakTrackingForThread();
|
||||
|
||||
DXGIGetDebugInterface1(0u, __uuidof<IDXGIInfoQueue>(), _dxgiInfoQueue.GetVoidAddressOf());
|
||||
_dxgiInfoQueue.Get()->SetBreakOnSeverity(DXGI_DEBUG_ALL, InfoQueueMessageSeverity.Error, true);
|
||||
_dxgiInfoQueue.Get()->SetBreakOnSeverity(DXGI_DEBUG_ALL, InfoQueueMessageSeverity.Corruption, true);
|
||||
_dxgiInfoQueue.Get()->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true);
|
||||
_dxgiInfoQueue.Get()->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_dxgiDebug.Get()->ReportLiveObjects(DXGI_DEBUG_ALL, ReportLiveObjectFlags.All);
|
||||
_dxgiDebug.Get()->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_ALL | DXGI_DEBUG_RLO_IGNORE_INTERNAL);
|
||||
|
||||
_d3d12Debug.Dispose();
|
||||
_dxgiDebug.Dispose();
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using TerraFX.Interop.DirectX;
|
||||
|
||||
using static TerraFX.Aliases.D3D12_Alias;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -19,10 +21,10 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
|
||||
public unsafe D3D12DescriptorAllocator(D3D12RenderDevice device, int initialRtvCount = 256, int initialDsvCount = 256, int initialSrvCount = 200_000, int initialSamplerCount = 256)
|
||||
{
|
||||
_rtvHeap = new D3D12DescriptorHeap("rtv", device, DescriptorHeapType.Rtv, initialRtvCount, initialRtvCount / 2);
|
||||
_dsvHeap = new D3D12DescriptorHeap("dsv", device, DescriptorHeapType.Dsv, initialDsvCount, initialDsvCount / 2);
|
||||
_cbvSrvUavHeap = new D3D12DescriptorHeap("srv", device, DescriptorHeapType.CbvSrvUav, initialSrvCount, initialSrvCount /2);
|
||||
_samplerHeap = new D3D12DescriptorHeap("sampler", device, DescriptorHeapType.Sampler, initialSamplerCount, initialSamplerCount);
|
||||
_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);
|
||||
}
|
||||
|
||||
~D3D12DescriptorAllocator()
|
||||
@@ -66,7 +68,7 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public CpuDescriptorHandle GetCpuHandle(Identifier<RTVDesc> descriptor)
|
||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<RTVDesc> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _rtvHeap.GetCpuHandle(descriptor.value);
|
||||
@@ -151,7 +153,7 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
public CpuDescriptorHandle GetCpuHandle(Identifier<DSVDesc> descriptor)
|
||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<DSVDesc> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _dsvHeap.GetCpuHandle(descriptor.value);
|
||||
@@ -236,19 +238,19 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
public CpuDescriptorHandle GetCpuHandle(Identifier<CbvSrvUavDesc> descriptor)
|
||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<CbvSrvUavDesc> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _cbvSrvUavHeap.GetCpuHandle(descriptor.value);
|
||||
}
|
||||
|
||||
public CpuDescriptorHandle GetCpuHandleShaderVisible(Identifier<CbvSrvUavDesc> descriptor)
|
||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandleShaderVisible(Identifier<CbvSrvUavDesc> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _cbvSrvUavHeap.GetCpuHandleShaderVisible(descriptor.value);
|
||||
}
|
||||
|
||||
public GpuDescriptorHandle GetGpuHandle(Identifier<CbvSrvUavDesc> descriptor)
|
||||
public D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(Identifier<CbvSrvUavDesc> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _cbvSrvUavHeap.GetGpuHandle(descriptor.value);
|
||||
@@ -333,19 +335,19 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
public CpuDescriptorHandle GetCpuHandle(Identifier<SamplerDesc> descriptor)
|
||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(Identifier<SamplerDesc> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _samplerHeap.GetCpuHandle(descriptor.value);
|
||||
}
|
||||
|
||||
public CpuDescriptorHandle GetCpuHandleShaderVisible(Identifier<SamplerDesc> descriptor)
|
||||
public D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandleShaderVisible(Identifier<SamplerDesc> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _samplerHeap.GetCpuHandleShaderVisible(descriptor.value);
|
||||
}
|
||||
|
||||
public GpuDescriptorHandle GetGpuHandle(Identifier<SamplerDesc> descriptor)
|
||||
public D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(Identifier<SamplerDesc> descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
return _samplerHeap.GetGpuHandle(descriptor.value);
|
||||
@@ -370,7 +372,7 @@ internal unsafe class D3D12DescriptorAllocator : IDisposable
|
||||
#endregion
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Release(D3D12ResourceDescriptor descriptor)
|
||||
public void Release(ResourceViewGroup descriptor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ internal unsafe class D3D12GraphicsEngine : IGraphicsEngine
|
||||
_resourceDatabase = new(_descriptorAllocator);
|
||||
_resourceAllocator = new(renderSystem, _device, _descriptorAllocator, _resourceDatabase);
|
||||
|
||||
_stateController = new(_device, _resourceDatabase);
|
||||
_stateController = new(_device, _resourceDatabase, null);
|
||||
_copyCommandBuffer = new(
|
||||
_device,
|
||||
_stateController,
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
#undef USE_TRANDITIONAL_BINDLESS
|
||||
#undef USE_TRADITIONAL_BINDLESS
|
||||
|
||||
using Ghost.Core;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.Data;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Ghost.Graphics.Utilities;
|
||||
using System.Runtime.InteropServices;
|
||||
using Win32;
|
||||
using Win32.Graphics.Direct3D;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using Win32.Graphics.Dxgi.Common;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
|
||||
using static TerraFX.Aliases.D3D12_Alias;
|
||||
using static TerraFX.Aliases.D3D_Alias;
|
||||
using static TerraFX.Aliases.DXGI_Alias;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -36,47 +38,6 @@ internal class D3D12ShaderPipeline : IShaderPipeline, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
internal unsafe struct D3D12GraphicsPipelineStream
|
||||
{
|
||||
public PipelineStateSubObjectType rootSignatureType;
|
||||
public ID3D12RootSignature* pRootSignature;
|
||||
|
||||
public PipelineStateSubObjectType vsType;
|
||||
public ShaderBytecode vs;
|
||||
|
||||
public PipelineStateSubObjectType psType;
|
||||
public ShaderBytecode ps;
|
||||
|
||||
public PipelineStateSubObjectType rasterizerType;
|
||||
public RasterizerDescription rasterizer;
|
||||
|
||||
public PipelineStateSubObjectType blendType;
|
||||
public BlendDescription blend;
|
||||
|
||||
public PipelineStateSubObjectType depthStencilType;
|
||||
public DepthStencilDescription depthStencil;
|
||||
|
||||
public PipelineStateSubObjectType topologyType;
|
||||
public PrimitiveTopologyType primitiveTopology;
|
||||
|
||||
public PipelineStateSubObjectType rtvFormatType;
|
||||
public RtFormatArray rtvFormats;
|
||||
|
||||
public PipelineStateSubObjectType dsvFormatType;
|
||||
public Format dsvFormat;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
internal unsafe struct ComputePipelineStream
|
||||
{
|
||||
public PipelineStateSubObjectType rootSignatureType;
|
||||
public ID3D12RootSignature* pRootSignature;
|
||||
|
||||
public PipelineStateSubObjectType csType;
|
||||
public ShaderBytecode cs;
|
||||
}
|
||||
|
||||
internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
{
|
||||
private readonly D3D12RenderDevice _device;
|
||||
@@ -87,6 +48,8 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
|
||||
private readonly Dictionary<Identifier<Shader>, D3D12ShaderPipeline> _shaderPipelines;
|
||||
|
||||
public ID3D12RootSignature* DefaultRootSignature => _defaultRootSignature.Get();
|
||||
|
||||
public D3D12PipelineLibrary(D3D12RenderDevice device, D3D12ResourceDatabase resourceDatabase, string? cachePath)
|
||||
{
|
||||
_device = device;
|
||||
@@ -115,7 +78,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
private void CreateDefaultRootSignature()
|
||||
{
|
||||
const int rootParamCount =
|
||||
#if USE_TRANDITIONAL_BINDLESS
|
||||
#if USE_TRADITIONAL_BINDLESS
|
||||
6
|
||||
#else
|
||||
4
|
||||
@@ -124,93 +87,85 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
|
||||
_defaultRootSignature = default;
|
||||
|
||||
// The layout of the root signature is:
|
||||
// - Global buffer (b0)
|
||||
// - Per-view buffer (b1)
|
||||
// - Per-object buffer (b2)
|
||||
// - Per-instance buffer (b3)
|
||||
// - Descriptor table for bindless textures (t0)
|
||||
// - Descriptor table for bindless samplers (s0)
|
||||
|
||||
// NOTE: Since we are targeting SM 6.6, we can use ResourceDescriptorHeap and SamplerDescriptorHeap directly without needing to set up descriptor tables.
|
||||
|
||||
var rootParameters = stackalloc RootParameter1[rootParamCount];
|
||||
rootParameters[0] = new RootParameter1
|
||||
var rootParameters = stackalloc D3D12_ROOT_PARAMETER1[rootParamCount];
|
||||
rootParameters[0] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = RootParameterType.Cbv,
|
||||
ShaderVisibility = ShaderVisibility.All,
|
||||
Descriptor = new RootDescriptor1(0, 0), // b0
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
|
||||
Descriptor = new D3D12_ROOT_DESCRIPTOR1(0, 0), // b0
|
||||
};
|
||||
|
||||
rootParameters[1] = new RootParameter1
|
||||
rootParameters[1] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = RootParameterType.Cbv,
|
||||
ShaderVisibility = ShaderVisibility.All,
|
||||
Descriptor = new RootDescriptor1(1, 0), // b1
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
|
||||
Descriptor = new D3D12_ROOT_DESCRIPTOR1(1, 0), // b1
|
||||
};
|
||||
|
||||
rootParameters[2] = new RootParameter1
|
||||
rootParameters[2] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = RootParameterType.Cbv,
|
||||
ShaderVisibility = ShaderVisibility.All,
|
||||
Descriptor = new RootDescriptor1(2, 0), // b2
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
|
||||
Descriptor = new D3D12_ROOT_DESCRIPTOR1(2, 0), // b2
|
||||
};
|
||||
|
||||
rootParameters[3] = new RootParameter1
|
||||
rootParameters[3] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = RootParameterType.Cbv,
|
||||
ShaderVisibility = ShaderVisibility.All,
|
||||
Descriptor = new RootDescriptor1(3, 0), // b3
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV,
|
||||
ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
|
||||
Descriptor = new D3D12_ROOT_DESCRIPTOR1(3, 0), // b3
|
||||
};
|
||||
|
||||
#if USE_TRANDITIONAL_BINDLESS
|
||||
#if USE_TRADITIONAL_BINDLESS
|
||||
// Descriptor table for bindless textures
|
||||
var srvRange = new DescriptorRange1(
|
||||
DescriptorRangeType.Srv,
|
||||
var srvRange = new D3D12_DESCRIPTOR_RANGE1(
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
|
||||
~0u,
|
||||
0,
|
||||
0,
|
||||
DescriptorRangeFlags.DataVolatile);
|
||||
D3D12_DESCRIPTOR_RANGE_FLAGS_DATA_VOLATILE);
|
||||
|
||||
rootParameters[4] = new RootParameter1
|
||||
rootParameters[4] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = RootParameterType.DescriptorTable,
|
||||
ShaderVisibility = ShaderVisibility.All,
|
||||
DescriptorTable = new RootDescriptorTable1(1, &srvRange)
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
|
||||
ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
|
||||
DescriptorTable = new D3D12_ROOT_DESCRIPTOR_TABLE1(1, &srvRange)
|
||||
};
|
||||
|
||||
// Descriptor table for bindless samplers
|
||||
var sampRange = new DescriptorRange1(
|
||||
DescriptorRangeType.Sampler,
|
||||
~0u,
|
||||
var sampRange = new D3D12_DESCRIPTOR_RANGE1(
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
|
||||
~0u,
|
||||
0,
|
||||
0,
|
||||
DescriptorRangeFlags.DataVolatile);
|
||||
D3D12_DESCRIPTOR_RANGE_FLAGS_DATA_VOLATILE);
|
||||
|
||||
rootParameters[5] = new RootParameter1
|
||||
rootParameters[5] = new D3D12_ROOT_PARAMETER1
|
||||
{
|
||||
ParameterType = RootParameterType.DescriptorTable,
|
||||
ShaderVisibility = ShaderVisibility.All,
|
||||
DescriptorTable = new RootDescriptorTable1(1, &sampRange)
|
||||
ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE,
|
||||
ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL,
|
||||
DescriptorTable = new D3D12_ROOT_DESCRIPTOR_TABLE1(1, &sampRange)
|
||||
};
|
||||
#endif
|
||||
|
||||
var rootSignatureDesc = new RootSignatureDescription1
|
||||
var rootSignatureDesc = new D3D12_ROOT_SIGNATURE_DESC1
|
||||
{
|
||||
NumParameters = rootParamCount,
|
||||
pParameters = rootParameters,
|
||||
NumStaticSamplers = 0,
|
||||
pStaticSamplers = null,
|
||||
Flags = RootSignatureFlags.AllowInputAssemblerInputLayout
|
||||
#if !USE_TRANDITIONAL_BINDLESS
|
||||
| RootSignatureFlags.CbvSrvUavHeapDirectlyIndexed
|
||||
| RootSignatureFlags.SamplerHeapDirectlyIndexed
|
||||
Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT
|
||||
#if !USE_TRADITIONAL_BINDLESS
|
||||
| D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED
|
||||
| D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED
|
||||
#endif
|
||||
};
|
||||
|
||||
var versionedDesc = new VersionedRootSignatureDescription
|
||||
|
||||
var versionedDesc = new D3D12_VERSIONED_ROOT_SIGNATURE_DESC
|
||||
{
|
||||
Version = RootSignatureVersion.V1_1,
|
||||
Version = D3D_ROOT_SIGNATURE_VERSION_1_1,
|
||||
Desc_1_1 = rootSignatureDesc
|
||||
};
|
||||
|
||||
@@ -218,7 +173,7 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
using ComPtr<ID3DBlob> error = default;
|
||||
|
||||
var serializeResult = D3D12SerializeVersionedRootSignature(&versionedDesc, signature.GetAddressOf(), error.GetAddressOf());
|
||||
if (serializeResult.Failure)
|
||||
if (serializeResult.FAILED)
|
||||
{
|
||||
var errorMsg = error.Get() != null ? Marshal.PtrToStringAnsi((nint)error.Get()->GetBufferPointer()) : "Unknown error";
|
||||
throw new InvalidOperationException($"Failed to serialize default root signature: {errorMsg}");
|
||||
@@ -230,12 +185,12 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
|
||||
public void StorePipeline(string psoIdentifier, ID3D12PipelineState* pso)
|
||||
{
|
||||
_library.Get()->StorePipeline(psoIdentifier.AsSpan().GetPointer(), pso);
|
||||
_library.Get()->StorePipeline(psoIdentifier.AsSpan().GetUnsafePtr(), pso);
|
||||
}
|
||||
|
||||
public void* LoadGraphicsPipeline(string psoIdentifier)
|
||||
{
|
||||
if (_library.Get()->LoadGraphicsPipeline(psoIdentifier.AsSpan().GetPointer(), __uuidof<ID3D12PipelineState>(), out var pso).Failure)
|
||||
if (_library.Get()->LoadGraphicsPipeline(psoIdentifier.AsSpan().GetUnsafePtr(), __uuidof<ID3D12PipelineState>(), out var pso).Failure)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -266,20 +221,20 @@ internal unsafe class D3D12PipelineLibrary : IPipelineLibrary, IDisposable
|
||||
// Create PSO from SDL (Shader Definition Language) file
|
||||
private void CreatePipelineStateObject(D3D12ShaderPipeline shaderPipeline)
|
||||
{
|
||||
var psoDesc = new GraphicsPipelineStateDescription
|
||||
var psoDesc = new D3D12_GRAPHICS_PIPELINE_STATE_DESC
|
||||
{
|
||||
pRootSignature = _defaultRootSignature.Get(),
|
||||
VS = new ShaderBytecode(shaderPipeline.vsResult.bytecode.GetUnsafePtr(), (nuint)shaderPipeline.vsResult.bytecode.Count),
|
||||
PS = new ShaderBytecode(shaderPipeline.psResult.bytecode.GetUnsafePtr(), (nuint)shaderPipeline.vsResult.bytecode.Count),
|
||||
VS = new D3D12_SHADER_BYTECODE(shaderPipeline.vsResult.bytecode.GetUnsafePtr(), (nuint)shaderPipeline.vsResult.bytecode.Count),
|
||||
PS = new D3D12_SHADER_BYTECODE(shaderPipeline.psResult.bytecode.GetUnsafePtr(), (nuint)shaderPipeline.psResult.bytecode.Count),
|
||||
InputLayout = D3D12PipelineResource.InputLayoutDescription,
|
||||
RasterizerState = RasterizerDescription.CullNone,
|
||||
BlendState = BlendDescription.Opaque,
|
||||
DepthStencilState = DepthStencilDescription.Default,
|
||||
RasterizerState = D3D12_RASTERIZER_DESC.CULL_NONE,
|
||||
BlendState = D3D12_BLEND_DESC.OPAQUE,
|
||||
DepthStencilState = D3D12_DEPTH_STENCIL_DESC.DEFAULT,
|
||||
SampleMask = uint.MaxValue,
|
||||
PrimitiveTopologyType = PrimitiveTopologyType.Triangle,
|
||||
PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE,
|
||||
NumRenderTargets = 1,
|
||||
SampleDesc = new SampleDescription(1, 0),
|
||||
DSVFormat = Format.Unknown,
|
||||
SampleDesc = new DXGI_SAMPLE_DESC(1, 0),
|
||||
DSVFormat = DXGI_FORMAT_UNKNOWN,
|
||||
};
|
||||
|
||||
psoDesc.RTVFormats[0] = D3D12PipelineResource.SWAP_CHAIN_BACK_BUFFER_FORMAT;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.RHI;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
using Win32;
|
||||
using Win32.Graphics.Direct3D;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using Win32.Graphics.Dxgi;
|
||||
using static TerraFX.Aliases.D3D_Alias;
|
||||
using static TerraFX.Aliases.DXGI_Alias;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -48,27 +47,27 @@ internal unsafe class D3D12RenderDevice : IRenderDevice
|
||||
private void InitializeDevice()
|
||||
{
|
||||
#if DEBUG
|
||||
CreateDXGIFactory2(true, __uuidof<IDXGIFactory7>(), _dxgiFactory.GetVoidAddressOf());
|
||||
CreateDXGIFactory2(TRUE, __uuidof<IDXGIFactory7>(), _dxgiFactory.GetVoidAddressOf());
|
||||
#else
|
||||
CreateDXGIFactory2(false, __uuidof<IDXGIFactory7>(), _dxgiFactory.GetVoidAddressOf());
|
||||
CreateDXGIFactory2(FALSE, __uuidof<IDXGIFactory7>(), _dxgiFactory.GetVoidAddressOf());
|
||||
#endif
|
||||
|
||||
using ComPtr<IDXGIAdapter1> adapter = default;
|
||||
|
||||
for (uint adapterIndex = 0;
|
||||
_dxgiFactory.Get()->EnumAdapterByGpuPreference(adapterIndex, GpuPreference.HighPerformance, __uuidof<IDXGIAdapter1>(), adapter.ReleaseAndGetVoidAddressOf()).Success;
|
||||
_dxgiFactory.Get()->EnumAdapterByGpuPreference(adapterIndex, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, __uuidof<IDXGIAdapter1>(), adapter.ReleaseAndGetVoidAddressOf()).SUCCEEDED;
|
||||
adapterIndex++)
|
||||
{
|
||||
AdapterDescription1 desc = default;
|
||||
DXGI_ADAPTER_DESC1 desc = default;
|
||||
adapter.Get()->GetDesc1(&desc);
|
||||
|
||||
// Don't select the Basic Render Driver adapter.
|
||||
if ((desc.Flags & AdapterFlags.Software) != AdapterFlags.None)
|
||||
if (desc.Flags.HasFlag(DXGI_ADAPTER_FLAG_SOFTWARE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (D3D12CreateDevice((IUnknown*)adapter.Get(), FeatureLevel.Level_12_0, __uuidof<ID3D12Device14>(), _device.GetVoidAddressOf()).Success)
|
||||
if (D3D12CreateDevice((IUnknown*)adapter.Get(), D3D_FEATURE_LEVEL_12_0, __uuidof<ID3D12Device14>(), _device.GetVoidAddressOf()).SUCCEEDED)
|
||||
{
|
||||
_adapter = adapter.Move();
|
||||
break;
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Core.Graphics;
|
||||
using Ghost.Graphics.Data;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Win32.Graphics.D3D12MemoryAllocator;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using Win32.Graphics.Dxgi;
|
||||
using Win32.Graphics.Dxgi.Common;
|
||||
using static Win32.Graphics.D3D12MemoryAllocator.Apis;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
using static TerraFX.Aliases.D3D12_Alias;
|
||||
using static TerraFX.Aliases.D3D12MA_Alias;
|
||||
using static TerraFX.Aliases.DXGI_Alias;
|
||||
using static TerraFX.Interop.DirectX.D3D12MemAlloc;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -17,9 +19,9 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
private const uint _MAX_TEXTURE2D_DIMENSION = 16384u;
|
||||
private const uint _MAX_TEXTURE3D_DIMENSION = 2048u;
|
||||
|
||||
private readonly ID3D12Device14* _device;
|
||||
private ComPtr<D3D12MA_Allocator> _allocator;
|
||||
|
||||
private readonly Allocator _allocator;
|
||||
private readonly D3D12RenderDevice _device;
|
||||
private readonly RenderSystem _renderSystem;
|
||||
private readonly D3D12DescriptorAllocator _descriptorAllocator;
|
||||
private readonly D3D12ResourceDatabase _resourceDatabase;
|
||||
@@ -39,16 +41,16 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
|
||||
public D3D12ResourceAllocator(RenderSystem renderSystem, D3D12RenderDevice device, D3D12DescriptorAllocator descriptorAllocator, D3D12ResourceDatabase resourceDatabase)
|
||||
{
|
||||
var desc = new AllocatorDesc
|
||||
var desc = new D3D12MA_ALLOCATOR_DESC
|
||||
{
|
||||
pAdapter = (IDXGIAdapter*)device.Adapter,
|
||||
pDevice = (ID3D12Device*)device.NativeDevice,
|
||||
Flags = AllocatorFlags.DefaultPoolsNotZeroed | AllocatorFlags.MSAATexturesAlwaysCommitted
|
||||
Flags = D3D12MA_ALLOCATOR_FLAG_DEFAULT_POOLS_NOT_ZEROED | D3D12MA_ALLOCATOR_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED,
|
||||
};
|
||||
|
||||
CreateAllocator(in desc, out _allocator);
|
||||
D3D12MA_CreateAllocator(&desc, _allocator.GetAddressOf());
|
||||
|
||||
_device = device.NativeDevice;
|
||||
_device = device;
|
||||
_renderSystem = renderSystem;
|
||||
_descriptorAllocator = descriptorAllocator;
|
||||
_resourceDatabase = resourceDatabase;
|
||||
@@ -78,9 +80,9 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private Handle<GPUResource> TrackResource(ref readonly Allocation allocation, ResourceStates state, D3D12ResourceDescriptor resourceDescriptor, ResourceDesc desc, bool isTemp)
|
||||
private Handle<GPUResource> TrackResource(ComPtr<D3D12MA_Allocation> allocation, D3D12_RESOURCE_STATES state, ResourceViewGroup resourceDescriptor, ResourceDesc desc, bool isTemp)
|
||||
{
|
||||
var handle = _resourceDatabase.AddResource(in allocation, _renderSystem.CPUFenceValue, D3D12StatesToRHIState(state), resourceDescriptor, desc);
|
||||
var handle = _resourceDatabase.AddResource(allocation, _renderSystem.CPUFenceValue, D3D12StatesToRHIState(state), resourceDescriptor, desc);
|
||||
|
||||
if (isTemp)
|
||||
{
|
||||
@@ -90,58 +92,266 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
return handle;
|
||||
}
|
||||
|
||||
private void CreateSRV(ID3D12Resource* pResource, CpuDescriptorHandle descriptorHandle, Format format, TextureDimension dimension, uint mipLevels, uint arraySize)
|
||||
private D3D12_SHADER_RESOURCE_VIEW_DESC CreateSrvDesc(ID3D12Resource* pResource, bool isCubeMap, uint mipLevels, uint arraySize)
|
||||
{
|
||||
var srvDesc = new ShaderResourceViewDescription
|
||||
var resourceDesc = pResource->GetDesc();
|
||||
var srvDesc = new D3D12_SHADER_RESOURCE_VIEW_DESC
|
||||
{
|
||||
Format = format,
|
||||
Format = resourceDesc.Format,
|
||||
Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING
|
||||
};
|
||||
|
||||
switch (dimension)
|
||||
switch (resourceDesc.Dimension)
|
||||
{
|
||||
case TextureDimension.Texture2D:
|
||||
srvDesc.ViewDimension = SrvDimension.Texture2D;
|
||||
srvDesc.Texture2D = new Texture2DSrv
|
||||
case D3D12_RESOURCE_DIMENSION_BUFFER:
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
|
||||
srvDesc.Buffer = new D3D12_BUFFER_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
FirstElement = 0,
|
||||
NumElements = (uint)(resourceDesc.Width / 4),
|
||||
StructureByteStride = 0,
|
||||
Flags = D3D12_BUFFER_SRV_FLAG_RAW,
|
||||
};
|
||||
break;
|
||||
case TextureDimension.Texture3D:
|
||||
srvDesc.ViewDimension = SrvDimension.Texture3D;
|
||||
srvDesc.Texture3D = new Texture3DSrv
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
||||
if (resourceDesc.DepthOrArraySize > 1)
|
||||
{
|
||||
MipLevels = 0,
|
||||
};
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY;
|
||||
srvDesc.Texture1DArray = new D3D12_TEX1D_ARRAY_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
ArraySize = arraySize,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
|
||||
srvDesc.Texture1D = new D3D12_TEX1D_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
};
|
||||
}
|
||||
break;
|
||||
case TextureDimension.Texture2DArray:
|
||||
srvDesc.ViewDimension = SrvDimension.Texture2DArray;
|
||||
srvDesc.Texture2DArray = new Texture2DArraySrv
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
||||
if (resourceDesc.DepthOrArraySize > 1)
|
||||
{
|
||||
if (isCubeMap)
|
||||
{
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
|
||||
srvDesc.TextureCubeArray = new D3D12_TEXCUBE_ARRAY_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
NumCubes = arraySize / 6,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
srvDesc.ViewDimension = resourceDesc.SampleDesc.Count > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY : D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
|
||||
srvDesc.Texture2DArray = new D3D12_TEX2D_ARRAY_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
ArraySize = arraySize,
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isCubeMap)
|
||||
{
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
|
||||
srvDesc.TextureCube = new D3D12_TEXCUBE_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
srvDesc.ViewDimension = resourceDesc.SampleDesc.Count > 1 ? D3D12_SRV_DIMENSION_TEXTURE2DMS : D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D = new D3D12_TEX2D_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
};
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
||||
srvDesc.Texture3D = new D3D12_TEX3D_SRV
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
ArraySize = arraySize,
|
||||
};
|
||||
break;
|
||||
case TextureDimension.TextureCube:
|
||||
srvDesc.ViewDimension = SrvDimension.TextureCube;
|
||||
srvDesc.TextureCube = new TexureCubeSrv
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
};
|
||||
break;
|
||||
case TextureDimension.TextureCubeArray:
|
||||
srvDesc.ViewDimension = SrvDimension.TextureCubeArray;
|
||||
srvDesc.TextureCubeArray = new TexureCubeArraySrv
|
||||
{
|
||||
MipLevels = mipLevels,
|
||||
NumCubes = arraySize / 6,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported texture dimension for SRV: {dimension}");
|
||||
throw new ArgumentException($"Unsupported texture dimension for SRV: {resourceDesc.Dimension}");
|
||||
}
|
||||
|
||||
_device->CreateShaderResourceView(pResource, &srvDesc, descriptorHandle);
|
||||
return srvDesc;
|
||||
}
|
||||
|
||||
private D3D12_RENDER_TARGET_VIEW_DESC CreateRtvDesc(ID3D12Resource* pResource, uint mipSlice = 0, uint firstArraySlice = 0, uint planeSlice = 0)
|
||||
{
|
||||
var resourceDesc = pResource->GetDesc();
|
||||
var rtvDesc = new D3D12_RENDER_TARGET_VIEW_DESC();
|
||||
|
||||
switch (resourceDesc.Dimension)
|
||||
{
|
||||
case D3D12_RESOURCE_DIMENSION_BUFFER:
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_BUFFER;
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
||||
rtvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_RTV_DIMENSION_TEXTURE1DARRAY : D3D12_RTV_DIMENSION_TEXTURE1D;
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
||||
if (resourceDesc.SampleDesc.Count > 1)
|
||||
{
|
||||
rtvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY : D3D12_RTV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_RTV_DIMENSION_TEXTURE2DARRAY : D3D12_RTV_DIMENSION_TEXTURE2D;
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
||||
rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported texture dimension for SRV: {resourceDesc.Dimension}");
|
||||
}
|
||||
|
||||
rtvDesc.Format = resourceDesc.Format;
|
||||
|
||||
var isArray =
|
||||
rtvDesc.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2DARRAY ||
|
||||
rtvDesc.ViewDimension == D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
|
||||
var arraySize = 1u;
|
||||
if (isArray)
|
||||
{
|
||||
arraySize = resourceDesc.ArraySize() - firstArraySlice;
|
||||
}
|
||||
|
||||
switch (rtvDesc.ViewDimension)
|
||||
{
|
||||
case D3D12_RTV_DIMENSION_BUFFER:
|
||||
rtvDesc.Buffer.FirstElement = firstArraySlice;
|
||||
rtvDesc.Buffer.NumElements = arraySize;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE1D:
|
||||
rtvDesc.Texture1D.MipSlice = mipSlice;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE1DARRAY:
|
||||
rtvDesc.Texture1DArray.MipSlice = mipSlice;
|
||||
rtvDesc.Texture1DArray.FirstArraySlice = firstArraySlice;
|
||||
rtvDesc.Texture1DArray.ArraySize = arraySize;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE2D:
|
||||
rtvDesc.Texture2D.MipSlice = mipSlice;
|
||||
rtvDesc.Texture2D.PlaneSlice = planeSlice;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE2DARRAY:
|
||||
rtvDesc.Texture2DArray.MipSlice = mipSlice;
|
||||
rtvDesc.Texture2DArray.FirstArraySlice = firstArraySlice;
|
||||
rtvDesc.Texture2DArray.ArraySize = arraySize;
|
||||
rtvDesc.Texture2DArray.PlaneSlice = planeSlice;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE2DMS:
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY:
|
||||
rtvDesc.Texture2DMSArray.FirstArraySlice = firstArraySlice;
|
||||
rtvDesc.Texture2DMSArray.ArraySize = arraySize;
|
||||
break;
|
||||
|
||||
case D3D12_RTV_DIMENSION_TEXTURE3D:
|
||||
rtvDesc.Texture3D.MipSlice = mipSlice;
|
||||
rtvDesc.Texture3D.FirstWSlice = firstArraySlice;
|
||||
rtvDesc.Texture3D.WSize = arraySize;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported RTV dimension: {rtvDesc.ViewDimension}");
|
||||
}
|
||||
|
||||
return rtvDesc;
|
||||
}
|
||||
|
||||
private D3D12_DEPTH_STENCIL_VIEW_DESC CreateDsvDesc(ID3D12Resource* pResource, uint mipSlice = 0, uint firstArraySlice = 0, D3D12_DSV_FLAGS flags = D3D12_DSV_FLAG_NONE)
|
||||
{
|
||||
var resourceDesc = pResource->GetDesc();
|
||||
var dsvDesc = new D3D12_DEPTH_STENCIL_VIEW_DESC
|
||||
{
|
||||
Flags = flags,
|
||||
};
|
||||
|
||||
switch (resourceDesc.Dimension)
|
||||
{
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
||||
dsvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_DSV_DIMENSION_TEXTURE1DARRAY : D3D12_DSV_DIMENSION_TEXTURE1D;
|
||||
break;
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
||||
if (resourceDesc.SampleDesc.Count > 1)
|
||||
{
|
||||
dsvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY : D3D12_DSV_DIMENSION_TEXTURE2DMS;
|
||||
}
|
||||
else
|
||||
{
|
||||
dsvDesc.ViewDimension = resourceDesc.DepthOrArraySize > 1 ? D3D12_DSV_DIMENSION_TEXTURE2DARRAY : D3D12_DSV_DIMENSION_TEXTURE2D;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dsvDesc.Format = resourceDesc.Format;
|
||||
|
||||
var isArray =
|
||||
dsvDesc.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DARRAY ||
|
||||
dsvDesc.ViewDimension == D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY;
|
||||
|
||||
var arraySize = 1u;
|
||||
if (isArray)
|
||||
{
|
||||
arraySize = resourceDesc.ArraySize() - firstArraySlice;
|
||||
}
|
||||
|
||||
switch (dsvDesc.ViewDimension)
|
||||
{
|
||||
case D3D12_DSV_DIMENSION_TEXTURE1D:
|
||||
dsvDesc.Texture1D.MipSlice = mipSlice;
|
||||
break;
|
||||
case D3D12_DSV_DIMENSION_TEXTURE1DARRAY:
|
||||
dsvDesc.Texture1DArray.MipSlice = mipSlice;
|
||||
dsvDesc.Texture1DArray.FirstArraySlice = firstArraySlice;
|
||||
dsvDesc.Texture1DArray.ArraySize = arraySize;
|
||||
break;
|
||||
case D3D12_DSV_DIMENSION_TEXTURE2D:
|
||||
dsvDesc.Texture2D.MipSlice = mipSlice;
|
||||
break;
|
||||
case D3D12_DSV_DIMENSION_TEXTURE2DARRAY:
|
||||
dsvDesc.Texture2DArray.MipSlice = mipSlice;
|
||||
dsvDesc.Texture2DArray.FirstArraySlice = firstArraySlice;
|
||||
dsvDesc.Texture2DArray.ArraySize = arraySize;
|
||||
break;
|
||||
case D3D12_DSV_DIMENSION_TEXTURE2DMS:
|
||||
break;
|
||||
case D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY:
|
||||
dsvDesc.Texture2DMSArray.FirstArraySlice = firstArraySlice;
|
||||
dsvDesc.Texture2DMSArray.ArraySize = arraySize;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return dsvDesc;
|
||||
}
|
||||
|
||||
public Handle<Texture> CreateTexture(ref readonly TextureDesc desc, bool isTemp = false)
|
||||
@@ -154,33 +364,33 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
var resourceFlags = ConvertTextureUsage(desc.Usage);
|
||||
var resourceDesc = desc.Dimension switch
|
||||
{
|
||||
TextureDimension.Texture2D => ResourceDescription.Tex2D(
|
||||
TextureDimension.Texture2D => D3D12_RESOURCE_DESC.Tex2D(
|
||||
d3d12Format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
mipLevels: mipLevels,
|
||||
flags: resourceFlags),
|
||||
TextureDimension.Texture3D => ResourceDescription.Tex3D(
|
||||
TextureDimension.Texture3D => D3D12_RESOURCE_DESC.Tex3D(
|
||||
d3d12Format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
(ushort)desc.Slice,
|
||||
flags: resourceFlags),
|
||||
TextureDimension.TextureCube => ResourceDescription.Tex2D(
|
||||
TextureDimension.TextureCube => D3D12_RESOURCE_DESC.Tex2D(
|
||||
d3d12Format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
mipLevels: mipLevels,
|
||||
arraySize: 6,
|
||||
flags: resourceFlags),
|
||||
TextureDimension.Texture2DArray => ResourceDescription.Tex2D(
|
||||
TextureDimension.Texture2DArray => D3D12_RESOURCE_DESC.Tex2D(
|
||||
d3d12Format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
mipLevels: mipLevels,
|
||||
arraySize: (ushort)desc.Slice,
|
||||
flags: resourceFlags),
|
||||
TextureDimension.TextureCubeArray => ResourceDescription.Tex2D(
|
||||
TextureDimension.TextureCubeArray => D3D12_RESOURCE_DESC.Tex2D(
|
||||
d3d12Format,
|
||||
desc.Width,
|
||||
desc.Height,
|
||||
@@ -190,57 +400,64 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
_ => throw new ArgumentException($"Unsupported texture dimension: {desc.Dimension}"),
|
||||
};
|
||||
|
||||
var allocationDesc = new AllocationDesc
|
||||
var allocationDesc = new D3D12MA_ALLOCATION_DESC
|
||||
{
|
||||
HeapType = HeapType.Default,
|
||||
Flags = AllocationFlags.None
|
||||
HeapType = D3D12_HEAP_TYPE_DEFAULT,
|
||||
Flags = D3D12MA_ALLOCATION_FLAG_NONE
|
||||
};
|
||||
|
||||
var initialState = DetermineInitialTextureState(desc.Usage);
|
||||
|
||||
Allocation allocation = default;
|
||||
ThrowIfFailed(_allocator.CreateResource(&allocationDesc, in resourceDesc, initialState, null, &allocation, IID_NULL, null));
|
||||
ComPtr<D3D12MA_Allocation> allocation = default;
|
||||
ThrowIfFailed(_allocator.Get()->CreateResource(&allocationDesc, &resourceDesc, initialState, null, allocation.GetAddressOf(), IID_NULL, null));
|
||||
|
||||
var resourceDescriptor = D3D12ResourceDescriptor.Invalid;
|
||||
var resourceDescriptor = ResourceViewGroup.Invalid;
|
||||
if (desc.Usage.HasFlag(TextureUsage.ShaderResource))
|
||||
{
|
||||
resourceDescriptor.srv = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv);
|
||||
|
||||
CreateSRV(allocation.Resource, cpuHandle, d3d12Format, desc.Dimension, mipLevels, desc.Slice);
|
||||
var isCubeMap = desc.Dimension == TextureDimension.TextureCube || desc.Dimension == TextureDimension.TextureCubeArray;
|
||||
var srvDesc = CreateSrvDesc(allocation.Get()->GetResource(), isCubeMap, mipLevels, desc.Slice);
|
||||
|
||||
_device.NativeDevice->CreateShaderResourceView(allocation.Get()->GetResource(), &srvDesc, cpuHandle);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(TextureUsage.RenderTarget))
|
||||
{
|
||||
resourceDescriptor.rtv = _descriptorAllocator.AllocateRTV(isTemp);
|
||||
var rtvDesc = new RenderTargetViewDescription(allocation.Resource);
|
||||
_device->CreateRenderTargetView(allocation.Resource, &rtvDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.rtv));
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.rtv);
|
||||
var rtvDesc = CreateRtvDesc(allocation.Get()->GetResource());
|
||||
|
||||
_device.NativeDevice->CreateRenderTargetView(allocation.Get()->GetResource(), &rtvDesc, cpuHandle);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(TextureUsage.DepthStencil))
|
||||
{
|
||||
resourceDescriptor.dsv = _descriptorAllocator.AllocateDSV(isTemp);
|
||||
var dsvDesc = new DepthStencilViewDescription(allocation.Resource);
|
||||
_device->CreateDepthStencilView(allocation.Resource, &dsvDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.dsv));
|
||||
var cpuHandle = _descriptorAllocator.GetCpuHandle(resourceDescriptor.dsv);
|
||||
var dsvDesc = CreateDsvDesc(allocation.Get()->GetResource());
|
||||
|
||||
_device.NativeDevice->CreateDepthStencilView(allocation.Get()->GetResource(), &dsvDesc, cpuHandle);
|
||||
}
|
||||
|
||||
if (desc.Usage.HasFlag(TextureUsage.UnorderedAccess))
|
||||
{
|
||||
resourceDescriptor.uav = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
var uavDesc = new UnorderedAccessViewDescription
|
||||
var uavDesc = new D3D12_UNORDERED_ACCESS_VIEW_DESC
|
||||
{
|
||||
ViewDimension = UavDimension.Texture2D,
|
||||
ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D,
|
||||
Format = d3d12Format,
|
||||
Texture2D = new Texture2DUav
|
||||
Texture2D = new D3D12_TEX2D_UAV
|
||||
{
|
||||
MipSlice = 0,
|
||||
PlaneSlice = 0,
|
||||
}
|
||||
};
|
||||
_device->CreateUnorderedAccessView(allocation.Resource, null, &uavDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.uav));
|
||||
_device.NativeDevice->CreateUnorderedAccessView(allocation.Get()->GetResource(), null, &uavDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.uav));
|
||||
}
|
||||
|
||||
var handle = TrackResource(ref allocation, initialState, resourceDescriptor, ResourceDesc.Texture(desc), isTemp);
|
||||
var handle = TrackResource(allocation, initialState, resourceDescriptor, ResourceDesc.Texture(desc), isTemp);
|
||||
|
||||
return handle.AsTexture();
|
||||
}
|
||||
@@ -253,56 +470,56 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
|
||||
public Handle<GraphicsBuffer> CreateBuffer(ref readonly BufferDesc desc, bool isTemp = false)
|
||||
{
|
||||
CheckBufferSize((uint)desc.Size);
|
||||
CheckBufferSize(desc.Size);
|
||||
|
||||
var resourceDescription = ResourceDescription.Buffer(desc.Size, ConvertBufferUsage(desc.Usage));
|
||||
var allocationDesc = new AllocationDesc
|
||||
var resourceDescription = D3D12_RESOURCE_DESC.Buffer(desc.Size, ConvertBufferUsage(desc.Usage));
|
||||
var allocationDesc = new D3D12MA_ALLOCATION_DESC
|
||||
{
|
||||
HeapType = ConvertMemoryType(desc.MemoryType),
|
||||
Flags = AllocationFlags.None
|
||||
Flags = D3D12MA_ALLOCATION_FLAG_NONE
|
||||
};
|
||||
|
||||
var initialState = DetermineInitialBufferState(desc.Usage, desc.MemoryType);
|
||||
|
||||
Allocation allocation = default;
|
||||
ThrowIfFailed(_allocator.CreateResource(&allocationDesc, in resourceDescription, initialState, null, &allocation, IID_NULL, null));
|
||||
ComPtr<D3D12MA_Allocation> allocation = default;
|
||||
ThrowIfFailed(_allocator.Get()->CreateResource(&allocationDesc, &resourceDescription, initialState, null, allocation.GetAddressOf(), IID_NULL, null));
|
||||
|
||||
var resourceDescriptor = D3D12ResourceDescriptor.Invalid;
|
||||
if (desc.Usage.HasFlag(BufferUsage.ShaderResource) && desc.CreationFlags.HasFlag(BufferCreationFlags.Bindless))
|
||||
var resourceDescriptor = ResourceViewGroup.Invalid;
|
||||
if (desc.Usage.HasFlag(BufferUsage.ShaderResource))
|
||||
{
|
||||
resourceDescriptor.srv = _descriptorAllocator.AllocateCbvSrvUav(isTemp);
|
||||
|
||||
var srvDesc = new ShaderResourceViewDescription
|
||||
var srvDesc = new D3D12_SHADER_RESOURCE_VIEW_DESC
|
||||
{
|
||||
ViewDimension = SrvDimension.Buffer,
|
||||
ViewDimension = D3D12_SRV_DIMENSION_BUFFER,
|
||||
Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING
|
||||
};
|
||||
|
||||
if (desc.Usage.HasFlag(BufferUsage.Raw))
|
||||
{
|
||||
srvDesc.Format = Format.R32Typeless;
|
||||
srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
|
||||
srvDesc.Buffer.FirstElement = 0;
|
||||
srvDesc.Buffer.NumElements = (uint)(desc.Size / 4);
|
||||
srvDesc.Buffer.NumElements = desc.Size / 4;
|
||||
srvDesc.Buffer.StructureByteStride = 0;
|
||||
srvDesc.Buffer.Flags = BufferSrvFlags.Raw;
|
||||
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
|
||||
}
|
||||
else
|
||||
{
|
||||
srvDesc.Format = Format.Unknown;
|
||||
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
srvDesc.Buffer.FirstElement = 0;
|
||||
srvDesc.Buffer.NumElements = (uint)(desc.Size / desc.Stride);
|
||||
srvDesc.Buffer.NumElements = desc.Size / desc.Stride;
|
||||
srvDesc.Buffer.StructureByteStride = desc.Stride;
|
||||
srvDesc.Buffer.Flags = BufferSrvFlags.None;
|
||||
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
|
||||
}
|
||||
|
||||
_device->CreateShaderResourceView(allocation.Resource, &srvDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv));
|
||||
_device.NativeDevice->CreateShaderResourceView(allocation.Get()->GetResource(), &srvDesc, _descriptorAllocator.GetCpuHandle(resourceDescriptor.srv));
|
||||
}
|
||||
|
||||
var handle = TrackResource(ref allocation, initialState, resourceDescriptor, ResourceDesc.Buffer(desc), isTemp);
|
||||
var handle = TrackResource(allocation, initialState, resourceDescriptor, ResourceDesc.Buffer(desc), isTemp);
|
||||
return handle.AsGraphicsBuffer();
|
||||
}
|
||||
|
||||
public Handle<GraphicsBuffer> CreateUploadBuffer(ulong size, bool isTemp = true)
|
||||
public Handle<GraphicsBuffer> CreateUploadBuffer(uint size, bool isTemp = true)
|
||||
{
|
||||
var desc = new BufferDesc
|
||||
{
|
||||
@@ -318,20 +535,18 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
{
|
||||
var vertexBufferDesc = new BufferDesc
|
||||
{
|
||||
Size = (ulong)(vertices.Count * Unsafe.SizeOf<Vertex>()),
|
||||
Size = (uint)(vertices.Count * Unsafe.SizeOf<Vertex>()),
|
||||
Stride = (uint)Unsafe.SizeOf<Vertex>(),
|
||||
Usage = BufferUsage.Vertex | BufferUsage.ShaderResource,
|
||||
MemoryType = MemoryType.Default,
|
||||
CreationFlags = BufferCreationFlags.Bindless
|
||||
};
|
||||
|
||||
var indexBufferDesc = new BufferDesc
|
||||
{
|
||||
Size = (ulong)(indices.Count * sizeof(uint)),
|
||||
Size = (uint)(indices.Count * sizeof(uint)),
|
||||
Stride = sizeof(uint),
|
||||
Usage = BufferUsage.Index | BufferUsage.ShaderResource,
|
||||
MemoryType = MemoryType.Default,
|
||||
CreationFlags = BufferCreationFlags.Bindless
|
||||
};
|
||||
|
||||
var vertexBuffer = CreateBuffer(ref vertexBufferDesc);
|
||||
@@ -357,30 +572,20 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
|
||||
ref var shaderRef = ref _resourceDatabase.GetShaderReference(shader);
|
||||
|
||||
if (shaderRef.ConstantBuffers.Count > 0)
|
||||
var desc = new BufferDesc
|
||||
{
|
||||
var maxSlot = shaderRef.ConstantBuffers.Max(cb => cb.RegisterSlot);
|
||||
materialData._cBufferCaches = new UnsafeArray<CBufferCache>((int)maxSlot + 1, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
||||
Size = shaderRef.PerMaterialBufferInfo.Size,
|
||||
Usage = BufferUsage.Constant,
|
||||
MemoryType = MemoryType.Default,
|
||||
};
|
||||
|
||||
foreach (var cbufferInfo in shaderRef.ConstantBuffers)
|
||||
{
|
||||
var desc = new BufferDesc
|
||||
{
|
||||
Size = cbufferInfo.Size,
|
||||
Usage = BufferUsage.Constant,
|
||||
MemoryType = MemoryType.Default,
|
||||
};
|
||||
|
||||
var buffer = CreateBuffer(ref desc);
|
||||
|
||||
materialData._cBufferCaches[cbufferInfo.RegisterSlot] = new CBufferCache(buffer, cbufferInfo.Size);
|
||||
}
|
||||
}
|
||||
var buffer = CreateBuffer(ref desc);
|
||||
materialData._materialPropertiesCache = new CBufferCache(buffer, shaderRef.PerMaterialBufferInfo.Size);
|
||||
|
||||
return _resourceDatabase.AddMaterial(ref materialData);
|
||||
}
|
||||
|
||||
public Identifier<Shader> CreateShader()
|
||||
public Identifier<Shader> CreateShader(ShaderDescriptor descriptor)
|
||||
{
|
||||
var shaderData = new Shader();
|
||||
return _resourceDatabase.AddShader(ref shaderData);
|
||||
@@ -388,149 +593,136 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
|
||||
#region Conversion Methods
|
||||
|
||||
private static Format ConvertTextureFormat(TextureFormat format)
|
||||
private static DXGI_FORMAT ConvertTextureFormat(TextureFormat format)
|
||||
{
|
||||
return format switch
|
||||
{
|
||||
TextureFormat.R8G8B8A8_UNorm => Format.R8G8B8A8Unorm,
|
||||
TextureFormat.B8G8R8A8_UNorm => Format.B8G8R8A8Unorm,
|
||||
TextureFormat.R16G16B16A16_Float => Format.R16G16B16A16Float,
|
||||
TextureFormat.R32G32B32A32_Float => Format.R32G32B32A32Float,
|
||||
TextureFormat.D24_UNorm_S8_UInt => Format.D24UnormS8Uint,
|
||||
TextureFormat.D32_Float => Format.D32Float,
|
||||
TextureFormat.R8G8B8A8_UNorm => DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
TextureFormat.B8G8R8A8_UNorm => DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
TextureFormat.R16G16B16A16_Float => DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
TextureFormat.R32G32B32A32_Float => DXGI_FORMAT_R32G32B32A32_FLOAT,
|
||||
TextureFormat.D24_UNorm_S8_UInt => DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
TextureFormat.D32_Float => DXGI_FORMAT_D32_FLOAT,
|
||||
_ => throw new ArgumentException($"Unsupported texture format: {format}")
|
||||
};
|
||||
}
|
||||
|
||||
private static ResourceFlags ConvertTextureUsage(TextureUsage usage)
|
||||
private static D3D12_RESOURCE_FLAGS ConvertTextureUsage(TextureUsage usage)
|
||||
{
|
||||
var flags = ResourceFlags.None;
|
||||
var flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
if (usage.HasFlag(TextureUsage.RenderTarget))
|
||||
{
|
||||
flags |= ResourceFlags.AllowRenderTarget;
|
||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(TextureUsage.DepthStencil))
|
||||
{
|
||||
flags |= ResourceFlags.AllowDepthStencil;
|
||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(TextureUsage.UnorderedAccess))
|
||||
{
|
||||
flags |= ResourceFlags.AllowUnorderedAccess;
|
||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
private static ResourceFlags ConvertBufferUsage(BufferUsage usage)
|
||||
private static D3D12_RESOURCE_FLAGS ConvertBufferUsage(BufferUsage usage)
|
||||
{
|
||||
var flags = ResourceFlags.None;
|
||||
var flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
if (usage.HasFlag(BufferUsage.Raw))
|
||||
{
|
||||
flags |= ResourceFlags.AllowUnorderedAccess;
|
||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
private static HeapType ConvertMemoryType(MemoryType memoryType)
|
||||
private static D3D12_HEAP_TYPE ConvertMemoryType(MemoryType memoryType)
|
||||
{
|
||||
return memoryType switch
|
||||
{
|
||||
MemoryType.Default => HeapType.Default,
|
||||
MemoryType.Upload => HeapType.Upload,
|
||||
MemoryType.Readback => HeapType.Readback,
|
||||
MemoryType.Default => D3D12_HEAP_TYPE_DEFAULT,
|
||||
MemoryType.Upload => D3D12_HEAP_TYPE_UPLOAD,
|
||||
MemoryType.Readback => D3D12_HEAP_TYPE_READBACK,
|
||||
_ => throw new ArgumentException($"Unsupported memory type: {memoryType}")
|
||||
};
|
||||
}
|
||||
|
||||
private static ResourceStates DetermineInitialTextureState(TextureUsage usage)
|
||||
private static D3D12_RESOURCE_STATES DetermineInitialTextureState(TextureUsage usage)
|
||||
{
|
||||
if (usage.HasFlag(TextureUsage.RenderTarget))
|
||||
{
|
||||
return ResourceStates.RenderTarget;
|
||||
return D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(TextureUsage.DepthStencil))
|
||||
{
|
||||
return ResourceStates.DepthWrite;
|
||||
return D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(TextureUsage.UnorderedAccess))
|
||||
{
|
||||
return ResourceStates.UnorderedAccess;
|
||||
return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
}
|
||||
|
||||
return ResourceStates.Common;
|
||||
return D3D12_RESOURCE_STATE_COMMON;
|
||||
}
|
||||
|
||||
private static ResourceStates DetermineInitialBufferState(BufferUsage usage, MemoryType memoryType)
|
||||
private static D3D12_RESOURCE_STATES DetermineInitialBufferState(BufferUsage usage, MemoryType memoryType)
|
||||
{
|
||||
if (memoryType == MemoryType.Upload)
|
||||
{
|
||||
return ResourceStates.GenericRead;
|
||||
return D3D12_RESOURCE_STATE_GENERIC_READ;
|
||||
}
|
||||
|
||||
if (memoryType == MemoryType.Readback)
|
||||
{
|
||||
return ResourceStates.CopyDest;
|
||||
return D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(BufferUsage.Vertex))
|
||||
{
|
||||
return ResourceStates.VertexAndConstantBuffer;
|
||||
return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(BufferUsage.Index))
|
||||
{
|
||||
return ResourceStates.IndexBuffer;
|
||||
return D3D12_RESOURCE_STATE_INDEX_BUFFER;
|
||||
}
|
||||
|
||||
if (usage.HasFlag(BufferUsage.Constant))
|
||||
{
|
||||
return ResourceStates.VertexAndConstantBuffer;
|
||||
return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
|
||||
}
|
||||
|
||||
return ResourceStates.Common;
|
||||
return D3D12_RESOURCE_STATE_COMMON;
|
||||
}
|
||||
|
||||
private static ResourceState D3D12StatesToRHIState(ResourceStates states)
|
||||
private static ResourceState D3D12StatesToRHIState(D3D12_RESOURCE_STATES states)
|
||||
{
|
||||
switch (states)
|
||||
return states switch
|
||||
{
|
||||
//case ResourceStates.None:
|
||||
//case ResourceStates.Present:
|
||||
case ResourceStates.Common:
|
||||
return ResourceState.Common;
|
||||
case ResourceStates.VertexAndConstantBuffer:
|
||||
return ResourceState.VertexAndConstantBuffer;
|
||||
case ResourceStates.IndexBuffer:
|
||||
return ResourceState.IndexBuffer;
|
||||
case ResourceStates.RenderTarget:
|
||||
return ResourceState.RenderTarget;
|
||||
case ResourceStates.UnorderedAccess:
|
||||
return ResourceState.UnorderedAccess;
|
||||
case ResourceStates.DepthWrite:
|
||||
return ResourceState.DepthWrite;
|
||||
case ResourceStates.DepthRead:
|
||||
return ResourceState.DepthRead;
|
||||
case ResourceStates.PixelShaderResource:
|
||||
return ResourceState.PixelShaderResource;
|
||||
D3D12_RESOURCE_STATE_COMMON => ResourceState.Common,
|
||||
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER => ResourceState.VertexAndConstantBuffer,
|
||||
D3D12_RESOURCE_STATE_INDEX_BUFFER => ResourceState.IndexBuffer,
|
||||
D3D12_RESOURCE_STATE_RENDER_TARGET => ResourceState.RenderTarget,
|
||||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS => ResourceState.UnorderedAccess,
|
||||
D3D12_RESOURCE_STATE_DEPTH_WRITE => ResourceState.DepthWrite,
|
||||
D3D12_RESOURCE_STATE_DEPTH_READ => ResourceState.DepthRead,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE => ResourceState.PixelShaderResource,
|
||||
//case ResourceStates.Predication:
|
||||
case ResourceStates.IndirectArgument:
|
||||
return ResourceState.IndirectArgument;
|
||||
case ResourceStates.CopyDest:
|
||||
return ResourceState.CopyDest;
|
||||
case ResourceStates.CopySource:
|
||||
return ResourceState.CopySource;
|
||||
case ResourceStates.GenericRead:
|
||||
return ResourceState.GenericRead;
|
||||
default:
|
||||
return ResourceState.Common;
|
||||
}
|
||||
D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT => ResourceState.IndirectArgument,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST => ResourceState.CopyDest,
|
||||
D3D12_RESOURCE_STATE_COPY_SOURCE => ResourceState.CopySource,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ => ResourceState.GenericRead,
|
||||
_ => ResourceState.Common,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -580,7 +772,7 @@ internal unsafe class D3D12ResourceAllocator : IResourceAllocator, IDisposable
|
||||
}
|
||||
|
||||
_temResources.Dispose();
|
||||
_allocator.Release();
|
||||
_allocator.Dispose();
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.Data;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.Collections;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System.Runtime.InteropServices;
|
||||
using Win32;
|
||||
using Win32.Graphics.D3D12MemoryAllocator;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -15,42 +15,38 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
internal unsafe struct ResourceInfo
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
private struct ResourceUnion
|
||||
public struct ResourceUnion
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public Allocation allocation;
|
||||
public ComPtr<D3D12MA_Allocation> allocation;
|
||||
[FieldOffset(0)]
|
||||
public ComPtr<ID3D12Resource> resource;
|
||||
|
||||
public ResourceUnion(Allocation allocation)
|
||||
public ResourceUnion(ComPtr<D3D12MA_Allocation> allocation)
|
||||
{
|
||||
this.allocation = allocation;
|
||||
this.resource = default;
|
||||
}
|
||||
|
||||
public ResourceUnion(ComPtr<ID3D12Resource> resource)
|
||||
{
|
||||
this.resource = resource;
|
||||
this.allocation = default;
|
||||
}
|
||||
}
|
||||
|
||||
private ResourceUnion _resourceUnion;
|
||||
private readonly bool _isExternal;
|
||||
|
||||
public D3D12ResourceDescriptor descriptor;
|
||||
|
||||
public ResourceDesc desc;
|
||||
public ResourceViewGroup descriptor;
|
||||
public ResourceUnion resourceUnion;
|
||||
public uint cpuFenceValue;
|
||||
public ResourceState state;
|
||||
public ResourceDesc desc;
|
||||
public readonly bool isExternal;
|
||||
|
||||
public readonly bool Allocated => _isExternal ? _resourceUnion.resource.Get() != null : _resourceUnion.allocation.IsNotNull;
|
||||
public readonly ID3D12Resource* ResourcePtr => _isExternal ? _resourceUnion.resource.Get() : _resourceUnion.allocation.Resource;
|
||||
public readonly bool Allocated => isExternal ? resourceUnion.resource.Get() != null : resourceUnion.allocation.Get()->IsNotNull;
|
||||
public readonly ID3D12Resource* ResourcePtr => isExternal ? resourceUnion.resource.Get() : resourceUnion.allocation.Get()->GetResource();
|
||||
|
||||
public ResourceInfo(in Allocation allocation, uint cpuFenceValue, ResourceState state, D3D12ResourceDescriptor resourceDescriptor, ResourceDesc desc)
|
||||
public ResourceInfo(ComPtr<D3D12MA_Allocation> allocation, uint cpuFenceValue, ResourceState state, ResourceViewGroup resourceDescriptor, ResourceDesc desc)
|
||||
{
|
||||
this._resourceUnion = new ResourceUnion(allocation);
|
||||
this._isExternal = false;
|
||||
this.resourceUnion = new ResourceUnion(allocation);
|
||||
this.isExternal = false;
|
||||
|
||||
this.descriptor = resourceDescriptor;
|
||||
this.cpuFenceValue = cpuFenceValue;
|
||||
@@ -60,8 +56,8 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
|
||||
public ResourceInfo(ComPtr<ID3D12Resource> resource, ResourceState state)
|
||||
{
|
||||
this._resourceUnion = new ResourceUnion(resource);
|
||||
this._isExternal = true;
|
||||
this.resourceUnion = new ResourceUnion(resource);
|
||||
this.isExternal = true;
|
||||
|
||||
this.descriptor = default;
|
||||
this.cpuFenceValue = ~0u;
|
||||
@@ -74,16 +70,16 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
var refCount = 0u;
|
||||
if (Allocated)
|
||||
{
|
||||
if (_isExternal)
|
||||
if (isExternal)
|
||||
{
|
||||
refCount = _resourceUnion.resource.Get()->Release();
|
||||
refCount = resourceUnion.resource.Get()->Release();
|
||||
}
|
||||
else
|
||||
{
|
||||
refCount = _resourceUnion.allocation.Release();
|
||||
refCount = resourceUnion.allocation.Get()->Release();
|
||||
}
|
||||
|
||||
_resourceUnion = default;
|
||||
resourceUnion = default;
|
||||
descriptor = default;
|
||||
}
|
||||
|
||||
@@ -131,7 +127,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public unsafe Handle<GPUResource> ImportExternalResource<T>(T resource, ResourceState initialState)
|
||||
public Handle<GPUResource> ImportExternalResource<T>(T resource, ResourceState initialState)
|
||||
where T : unmanaged
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
@@ -145,7 +141,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase, IDisposable
|
||||
return new Handle<GPUResource>(id, generation);
|
||||
}
|
||||
|
||||
public Handle<GPUResource> AddResource(ref readonly Allocation allocation, uint cpuFenceValue, ResourceState initialState, D3D12ResourceDescriptor resourceDescriptor, ResourceDesc desc)
|
||||
public Handle<GPUResource> AddResource(ComPtr<D3D12MA_Allocation> allocation, uint cpuFenceValue, ResourceState initialState, ResourceViewGroup resourceDescriptor, ResourceDesc desc)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#undef SUPPORT_TEXTURE_BINDING
|
||||
|
||||
using Ghost.Graphics.D3D12.Utilities;
|
||||
using Ghost.Graphics.Data;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Win32;
|
||||
using Win32.Graphics.Direct3D;
|
||||
using Win32.Graphics.Direct3D.Dxc;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -71,8 +73,11 @@ internal unsafe static class D3D12ShaderCompiler
|
||||
using ComPtr<IDxcIncludeHandler> includeHandler = default;
|
||||
|
||||
// Create DXC compiler and utils
|
||||
DxcCreateInstance(in CLSID_DxcCompiler, __uuidof<IDxcCompiler3>(), compiler.GetVoidAddressOf());
|
||||
DxcCreateInstance(in CLSID_DxcUtils, __uuidof<IDxcUtils>(), utils.GetVoidAddressOf());
|
||||
var pDxcCompiler = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcCompiler);
|
||||
var pDxcUtils = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcUtils);
|
||||
|
||||
DxcCreateInstance(pDxcCompiler, __uuidof<IDxcCompiler3>(), compiler.GetVoidAddressOf());
|
||||
DxcCreateInstance(pDxcUtils, __uuidof<IDxcUtils>(), utils.GetVoidAddressOf());
|
||||
utils.Get()->CreateDefaultIncludeHandler(includeHandler.GetAddressOf());
|
||||
|
||||
// Create source blob
|
||||
@@ -116,16 +121,16 @@ internal unsafe static class D3D12ShaderCompiler
|
||||
{
|
||||
Ptr = sourceBlob.Get()->GetBufferPointer(),
|
||||
Size = sourceBlob.Get()->GetBufferSize(),
|
||||
Encoding = DXC_CP_UTF8
|
||||
Encoding = DXC.DXC_CP_UTF8
|
||||
};
|
||||
|
||||
compiler.Get()->Compile(&buffer, (char**)argsPtr, (uint)argsArray.Length, includeHandler.Get(), __uuidof<IDxcResult>(), result.GetVoidAddressOf());
|
||||
}
|
||||
|
||||
// Check compilation result
|
||||
HResult hrStatus;
|
||||
HRESULT hrStatus;
|
||||
result.Get()->GetStatus(&hrStatus);
|
||||
if (hrStatus.Failure)
|
||||
if (hrStatus.FAILED)
|
||||
{
|
||||
// Get error messages
|
||||
using ComPtr<IDxcBlobEncoding> errorBlob = default;
|
||||
@@ -153,7 +158,7 @@ internal unsafe static class D3D12ShaderCompiler
|
||||
|
||||
// Get reflection data using DXC API
|
||||
using ComPtr<IDxcBlob> reflectionBlob = default;
|
||||
result.Get()->GetOutput(DxcOutKind.Reflection, __uuidof<IDxcBlob>(), reflectionBlob.GetVoidAddressOf(), null);
|
||||
result.Get()->GetOutput(DXC_OUT_KIND.DXC_OUT_REFLECTION, __uuidof<IDxcBlob>(), reflectionBlob.GetVoidAddressOf(), null);
|
||||
|
||||
if (reflectionBlob.Get() == null)
|
||||
{
|
||||
@@ -188,18 +193,20 @@ internal unsafe static class D3D12ShaderCompiler
|
||||
shader.PropertyNameToIdMap[name] = id;
|
||||
}
|
||||
|
||||
// TODO: Since we are using fixed root signature layout, the reflection pass should only validate the layout, not generate it.
|
||||
public static void PerformDXCReflection(ref Shader shader, IDxcBlob* reflectionBlob)
|
||||
{
|
||||
// Create DXC utils to parse reflection data
|
||||
var pDxcUtils = (Guid*)Unsafe.AsPointer(in CLSID.CLSID_DxcUtils);
|
||||
using ComPtr<IDxcUtils> utils = default;
|
||||
DxcCreateInstance(CLSID_DxcUtils, __uuidof<IDxcUtils>(), utils.GetVoidAddressOf());
|
||||
DxcCreateInstance(pDxcUtils, __uuidof<IDxcUtils>(), utils.GetVoidAddressOf());
|
||||
|
||||
// Create reflection interface from blob
|
||||
var reflectionData = new DxcBuffer
|
||||
{
|
||||
Ptr = reflectionBlob->GetBufferPointer(),
|
||||
Size = reflectionBlob->GetBufferSize(),
|
||||
Encoding = DXC_CP_ACP
|
||||
Encoding = DXC.DXC_CP_ACP
|
||||
};
|
||||
|
||||
using ComPtr<ID3D12ShaderReflection> reflection = default;
|
||||
@@ -210,7 +217,7 @@ internal unsafe static class D3D12ShaderCompiler
|
||||
throw new Exception("Failed to create shader reflection from DXC output");
|
||||
}
|
||||
|
||||
ShaderDescription shaderDesc;
|
||||
D3D12_SHADER_DESC shaderDesc;
|
||||
reflection.Get()->GetDesc(&shaderDesc);
|
||||
|
||||
var cbufferRegistry = new Dictionary<string, CBufferInfo>();
|
||||
@@ -218,12 +225,12 @@ internal unsafe static class D3D12ShaderCompiler
|
||||
|
||||
for (uint i = 0; i < shaderDesc.BoundResources; i++)
|
||||
{
|
||||
ShaderInputBindDescription bindDesc;
|
||||
D3D12_SHADER_INPUT_BIND_DESC bindDesc;
|
||||
reflection.Get()->GetResourceBindingDesc(i, &bindDesc);
|
||||
|
||||
switch (bindDesc.Type)
|
||||
{
|
||||
case ShaderInputType.ConstantBuffer:
|
||||
case D3D_SHADER_INPUT_TYPE.D3D_SIT_CBUFFER:
|
||||
{
|
||||
var cbufferName = Marshal.PtrToStringAnsi((IntPtr)bindDesc.Name);
|
||||
if (cbufferName == null || cbufferRegistry.ContainsKey(cbufferName))
|
||||
@@ -232,7 +239,7 @@ internal unsafe static class D3D12ShaderCompiler
|
||||
}
|
||||
|
||||
var cbuffer = reflection.Get()->GetConstantBufferByName(bindDesc.Name);
|
||||
ShaderBufferDescription cbufferDesc;
|
||||
D3D12_SHADER_BUFFER_DESC cbufferDesc;
|
||||
cbuffer->GetDesc(&cbufferDesc);
|
||||
|
||||
var cbufferInfo = new CBufferInfo
|
||||
@@ -245,7 +252,7 @@ internal unsafe static class D3D12ShaderCompiler
|
||||
for (uint j = 0; j < cbufferDesc.Variables; j++)
|
||||
{
|
||||
var variable = cbuffer->GetVariableByIndex(j);
|
||||
ShaderVariableDescription varDesc;
|
||||
D3D12_SHADER_VARIABLE_DESC varDesc;
|
||||
variable->GetDesc(&varDesc);
|
||||
|
||||
var variableName = Marshal.PtrToStringAnsi((IntPtr)varDesc.Name);
|
||||
@@ -267,8 +274,9 @@ internal unsafe static class D3D12ShaderCompiler
|
||||
break;
|
||||
}
|
||||
|
||||
case ShaderInputType.Texture:
|
||||
case D3D_SHADER_INPUT_TYPE.D3D_SIT_TEXTURE:
|
||||
{
|
||||
#if SUPPORT_TEXTURE_BINDING
|
||||
var textureName = Marshal.PtrToStringAnsi((IntPtr)bindDesc.Name);
|
||||
if (textureName == null || textureRegistry.ContainsKey(textureName))
|
||||
{
|
||||
@@ -285,20 +293,16 @@ internal unsafe static class D3D12ShaderCompiler
|
||||
|
||||
textureRegistry.Add(textureName, textureInfo);
|
||||
break;
|
||||
#endif
|
||||
throw new NotSupportedException("Texture bindings are not supported in current version. Please use bindless textures.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shader.ConstantBuffers.Clear();
|
||||
shader.PerMaterialBufferInfo.Clear();
|
||||
foreach (var cbuf in cbufferRegistry.Values)
|
||||
{
|
||||
shader.ConstantBuffers.Add(cbuf);
|
||||
}
|
||||
|
||||
shader.RegularTextures.Clear();
|
||||
foreach (var tex in textureRegistry.Values)
|
||||
{
|
||||
shader.RegularTextures.Add(tex);
|
||||
shader.PerMaterialBufferInfo.Add(cbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,10 @@ using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Win32;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using Win32.Graphics.Dxgi;
|
||||
using Win32.Graphics.Dxgi.Common;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
using static TerraFX.Aliases.DXGI_Alias;
|
||||
|
||||
namespace Ghost.Graphics.D3D12;
|
||||
|
||||
@@ -55,18 +55,18 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
|
||||
private void CreateSwapChain(IDXGIFactory7* pFactory, ID3D12CommandQueue* commandQueue, SwapChainDesc desc)
|
||||
{
|
||||
var swapChainDesc = new SwapChainDescription1
|
||||
var swapChainDesc = new DXGI_SWAP_CHAIN_DESC1
|
||||
{
|
||||
Width = desc.width,
|
||||
Height = desc.height,
|
||||
Format = ConvertTextureFormat(desc.format),
|
||||
SampleDesc = new SampleDescription(1, 0),
|
||||
BufferUsage = Usage.BackBuffer | Usage.RenderTargetOutput,
|
||||
Format = desc.format.ToD3D12Format(),
|
||||
SampleDesc = new DXGI_SAMPLE_DESC(1, 0),
|
||||
BufferUsage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
BufferCount = D3D12PipelineResource.BACK_BUFFER_COUNT,
|
||||
Scaling = Scaling.Stretch,
|
||||
SwapEffect = SwapEffect.FlipDiscard,
|
||||
AlphaMode = AlphaMode.Ignore,
|
||||
Flags = SwapChainFlags.AllowTearing,
|
||||
Scaling = DXGI_SCALING_STRETCH,
|
||||
SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
|
||||
AlphaMode = DXGI_ALPHA_MODE_IGNORE,
|
||||
Flags = (uint)DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING,
|
||||
Stereo = false,
|
||||
};
|
||||
|
||||
@@ -86,14 +86,14 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
break;
|
||||
|
||||
case SwapChainTargetType.WindowHandle:
|
||||
var swapChainFullscreenDesc = new SwapChainFullscreenDescription
|
||||
var swapChainFullscreenDesc = new DXGI_SWAP_CHAIN_FULLSCREEN_DESC
|
||||
{
|
||||
Windowed = true,
|
||||
};
|
||||
|
||||
pFactory->CreateSwapChainForHwnd(
|
||||
(IUnknown*)commandQueue,
|
||||
desc.target.windowHandle,
|
||||
new HWND(desc.target.windowHandle.ToPointer()),
|
||||
&swapChainDesc,
|
||||
&swapChainFullscreenDesc,
|
||||
null,
|
||||
@@ -104,7 +104,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
throw new ArgumentException("Unsupported swap chain target type.");
|
||||
}
|
||||
|
||||
if (tempSwapChain.Get()->QueryInterface(__uuidof<IDXGISwapChain4>(), _swapChain.GetVoidAddressOf()).Failure)
|
||||
if (tempSwapChain.Get()->QueryInterface(__uuidof<IDXGISwapChain4>(), _swapChain.GetVoidAddressOf()).FAILED)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to create IDXGISwapChain4 interface.");
|
||||
}
|
||||
@@ -130,10 +130,10 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
|
||||
public void Present(bool vsync = true)
|
||||
{
|
||||
var presentFlags = PresentFlags.None;
|
||||
var presentFlags = 0u;
|
||||
var syncInterval = vsync ? 1u : 0u;
|
||||
|
||||
if (_swapChain.Get()->Present(syncInterval, presentFlags).Failure)
|
||||
if (_swapChain.Get()->Present(syncInterval, presentFlags).FAILED)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to present swap chain.");
|
||||
}
|
||||
@@ -153,7 +153,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
}
|
||||
|
||||
// Resize the swap chain
|
||||
if (_swapChain.Get()->ResizeBuffers(BufferCount, width, height, Format.B8G8R8A8Unorm, SwapChainFlags.AllowTearing).Failure)
|
||||
if (_swapChain.Get()->ResizeBuffers(BufferCount, width, height, DXGI_FORMAT_B8G8R8A8_UNORM, (uint)DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING).FAILED)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to resize swap chain buffers.");
|
||||
}
|
||||
@@ -165,18 +165,6 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
CreateBackBuffers();
|
||||
}
|
||||
|
||||
private static Format ConvertTextureFormat(TextureFormat format)
|
||||
{
|
||||
return format switch
|
||||
{
|
||||
TextureFormat.R8G8B8A8_UNorm => Format.R8G8B8A8Unorm,
|
||||
TextureFormat.B8G8R8A8_UNorm => Format.B8G8R8A8Unorm,
|
||||
TextureFormat.R16G16B16A16_Float => Format.R16G16B16A16Float,
|
||||
TextureFormat.R32G32B32A32_Float => Format.R32G32B32A32Float,
|
||||
_ => throw new ArgumentException($"Unsupported texture format: {format}")
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
|
||||
@@ -7,7 +7,7 @@ internal readonly struct DSVDesc : IIdentifierType;
|
||||
internal readonly struct CbvSrvUavDesc : IIdentifierType;
|
||||
internal readonly struct SamplerDesc : IIdentifierType;
|
||||
|
||||
internal struct D3D12ResourceDescriptor
|
||||
internal struct ResourceViewGroup
|
||||
{
|
||||
public Identifier<RTVDesc> rtv;
|
||||
public Identifier<DSVDesc> dsv;
|
||||
@@ -16,11 +16,13 @@ internal struct D3D12ResourceDescriptor
|
||||
public Identifier<CbvSrvUavDesc> uav;
|
||||
public Identifier<SamplerDesc> sampler;
|
||||
|
||||
public static D3D12ResourceDescriptor Invalid => new()
|
||||
public static ResourceViewGroup Invalid => new()
|
||||
{
|
||||
rtv = Identifier<RTVDesc>.Invalid,
|
||||
dsv = Identifier<DSVDesc>.Invalid,
|
||||
srv = Identifier<CbvSrvUavDesc>.Invalid,
|
||||
cbv = Identifier<CbvSrvUavDesc>.Invalid,
|
||||
uav = Identifier<CbvSrvUavDesc>.Invalid,
|
||||
sampler = Identifier<SamplerDesc>.Invalid,
|
||||
};
|
||||
}
|
||||
@@ -1,32 +1,34 @@
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using Win32;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using DescriptorIndex = System.Int32;
|
||||
using TerraFX.Interop.DirectX;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
using static TerraFX.Aliases.D3D12_Alias;
|
||||
|
||||
namespace Ghost.Graphics.D3D12.Utilities;
|
||||
|
||||
internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
{
|
||||
private const DescriptorIndex _INVALID_DESCRIPTOR_INDEX = -1;
|
||||
private const int _INVALID_DESCRIPTOR_INDEX = -1;
|
||||
|
||||
private readonly D3D12RenderDevice _device;
|
||||
|
||||
private ComPtr<ID3D12DescriptorHeap> _heap;
|
||||
private ComPtr<ID3D12DescriptorHeap> _shaderVisibleHeap;
|
||||
private CpuDescriptorHandle _startCpuHandle;
|
||||
private CpuDescriptorHandle _startCpuHandleShaderVisible;
|
||||
private GpuDescriptorHandle _startGpuHandleShaderVisible;
|
||||
private DescriptorIndex _searchStart;
|
||||
private D3D12_CPU_DESCRIPTOR_HANDLE _startCpuHandle;
|
||||
private D3D12_CPU_DESCRIPTOR_HANDLE _startCpuHandleShaderVisible;
|
||||
private D3D12_GPU_DESCRIPTOR_HANDLE _startGpuHandleShaderVisible;
|
||||
private int _searchStart;
|
||||
private UnsafeArray<bool> _allocatedDescriptors;
|
||||
|
||||
private readonly DescriptorIndex _dynamicHeapStart;
|
||||
private DescriptorIndex _currentDynamicOffset;
|
||||
private readonly int _dynamicHeapStart;
|
||||
private int _currentDynamicOffset;
|
||||
|
||||
private readonly Lock _lock = new();
|
||||
|
||||
public DescriptorHeapType HeapType
|
||||
public D3D12_DESCRIPTOR_HEAP_TYPE HeapType
|
||||
{
|
||||
get;
|
||||
}
|
||||
@@ -54,7 +56,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
public readonly ID3D12DescriptorHeap* Heap => _heap.Get();
|
||||
public readonly ID3D12DescriptorHeap* ShaderVisibleHeap => _shaderVisibleHeap.Get();
|
||||
|
||||
public D3D12DescriptorHeap(string name, D3D12RenderDevice device, DescriptorHeapType type, int numDescriptors, int dynamicHeapStart)
|
||||
public D3D12DescriptorHeap(string name, D3D12RenderDevice device, D3D12_DESCRIPTOR_HEAP_TYPE type, int numDescriptors, int dynamicHeapStart)
|
||||
{
|
||||
numDescriptors = Math.Max(64, numDescriptors);
|
||||
|
||||
@@ -62,7 +64,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
|
||||
HeapType = type;
|
||||
NumDescriptors = numDescriptors;
|
||||
ShaderVisible = type == DescriptorHeapType.CbvSrvUav || type == DescriptorHeapType.Sampler;
|
||||
ShaderVisible = type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV || type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
Stride = device.NativeDevice->GetDescriptorHandleIncrementSize(type);
|
||||
|
||||
_dynamicHeapStart = Math.Clamp(dynamicHeapStart, 0, numDescriptors);
|
||||
@@ -71,16 +73,16 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
var success = AllocateResources(numDescriptors);
|
||||
Debug.Assert(success);
|
||||
|
||||
_heap.Get()->SetName(name);
|
||||
_heap.Get()->SetName(name.AsSpan().GetUnsafePtr());
|
||||
if (ShaderVisible)
|
||||
{
|
||||
_shaderVisibleHeap.Get()->SetName($"{name} Shader Visible");
|
||||
_shaderVisibleHeap.Get()->SetName($"{name} Shader Visible".AsSpan().GetUnsafePtr());
|
||||
}
|
||||
}
|
||||
|
||||
public DescriptorIndex AllocateDescriptor() => AllocateDescriptors(1);
|
||||
public int AllocateDescriptor() => AllocateDescriptors(1);
|
||||
|
||||
public DescriptorIndex AllocateDescriptors(int count)
|
||||
public int AllocateDescriptors(int count)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
@@ -125,9 +127,9 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public DescriptorIndex AllocateDescriptorDynamic() => AllocateDescriptorsDynamic(1);
|
||||
public int AllocateDescriptorDynamic() => AllocateDescriptorsDynamic(1);
|
||||
|
||||
public DescriptorIndex AllocateDescriptorsDynamic(int count)
|
||||
public int AllocateDescriptorsDynamic(int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
{
|
||||
@@ -157,9 +159,9 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public void ReleaseDescriptor(DescriptorIndex index) => ReleaseDescriptors(index, 1);
|
||||
public void ReleaseDescriptor(int index) => ReleaseDescriptors(index, 1);
|
||||
|
||||
public void ReleaseDescriptors(DescriptorIndex baseIndex, int count = 1)
|
||||
public void ReleaseDescriptors(int baseIndex, int count = 1)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
@@ -203,7 +205,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public readonly CpuDescriptorHandle GetCpuHandle(DescriptorIndex index)
|
||||
public readonly D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(int index)
|
||||
{
|
||||
if (index < 0 || index >= NumDescriptors)
|
||||
{
|
||||
@@ -213,7 +215,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
return _startCpuHandle.Offset(index, Stride);
|
||||
}
|
||||
|
||||
public readonly CpuDescriptorHandle GetCpuHandleShaderVisible(DescriptorIndex index)
|
||||
public readonly D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandleShaderVisible(int index)
|
||||
{
|
||||
if (index < 0 || index >= NumDescriptors)
|
||||
{
|
||||
@@ -228,7 +230,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
return _startCpuHandleShaderVisible.Offset(index, Stride);
|
||||
}
|
||||
|
||||
public readonly GpuDescriptorHandle GetGpuHandle(DescriptorIndex index)
|
||||
public readonly D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(int index)
|
||||
{
|
||||
if (index < 0 || index >= NumDescriptors)
|
||||
{
|
||||
@@ -243,7 +245,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
return _startGpuHandleShaderVisible.Offset(index, Stride);
|
||||
}
|
||||
|
||||
public DescriptorIndex CopyToPersistentHeap(DescriptorIndex index, int count = 1)
|
||||
public int CopyToPersistentHeap(int index, int count = 1)
|
||||
{
|
||||
if (index < _dynamicHeapStart)
|
||||
{
|
||||
@@ -256,7 +258,7 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
return newLocation;
|
||||
}
|
||||
|
||||
public readonly void CopyToShaderVisibleHeap(DescriptorIndex index, int count = 1)
|
||||
public readonly void CopyToShaderVisibleHeap(int index, int count = 1)
|
||||
{
|
||||
_device.NativeDevice->CopyDescriptorsSimple((uint)count, GetCpuHandleShaderVisible(index), GetCpuHandle(index), HeapType);
|
||||
}
|
||||
@@ -267,18 +269,18 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
_heap.Dispose();
|
||||
_shaderVisibleHeap.Dispose();
|
||||
|
||||
DescriptorHeapDescription heapDesc = new()
|
||||
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = new()
|
||||
{
|
||||
Type = HeapType,
|
||||
NumDescriptors = (uint)numDescriptors,
|
||||
Flags = DescriptorHeapFlags.None,
|
||||
Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE,
|
||||
NodeMask = 0
|
||||
};
|
||||
|
||||
fixed (void* heapPtr = &_heap)
|
||||
{
|
||||
var hr = _device.NativeDevice->CreateDescriptorHeap(&heapDesc, __uuidof<ID3D12DescriptorHeap>(), (void**)heapPtr);
|
||||
if (hr.Failure)
|
||||
if (hr.FAILED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -289,12 +291,12 @@ internal unsafe struct D3D12DescriptorHeap : IDisposable
|
||||
|
||||
if (ShaderVisible)
|
||||
{
|
||||
heapDesc.Flags = DescriptorHeapFlags.ShaderVisible;
|
||||
heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
|
||||
fixed (void* heapPtr = &_shaderVisibleHeap)
|
||||
{
|
||||
var hr = _device.NativeDevice->CreateDescriptorHeap(&heapDesc, __uuidof<ID3D12DescriptorHeap>(), (void**)heapPtr);
|
||||
if (hr.Failure)
|
||||
if (hr.FAILED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Ghost.Graphics.Data;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Win32.Graphics.Direct3D12;
|
||||
using Win32.Graphics.Dxgi.Common;
|
||||
using TerraFX.Interop.DirectX;
|
||||
|
||||
namespace Ghost.Graphics.D3D12.Utilities;
|
||||
|
||||
@@ -9,19 +8,19 @@ internal unsafe static class D3D12PipelineResource
|
||||
{
|
||||
public const int BACK_BUFFER_COUNT = 2;
|
||||
|
||||
private readonly static InputElementDescription[] s_inputElementDescs = [
|
||||
new InputElementDescription{ SemanticName = Vertex.Semantic.position.GetUnsafePointer(), SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 0u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
|
||||
new InputElementDescription{ SemanticName = Vertex.Semantic.normal.GetUnsafePointer(), SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 16u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
|
||||
new InputElementDescription{ SemanticName = Vertex.Semantic.tangent.GetUnsafePointer(), SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 32u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
|
||||
new InputElementDescription{ SemanticName = Vertex.Semantic.uv.GetUnsafePointer(), SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 48u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
|
||||
new InputElementDescription{ SemanticName = Vertex.Semantic.color.GetUnsafePointer(), SemanticIndex = 0u, Format = Format.R32G32B32A32Float, InputSlot = 0u, AlignedByteOffset = 64u, InputSlotClass = InputClassification.PerVertexData, InstanceDataStepRate = 0 },
|
||||
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 },
|
||||
];
|
||||
|
||||
public const Format SWAP_CHAIN_BACK_BUFFER_FORMAT = Format.B8G8R8A8Unorm;
|
||||
public const DXGI_FORMAT SWAP_CHAIN_BACK_BUFFER_FORMAT = DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
public static InputLayoutDescription InputLayoutDescription => new()
|
||||
public static D3D12_INPUT_LAYOUT_DESC InputLayoutDescription => new()
|
||||
{
|
||||
pInputElementDescs = (InputElementDescription*)Unsafe.AsPointer(ref s_inputElementDescs[0]),
|
||||
pInputElementDescs = (D3D12_INPUT_ELEMENT_DESC*)Unsafe.AsPointer(ref s_inputElementDescs[0]),
|
||||
NumElements = (uint)s_inputElementDescs.Length
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,163 @@
|
||||
namespace Ghost.Graphics.D3D12.Utilities;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using TerraFX.Interop.DirectX;
|
||||
|
||||
internal static class D3D12Utility
|
||||
using static TerraFX.Aliases.D3D12_Alias;
|
||||
|
||||
namespace Ghost.Graphics.D3D12.Utilities;
|
||||
|
||||
internal unsafe static class ID3D12Resource_Extensions
|
||||
{
|
||||
extension(ID3D12Resource resource)
|
||||
{
|
||||
public void SetName(ReadOnlySpan<char> name)
|
||||
{
|
||||
resource.SetName(name.GetUnsafePtr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class D3D12_RASTERIZER_DESC_Extensions
|
||||
{
|
||||
extension(D3D12_RASTERIZER_DESC)
|
||||
{
|
||||
public static D3D12_RASTERIZER_DESC CULL_NONE => Create(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE);
|
||||
public static D3D12_RASTERIZER_DESC CULL_CLOCKWISE => Create(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_FRONT);
|
||||
public static D3D12_RASTERIZER_DESC CULL_COUNTER_CLOCKWISE => Create(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_BACK);
|
||||
public static D3D12_RASTERIZER_DESC WIREFRAME => Create(D3D12_FILL_MODE_WIREFRAME, D3D12_CULL_MODE_NONE);
|
||||
|
||||
public static D3D12_RASTERIZER_DESC Create(
|
||||
D3D12_FILL_MODE fillMode,
|
||||
D3D12_CULL_MODE cullMode,
|
||||
bool frontCounterClockwise = false,
|
||||
int depthBias = D3D12_DEFAULT_DEPTH_BIAS,
|
||||
float depthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
|
||||
float slopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
|
||||
bool depthClipEnable = true,
|
||||
bool multisampleEnable = true,
|
||||
bool antialiasedLineEnable = false,
|
||||
uint forcedSampleCount = 0,
|
||||
D3D12_CONSERVATIVE_RASTERIZATION_MODE conservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF)
|
||||
{
|
||||
return new D3D12_RASTERIZER_DESC
|
||||
{
|
||||
FillMode = fillMode,
|
||||
CullMode = cullMode,
|
||||
FrontCounterClockwise = frontCounterClockwise ? TRUE : FALSE,
|
||||
DepthBias = depthBias,
|
||||
DepthBiasClamp = depthBiasClamp,
|
||||
SlopeScaledDepthBias = slopeScaledDepthBias,
|
||||
DepthClipEnable = depthClipEnable ? TRUE : FALSE,
|
||||
MultisampleEnable = multisampleEnable ? TRUE : FALSE,
|
||||
AntialiasedLineEnable = antialiasedLineEnable ? TRUE : FALSE,
|
||||
ForcedSampleCount = forcedSampleCount,
|
||||
ConservativeRaster = conservativeRaster
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class D3D12_BLEND_DESC_Extensions
|
||||
{
|
||||
extension(D3D12_BLEND_DESC)
|
||||
{
|
||||
public static D3D12_BLEND_DESC OPAQUE => Create(D3D12_BLEND_ONE, D3D12_BLEND_ZERO);
|
||||
public static D3D12_BLEND_DESC ALPHA_BLEND => Create(D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA);
|
||||
public static D3D12_BLEND_DESC ADDITIVE => Create(D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_ONE);
|
||||
public static D3D12_BLEND_DESC NON_PREMULTIPLIED => Create(D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA);
|
||||
|
||||
public static D3D12_BLEND_DESC Create(D3D12_BLEND srcBlend, D3D12_BLEND destBlend)
|
||||
{
|
||||
var blendDesc = new D3D12_BLEND_DESC
|
||||
{
|
||||
AlphaToCoverageEnable = false,
|
||||
IndependentBlendEnable = false
|
||||
};
|
||||
|
||||
for (var i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
|
||||
{
|
||||
blendDesc.RenderTarget[i].BlendEnable = srcBlend != D3D12_BLEND_ONE || destBlend != D3D12_BLEND_ZERO;
|
||||
blendDesc.RenderTarget[i].LogicOp = D3D12_LOGIC_OP_NOOP;
|
||||
blendDesc.RenderTarget[i].SrcBlend = srcBlend;
|
||||
blendDesc.RenderTarget[i].DestBlend = destBlend;
|
||||
blendDesc.RenderTarget[i].BlendOp = D3D12_BLEND_OP_ADD;
|
||||
blendDesc.RenderTarget[i].SrcBlendAlpha = srcBlend;
|
||||
blendDesc.RenderTarget[i].DestBlendAlpha = destBlend;
|
||||
blendDesc.RenderTarget[i].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||
blendDesc.RenderTarget[i].RenderTargetWriteMask = (byte)D3D12_COLOR_WRITE_ENABLE_ALL;
|
||||
}
|
||||
|
||||
return blendDesc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class D3D12_DEPTH_STENCIL_DESC_Extensions
|
||||
{
|
||||
extension(D3D12_DEPTH_STENCIL_DESC)
|
||||
{
|
||||
public static D3D12_DEPTH_STENCIL_DESC NONE => Create(false, false, D3D12_COMPARISON_FUNC_LESS_EQUAL);
|
||||
public static D3D12_DEPTH_STENCIL_DESC READ => Create(true, false, D3D12_COMPARISON_FUNC_LESS_EQUAL);
|
||||
public static D3D12_DEPTH_STENCIL_DESC REVERSE_Z => Create(true, true, D3D12_COMPARISON_FUNC_GREATER_EQUAL);
|
||||
public static D3D12_DEPTH_STENCIL_DESC READ_REVERSE_Z => Create(true, false, D3D12_COMPARISON_FUNC_GREATER_EQUAL);
|
||||
|
||||
public static D3D12_DEPTH_STENCIL_DESC Create(bool depthEnable,
|
||||
bool depthWriteEnable,
|
||||
D3D12_COMPARISON_FUNC depthFunc,
|
||||
bool stencilEnable = false,
|
||||
byte stencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK,
|
||||
byte stencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK,
|
||||
D3D12_STENCIL_OP frontStencilFailOp = D3D12_STENCIL_OP_KEEP,
|
||||
D3D12_STENCIL_OP frontStencilDepthFailOp = D3D12_STENCIL_OP_KEEP,
|
||||
D3D12_STENCIL_OP frontStencilPassOp = D3D12_STENCIL_OP_KEEP,
|
||||
D3D12_COMPARISON_FUNC frontStencilFunc = D3D12_COMPARISON_FUNC_ALWAYS,
|
||||
D3D12_STENCIL_OP backStencilFailOp = D3D12_STENCIL_OP_KEEP,
|
||||
D3D12_STENCIL_OP backStencilDepthFailOp = D3D12_STENCIL_OP_KEEP,
|
||||
D3D12_STENCIL_OP backStencilPassOp = D3D12_STENCIL_OP_KEEP,
|
||||
D3D12_COMPARISON_FUNC backStencilFunc = D3D12_COMPARISON_FUNC_ALWAYS)
|
||||
{
|
||||
return new D3D12_DEPTH_STENCIL_DESC
|
||||
{
|
||||
DepthEnable = depthEnable,
|
||||
DepthWriteMask = depthWriteEnable ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO,
|
||||
DepthFunc = depthFunc,
|
||||
StencilEnable = stencilEnable,
|
||||
StencilReadMask = stencilReadMask,
|
||||
StencilWriteMask = stencilWriteMask,
|
||||
FrontFace = D3D12_DEPTH_STENCILOP_DESC.Create(frontStencilFailOp, frontStencilDepthFailOp, frontStencilPassOp, frontStencilFunc),
|
||||
BackFace = D3D12_DEPTH_STENCILOP_DESC.Create(backStencilFailOp, backStencilDepthFailOp, backStencilPassOp, backStencilFunc)
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal static class D3D12_DEPTH_STENCILOP_DESC_Extensions
|
||||
{
|
||||
extension(D3D12_DEPTH_STENCILOP_DESC)
|
||||
{
|
||||
public static D3D12_DEPTH_STENCILOP_DESC DEFAULT => Create(D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS);
|
||||
|
||||
public static D3D12_DEPTH_STENCILOP_DESC Create(D3D12_STENCIL_OP stencilFailOp, D3D12_STENCIL_OP stencilDepthFailOp, D3D12_STENCIL_OP stencilPassOp, D3D12_COMPARISON_FUNC stencilFunc)
|
||||
{
|
||||
return new D3D12_DEPTH_STENCILOP_DESC
|
||||
{
|
||||
StencilFailOp = stencilFailOp,
|
||||
StencilDepthFailOp = stencilDepthFailOp,
|
||||
StencilPassOp = stencilPassOp,
|
||||
StencilFunc = stencilFunc
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe static class D3D12MA_Allocation_Extensions
|
||||
{
|
||||
extension(ref readonly D3D12MA_Allocation allocation)
|
||||
{
|
||||
public bool IsNull => allocation.GetResource() == null
|
||||
&& allocation.GetHeap() == null
|
||||
&& allocation.GetSize() == 0;
|
||||
|
||||
public bool IsNotNull => !allocation.IsNull;
|
||||
}
|
||||
}
|
||||
13335
Ghost.Graphics/D3D12/Utilities/EnumAliases.cs
Normal file
13335
Ghost.Graphics/D3D12/Utilities/EnumAliases.cs
Normal file
File diff suppressed because it is too large
Load Diff
41
Ghost.Graphics/D3D12/Utilities/Win32Utility.cs
Normal file
41
Ghost.Graphics/D3D12/Utilities/Win32Utility.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using TerraFX.Interop.Windows;
|
||||
|
||||
namespace Ghost.Graphics.D3D12.Utilities;
|
||||
|
||||
internal unsafe static class Win32Utility
|
||||
{
|
||||
public static void ThrowIfFailed(this HRESULT hr)
|
||||
{
|
||||
if (hr.FAILED)
|
||||
{
|
||||
throw new InvalidOperationException($"Operation failed with HRESULT: 0x{hr.Value:X8}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void** GetVoidAddressOf<T>(this ComPtr<T> comPtr)
|
||||
where T : unmanaged, IUnknown.Interface
|
||||
{
|
||||
return (void**)comPtr.GetAddressOf();
|
||||
}
|
||||
|
||||
public static void** ReleaseAndGetVoidAddressOf<T>(this ComPtr<T> comPtr)
|
||||
where T : unmanaged, IUnknown.Interface
|
||||
{
|
||||
return (void**)comPtr.ReleaseAndGetAddressOf();
|
||||
}
|
||||
|
||||
public static ComPtr<T> Move<T>(this ComPtr<T> comPtr)
|
||||
where T : unmanaged, IUnknown.Interface
|
||||
{
|
||||
ComPtr<T> copy = default;
|
||||
Unsafe.AsRef(in comPtr).Swap(ref copy);
|
||||
return copy;
|
||||
}
|
||||
|
||||
public static bool HasFlag<T>(this uint flags, T flag)
|
||||
where T : Enum
|
||||
{
|
||||
return (flags & Unsafe.As<T, uint>(ref flag)) != 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user