feat(rhi): refactor resource & barrier management for D3D12
Modernizes resource and barrier management for the D3D12 backend. Key changes: - Simplifies BarrierDesc by removing nullable "before" states; now inferred from resource database. - Adds IsAliasing flag to BarrierDesc for aliasing transitions. - Replaces ResourceMemoryType with HeapType in BufferDesc and related APIs. - Enhances ResourceViewGroup with usage inference methods. - Adds D3D12 utility helpers for heap/flag conversions and resource description extraction. - Optimizes command buffer barrier emission, skipping redundant barriers. - Refactors Material and RenderContext to use new APIs and state tracking. - Updates ResourceManager pooling to use HeapType and standard Queue. - Simplifies RenderGraphExecutor barrier logic and aliasing handling. - Improves RenderSystem frame synchronization and resource retirement. - Cleans up obsolete code and improves debug output. BREAKING CHANGE: Updates to resource and barrier APIs require changes to all code interfacing with resource creation, barriers, and memory types.
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Core.Graphics;
|
||||
using Ghost.DSL.ShaderCompiler;
|
||||
using Ghost.Engine.Components;
|
||||
using Ghost.Graphics.Core;
|
||||
using Ghost.Graphics.RenderGraphModule;
|
||||
using Ghost.Graphics.RenderPipeline;
|
||||
@@ -77,9 +75,9 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
||||
|
||||
private static float3 IntersectFrustumPlanes(float4 p0, float4 p1, float4 p2)
|
||||
{
|
||||
float3 n0 = p0.xyz;
|
||||
float3 n1 = p1.xyz;
|
||||
float3 n2 = p2.xyz;
|
||||
var n0 = p0.xyz;
|
||||
var n1 = p1.xyz;
|
||||
var n2 = p2.xyz;
|
||||
|
||||
float det = math.dot(math.cross(n0, n1), n2);
|
||||
return (math.cross(n2, n1) * p0.w + math.cross(n0, n2) * p1.w - math.cross(n0, n1) * p2.w) * (1.0f / det);
|
||||
@@ -225,7 +223,7 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
||||
Size = instanceDataSize,
|
||||
Stride = (uint)sizeof(InstanceData),
|
||||
Usage = BufferUsage.Raw | BufferUsage.ShaderResource,
|
||||
MemoryType = ResourceMemoryType.Upload, // Upload directly for simplicity in testing
|
||||
HeapType = HeapType.Upload, // Upload directly for simplicity in testing
|
||||
};
|
||||
|
||||
instanceBufferHandle = resourceManager.CreateTransientBuffer(in instanceBufferDesc, "Instance Buffer");
|
||||
@@ -255,9 +253,9 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
||||
};
|
||||
}
|
||||
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(instanceBufferResource, null, BarrierSync.Copy, null, BarrierAccess.CopyDest));
|
||||
ctx.CommandBuffer.UploadBuffer(instanceBufferHandle, instanceDataArray.AsSpan());
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(instanceBufferResource, BarrierSync.Copy, BarrierSync.AllShading, BarrierAccess.CopyDest, BarrierAccess.ShaderResource));
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(instanceBufferResource, BarrierSync.Copy, BarrierAccess.CopyDest));
|
||||
ctx.UploadBuffer(instanceBufferHandle, instanceDataArray.AsSpan());
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(instanceBufferResource, BarrierSync.AllShading, BarrierAccess.ShaderResource));
|
||||
|
||||
// 2. Allocate and populate View Data buffer
|
||||
var viewBufferDesc = new BufferDesc
|
||||
@@ -265,7 +263,7 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
||||
Size = (uint)sizeof(ViewData),
|
||||
Stride = (uint)sizeof(ViewData),
|
||||
Usage = BufferUsage.Raw | BufferUsage.ShaderResource,
|
||||
MemoryType = ResourceMemoryType.Upload,
|
||||
HeapType = HeapType.Upload,
|
||||
};
|
||||
|
||||
viewBufferHandle = resourceManager.CreateTransientBuffer(in viewBufferDesc, "View Buffer");
|
||||
@@ -282,9 +280,9 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
||||
screenSize = new float4(request.view.sensorSize.x, request.view.sensorSize.y, 1.0f / request.view.sensorSize.x, 1.0f / request.view.sensorSize.y)
|
||||
};
|
||||
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(viewBufferResource, null, BarrierSync.Copy, null, BarrierAccess.CopyDest));
|
||||
ctx.CommandBuffer.UploadBuffer(viewBufferHandle, new ReadOnlySpan<ViewData>(in viewData));
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(viewBufferResource, BarrierSync.Copy, BarrierSync.AllShading, BarrierAccess.CopyDest, BarrierAccess.ShaderResource));
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(viewBufferResource, BarrierSync.Copy, BarrierAccess.CopyDest));
|
||||
ctx.UploadBuffer(viewBufferHandle, new ReadOnlySpan<ViewData>(in viewData));
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(viewBufferResource, BarrierSync.AllShading, BarrierAccess.ShaderResource));
|
||||
|
||||
// 3. Allocate and populate Global Frame Data buffer
|
||||
var frameDataSize = (uint)sizeof(FrameData);
|
||||
@@ -293,7 +291,7 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
||||
Size = frameDataSize,
|
||||
Stride = frameDataSize,
|
||||
Usage = BufferUsage.Raw | BufferUsage.ShaderResource,
|
||||
MemoryType = ResourceMemoryType.Upload,
|
||||
HeapType = HeapType.Upload,
|
||||
};
|
||||
|
||||
frameBufferHandle = resourceManager.CreateTransientBuffer(in frameBufferDesc, "Frame Buffer");
|
||||
@@ -305,9 +303,9 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
||||
instanceBufferIndex = resourceDatabase.GetBindlessIndex(instanceBufferResource),
|
||||
};
|
||||
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(frameBufferResource, null, BarrierSync.Copy, null, BarrierAccess.CopyDest));
|
||||
ctx.CommandBuffer.UploadBuffer(frameBufferHandle, new ReadOnlySpan<FrameData>(in frameData));
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(frameBufferResource, BarrierSync.Copy, BarrierSync.AllShading, BarrierAccess.CopyDest, BarrierAccess.ShaderResource));
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(frameBufferResource, BarrierSync.Copy, BarrierAccess.CopyDest));
|
||||
ctx.UploadBuffer(frameBufferHandle, new ReadOnlySpan<FrameData>(in frameData));
|
||||
ctx.CommandBuffer.Barrier(BarrierDesc.Buffer(frameBufferResource, BarrierSync.AllShading, BarrierAccess.ShaderResource));
|
||||
|
||||
if (request.renderFunc != null)
|
||||
{
|
||||
@@ -319,7 +317,7 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
||||
|
||||
var backBuffer = _renderGraph.ImportTexture(rt, "BackBuffer");
|
||||
|
||||
MeshletDebugPass(backBuffer, request.opaqueRenderList,
|
||||
MeshletDebugPass(backBuffer, request.opaqueRenderList,
|
||||
resourceDatabase.GetBindlessIndex(frameBufferResource),
|
||||
resourceDatabase.GetBindlessIndex(viewBufferResource),
|
||||
resourceDatabase.GetBindlessIndex(instanceBufferResource));
|
||||
@@ -360,7 +358,7 @@ public unsafe partial class TestRenderPipeline : IRenderPipeline
|
||||
builder.SetColorAttachment(backbuffer, 0);
|
||||
builder.SetDepthAttachment(depth);
|
||||
|
||||
builder.SetRenderFunc<MeshletDebugPassData>(static (data, ctx)=>
|
||||
builder.SetRenderFunc<MeshletDebugPassData>(static (data, ctx) =>
|
||||
{
|
||||
ctx.SetGlobalData(data.globalIndex, data.viewIndex);
|
||||
ctx.SetInstanceData(data.instanceIndex);
|
||||
|
||||
@@ -10,6 +10,7 @@ using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.Mathematics;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ghost.Graphics.Test.Windows;
|
||||
|
||||
@@ -113,9 +114,9 @@ public sealed partial class GraphicsTestWindow : Window
|
||||
//MeshBuilder.CreateCube(0.75f, default, Allocator.Persistent, out var vertices, out var indices);
|
||||
Utilities.MeshUtility.LoadMesh("F:/c/SimpleRayTracer/native/assets/bunny.obj", Allocator.Persistent, out var vertices, out var indices).ThrowIfFailed();
|
||||
|
||||
// TODO: Put this to the beginning of the frame without createing another command buffer?
|
||||
// TODO: Put this to the beginning of the frame without creating another command buffer?
|
||||
using var directCmd = _renderSystem.GraphicsEngine.CreateCommandBuffer(CommandBufferType.Graphics);
|
||||
var ctx = new RenderingContext(_renderSystem.GraphicsEngine, _renderSystem.ResourceManager, directCmd);
|
||||
var ctx = new RenderContext(_renderSystem.GraphicsEngine, _renderSystem.ResourceManager, directCmd);
|
||||
|
||||
using var cmdAllocator = _renderSystem.GraphicsEngine.CreateCommandAllocator(CommandBufferType.Graphics);
|
||||
directCmd.Begin(cmdAllocator);
|
||||
@@ -158,7 +159,6 @@ public sealed partial class GraphicsTestWindow : Window
|
||||
|
||||
_renderSystem?.ResourceManager.ReleaseMesh(_meshHandle);
|
||||
|
||||
_swapChain?.Dispose();
|
||||
//_jobScheduler.Dispose();
|
||||
_renderSystem?.Dispose();
|
||||
|
||||
@@ -203,8 +203,9 @@ public sealed partial class GraphicsTestWindow : Window
|
||||
return;
|
||||
}
|
||||
|
||||
if (_renderSystem.CPUFenceValue < _renderSystem.GPUFenceValue + _renderSystem.MaxFrameLatency)
|
||||
if (_renderSystem.TryAcquireCPUFrame())
|
||||
{
|
||||
//Debug.WriteLine($"CPU: Frame started.");
|
||||
_world.SystemManager.UpdateAll(default);
|
||||
_renderSystem.SignalCPUReady();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user