Add render graph proof of concept and refactor graphics
Implemented a transient render graph system as a proof of concept, including resource aliasing, pass culling, and typed pass data. Added new project `Ghost.RenderGraph.Concept` targeting `.NET 10.0`. Refactored graphics-related components: - Simplified resource state transitions in `RenderingContext`. - Improved resize handling in `GraphicsTestWindow`. - Updated `D3D12GraphicsEngine` to streamline frame rendering. - Enhanced `D3D12ResourceDatabase` and `D3D12SwapChain` for better resource management. Added detailed documentation: - `ALIASING.md` explains resource aliasing techniques. - `API_DESIGN.md` outlines the render graph API design. Updated solution to include the new render graph project.
This commit is contained in:
@@ -291,6 +291,11 @@ internal unsafe class D3D12CommandBuffer : ICommandBuffer
|
||||
}
|
||||
|
||||
ref var record = ref recordResult.Value;
|
||||
if (record.state == stateAfter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var barrier = D3D12_RESOURCE_BARRIER.InitTransition(record.ResourcePtr,
|
||||
record.state.ToD3D12States(), stateAfter.ToD3D12States());
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ internal unsafe class D3D12CommandQueue : ICommandQueue
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
_fenceValue = value;
|
||||
_commandQueue.Get()->Signal((ID3D12Fence*)_fence.Get(), _fenceValue);
|
||||
ThrowIfFailed(_commandQueue.Get()->Signal((ID3D12Fence*)_fence.Get(), _fenceValue));
|
||||
return _fenceValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace Ghost.Graphics.D3D12;
|
||||
|
||||
internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
{
|
||||
private readonly IRenderSystem _renderSystem;
|
||||
|
||||
#if DEBUG
|
||||
private readonly D3D12DebugLayer _debugLayer;
|
||||
#endif
|
||||
@@ -34,6 +36,8 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
|
||||
public D3D12GraphicsEngine(IRenderSystem renderSystem)
|
||||
{
|
||||
_renderSystem = renderSystem;
|
||||
|
||||
#if DEBUG
|
||||
_debugLayer = new D3D12DebugLayer();
|
||||
#endif
|
||||
@@ -106,10 +110,10 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
public ISwapChain CreateSwapChain(SwapChainDesc desc)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return new D3D12SwapChain(_resourceDatabase, _descriptorAllocator, _device, desc);
|
||||
return new D3D12SwapChain(_resourceDatabase, _descriptorAllocator, _device, desc, _renderSystem.MaxFrameLatency);
|
||||
}
|
||||
|
||||
public void BeginFrame()
|
||||
public void RenderFrame()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
@@ -119,21 +123,11 @@ internal class D3D12GraphicsEngine : IGraphicsEngine
|
||||
}
|
||||
|
||||
_copyCommandBuffer.Begin();
|
||||
}
|
||||
|
||||
public void RenderFrame()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
foreach (var renderer in _renderers)
|
||||
{
|
||||
renderer.Render();
|
||||
}
|
||||
}
|
||||
|
||||
public void EndFrame()
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
_copyCommandBuffer.End().ThrowIfFailed();
|
||||
_resourceAllocator.ReleaseTempResources();
|
||||
|
||||
@@ -136,7 +136,7 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
resource = default!;
|
||||
}
|
||||
|
||||
public unsafe Handle<GPUResource> ImportExternalResource(ID3D12Resource* pResource, ResourceState initialState, ResourceViewGroup viewGroup, string name = "")
|
||||
public unsafe Handle<GPUResource> ImportExternalResource(ID3D12Resource* pResource, ResourceState initialState, ResourceViewGroup viewGroup, string? name = null)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
@@ -144,14 +144,17 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
var handle = new Handle<GPUResource>(id, generation);
|
||||
|
||||
#if DEBUG || GHOST_EDITOR
|
||||
pResource->SetName(name);
|
||||
_resourceName[handle] = name;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
pResource->SetName(name);
|
||||
_resourceName[handle] = name;
|
||||
}
|
||||
#endif
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
public unsafe Handle<GPUResource> AddResource(D3D12MA_Allocation* allocation, uint cpuFenceValue, ResourceState initialState, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string name = "")
|
||||
public unsafe Handle<GPUResource> AddResource(D3D12MA_Allocation* allocation, uint cpuFenceValue, ResourceState initialState, ResourceViewGroup resourceDescriptor, ResourceDesc desc, string? name = null)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
@@ -159,8 +162,11 @@ internal class D3D12ResourceDatabase : IResourceDatabase
|
||||
var handle = new Handle<GPUResource>(id, generation);
|
||||
|
||||
#if DEBUG || GHOST_EDITOR
|
||||
allocation->SetName(name);
|
||||
_resourceName[handle] = name;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
allocation->SetName(name);
|
||||
_resourceName[handle] = name;
|
||||
}
|
||||
#endif
|
||||
|
||||
return handle;
|
||||
|
||||
@@ -42,26 +42,20 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
get; private set;
|
||||
}
|
||||
|
||||
public uint BufferCount
|
||||
public D3D12SwapChain(D3D12ResourceDatabase resourceDatabase, D3D12DescriptorAllocator descriptorAllocator, D3D12RenderDevice device, SwapChainDesc desc, uint bufferCount)
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public D3D12SwapChain(D3D12ResourceDatabase resourceDatabase, D3D12DescriptorAllocator descriptorAllocator, D3D12RenderDevice device, SwapChainDesc desc)
|
||||
{
|
||||
Debug.Assert(desc.BufferCount >= 2);
|
||||
Debug.Assert(bufferCount >= 2);
|
||||
|
||||
_resourceDatabase = resourceDatabase;
|
||||
_descriptorAllocator = descriptorAllocator;
|
||||
_renderDevice = device;
|
||||
|
||||
_backBuffers = new UnsafeArray<Handle<Texture>>((int)desc.BufferCount, Allocator.Persistent);
|
||||
_backBuffers = new UnsafeArray<Handle<Texture>>((int)bufferCount, Allocator.Persistent);
|
||||
|
||||
Width = desc.Width;
|
||||
Height = desc.Height;
|
||||
BufferCount = desc.BufferCount;
|
||||
|
||||
CreateSwapChain(desc);
|
||||
CreateSwapChain(desc, bufferCount);
|
||||
CreateBackBuffers();
|
||||
|
||||
_compositionSurface = desc.Target.CompositionSurface;
|
||||
@@ -72,7 +66,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private void CreateSwapChain(SwapChainDesc desc)
|
||||
private void CreateSwapChain(SwapChainDesc desc, uint bufferCount)
|
||||
{
|
||||
var swapChainDesc = new DXGI_SWAP_CHAIN_DESC1
|
||||
{
|
||||
@@ -81,7 +75,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
Format = desc.Format.ToDXGIFormat(),
|
||||
SampleDesc = new DXGI_SAMPLE_DESC(1, 0),
|
||||
BufferUsage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT,
|
||||
BufferCount = desc.BufferCount,
|
||||
BufferCount = bufferCount,
|
||||
Scaling = DXGI_SCALING_STRETCH,
|
||||
SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
|
||||
AlphaMode = DXGI_ALPHA_MODE_IGNORE,
|
||||
@@ -135,7 +129,7 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
|
||||
private void CreateBackBuffers()
|
||||
{
|
||||
for (uint i = 0; i < BufferCount; i++)
|
||||
for (uint i = 0; i < _backBuffers.Count; i++)
|
||||
{
|
||||
ID3D12Resource* pBackBuffer = default;
|
||||
ThrowIfFailed(_swapChain.Get()->GetBuffer(i, __uuidof(pBackBuffer), (void**)&pBackBuffer));
|
||||
@@ -186,12 +180,26 @@ internal unsafe class D3D12SwapChain : ISwapChain
|
||||
_resourceDatabase.ReleaseResource(_backBuffers[i].AsResource());
|
||||
}
|
||||
|
||||
ThrowIfFailed(_swapChain.Get()->ResizeBuffers(BufferCount, width, height, DXGI_FORMAT_B8G8R8A8_UNORM, (uint)DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING));
|
||||
ThrowIfFailed(_swapChain.Get()->ResizeBuffers((uint)_backBuffers.Count, width, height, DXGI_FORMAT_B8G8R8A8_UNORM, (uint)DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING));
|
||||
|
||||
Width = width;
|
||||
Height = height;
|
||||
|
||||
CreateBackBuffers();
|
||||
|
||||
//float inverseScale = 1.0f / scale;
|
||||
|
||||
//DXGI_MATRIX_3X2_F inverseScaleMatrix = new DXGI_MATRIX_3X2_F
|
||||
//{
|
||||
// _11 = inverseScale, // Scale X
|
||||
// _22 = inverseScale, // Scale Y
|
||||
// _12 = 0.0f,
|
||||
// _21 = 0.0f,
|
||||
// _31 = 0.0f, // Offset X
|
||||
// _32 = 0.0f // Offset Y
|
||||
//};
|
||||
|
||||
//_swapChain.Get()->SetMatrixTransform(&inverseScaleMatrix);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -11,7 +11,7 @@ internal unsafe static class D3D12Utility
|
||||
public static void SetName<T>(ref this T obj, ReadOnlySpan<char> name)
|
||||
where T : unmanaged, ID3D12Object.Interface
|
||||
{
|
||||
if (name.Length == 0)
|
||||
if (name.IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -24,6 +24,11 @@ internal unsafe static class D3D12Utility
|
||||
|
||||
public static void SetName(ref this D3D12MA_Allocation obj, ReadOnlySpan<char> name)
|
||||
{
|
||||
if (name.IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fixed (char* pName = name)
|
||||
{
|
||||
obj.SetName(pName);
|
||||
@@ -84,6 +89,9 @@ internal unsafe static class D3D12Utility
|
||||
ResourceState.PixelShaderResource => D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
|
||||
ResourceState.CopyDest => D3D12_RESOURCE_STATE_COPY_DEST,
|
||||
ResourceState.CopySource => D3D12_RESOURCE_STATE_COPY_SOURCE,
|
||||
ResourceState.GenericRead => D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
ResourceState.IndirectArgument => D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT,
|
||||
ResourceState.NonPixelShaderResource => D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
|
||||
_ => throw new ArgumentException($"Unknown resource state: {state}")
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user