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:
2025-12-01 22:31:17 +09:00
parent 85280c746d
commit 676f8bb74c
31 changed files with 2167 additions and 142 deletions

View File

@@ -0,0 +1,105 @@
namespace Ghost.RenderGraph.Concept;
public interface IRenderGraphBuilder
{
RenderGraphTextureHandle ReadTexture(RenderGraphTextureHandle handle);
RenderGraphTextureHandle WriteTexture(RenderGraphTextureHandle handle);
RenderGraphTextureHandle UseDepthBuffer(RenderGraphTextureHandle handle, bool writeAccess);
RenderGraphTextureHandle CreateTexture(TextureDescriptor descriptor);
RenderGraphBufferHandle ReadBuffer(RenderGraphBufferHandle handle);
RenderGraphBufferHandle WriteBuffer(RenderGraphBufferHandle handle);
RenderGraphBufferHandle CreateBuffer(BufferDescriptor descriptor);
}
public class RenderGraphPassBuilder<TPassData> : IRenderGraphBuilder, IDisposable
where TPassData : class, new()
{
private readonly RenderGraph _graph;
private readonly string _passName;
private readonly int _passIndex;
private readonly List<(RenderGraphResourceHandle handle, ResourceState state)> _resourceAccesses = new();
private Action<TPassData, ICommandBuffer>? _renderFunc;
private bool _committed;
private bool _allowCulling = true;
public TPassData PassData { get; }
internal RenderGraphPassBuilder(RenderGraph graph, string passName, int passIndex)
{
_graph = graph;
_passName = passName;
_passIndex = passIndex;
PassData = new TPassData();
}
internal IReadOnlyList<(RenderGraphResourceHandle handle, ResourceState state)> ResourceAccesses => _resourceAccesses;
internal Action<TPassData, ICommandBuffer>? RenderFunc => _renderFunc;
internal bool AllowCulling => _allowCulling;
public RenderGraphTextureHandle ReadTexture(RenderGraphTextureHandle handle)
{
_resourceAccesses.Add((handle, ResourceState.ShaderResource));
return handle;
}
public RenderGraphTextureHandle WriteTexture(RenderGraphTextureHandle handle)
{
_resourceAccesses.Add((handle, ResourceState.RenderTarget));
return handle;
}
public RenderGraphTextureHandle UseDepthBuffer(RenderGraphTextureHandle handle, bool writeAccess)
{
_resourceAccesses.Add((handle, writeAccess ? ResourceState.DepthWrite : ResourceState.DepthRead));
return handle;
}
public RenderGraphTextureHandle CreateTexture(TextureDescriptor descriptor)
{
var handle = _graph.CreateTransientTexture(descriptor);
return handle;
}
public RenderGraphBufferHandle ReadBuffer(RenderGraphBufferHandle handle)
{
_resourceAccesses.Add((handle, ResourceState.ShaderResource));
return handle;
}
public RenderGraphBufferHandle WriteBuffer(RenderGraphBufferHandle handle)
{
_resourceAccesses.Add((handle, ResourceState.UnorderedAccess));
return handle;
}
public RenderGraphBufferHandle CreateBuffer(BufferDescriptor descriptor)
{
var handle = _graph.CreateTransientBuffer(descriptor);
return handle;
}
public void SetRenderFunc(Action<TPassData, ICommandBuffer> renderFunc)
{
_renderFunc = renderFunc;
}
/// <summary>
/// Controls whether this pass can be culled if it doesn't contribute to the final output.
/// Set to false for synchronization passes, debug markers, or async compute boundaries.
/// Default is true.
/// </summary>
public void SetAllowCulling(bool allowCulling)
{
_allowCulling = allowCulling;
}
public void Dispose()
{
// Commit the pass when disposed (at end of using block)
if (!_committed)
{
_graph.CommitPass(this, _passName);
_committed = true;
}
}
}