From 7860e5e341fc4ee2d937a39c62b1e6f4440bd48e Mon Sep 17 00:00:00 2001 From: Misaki Date: Tue, 24 Mar 2026 20:14:26 +0900 Subject: [PATCH] feat(render): add ECS-based test render pipeline Introduce TestRenderPipeline and settings, replacing MeshRenderPass. The new pipeline manages per-frame instance, view, and global data buffers, and uploads them for each render request. Refactor GraphicsTestWindow to use ECS World, setting up camera and mesh entities. Remove MeshRenderPass and related demo code. Add TotalRecordCount to RenderList, new data structs for buffer uploads, and static masks to RenderingLayerMask. Update project references and InternalsVisibleTo for Ghost.Graphics.Test access. --- src/Runtime/Ghost.Entities/AssemblyInfo.cs | 1 + .../Ghost.Graphics.RHI/RootSignatureLayout.cs | 16 +- src/Runtime/Ghost.Graphics/Core/RenderList.cs | 13 + .../Ghost.Graphics/Core/RenderingContext.cs | 7 +- .../Ghost.Graphics/Core/RenderingLayerMask.cs | 3 + .../Ghost.Graphics.Test.csproj | 1 + .../RenderPasses/MeshRenderPass.cs | 337 ------------------ .../RenderPasses/TestRenderPipeline.cs | 160 +++++++++ .../Windows/GraphicsTestWindow.xaml.cs | 124 ++++++- 9 files changed, 308 insertions(+), 354 deletions(-) delete mode 100644 src/Test/Ghost.Graphics.Test/RenderPasses/MeshRenderPass.cs create mode 100644 src/Test/Ghost.Graphics.Test/RenderPasses/TestRenderPipeline.cs diff --git a/src/Runtime/Ghost.Entities/AssemblyInfo.cs b/src/Runtime/Ghost.Entities/AssemblyInfo.cs index 37da096..b763b83 100644 --- a/src/Runtime/Ghost.Entities/AssemblyInfo.cs +++ b/src/Runtime/Ghost.Entities/AssemblyInfo.cs @@ -7,6 +7,7 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Ghost.Engine")] [assembly: InternalsVisibleTo("Ghost.Editor.Core")] [assembly: InternalsVisibleTo("Ghost.Entities.Test")] +[assembly: InternalsVisibleTo("Ghost.Graphics.Test")] [assembly: EngineAssembly] diff --git a/src/Runtime/Ghost.Graphics.RHI/RootSignatureLayout.cs b/src/Runtime/Ghost.Graphics.RHI/RootSignatureLayout.cs index 3911a2f..9ab41a2 100644 --- a/src/Runtime/Ghost.Graphics.RHI/RootSignatureLayout.cs +++ b/src/Runtime/Ghost.Graphics.RHI/RootSignatureLayout.cs @@ -41,15 +41,29 @@ public static class RootSignatureLayout public const int ROOT_PARAMETER_COUNT = 1; } -[StructLayout(LayoutKind.Sequential, Size = 16)] +[StructLayout(LayoutKind.Sequential, Size = 20)] public struct PushConstantsData { public uint globalIndex; public uint viewIndex; + public uint instanceIndex; public uint objectIndex; public uint materialIndex; } +[StructLayout(LayoutKind.Sequential, Size = 8)] +public struct GlobalFrameData +{ + public uint viewBufferIndex; + public uint instanceBufferIndex; +} + +[StructLayout(LayoutKind.Sequential, Pack = 1)] +public struct InstanceData +{ + public float4x4 localToWorld; +} + // The size should be 176 bytes (16-byte aligned) [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct PerViewData diff --git a/src/Runtime/Ghost.Graphics/Core/RenderList.cs b/src/Runtime/Ghost.Graphics/Core/RenderList.cs index 24ae384..e87bbe4 100644 --- a/src/Runtime/Ghost.Graphics/Core/RenderList.cs +++ b/src/Runtime/Ghost.Graphics/Core/RenderList.cs @@ -63,6 +63,19 @@ public struct RenderList : IDisposable private UnsafeArray> _threadLocalRecords; public readonly int ThreadLocalCount => _threadLocalRecords.Length; + public readonly int TotalRecordCount + { + get + { + var count = 0; + for (var i = 0; i < _threadLocalRecords.Length; i++) + { + count += _threadLocalRecords[i].Count; + } + + return count; + } + } public readonly bool IsCreated => _threadLocalRecords.IsCreated; public RenderList(int maxLevelOfConcurrency, int capacity, AllocationHandle allocationHandle) diff --git a/src/Runtime/Ghost.Graphics/Core/RenderingContext.cs b/src/Runtime/Ghost.Graphics/Core/RenderingContext.cs index 750e17a..45d8c23 100644 --- a/src/Runtime/Ghost.Graphics/Core/RenderingContext.cs +++ b/src/Runtime/Ghost.Graphics/Core/RenderingContext.cs @@ -160,8 +160,11 @@ public readonly unsafe ref struct RenderingContext public void UploadMeshlets(Handle mesh) { var r = _resourceManager.GetMeshReference(mesh); - if (r.IsFailure) return; - + if (r.IsFailure) + { + return; + } + ref var meshRef = ref r.Value; ref readonly var meshletData = ref meshRef.MeshletData; diff --git a/src/Runtime/Ghost.Graphics/Core/RenderingLayerMask.cs b/src/Runtime/Ghost.Graphics/Core/RenderingLayerMask.cs index 2d283ed..0144ad1 100644 --- a/src/Runtime/Ghost.Graphics/Core/RenderingLayerMask.cs +++ b/src/Runtime/Ghost.Graphics/Core/RenderingLayerMask.cs @@ -28,6 +28,9 @@ public readonly struct RenderingLayerMask : IEquatable private readonly uint _value; + public static readonly RenderingLayerMask Empty = new(0); + public static readonly RenderingLayerMask All = new(uint.MaxValue); + public RenderingLayerMask(uint value) { _value = value; diff --git a/src/Test/Ghost.Graphics.Test/Ghost.Graphics.Test.csproj b/src/Test/Ghost.Graphics.Test/Ghost.Graphics.Test.csproj index e8feb51..3d299fb 100644 --- a/src/Test/Ghost.Graphics.Test/Ghost.Graphics.Test.csproj +++ b/src/Test/Ghost.Graphics.Test/Ghost.Graphics.Test.csproj @@ -51,6 +51,7 @@ +