From 8556ff47087ff39b8d4d1dbd20b84c584d531c7f Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 4 Mar 2025 16:39:42 +0800 Subject: [PATCH 1/9] save --- Examples/HelloTriangle/Shaders/Shader.hlsl | 10 +++++++--- Examples/HelloTriangleVertex/Shaders/Shader.hlsl | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Examples/HelloTriangle/Shaders/Shader.hlsl b/Examples/HelloTriangle/Shaders/Shader.hlsl index 63b5d43..e3cf836 100644 --- a/Examples/HelloTriangle/Shaders/Shader.hlsl +++ b/Examples/HelloTriangle/Shaders/Shader.hlsl @@ -48,9 +48,13 @@ float SdTriangle(float2 p, float2 p0, float2 p1, float2 p2) float d2 = dot2(v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0)); float o = e0.x * e2.y - e0.y * e2.x; - float2 d = min(min(float2(d0, o * (v0.x * e0.y - v0.y * e0.x)), - float2(d1, o * (v1.x * e1.y - v1.y * e1.x))), - float2(d2, o * (v2.x * e2.y - v2.y * e2.x))); + float2 d = min( + min( + float2(d0, o * (v0.x * e0.y - v0.y * e0.x)), + float2(d1, o * (v1.x * e1.y - v1.y * e1.x)) + ), + float2(d2, o * (v2.x * e2.y - v2.y * e2.x)) + ); return -sqrt(d.x) * sign(d.y); } diff --git a/Examples/HelloTriangleVertex/Shaders/Shader.hlsl b/Examples/HelloTriangleVertex/Shaders/Shader.hlsl index 6dfa510..455a5bf 100644 --- a/Examples/HelloTriangleVertex/Shaders/Shader.hlsl +++ b/Examples/HelloTriangleVertex/Shaders/Shader.hlsl @@ -34,9 +34,13 @@ float SdTriangle(float2 p, float2 p0, float2 p1, float2 p2) float d2 = dot2(v2 - e2 * clamp(dot(v2, e2) / dot(e2, e2), 0.0, 1.0)); float o = e0.x * e2.y - e0.y * e2.x; - float2 d = min(min(float2(d0, o * (v0.x * e0.y - v0.y * e0.x)), - float2(d1, o * (v1.x * e1.y - v1.y * e1.x))), - float2(d2, o * (v2.x * e2.y - v2.y * e2.x))); + float2 d = min( + min( + float2(d0, o * (v0.x * e0.y - v0.y * e0.x)), + float2(d1, o * (v1.x * e1.y - v1.y * e1.x)) + ), + float2(d2, o * (v2.x * e2.y - v2.y * e2.x)) + ); return -sqrt(d.x) * sign(d.y); } From 2a9c81639fc52ee58db3dca1baff0c880b43fc58 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Wed, 5 Mar 2025 15:54:23 +0800 Subject: [PATCH 2/9] update package --- .../Coplt.Graphics.Core.csproj | 4 ++-- Coplt.Graphics.Core/Native/Native.cs | 21 ++++++++++++++++--- Examples/Colorful/Colorful.csproj | 2 +- Examples/Colorful/Example.cs | 4 ++-- Examples/HelloTriangle/HelloTriangle.csproj | 2 +- .../HelloTriangleVertex.csproj | 2 +- 6 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Coplt.Graphics.Core/Coplt.Graphics.Core.csproj b/Coplt.Graphics.Core/Coplt.Graphics.Core.csproj index 6ce33f6..90ad423 100644 --- a/Coplt.Graphics.Core/Coplt.Graphics.Core.csproj +++ b/Coplt.Graphics.Core/Coplt.Graphics.Core.csproj @@ -15,8 +15,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 7d550bf..68f1156 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -3058,6 +3058,15 @@ public partial struct FRenderInfo [NativeTypeName("u32[8]")] public _ResolveInfoIndex_e__FixedBuffer ResolveInfoIndex; + [NativeTypeName("Coplt::u32")] + public uint DsvResolveInfoIndex; + + [NativeTypeName("FGraphicsFormat[8]")] + public _RtvFormat_e__FixedBuffer RtvFormat; + + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat DsvFormat; + [NativeTypeName("f32[32]")] public _Color_e__FixedBuffer Color; @@ -3094,6 +3103,12 @@ public partial struct _ResolveInfoIndex_e__FixedBuffer public uint e0; } + [InlineArray(8)] + public partial struct _RtvFormat_e__FixedBuffer + { + public FGraphicsFormat e0; + } + [InlineArray(32)] public partial struct _Color_e__FixedBuffer { @@ -3468,7 +3483,7 @@ public partial struct FCommandDispatch public partial struct FCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L489_C9")] + [NativeTypeName("__AnonymousRecord_Command_L492_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -3666,7 +3681,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FRenderCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L517_C9")] + [NativeTypeName("__AnonymousRecord_Command_L520_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -3836,7 +3851,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FComputeCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L540_C9")] + [NativeTypeName("__AnonymousRecord_Command_L543_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Examples/Colorful/Colorful.csproj b/Examples/Colorful/Colorful.csproj index a61559b..22e9c0f 100644 --- a/Examples/Colorful/Colorful.csproj +++ b/Examples/Colorful/Colorful.csproj @@ -26,7 +26,7 @@ - + diff --git a/Examples/Colorful/Example.cs b/Examples/Colorful/Example.cs index eed5976..fce2a29 100644 --- a/Examples/Colorful/Example.cs +++ b/Examples/Colorful/Example.cs @@ -56,12 +56,12 @@ protected override async Task LoadResources(CommandList cmd) }, Name: "Args" ); - // cmd.Bind(ShaderBinding, [new(0, ArgBuffer)]); + cmd.Bind(ShaderBinding, [new(0, ArgBuffer)]); } protected override void Render(CommandList cmd, Time time) { cmd.Upload(ArgBuffer, [(float)time.Total.TotalSeconds]); using var render = cmd.Render([new(Output, new float4(0.83f, 0.8f, 0.97f, 1f))]); - render.Draw(Pipeline, 4); + render.Draw(Pipeline, 4, Binding: ShaderBinding); } } diff --git a/Examples/HelloTriangle/HelloTriangle.csproj b/Examples/HelloTriangle/HelloTriangle.csproj index a61559b..22e9c0f 100644 --- a/Examples/HelloTriangle/HelloTriangle.csproj +++ b/Examples/HelloTriangle/HelloTriangle.csproj @@ -26,7 +26,7 @@ - + diff --git a/Examples/HelloTriangleVertex/HelloTriangleVertex.csproj b/Examples/HelloTriangleVertex/HelloTriangleVertex.csproj index a61559b..22e9c0f 100644 --- a/Examples/HelloTriangleVertex/HelloTriangleVertex.csproj +++ b/Examples/HelloTriangleVertex/HelloTriangleVertex.csproj @@ -26,7 +26,7 @@ - + From df1d8cbe1c971ea7fe61695f27d66c1ea891ccfb Mon Sep 17 00:00:00 2001 From: U2A5F Date: Wed, 5 Mar 2025 23:45:10 +0800 Subject: [PATCH 3/9] save --- Coplt.Graphics.Core/Core/CommandList.cs | 287 ++++++--- Coplt.Graphics.Core/Core/ResState.cs | 25 +- Coplt.Graphics.Core/Core/ShaderBinding.cs | 10 +- Coplt.Graphics.Core/Native/Native.D3d12.cs | 15 - Coplt.Graphics.Core/Native/Native.cs | 40 +- Coplt.Graphics.Core/Native/ResState.cs | 6 +- Coplt.Graphics.Native/Api/FFI/Binding.h | 5 +- Coplt.Graphics.Native/Api/FFI/Command.h | 7 - Coplt.Graphics.Native/Api/Include/HashMap.h | 619 ++++++++++++++++++++ Coplt.Graphics.Native/D3d12/Src/Binding.cc | 39 +- Coplt.Graphics.Native/D3d12/Src/Binding.h | 24 +- Coplt.Graphics.Native/D3d12/Src/Command.cc | 15 +- Coplt.Graphics.Native/D3d12/Src/Command.h | 1 + 13 files changed, 918 insertions(+), 175 deletions(-) diff --git a/Coplt.Graphics.Core/Core/CommandList.cs b/Coplt.Graphics.Core/Core/CommandList.cs index f5b1c4f..18d2503 100644 --- a/Coplt.Graphics.Core/Core/CommandList.cs +++ b/Coplt.Graphics.Core/Core/CommandList.cs @@ -231,7 +231,7 @@ public readonly bool IsCompatible(in ScopedState other, bool legacy, out bool sa same = Legacy == other.Legacy; return Legacy.IsCompatible(other.Legacy); } - if (Layout != other.Layout) goto no; + if (!Layout.IsCompatible(other.Layout)) goto no; if (Access != other.Access) { same = false; @@ -256,7 +256,11 @@ public void Merge(in ScopedState other, bool legacy, bool same) if (!same) { if (legacy) Legacy |= other.Legacy; - else Access |= other.Access; + else + { + Layout = Layout.Merge(other.Layout, (Access & ResAccess.NoAccess) != 0); + Access |= other.Access; + } } } } @@ -434,14 +438,14 @@ internal ref ScopedState RecordScopedResState(FResourceRef res, ScopedState stat } internal ArgumentException Incompatible( - string Name, in ScopedState old_state, LegacyState Legacy, ResAccess Access + string Name, in ScopedState old_state, LegacyState Legacy, ResAccess Access, ResLayout Layout ) => UseLegacyState ? new ArgumentException( $"{Name} cannot be in [{Legacy}] and [{old_state.Legacy}] states at the same time" ) : new ArgumentException( - $"{Name} cannot be in [{Access}] and [{old_state.Access}] states at the same time" + $"{Name} cannot be in [{Access};{Layout}] and [{old_state.Access};{old_state.Layout}] states at the same time" ); #endregion @@ -811,6 +815,7 @@ public void Bind( ShaderBinding Binding, ReadOnlySpan Items ) { + if (Items.Length == 0) return; AddObject(Binding); var cmd = new FCommandBind { @@ -819,26 +824,24 @@ public void Bind( ItemCount = (uint)Items.Length, ItemsIndex = 0 }; - if (Items.Length > 0) - { - var index = m_bind_items.Count; - cmd.ItemsIndex = (uint)index; - CollectionsMarshal.SetCount(m_bind_items, m_bind_items.Count + Items.Length); - var dst = CollectionsMarshal.AsSpan(m_bind_items).Slice(index, Items.Length); - var defines = Binding.Layout.NativeDefines; - var views = Binding.MutViews; - for (var i = 0; i < Items.Length; i++) + var index = m_bind_items.Count; + cmd.ItemsIndex = (uint)index; + CollectionsMarshal.SetCount(m_bind_items, m_bind_items.Count + Items.Length); + var dst = CollectionsMarshal.AsSpan(m_bind_items).Slice(index, Items.Length); + var defines = Binding.Layout.NativeDefines; + var views = Binding.MutViews; + for (var i = 0; i < Items.Length; i++) + { + var src = Items[i]; + ref readonly var define = ref defines[(int)src.Index]; + define.CheckCompatible(src.View, (int)src.Index); + dst[i] = new() { - var src = Items[i]; - ref readonly var define = ref defines[(int)src.Index]; - define.CheckCompatible(src.View, (int)src.Index); - dst[i] = new() - { - Index = src.Index, - View = src.View.ToFFI(), - }; - views[(int)src.Index] = src.View; - } + Index = src.Index, + View = src.View.ToFFI(), + }; + ref var view = ref views[(int)src.Index]; + view = src.View; } m_commands.Add(new() { Bind = cmd }); } @@ -1163,31 +1166,40 @@ public RenderScope Render( #region State - if (has_dsv) - { - ref var old_state = ref RecordScopedResState( - info.Dsv, new( - ScopedStateUsage.Pixel, - ResLayout.DepthStencilWrite, - ResAccess.DepthStencilWrite, - LegacyState.DepthWrite - ), out var compatible - ); - if (!compatible) - throw Incompatible("Depth Stencil", old_state, LegacyState.DepthWrite, ResAccess.DepthStencilWrite); - } - for (var i = 0; i < info.NumRtv; i++) + if (AutoBarrierEnabled) { - ref var old_state = ref RecordScopedResState( - info.Rtv[i], new( - ScopedStateUsage.Pixel, - ResLayout.RenderTarget, - ResAccess.RenderTarget, - LegacyState.RenderTarget - ), out var compatible - ); - if (!compatible) - throw Incompatible("Render Target", old_state, LegacyState.RenderTarget, ResAccess.RenderTarget); + if (has_dsv) + { + ref var old_state = ref RecordScopedResState( + info.Dsv, new( + ScopedStateUsage.Pixel, + ResLayout.DepthStencilWrite, + ResAccess.DepthStencilWrite, + LegacyState.DepthWrite + ), out var compatible + ); + if (!compatible) + throw Incompatible( + "Depth Stencil", old_state, LegacyState.DepthWrite, + ResAccess.DepthStencilWrite, ResLayout.DepthStencilWrite + ); + } + for (var i = 0; i < info.NumRtv; i++) + { + ref var old_state = ref RecordScopedResState( + info.Rtv[i], new( + ScopedStateUsage.Pixel, + ResLayout.RenderTarget, + ResAccess.RenderTarget, + LegacyState.RenderTarget + ), out var compatible + ); + if (!compatible) + throw Incompatible( + "Render Target", old_state, LegacyState.RenderTarget, + ResAccess.RenderTarget, ResLayout.RenderTarget + ); + } } #endregion @@ -1261,6 +1273,79 @@ public ComputeScope Compute(string? Name = null, ReadOnlySpan Name8 = defa #endregion #endregion + + #region SyncBinding + + /// + /// 必须在 Render 或者 Compute 范围内使用 + /// + internal void SyncBinding(ShaderBinding? Binding) + { + if (Binding == null) return; + if (!AutoBarrierEnabled) return; + for (var i = 0; i < Binding.Views.Length; i++) + { + ref readonly var def = ref Binding.Layout.NativeDefines[i]; + if (def.View is FShaderLayoutItemView.Sampler) continue; + ref readonly var view = ref Binding.Views[i]; + if (view.Tag is View.Tags.None) continue; + var is_buffer = view.Tag is View.Tags.Buffer; + var res = view.Tag switch + { + View.Tags.Buffer => AddResource(view.Buffer), + _ => throw new ArgumentOutOfRangeException() + }; + var Usage = def.Stage switch + { + FShaderStage.Compute => ScopedStateUsage.Compute, + FShaderStage.Pixel => ScopedStateUsage.Pixel, + FShaderStage.Vertex => ScopedStateUsage.Vertex, + FShaderStage.Mesh => ScopedStateUsage.Mesh, + FShaderStage.Task => ScopedStateUsage.Mesh, + _ => throw new ArgumentOutOfRangeException() + }; + var Layout = ResLayout.None; + ResAccess Access; + LegacyState Legacy; + switch (def.View) + { + case FShaderLayoutItemView.Cbv: + case FShaderLayoutItemView.Constants: + if (!is_buffer) + throw new ArgumentException($"The binding {i} requires a Cbv but actually resource is not buffer."); + Access = ResAccess.ConstantBuffer; + Legacy = LegacyState.ConstantBuffer; + break; + case FShaderLayoutItemView.Srv: + if (!is_buffer) Layout = ResLayout.ShaderResource; + Access = ResAccess.ShaderResource; + Legacy = LegacyState.ShaderResource; + break; + case FShaderLayoutItemView.Uav: + if (!is_buffer) Layout = ResLayout.UnorderedAccess; + Access = ResAccess.UnorderedAccess; + Legacy = LegacyState.UnorderedAccess; + break; + case FShaderLayoutItemView.Sampler: + continue; + default: + throw new ArgumentOutOfRangeException(); + } + ref var old_state = ref RecordScopedResState( + res, new() + { + Usage = Usage, + Layout = Layout, + Access = Access, + Legacy = Legacy + }, out var compatible + ); + if (!compatible) + throw Incompatible($"{Binding}::[{i}]", old_state, Legacy, Access, Layout); + } + } + + #endregion } #region DebugScope @@ -1607,6 +1692,20 @@ public void SetBinding(ShaderBinding Binding) Binding = Binding.m_ptr, }; m_commands.Add(new() { SetBinding = cmd }); + if (!m_has_uav_writes) + { + for (var i = 0; i < Binding.Views.Length; i++) + { + ref readonly var view = ref Binding.Views[i]; + if (view.Tag is View.Tags.None) continue; + ref readonly var def = ref Binding.Layout.NativeDefines[i]; + if (def.View is FShaderLayoutItemView.Uav) + { + m_has_uav_writes = true; + break; + } + } + } } #endregion @@ -1681,13 +1780,19 @@ ReadOnlySpan VertexBuffers Offset = index_buffer.Offset, Size = index_buffer.Size == uint.MaxValue ? (uint)index_buffer.Buffer.Size : index_buffer.Size, }; - ref var old_state = ref self.RecordScopedResState( - buf.IndexBuffer.Buffer, new( - ScopedStateUsage.Vertex, ResLayout.None, ResAccess.IndexBuffer, LegacyState.IndexBuffer - ), out var compatible - ); - if (!compatible) - throw self.Incompatible("Index buffer", old_state, LegacyState.IndexBuffer, ResAccess.IndexBuffer); + if (self.AutoBarrierEnabled) + { + ref var old_state = ref self.RecordScopedResState( + buf.IndexBuffer.Buffer, new( + ScopedStateUsage.Vertex, ResLayout.None, ResAccess.IndexBuffer, LegacyState.IndexBuffer + ), out var compatible + ); + if (!compatible) + throw self.Incompatible( + "Index buffer", old_state, LegacyState.IndexBuffer, + ResAccess.IndexBuffer, ResLayout.None + ); + } } if (VertexBuffers.Length > 0) { @@ -1711,15 +1816,19 @@ ReadOnlySpan VertexBuffers }, Index = buffer.Index, }; - ref var old_state = ref self.RecordScopedResState( - dst.Base.Buffer, new( - ScopedStateUsage.Vertex, ResLayout.None, ResAccess.VertexBuffer, LegacyState.VertexBuffer - ), out var compatible - ); - if (!compatible) - throw self.Incompatible( - "Vertex buffer", old_state, LegacyState.VertexBuffer, ResAccess.IndexBuffer + if (self.AutoBarrierEnabled) + { + ref var old_state = ref self.RecordScopedResState( + dst.Base.Buffer, new( + ScopedStateUsage.Vertex, ResLayout.None, ResAccess.VertexBuffer, LegacyState.VertexBuffer + ), out var compatible ); + if (!compatible) + throw self.Incompatible( + "Vertex buffer", old_state, LegacyState.VertexBuffer, + ResAccess.IndexBuffer, ResLayout.None + ); + } } } self.m_mesh_buffers.Add(buf); @@ -1789,6 +1898,7 @@ public void Draw( m_commands.Add(new() { Draw = cmd }); m_has_pixel_shader = true; m_has_vertex_shader = true; + self.SyncBinding(m_current_binding); } #endregion @@ -1796,12 +1906,14 @@ public void Draw( #region DispatchMesh public void DispatchMesh( - uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1 - ) => DispatchMesh(null, GroupCountX, GroupCountY, GroupCountZ); + uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1, + ShaderBinding? Binding = null + ) => DispatchMesh(null, GroupCountX, GroupCountY, GroupCountZ, Binding); public void DispatchMesh( ShaderPipeline? Pipeline, - uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1 + uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1, + ShaderBinding? Binding = null ) { if (Pipeline != null) @@ -1816,6 +1928,7 @@ public void DispatchMesh( if (!m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) throw new ArgumentException("Only Mesh shaders can use DispatchMesh"); } + if (Binding != null) SetBinding(Binding); var cmd = new FCommandDispatch { Base = { Type = FCommandType.Draw }, @@ -1828,6 +1941,7 @@ public void DispatchMesh( m_has_pixel_shader = true; m_has_mesh_shader = true; m_has_task_shader = m_current_pipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Task); + self.SyncBinding(m_current_binding); } #endregion @@ -2021,26 +2135,31 @@ public void SetBinding(ShaderBinding Binding) #region Dispatch public void Dispatch( - uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1 - ) => Dispatch(null, DispatchType.Compute, GroupCountX, GroupCountY, GroupCountZ); + uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1, + ShaderBinding? Binding = null + ) => Dispatch(null, DispatchType.Compute, GroupCountX, GroupCountY, GroupCountZ, Binding); public void DispatchMesh( - uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1 - ) => Dispatch(null, DispatchType.Mesh, GroupCountX, GroupCountY, GroupCountZ); + uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1, + ShaderBinding? Binding = null + ) => Dispatch(null, DispatchType.Mesh, GroupCountX, GroupCountY, GroupCountZ, Binding); public void Dispatch( ShaderPipeline Pipeline, - uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1 - ) => Dispatch(Pipeline, DispatchType.Auto, GroupCountX, GroupCountY, GroupCountZ); + uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1, + ShaderBinding? Binding = null + ) => Dispatch(Pipeline, DispatchType.Auto, GroupCountX, GroupCountY, GroupCountZ, Binding); public void DispatchMesh( ShaderPipeline Pipeline, - uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1 - ) => Dispatch(Pipeline, DispatchType.Mesh, GroupCountX, GroupCountY, GroupCountZ); + uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1, + ShaderBinding? Binding = null + ) => Dispatch(Pipeline, DispatchType.Mesh, GroupCountX, GroupCountY, GroupCountZ, Binding); public void Dispatch( ShaderPipeline? Pipeline, DispatchType Type, - uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1 + uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1, + ShaderBinding? Binding = null ) { if (Pipeline != null) @@ -2055,21 +2174,36 @@ public void Dispatch( if (!m_current_pipeline.Shader.Stages.HasAnyFlags(ShaderStageFlags.Compute | ShaderStageFlags.Mesh)) throw new ArgumentException("Only Mesh and Compute shaders can use Dispatch/DispatchMesh"); } + if (Binding != null) SetBinding(Binding); if (Type == DispatchType.Auto) { - if (m_current_pipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Compute)) Type = DispatchType.Compute; - else if (m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) Type = DispatchType.Mesh; + if (m_current_pipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Compute)) + { + Type = DispatchType.Compute; + m_has_compute_shader = true; + } + else if (m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) + { + Type = DispatchType.Mesh; + m_has_mesh_shader = true; + if (m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Task)) + m_has_task_shader = true; + } else throw new UnreachableException(); } else if (Type == DispatchType.Mesh) { if (!m_current_pipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) throw new ArgumentException("Only Mesh shaders can use DispatchMesh"); + m_has_mesh_shader = true; + if (m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Task)) + m_has_task_shader = true; } else if (Type == DispatchType.Compute) { if (!m_current_pipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Compute)) throw new ArgumentException("Only Compute shaders can use Dispatch"); + m_has_compute_shader = true; } var cmd = new FCommandDispatch { @@ -2086,6 +2220,7 @@ public void Dispatch( }, }; m_commands.Add(new() { Dispatch = cmd }); + self.SyncBinding(m_current_binding); } #endregion diff --git a/Coplt.Graphics.Core/Core/ResState.cs b/Coplt.Graphics.Core/Core/ResState.cs index fa92068..e5cfd20 100644 --- a/Coplt.Graphics.Core/Core/ResState.cs +++ b/Coplt.Graphics.Core/Core/ResState.cs @@ -1,4 +1,5 @@ -using Coplt.Graphics.Native; +using System.Diagnostics; +using Coplt.Graphics.Native; namespace Coplt.Graphics.Core; @@ -136,4 +137,26 @@ public static partial class GraphicsExtensions Legacy = value.Legacy.FromFFI(), CrossQueue = value.CrossQueue, }; + + public static bool IsReadOnly(this ResLayout self) => + self is ResLayout.GenericRead or ResLayout.ShaderResource or ResLayout.CopySrc or + ResLayout.DepthStencilRead or ResLayout.ResolveSrc or ResLayout.ShadingRate or + ResLayout.VideoDecodeRead or ResLayout.VideoProcessRead or ResLayout.VideoEncodeRead; + + public static bool IsCompatible(this ResLayout self, ResLayout other) + { + if (self == other) return true; + return self.IsReadOnly() && other.IsReadOnly(); + } + + public static ResLayout Merge(this ResLayout self, ResLayout other, bool strict) + { + if (self == other) return self; + if (self.IsReadOnly() && other.IsReadOnly()) + { + if (strict) return other; + return ResLayout.GenericRead; + } + return self; + } } diff --git a/Coplt.Graphics.Core/Core/ShaderBinding.cs b/Coplt.Graphics.Core/Core/ShaderBinding.cs index db361ac..b0ee7d9 100644 --- a/Coplt.Graphics.Core/Core/ShaderBinding.cs +++ b/Coplt.Graphics.Core/Core/ShaderBinding.cs @@ -16,7 +16,6 @@ public sealed unsafe partial class ShaderBinding internal readonly GpuDevice m_device; internal readonly GpuQueue m_queue; internal readonly ShaderLayout m_layout; - internal readonly FRoSlice m_native_views; internal readonly View[] m_views; #endregion @@ -27,7 +26,6 @@ public sealed unsafe partial class ShaderBinding public GpuDevice Device => m_device; public GpuQueue Queue => m_queue; public ShaderLayout Layout => m_layout; - public ReadOnlySpan NativeViews => m_native_views.Span; public ReadOnlySpan Views => m_views; internal Span MutViews => m_views; public ref readonly View this[int index] => ref m_views[index]; @@ -44,13 +42,7 @@ internal ShaderBinding(FShaderBinding* ptr, string? name, GpuDevice device, GpuQ m_queue = queue; m_layout = layout; - { - uint size = 0; - var views = m_ptr->GetViews(&size); - m_native_views = new(views, size); - } - - m_views = new View[m_native_views.Length]; + m_views = new View[m_layout.m_native_defines.Length]; } #endregion diff --git a/Coplt.Graphics.Core/Native/Native.D3d12.cs b/Coplt.Graphics.Core/Native/Native.D3d12.cs index cb1eed9..d2aee49 100644 --- a/Coplt.Graphics.Core/Native/Native.D3d12.cs +++ b/Coplt.Graphics.Core/Native/Native.D3d12.cs @@ -502,21 +502,6 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FD3d12ShaderBinding*)Unsafe.AsPointer(ref this), &result, name); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FView *")] - public FView* GetViews([NativeTypeName("Coplt::u32 *")] uint* out_size) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FD3d12ShaderBinding*)Unsafe.AsPointer(ref this), out_size); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Set([NativeTypeName("Coplt::u32")] uint count, [NativeTypeName("const FShaderBindingBatchSet *")] FShaderBindingBatchSet* bindings) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FD3d12ShaderBinding*)Unsafe.AsPointer(ref this), &result, count, bindings); - } - public interface Interface : FShaderBinding.Interface { } diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 68f1156..1d993c5 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1534,7 +1534,7 @@ public unsafe partial struct FShaderBindingCreateOptions public FShaderLayout* Layout; } - public partial struct FShaderBindingBatchSet + public partial struct FBindItem { [NativeTypeName("Coplt::FView")] public FView View; @@ -1585,28 +1585,8 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FShaderBinding*)Unsafe.AsPointer(ref this), &result, name); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FView *")] - public FView* GetViews([NativeTypeName("Coplt::u32 *")] uint* out_size) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderBinding*)Unsafe.AsPointer(ref this), out_size); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Set([NativeTypeName("Coplt::u32")] uint count, [NativeTypeName("const FShaderBindingBatchSet *")] FShaderBindingBatchSet* bindings) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderBinding*)Unsafe.AsPointer(ref this), &result, count, bindings); - } - public interface Interface : FGpuObject.Interface { - [return: NativeTypeName("Coplt::FView *")] - FView* GetViews([NativeTypeName("Coplt::u32 *")] uint* out_size); - - [return: NativeTypeName("Coplt::FResult")] - FResult Set([NativeTypeName("Coplt::u32")] uint count, [NativeTypeName("const FShaderBindingBatchSet *")] FShaderBindingBatchSet* bindings); } } @@ -2953,18 +2933,6 @@ public enum FDepthStencilClearFlags : byte Stencil = 2, } - public partial struct FBindItem - { - [NativeTypeName("Coplt::FCommandType")] - public FCommandType Type; - - [NativeTypeName("Coplt::FView")] - public FView View; - - [NativeTypeName("Coplt::u32")] - public uint Index; - } - public partial struct FUploadLoc { [NativeTypeName("Coplt::u32")] @@ -3483,7 +3451,7 @@ public partial struct FCommandDispatch public partial struct FCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L492_C9")] + [NativeTypeName("__AnonymousRecord_Command_L485_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -3681,7 +3649,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FRenderCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L520_C9")] + [NativeTypeName("__AnonymousRecord_Command_L513_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -3851,7 +3819,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FComputeCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L543_C9")] + [NativeTypeName("__AnonymousRecord_Command_L536_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Coplt.Graphics.Core/Native/ResState.cs b/Coplt.Graphics.Core/Native/ResState.cs index 7e934d5..76e8bda 100644 --- a/Coplt.Graphics.Core/Native/ResState.cs +++ b/Coplt.Graphics.Core/Native/ResState.cs @@ -15,7 +15,7 @@ public readonly bool IsCompatible(in FResState other, bool legacy, /* 顺序 */ same = Legacy == other.Legacy; return Legacy.FromFFI().IsCompatible(other.Legacy.FromFFI()); } - if (Layout != other.Layout || CrossQueue != other.CrossQueue) goto no; + if (!Layout.FromFFI().IsCompatible(other.Layout.FromFFI()) || CrossQueue != other.CrossQueue) goto no; if (Access != other.Access) { same = false; @@ -68,6 +68,7 @@ public readonly FResState Merge(in FResState other, bool legacy, /* 顺序 */ bo var ona = (other.Access.FromFFI() & ResAccess.NoAccess) != 0; if (b2a) { + var Layout = this.Layout.FromFFI().Merge(other.Layout.FromFFI(), sna).ToFFI(); if (sna) return new() { @@ -82,6 +83,7 @@ public readonly FResState Merge(in FResState other, bool legacy, /* 顺序 */ bo } else { + var Layout = this.Layout.FromFFI().Merge(other.Layout.FromFFI(), ona).ToFFI(); if (ona) return new() { @@ -96,7 +98,7 @@ public readonly FResState Merge(in FResState other, bool legacy, /* 顺序 */ bo } return new() { - Layout = Layout, + Layout = this.Layout.FromFFI().Merge(other.Layout.FromFFI(), false).ToFFI(), // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags Access = Access | other.Access, // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags diff --git a/Coplt.Graphics.Native/Api/FFI/Binding.h b/Coplt.Graphics.Native/Api/FFI/Binding.h index d14b574..65e737f 100644 --- a/Coplt.Graphics.Native/Api/FFI/Binding.h +++ b/Coplt.Graphics.Native/Api/FFI/Binding.h @@ -12,7 +12,7 @@ namespace Coplt FShaderLayout* Layout{}; }; - struct FShaderBindingBatchSet + struct FBindItem { FView View{}; u32 Index{}; @@ -20,8 +20,5 @@ namespace Coplt COPLT_INTERFACE_DEFINE(FShaderBinding, "a3ca644a-0e02-4d25-9a18-8835d66600f7", FGpuObject) { - virtual FView* GetViews(u32* out_size) noexcept = 0; - - virtual FResult Set(u32 count, const FShaderBindingBatchSet* bindings) noexcept = 0; }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Command.h b/Coplt.Graphics.Native/Api/FFI/Command.h index 854fd50..b23be68 100644 --- a/Coplt.Graphics.Native/Api/FFI/Command.h +++ b/Coplt.Graphics.Native/Api/FFI/Command.h @@ -196,13 +196,6 @@ namespace Coplt Stencil = 2, }; - struct FBindItem - { - FCommandType Type{}; - FView View{}; - u32 Index{}; - }; - struct FUploadLoc { u32 Index{}; diff --git a/Coplt.Graphics.Native/Api/Include/HashMap.h b/Coplt.Graphics.Native/Api/Include/HashMap.h index b36966d..a04e6a7 100644 --- a/Coplt.Graphics.Native/Api/Include/HashMap.h +++ b/Coplt.Graphics.Native/Api/Include/HashMap.h @@ -59,6 +59,9 @@ namespace Coplt }; template Hash = std::hash, Eq Eq = std::equal_to> + class HashMap; + + template Hash , Eq Eq> class HashMap final { using HashHelpers = _HashMap_internal::HashHelpers; @@ -1016,4 +1019,620 @@ namespace Coplt return entries; } }; + + template Hash , Eq Eq> + class HashMap final + { + using HashHelpers = _HashMap_internal::HashHelpers; + using Slot = _HashMap_internal::Slot; + + template + using UP = Uninit&; + template + using RP = T&; + + private: + i32* m_p_buckets{}; + Slot* m_p_slots{}; + Key* m_p_keys{}; + u64 m_fast_mod_multiplier{}; + u32 m_cap{}; + i32 m_count{}; + i32 m_free_list{}; + i32 m_free_count{}; + Hash m_hash{}; + Eq m_eq{}; + + constexpr static i32 StartOfFreeList = -3; + + std::span Slots() const + { + return std::span(m_p_slots, m_cap); + } + + std::span Keys() const + { + return std::span(m_p_keys, m_cap); + } + + public: + HashMap() = default; + + ~HashMap() + { + if (m_p_buckets != nullptr) + { + mi_free_aligned(m_p_buckets, alignof(i32)); + } + if (m_p_slots != nullptr) + { + mi_free_aligned(m_p_slots, alignof(Slot)); + } + if (m_p_keys != nullptr) + { + if constexpr (!std::is_trivially_destructible()) + { + auto iter = Iterator(); + while (auto key = iter.Next()) + { + key->~Key(); + } + } + mi_free_aligned(m_p_keys, alignof(Key)); + } + } + + HashMap(HashMap&& other) noexcept + : m_p_buckets(std::exchange(other.m_p_buckets, nullptr)), + m_p_slots(std::exchange(other.m_p_slots, nullptr)), + m_p_keys(std::exchange(other.m_p_keys, nullptr)), + m_fast_mod_multiplier(std::exchange(other.m_fast_mod_multiplier, 0)), + m_cap(std::exchange(other.m_cap, 0)), + m_count(std::exchange(other.m_count, 0)), + m_free_list(std::exchange(other.m_free_list, 0)) + { + } + + HashMap& operator=(HashMap&& other) noexcept + { + if (this == &other) return *this; + new HashMap(std::move(*this)); + new(this) HashMap(std::forward(other)); + return *this; + } + + HashMap(HashMap& other) noexcept = delete; + + HashMap& operator=(HashMap& other) = delete; + + usize Count() const noexcept + { + return m_count; + } + + bool IsEmpty() const noexcept + { + return m_count == 0; + } + + private: + i32 Initialize(const i32 capacity) + { + const auto size = HashHelpers::GetPrime(capacity); + + m_cap = size; + m_p_buckets = static_cast(mi_zalloc_aligned(size * sizeof(i32), alignof(i32))); + m_p_slots = static_cast(mi_zalloc_aligned(size * sizeof(Slot), alignof(Slot))); + m_p_keys = static_cast(mi_malloc_aligned(size * sizeof(Key), alignof(Key))); + + m_free_list = -1; + m_fast_mod_multiplier = HashHelpers::GetFastModMultiplier(static_cast(size)); + + return size; + } + + i32* GetBucket(const usize hash_code) const + { + const auto index = HashHelpers::FastMod(hash_code, m_cap, m_fast_mod_multiplier); + return &m_p_buckets[index]; + } + + void Resize() + { + Resize(HashHelpers::ExpandPrime(m_count)); + } + + void Resize(i32 new_size) + { + m_cap = new_size; + mi_free_aligned(m_p_buckets, alignof(i32)); + m_p_buckets = static_cast(mi_zalloc_aligned(new_size * sizeof(i32), alignof(i32))); + m_p_slots = static_cast(mi_rezalloc_aligned(m_p_slots, new_size * sizeof(Slot), alignof(Slot))); + m_p_keys = static_cast( + mi_realloc_aligned(m_p_keys, new_size * sizeof(Key), alignof(Key)) + ); + m_fast_mod_multiplier = HashHelpers::GetFastModMultiplier(static_cast(new_size)); + + const auto count = m_count; + for (int i = 0; i < count; i++) + { + if (auto& slot = m_p_slots[i]; slot.next >= -1) + { + const auto bucket = GetBucket(slot.hash_code()); + slot.next = *bucket - 1; // Value in _buckets is 1-based + *bucket = i + 1; + } + } + } + + public: + // 返回是否成功添加,false 表示已经存在 + template QueryKey, Fn> CreateKey> + bool Add(QueryKey query_key, CreateKey create_key) + { + if (m_p_buckets == nullptr) Initialize(0); + + const Key& key = query_key(); + const usize hash_code = m_hash(key); + + u32 collision_count = 0; + auto bucket = GetBucket(hash_code); + auto i = *bucket - 1; + + while (static_cast(i) < m_cap) + { + auto& slot = m_p_slots[i]; + auto& slot_key = m_p_keys[i]; + if (slot.hash_code() == hash_code && m_eq(slot_key, key)) + { + return false; + } + + i = slot.next; + + collision_count++; + if (collision_count >= m_cap) + { + throw std::out_of_range("HashMap does not support concurrent operations"); + } + } + + i32 index{}; + if (m_free_count > 0) + { + index = m_free_list; + m_free_list = StartOfFreeList - m_p_slots[m_free_list].next; + m_free_count--; + } + else + { + const auto count = m_count; + if (count == m_cap) + { + Resize(); + bucket = GetBucket(hash_code); + } + index = count; + m_count = count + 1; + } + + auto& slot = m_p_slots[index]; + auto& slot_key = m_p_keys[index]; + slot.hash_code() = hash_code; + slot.next = *bucket - 1; + Uninit u_key(slot_key); + create_key(u_key); + *bucket = index + 1; + + return true; + } + + // 返回是否成功添加,false 表示已经存在 + bool Add(Key&& key) + { + return Add( + [&] -> const Key& { return key; }, + [&](UP p) -> void { new(p.unsafe_put()) Key(std::move(key)); } + ); + } + + // 返回是否成功添加,false 表示已经存在 + bool Add(const Key& key) + { + return Add( + [&] -> const Key& { return key; }, + [&](UP p) -> void { new(p.unsafe_put()) Key(key); } + ); + } + + template QHash = std::hash, Coplt::Eq QEq = std::equal_to> + bool Contains(const QKey& query_key, QHash hasher, QEq eq) const + { + Slot* slot = nullptr; + Key* slot_key = nullptr; + if (m_p_buckets == nullptr) return false; + + auto hash_code = hasher(query_key); + auto i = *GetBucket(hash_code); + u32 collision_count = 0; + + --i; + // Value in _buckets is 1-based; subtract 1 from i. We do it here so it fuses with the following conditional. + do + { + if (static_cast(i) >= m_cap) + { + return false; + } + + slot = std::addressof(m_p_slots[i]); + slot_key = std::addressof(m_p_keys[i]); + if (slot->hash_code() == hash_code && eq(*slot_key, query_key)) + { + return true; + } + + i = slot->next; + + collision_count++; + } + while (collision_count <= m_cap); + + // The chain of entries forms a loop; which means a concurrent update has happened. + // Break out of the loop and throw, rather than looping forever. + throw std::out_of_range("HashMap does not support concurrent operations"); + } + + bool Contains(const Key& key) const + { + return Contains(key, m_hash, m_eq); + } + + // 返回是否删除,如果删除并且 out_key 不为空将写入 out_key + template QHash = std::hash, Coplt::Eq QEq = std::equal_to> + bool Remove(const QKey& query_key, QHash hasher, QEq eq, Key* out_key) + { + if (m_p_buckets == nullptr) return false; + u32 collision_count = 0; + auto hash_code = hasher(query_key); + auto bucket = GetBucket(hash_code); + i32 last = -1; + i32 i = *bucket - 1; // Value in buckets is 1-based + while (i >= 0) + { + auto& slot = m_p_slots[i]; + auto& slot_key = m_p_keys[i]; + + if (slot.hash_code() == hash_code && eq(slot_key, query_key)) + { + if (last < 0) + { + *bucket = slot.next + 1; // Value in buckets is 1-based + } + else + { + m_p_slots[last].next = slot.next; + } + + slot.next = StartOfFreeList - m_free_list; + + if (out_key != nullptr) + { + *out_key = std::move(slot_key); + } + if constexpr (std::is_trivially_destructible()) + { + slot_key.~Key(); + } + + m_free_list = i; + m_free_count++; + return true; + } + + last = i; + i = slot.next; + + collision_count++; + if (collision_count > m_cap) + { + throw std::out_of_range("HashMap does not support concurrent operations"); + } + } + return false; + } + + // 返回是否删除 + template QHash = std::hash, Coplt::Eq QEq = std::equal_to> + bool Remove(const QKey& query_key, QHash hasher, QEq eq) + { + return Remove(query_key, fove(hasher), fove(eq), nullptr); + } + + // 返回是否删除,如果删除并且 out_key 不为空将写入 out_key + bool Remove(const Key& key, Key* out_key) + { + return Remove(key, m_hash, m_eq, out_key); + } + + // 返回是否删除 + bool Remove(const Key& key) + { + return Remove(key, m_hash, m_eq, nullptr); + } + + void Clear() + { + if (m_count > 0) + { + if constexpr (!std::is_trivially_destructible()) + { + auto iter = Iterator(); + while (auto key = iter.Next()) + { + key->~Key(); + } + } + + std::fill_n(m_p_buckets, m_cap, 0); + std::fill_n(m_p_slots, m_cap, Slot{}); + + m_count = 0; + m_free_list = -1; + m_free_count = 0; + } + } + + class MutIterator + { + HashMap* m_self{}; + i32 m_index{0}; + + public: + explicit MutIterator(HashMap* self) : m_self(self) + { + } + + // 尝试获取下个项,如果成功获取将不是 null + Key* Next() + { + while (static_cast(m_index) < static_cast(m_self->m_count)) + { + auto i = m_index++; + auto& slot = m_self->m_p_slots[i]; + auto& slot_key = m_self->m_p_keys[i]; + + if (slot.next >= -1) + { + return std::addressof(slot_key); + } + } + + m_index = m_self->m_count + 1; + return nullptr; + } + }; + + MutIterator Iterator() + { + return MutIterator(this); + } + + class ImmIterator + { + const HashMap* m_self{}; + i32 m_index{0}; + + public: + explicit ImmIterator(const HashMap* self) : m_self(self) + { + } + + // 尝试获取下个项,如果成功获取将不是 null + const Key* Next() + { + while (static_cast(m_index) < static_cast(m_self->m_count)) + { + auto i = m_index++; + auto& slot = m_self->m_p_slots[i]; + auto& slot_key = m_self->m_p_keys[i]; + + if (slot.next >= -1) + { + return std::addressof(slot_key); + } + } + + m_index = m_self->m_count + 1; + return nullptr; + } + }; + + ImmIterator Iterator() const + { + return ImmIterator(this); + } + + class StdIterator + { + HashMap* m_self{}; + i32 m_index{0}; + + void AdvanceToValid() + { + while (m_self && m_index < m_self->m_count) + { + auto& slot = m_self->m_p_slots[m_index]; + if (slot.next >= -1) + { + break; + } + ++m_index; + } + } + + public: + using iterator_category = std::forward_iterator_tag; + using iterator_concept = std::forward_iterator_tag; + using value_type = Key; + using difference_type = std::ptrdiff_t;; + using pointer = Key*; + using reference = Key&; + + explicit StdIterator(HashMap* self, const i32 index) : m_self(self), m_index(index) + { + if (m_self) AdvanceToValid(); + } + + explicit StdIterator(HashMap* self) : StdIterator(self, 0) + { + } + + Key& operator*() const + { + return m_self->m_p_keys[m_index]; + } + + Key* operator->() const + { + return &m_self->m_p_keys[m_index]; + } + + // 前缀增量 + StdIterator& operator++() + { + ++m_index; + AdvanceToValid(); + return *this; + } + + // 后缀增量 + StdIterator operator++(int) + { + StdIterator temp = *this; + ++(*this); + return temp; + } + + bool operator==(const StdIterator& other) const + { + return m_self == other.m_self && m_index == other.m_index; + } + + bool operator!=(const StdIterator& other) const + { + return !(*this == other); + } + }; + + using iterator = StdIterator; + + class ConstIterator + { + const HashMap* m_self{}; + i32 m_index{0}; + + void AdvanceToValid() + { + while (m_self && m_index < m_self->m_count) + { + auto& slot = m_self->m_p_slots[m_index]; + if (slot.next >= -1) + { + break; + } + ++m_index; + } + } + + public: + using iterator_category = std::forward_iterator_tag; + using iterator_concept = std::forward_iterator_tag; + using value_type = Key; + using difference_type = std::ptrdiff_t;; + using pointer = const Key*; + using reference = const Key&; + + explicit ConstIterator(const HashMap* self) : ConstIterator(self, 0) + { + } + + explicit ConstIterator(const HashMap* self, const i32 index) : m_self(self), m_index(index) + { + if (m_self) AdvanceToValid(); + } + + const Key& operator*() const + { + return m_self->m_p_keys[m_index]; + } + + const Key* operator->() const + { + return &m_self->m_p_keys[m_index]; + } + + // 前缀增量 + ConstIterator& operator++() + { + ++m_index; + AdvanceToValid(); + return *this; + } + + // 后缀增量 + ConstIterator operator++(int) + { + ConstIterator temp = *this; + ++(*this); + return temp; + } + + bool operator==(const ConstIterator& other) const + { + return m_self == other.m_self && m_index == other.m_index; + } + + bool operator!=(const ConstIterator& other) const + { + return !(*this == other); + } + }; + + iterator begin() + { + return iterator(this); + } + + iterator end() + { + return iterator(this, m_count); + } + + ConstIterator begin() const + { + return ConstIterator(this); + } + + ConstIterator end() const + { + return ConstIterator(this, m_count); + } + + std::vector IntoVector() && + { + std::vector keys{}; + keys.reserve(m_count); + auto iter = Iterator(); + while (auto key = iter.Next()) + { + keys.push_back(std::move(*key)); + } + new HashMap(std::move(*this)); + return keys; + } + }; + + template Hash = std::hash, Eq Eq = std::equal_to> + using HashSet = HashMap; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index 8fe6524..731c04f 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -17,7 +17,6 @@ D3d12ShaderBinding::D3d12ShaderBinding( COPLT_THROW("Layout from different backends"); const auto item_metas = m_layout->GetItemMetas(); - m_f_views = std::vector(item_metas.size(), {}); m_views = std::vector(item_metas.size(), {}); } @@ -26,21 +25,7 @@ FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept return FResult::None(); } -FView* D3d12ShaderBinding::GetViews(u32* out_size) noexcept -{ - *out_size = m_f_views.size(); - return m_f_views.data(); -} - -FResult D3d12ShaderBinding::Set(const u32 count, const FShaderBindingBatchSet* bindings) noexcept -{ - return feb([&] - { - Set(std::span(bindings, count)); - }); -} - -void D3d12ShaderBinding::Set(const std::span bindings) +void D3d12ShaderBinding::Set(const std::span bindings) { auto item_metas = m_layout->GetItemMetas(); auto item_defines = m_layout->GetItemDefines(); @@ -58,7 +43,27 @@ void D3d12ShaderBinding::Set(const std::span bindi COPLT_THROW_FMT("Binding index {} is not allowed to bind to buffer.", Index); break; } - m_f_views[Index] = View; m_views[Index] = View; + m_changed.Add(Index); } } + +std::span D3d12ShaderBinding::Views() noexcept +{ + return m_views; +} + +bool D3d12ShaderBinding::Changed() noexcept +{ + return !m_changed.IsEmpty(); +} + +const HashSet& D3d12ShaderBinding::ChangedIndexes() noexcept +{ + return m_changed; +} + +void D3d12ShaderBinding::ApplyChange() +{ + m_changed.Clear(); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index 4e1f625..6dc0e79 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -9,23 +9,35 @@ namespace Coplt { - struct D3d12ShaderBinding final : Object + COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "84f2b3e2-bb16-4276-ba3f-5da54eda462d", FD3d12ShaderBinding) + { + virtual std::span Views() noexcept = 0; + virtual bool Changed() noexcept = 0; + virtual const HashSet& ChangedIndexes() noexcept = 0; + + virtual void Set(std::span bindings) = 0; + + virtual void ApplyChange() = 0; + }; + + struct D3d12ShaderBinding final : Object { Rc m_device{}; ComPtr m_dx_device{}; Rc m_layout{}; - std::vector m_f_views{}; std::vector m_views{}; - std::vector m_changed{}; + HashSet m_changed{}; explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; - FView* GetViews(u32* out_size) noexcept override; + void Set(std::span bindings) override; - FResult Set(u32 count, const FShaderBindingBatchSet* bindings) noexcept override; + std::span Views() noexcept override; + bool Changed() noexcept override; + const HashSet& ChangedIndexes() noexcept override; - void Set(std::span bindings); + void ApplyChange() override; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Command.cc b/Coplt.Graphics.Native/D3d12/Src/Command.cc index d15126d..47de7a1 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Command.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Command.cc @@ -1,6 +1,7 @@ #include "Command.h" #include "../../Api/FFI/Command.h" +#include "Binding.h" #include "Context.h" #include "DescriptorManager.h" #include "fmt/format.h" @@ -16,6 +17,7 @@ #include "../ThirdParty/DirectXTK12/Src/d3dx12.h" #include "pix3.h" +#include "../FFI/Binding.h" using namespace Coplt; @@ -107,7 +109,6 @@ void D3d12CommandInterpreter::Reset() void D3d12CommandInterpreter::Translate(const FCommandSubmit& submit) { - const auto& cmd_pack = m_queue->m_cmd; const std::span command_items(submit.Commands, submit.CommandCount); for (u32 i = 0; i < command_items.size(); i++) { @@ -136,7 +137,8 @@ void D3d12CommandInterpreter::Translate(const FCommandSubmit& submit) ClearDepthStencil(submit, i, item.ClearDepthStencil); continue; case FCommandType::Bind: - continue; // todo + Bind(submit, i, item.Bind); + continue; case FCommandType::BufferCopy: BufferCopy(submit, i, item.BufferCopy); continue; @@ -325,6 +327,15 @@ void D3d12CommandInterpreter::BufferCopy(const FCommandSubmit& submit, u32 i, co } } +void D3d12CommandInterpreter::Bind(const FCommandSubmit& submit, u32 i, const FCommandBind& cmd) const +{ + const auto binding = cmd.Binding->QueryInterface(); + if (binding == nullptr) + COPLT_THROW_FMT("Binding from different backends at command {}", i); + const auto items = std::span(submit.BindItems + cmd.ItemsIndex, cmd.ItemCount); + binding->Set(items); +} + void D3d12CommandInterpreter::Render(const FCommandSubmit& submit, u32 i, const FCommandRender& cmd) { m_context.Reset(); diff --git a/Coplt.Graphics.Native/D3d12/Src/Command.h b/Coplt.Graphics.Native/D3d12/Src/Command.h index 7993b5f..dc2730e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Command.h +++ b/Coplt.Graphics.Native/D3d12/Src/Command.h @@ -79,6 +79,7 @@ namespace Coplt void ClearColor(const FCommandSubmit& submit, u32 i, const FCommandClearColor& cmd) const; void ClearDepthStencil(const FCommandSubmit& submit, u32 i, const FCommandClearDepthStencil& cmd) const; void BufferCopy(const FCommandSubmit& submit, u32 i, const FCommandBufferCopy& cmd) const; + void Bind(const FCommandSubmit& submit, u32 i, const FCommandBind& cmd) const; void Render(const FCommandSubmit& submit, u32 i, const FCommandRender& cmd); void RenderDraw(const FCommandSubmit& submit, u32 i, const FCommandDraw& cmd) const; void RenderDispatch(const FCommandSubmit& submit, u32 i, const FCommandDispatch& cmd) const; From 08a6f04930c15013a0860c6b79c2c86d367b769d Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 6 Mar 2025 22:53:19 +0800 Subject: [PATCH 4/9] save --- Coplt.Graphics.Core/Core/CommandList.cs | 18 +- Coplt.Graphics.Core/Core/ShaderLayout.cs | 22 ++- .../Native/FShaderLayoutGroupClass.cs | 6 + .../Native/FShaderLayoutItemDefine.cs | 72 +++++++- Coplt.Graphics.Core/Native/Native.D3d12.cs | 16 +- Coplt.Graphics.Core/Native/Native.cs | 84 +++++++++ Coplt.Graphics.Native/Api/FFI/Command.h | 2 + Coplt.Graphics.Native/Api/FFI/Layout.h | 100 ++++++++++- Coplt.Graphics.Native/Api/FFI/Types.h | 21 ++- Coplt.Graphics.Native/Api/Include/HashMap.h | 6 + Coplt.Graphics.Native/D3d12/Src/Adapter.cc | 20 +-- Coplt.Graphics.Native/D3d12/Src/Adapter.h | 2 + Coplt.Graphics.Native/D3d12/Src/Binding.cc | 29 ++- Coplt.Graphics.Native/D3d12/Src/Binding.h | 11 +- Coplt.Graphics.Native/D3d12/Src/Command.cc | 127 ++++++++++++- Coplt.Graphics.Native/D3d12/Src/Command.h | 35 ++-- .../D3d12/Src/DescriptorManager.cc | 36 ++-- .../D3d12/Src/DescriptorManager.h | 50 ++++-- Coplt.Graphics.Native/D3d12/Src/Device.cc | 2 - Coplt.Graphics.Native/D3d12/Src/Device.h | 2 - Coplt.Graphics.Native/D3d12/Src/Layout.cc | 169 ++++++++++++++---- Coplt.Graphics.Native/D3d12/Src/Layout.h | 81 ++------- Coplt.Graphics.Native/D3d12/Src/Queue.cc | 2 +- Coplt.Graphics.Native/D3d12/Src/Queue.h | 2 + 24 files changed, 704 insertions(+), 211 deletions(-) create mode 100644 Coplt.Graphics.Core/Native/FShaderLayoutGroupClass.cs diff --git a/Coplt.Graphics.Core/Core/CommandList.cs b/Coplt.Graphics.Core/Core/CommandList.cs index 18d2503..cdf8437 100644 --- a/Coplt.Graphics.Core/Core/CommandList.cs +++ b/Coplt.Graphics.Core/Core/CommandList.cs @@ -1289,12 +1289,17 @@ internal void SyncBinding(ShaderBinding? Binding) if (def.View is FShaderLayoutItemView.Sampler) continue; ref readonly var view = ref Binding.Views[i]; if (view.Tag is View.Tags.None) continue; - var is_buffer = view.Tag is View.Tags.Buffer; - var res = view.Tag switch + var is_buffer = false; + FResourceRef res; + switch (view.Tag) { - View.Tags.Buffer => AddResource(view.Buffer), - _ => throw new ArgumentOutOfRangeException() - }; + case View.Tags.Buffer: + res = AddResource(view.Buffer); + is_buffer = true; + break; + default: + throw new ArgumentOutOfRangeException(); + } var Usage = def.Stage switch { FShaderStage.Compute => ScopedStateUsage.Compute, @@ -1311,8 +1316,6 @@ internal void SyncBinding(ShaderBinding? Binding) { case FShaderLayoutItemView.Cbv: case FShaderLayoutItemView.Constants: - if (!is_buffer) - throw new ArgumentException($"The binding {i} requires a Cbv but actually resource is not buffer."); Access = ResAccess.ConstantBuffer; Legacy = LegacyState.ConstantBuffer; break; @@ -1327,7 +1330,6 @@ internal void SyncBinding(ShaderBinding? Binding) Legacy = LegacyState.UnorderedAccess; break; case FShaderLayoutItemView.Sampler: - continue; default: throw new ArgumentOutOfRangeException(); } diff --git a/Coplt.Graphics.Core/Core/ShaderLayout.cs b/Coplt.Graphics.Core/Core/ShaderLayout.cs index 844a2fb..3db0aed 100644 --- a/Coplt.Graphics.Core/Core/ShaderLayout.cs +++ b/Coplt.Graphics.Core/Core/ShaderLayout.cs @@ -103,6 +103,8 @@ public sealed unsafe partial class ShaderLayout internal FShaderLayout* m_ptr; internal string? m_name; internal readonly FRoSlice m_native_defines; + internal readonly FRoSlice m_native_item_infos; + internal readonly FRoSlice m_native_group_classes; #endregion @@ -110,6 +112,8 @@ public sealed unsafe partial class ShaderLayout public FShaderLayout* Ptr => m_ptr; public ReadOnlySpan NativeDefines => m_native_defines.Span; + public ReadOnlySpan NativeItemInfos => m_native_item_infos.Span; + public ReadOnlySpan NativeGroupClasses => m_native_group_classes.Span; #endregion @@ -121,9 +125,21 @@ internal ShaderLayout(FShaderLayout* ptr, string? name) m_name = name; if (m_ptr != null) { - uint count = 0; - var defines = m_ptr->GetItemDefines(&count); - m_native_defines = new(defines, count); + { + uint count = 0; + var defines = m_ptr->GetItemDefines(&count); + m_native_defines = new(defines, count); + } + { + uint count = 0; + var defines = m_ptr->GetItemInfos(&count); + m_native_item_infos = new(defines, count); + } + { + uint count = 0; + var defines = m_ptr->GetGroupClasses(&count); + m_native_group_classes = new(defines, count); + } } } diff --git a/Coplt.Graphics.Core/Native/FShaderLayoutGroupClass.cs b/Coplt.Graphics.Core/Native/FShaderLayoutGroupClass.cs new file mode 100644 index 0000000..8082b7c --- /dev/null +++ b/Coplt.Graphics.Core/Native/FShaderLayoutGroupClass.cs @@ -0,0 +1,6 @@ +namespace Coplt.Graphics.Native; + +public unsafe partial struct FShaderLayoutGroupClass +{ + public ReadOnlySpan InfoSpan => new(Infos, (int)Size); +} diff --git a/Coplt.Graphics.Core/Native/FShaderLayoutItemDefine.cs b/Coplt.Graphics.Core/Native/FShaderLayoutItemDefine.cs index 1ee5c88..2d4dfaa 100644 --- a/Coplt.Graphics.Core/Native/FShaderLayoutItemDefine.cs +++ b/Coplt.Graphics.Core/Native/FShaderLayoutItemDefine.cs @@ -1,4 +1,5 @@ -using Coplt.Graphics.Core; +using System.Diagnostics; +using Coplt.Graphics.Core; namespace Coplt.Graphics.Native; @@ -9,15 +10,78 @@ public partial struct FShaderLayoutItemDefine /// public readonly void CheckCompatible(in View view, int index) { + if (View is FShaderLayoutItemView.Constants) + throw new ArgumentException( + $"Binding slot {index} required [{View}], [{View}] slot cannot bind resources." + ); switch (view.Tag) { case Core.View.Tags.None: break; case Core.View.Tags.Buffer: - if (Type is not (FShaderLayoutItemType.ConstantBuffer or FShaderLayoutItemType.RawBuffer - or FShaderLayoutItemType.StructureBuffer or FShaderLayoutItemType.StructureBufferWithCounter)) - throw new ArgumentException($"Binding slot {index} does not supports buffers"); + { + var buffer = view.Buffer; + switch (Type) + { + case FShaderLayoutItemType.RayTracingAccelerationStructure: + case FShaderLayoutItemType.ConstantBuffer: + case FShaderLayoutItemType.RawBuffer: + if (buffer.Usage is not BufferUsage.Raw) + throw new ArgumentException( + $"Binding slot [{index}] required [{Type} (Usage: {BufferUsage.Raw})] but usage of [{buffer}] is a [{buffer.Usage}]." + ); + break; + case FShaderLayoutItemType.StructureBuffer: + case FShaderLayoutItemType.StructureBufferWithCounter: + if (buffer.Usage is not BufferUsage.Raw) + throw new ArgumentException( + $"Binding slot [{index}] required [{Type} (Usage: {BufferUsage.Structured})] but usage of [{buffer}] is a [{buffer.Usage}]." + ); + break; + case FShaderLayoutItemType.Texture1D: + case FShaderLayoutItemType.Texture1DArray: + case FShaderLayoutItemType.Texture2D: + case FShaderLayoutItemType.Texture2DArray: + case FShaderLayoutItemType.Texture2DMultisample: + case FShaderLayoutItemType.Texture2DArrayMultisample: + case FShaderLayoutItemType.Texture3D: + case FShaderLayoutItemType.TextureCube: + case FShaderLayoutItemType.TextureCubeArray: + case FShaderLayoutItemType.Sampler: + throw new ArgumentException( + $"Binding slot [{index}] required [{Type}] but [{buffer}] is a {nameof(GpuBuffer)}." + ); + default: + throw new ArgumentOutOfRangeException(); + } + switch (View) + { + case FShaderLayoutItemView.Cbv: + if (!buffer.TryCbv()) + throw new ArgumentException( + $"Binding slot [{index}] required [{View}], but [{buffer}] cannot be used as [{View}]." + ); + break; + case FShaderLayoutItemView.Srv: + if (!buffer.TrySrv()) + throw new ArgumentException( + $"Binding slot [{index}] required [{View}], but [{buffer}] cannot be used as [{View}]." + ); + break; + case FShaderLayoutItemView.Uav: + if (!buffer.TryUav()) + throw new ArgumentException( + $"Binding slot [{index}] required [{View}], but [{buffer}] cannot be used as [{View}]." + ); + break; + case FShaderLayoutItemView.Sampler: + case FShaderLayoutItemView.Constants: + throw new UnreachableException(); + default: + throw new ArgumentOutOfRangeException(); + } break; + } default: throw new ArgumentOutOfRangeException(); } diff --git a/Coplt.Graphics.Core/Native/Native.D3d12.cs b/Coplt.Graphics.Core/Native/Native.D3d12.cs index d2aee49..fa20400 100644 --- a/Coplt.Graphics.Core/Native/Native.D3d12.cs +++ b/Coplt.Graphics.Core/Native/Native.D3d12.cs @@ -326,10 +326,24 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return ((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FD3d12ShaderLayout*)Unsafe.AsPointer(ref this), out_count); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("const FShaderLayoutItemInfo *")] + public FShaderLayoutItemInfo* GetItemInfos([NativeTypeName("Coplt::u32 *")] uint* out_count) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FD3d12ShaderLayout*)Unsafe.AsPointer(ref this), out_count); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("const FShaderLayoutGroupClass *")] + public FShaderLayoutGroupClass* GetGroupClasses([NativeTypeName("Coplt::u32 *")] uint* out_count) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FD3d12ShaderLayout*)Unsafe.AsPointer(ref this), out_count); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void* GetRootSignaturePtr() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FD3d12ShaderLayout*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FD3d12ShaderLayout*)Unsafe.AsPointer(ref this)); } public interface Interface : FShaderLayout.Interface diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 1d993c5..4a42a58 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1319,10 +1319,30 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return ((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("const FShaderLayoutItemInfo *")] + public FShaderLayoutItemInfo* GetItemInfos([NativeTypeName("Coplt::u32 *")] uint* out_count) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("const FShaderLayoutGroupClass *")] + public FShaderLayoutGroupClass* GetGroupClasses([NativeTypeName("Coplt::u32 *")] uint* out_count) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); + } + public interface Interface : FGpuObject.Interface { [return: NativeTypeName("const FShaderLayoutItemDefine *")] FShaderLayoutItemDefine* GetItemDefines([NativeTypeName("Coplt::u32 *")] uint* out_count); + + [return: NativeTypeName("const FShaderLayoutItemInfo *")] + FShaderLayoutItemInfo* GetItemInfos([NativeTypeName("Coplt::u32 *")] uint* out_count); + + [return: NativeTypeName("const FShaderLayoutGroupClass *")] + FShaderLayoutGroupClass* GetGroupClasses([NativeTypeName("Coplt::u32 *")] uint* out_count); } } @@ -2345,6 +2365,9 @@ public unsafe partial struct FCommandSubmit [NativeTypeName("Coplt::u32")] public uint ResourceCount; + + [NativeTypeName("Coplt::u32")] + public uint GrowBindingCapacity; } [Guid("F1C59CB4-7EE6-4EE2-80F4-07CC568920D2")] @@ -3955,6 +3978,15 @@ public enum FShaderLayoutItemView : byte Constants, } + [NativeTypeName("Coplt::u8")] + public enum FShaderLayoutGroupView : byte + { + Cbv, + Srv, + Uav, + Sampler, + } + [NativeTypeName("Coplt::u8")] public enum FShaderLayoutItemType : byte { @@ -4010,6 +4042,58 @@ public partial struct FShaderLayoutItemDefine public FShaderLayoutItemUsage Usage; } + [NativeTypeName("Coplt::u8")] + public enum FShaderLayoutItemPlace : byte + { + None, + Const, + Direct, + Grouped, + StaticSampler, + } + + public partial struct FShaderLayoutItemInfo + { + [NativeTypeName("Coplt::u32")] + public uint Index; + + [NativeTypeName("Coplt::u32")] + public uint Class; + + [NativeTypeName("Coplt::u32")] + public uint Group; + + [NativeTypeName("Coplt::FShaderLayoutItemPlace")] + public FShaderLayoutItemPlace Place; + } + + public partial struct FShaderLayoutGroupInfo + { + [NativeTypeName("Coplt::u32")] + public uint Index; + + [NativeTypeName("Coplt::u32")] + public uint Size; + + [NativeTypeName("Coplt::FShaderStage")] + public FShaderStage Stage; + + [NativeTypeName("Coplt::FShaderLayoutGroupView")] + public FShaderLayoutGroupView View; + } + + public unsafe partial struct FShaderLayoutGroupClass + { + [NativeTypeName("Coplt::FShaderLayoutGroupInfo *")] + public FShaderLayoutGroupInfo* Infos; + + [NativeTypeName("Coplt::u32")] + public uint Size; + + [NativeTypeName("Coplt::b8")] + public B8 Sampler; + } + [NativeTypeName("Coplt::u8")] public enum FShaderLayoutFlags : byte { diff --git a/Coplt.Graphics.Native/Api/FFI/Command.h b/Coplt.Graphics.Native/Api/FFI/Command.h index b23be68..d2653c9 100644 --- a/Coplt.Graphics.Native/Api/FFI/Command.h +++ b/Coplt.Graphics.Native/Api/FFI/Command.h @@ -572,6 +572,8 @@ namespace Coplt Char16* Str16{}; u32 CommandCount{}; u32 ResourceCount{}; + // 需要增长多少绑定容量,仅在后端使用描述符堆时使用 + u32 GrowBindingCapacity{}; }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Coplt.Graphics.Native/Api/FFI/Layout.h b/Coplt.Graphics.Native/Api/FFI/Layout.h index d278ca8..c047841 100644 --- a/Coplt.Graphics.Native/Api/FFI/Layout.h +++ b/Coplt.Graphics.Native/Api/FFI/Layout.h @@ -20,6 +20,14 @@ namespace Coplt Constants, }; + enum class FShaderLayoutGroupView : u8 + { + Cbv, + Srv, + Uav, + Sampler, + }; + enum class FShaderLayoutItemType : u8 { ConstantBuffer, @@ -39,6 +47,23 @@ namespace Coplt RayTracingAccelerationStructure, }; + #ifdef FFI_SRC + inline bool IsBuffer(const FShaderLayoutItemType value) + { + switch (value) + { + case FShaderLayoutItemType::ConstantBuffer: + case FShaderLayoutItemType::RawBuffer: + case FShaderLayoutItemType::StructureBuffer: + case FShaderLayoutItemType::StructureBufferWithCounter: + case FShaderLayoutItemType::RayTracingAccelerationStructure: + return true; + default: ; + } + return false; + } + #endif + enum class FShaderLayoutItemUsage : u8 { // 一般改变频率的变量,可能每帧都会改变 @@ -62,7 +87,7 @@ namespace Coplt FShaderLayoutItemType Type{}; FShaderLayoutItemUsage Usage{}; -#ifdef FFI_SRC + #ifdef FFI_SRC bool IsAllowBuffer() const { switch (Type) @@ -95,7 +120,52 @@ namespace Coplt return false; } } -#endif + #endif + }; + + enum class FShaderLayoutItemPlace : u8 + { + None, + Const, + Direct, + Grouped, + StaticSampler, + }; + + struct FShaderLayoutItemInfo + { + // Const | Direct 时是 Root Index,Grouped 时是 Group 内的 Index + u32 Index{}; + // 所属哪个绑定组类 + u32 Class{}; + // 所属哪个绑定组 + u32 Group{}; + // 绑定放在哪 + FShaderLayoutItemPlace Place{}; + }; + + struct FShaderLayoutGroupInfo + { + // Root Index + u32 Index{}; + // 包含多少个绑定 + u32 Size{}; + FShaderStage Stage{}; + FShaderLayoutGroupView View{}; + }; + + struct FShaderLayoutGroupClass + { + FShaderLayoutGroupInfo* Infos{}; + u32 Size{}; + b8 Sampler{}; + + #if FFI_SRC + std::span AsSpan() const noexcept + { + return std::span{Infos, static_cast(Size)}; + } + #endif }; COPLT_ENUM_FLAGS(FShaderLayoutFlags, u8) @@ -129,14 +199,28 @@ namespace Coplt FShaderLayoutFlags Flags{}; virtual const FShaderLayoutItemDefine* GetItemDefines(u32* out_count) noexcept = 0; + virtual const FShaderLayoutItemInfo* GetItemInfos(u32* out_count) noexcept = 0; + virtual const FShaderLayoutGroupClass* GetGroupClasses(u32* out_count) noexcept = 0; -#if FFI_SRC + #if FFI_SRC std::span GetItemDefines() noexcept { u32 count{}; return std::span{GetItemDefines(&count), static_cast(count)}; } -#endif + + std::span GetItemInfos() noexcept + { + u32 count{}; + return std::span{GetItemInfos(&count), static_cast(count)}; + } + + std::span GetGroupClasses() noexcept + { + u32 count{}; + return std::span{GetGroupClasses(&count), static_cast(count)}; + } + #endif }; struct FShaderInputLayoutCreateOptions @@ -150,13 +234,13 @@ namespace Coplt { virtual const FShaderInputLayoutElement* GetElements(u32* out_count) noexcept = 0; -#if FFI_SRC + #if FFI_SRC std::span GetElements() noexcept { u32 count{}; return std::span{GetElements(&count), static_cast(count)}; } -#endif + #endif }; struct FMeshLayoutCreateOptions @@ -176,7 +260,7 @@ namespace Coplt virtual const FMeshBufferElement* TryGetElement(u32 SlotId, u32 SlotIndex) const noexcept = 0; -#if FFI_SRC + #if FFI_SRC std::span GetBuffers() const noexcept { u32 count{}; @@ -188,6 +272,6 @@ namespace Coplt u32 count{}; return std::span{GetElements(&count), static_cast(count)}; } -#endif + #endif }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Types.h b/Coplt.Graphics.Native/Api/FFI/Types.h index 535e1a3..f440899 100644 --- a/Coplt.Graphics.Native/Api/FFI/Types.h +++ b/Coplt.Graphics.Native/Api/FFI/Types.h @@ -7,6 +7,7 @@ #ifdef FFI_SRC #include #include +#include #ifdef COPLT_X64 #include @@ -30,7 +31,7 @@ namespace Coplt using i32 = int32_t; using i64 = int64_t; -#ifdef FFI_SRC + #ifdef FFI_SRC using f32 = glm::f32; using f64 = glm::f64; @@ -58,7 +59,11 @@ namespace Coplt using Char8 = char8_t; using Char16 = char16_t; -#else + + using RwLock = std::shared_mutex; + using WriteLock = std::unique_lock; + using ReadLock = std::shared_lock; + #else using f32 = float; using f64 = double; @@ -86,7 +91,7 @@ namespace Coplt using Char8 = u8; using Char16 = u16; -#endif + #endif struct Guid { @@ -102,7 +107,7 @@ namespace Coplt u8 _j{}; u8 _k{}; -#ifdef FFI_SRC + #ifdef FFI_SRC constexpr explicit Guid() = default; constexpr explicit Guid( @@ -237,13 +242,13 @@ namespace Coplt } else { -#ifdef COPLT_X64 + #ifdef COPLT_X64 const __m128i a = _mm_loadu_si128(reinterpret_cast(this)); const __m128i b = _mm_loadu_si128(reinterpret_cast(&other)); const __m128i r = _mm_cmpeq_epi8(a, b); const auto mask = _mm_movemask_epi8(r); return mask == 0xFFFF; -#else + #else const auto src = reinterpret_cast(this); const auto dst = reinterpret_cast(&other); for (auto i = 0; i < sizeof(Guid); ++i) @@ -251,7 +256,7 @@ namespace Coplt if (src[i] != dst[i]) return false; } return true; -#endif + #endif } } @@ -295,6 +300,6 @@ namespace Coplt const auto r = static_cast(_a); return r ^ _a + 1 ^ _a + 2 ^ _a + 3; } -#endif + #endif }; } diff --git a/Coplt.Graphics.Native/Api/Include/HashMap.h b/Coplt.Graphics.Native/Api/Include/HashMap.h index a04e6a7..3a5fca2 100644 --- a/Coplt.Graphics.Native/Api/Include/HashMap.h +++ b/Coplt.Graphics.Native/Api/Include/HashMap.h @@ -866,6 +866,8 @@ namespace Coplt using pointer = Entry*; using reference = Entry&; + StdIterator() = default; + explicit StdIterator(HashMap* self, const i32 index) : m_self(self), m_index(index) { if (m_self) AdvanceToValid(); @@ -903,6 +905,7 @@ namespace Coplt bool operator==(const StdIterator& other) const { + if (m_self == nullptr || other.m_self == nullptr) return true; return m_self == other.m_self && m_index == other.m_index; } @@ -940,6 +943,8 @@ namespace Coplt using pointer = const Entry*; using reference = const Entry&; + ConstIterator() = default; + explicit ConstIterator(const HashMap* self) : ConstIterator(self, 0) { } @@ -977,6 +982,7 @@ namespace Coplt bool operator==(const ConstIterator& other) const { + if (m_self == nullptr || other.m_self == nullptr) return true; return m_self == other.m_self && m_index == other.m_index; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Adapter.cc b/Coplt.Graphics.Native/D3d12/Src/Adapter.cc index 40856c7..0be8f25 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Adapter.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Adapter.cc @@ -1,8 +1,5 @@ #include "Adapter.h" -#include "directx/d3d12.h" -#include "directx/d3dx12_check_feature_support.h" - #include "../../Api/Include/Error.h" using namespace Coplt; @@ -16,10 +13,9 @@ D3d12GpuAdapter::D3d12GpuAdapter( ComPtr device{}; chr | D3D12CreateDevice(m_adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device)); - CD3DX12FeatureSupport feature_support{}; - chr | feature_support.Init(device.Get()); + chr | m_feature_support.Init(device.Get()); - m_d3d_feature_level = static_cast(feature_support.MaxSupportedFeatureLevel()); + m_d3d_feature_level = static_cast(m_feature_support.MaxSupportedFeatureLevel()); DXGI_ADAPTER_DESC1 desc1{}; chr | m_adapter->GetDesc1(&desc1); @@ -32,7 +28,7 @@ D3d12GpuAdapter::D3d12GpuAdapter( { m_device_type = FDeviceType::Cpu; } - else if (feature_support.UMA()) + else if (m_feature_support.UMA()) { m_device_type = FDeviceType::IntegratedGpu; } @@ -52,15 +48,15 @@ D3d12GpuAdapter::D3d12GpuAdapter( m_features.DescriptorHeap = true; m_features.ArrBindless = true; - m_features.ShaderModelLevel = static_cast(feature_support.HighestShaderModel()); - if (m_features.ShaderModelLevel >= FShaderModelLevel::SM_6_6) + m_features.ShaderModelLevel = static_cast(m_feature_support.HighestShaderModel()); + if (m_features.ShaderModelLevel >= FShaderModelLevel::SM_6_6 && m_feature_support.ResourceBindingTier() >= D3D12_RESOURCE_BINDING_TIER_3) { m_features.DynBindless = true; } - if (feature_support.RaytracingTier() >= D3D12_RAYTRACING_TIER_1_0) m_features.RayTracing = true; - if (feature_support.MeshShaderTier() >= D3D12_MESH_SHADER_TIER_1) m_features.MeshShader = true; - if (feature_support.EnhancedBarriersSupported()) m_features.EnhancedBarriers = true; + if (m_feature_support.RaytracingTier() >= D3D12_RAYTRACING_TIER_1_0) m_features.RayTracing = true; + if (m_feature_support.MeshShaderTier() >= D3D12_MESH_SHADER_TIER_1) m_features.MeshShader = true; + if (m_feature_support.EnhancedBarriersSupported()) m_features.EnhancedBarriers = true; } FResult D3d12GpuAdapter::CreateDevice(const FGpuDeviceCreateOptions& options, FGpuDevice** out) noexcept diff --git a/Coplt.Graphics.Native/D3d12/Src/Adapter.h b/Coplt.Graphics.Native/D3d12/Src/Adapter.h index 9f4f58b..acce76a 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Adapter.h +++ b/Coplt.Graphics.Native/D3d12/Src/Adapter.h @@ -1,6 +1,7 @@ #pragma once #include +#include "directx/d3dx12.h" #include "Device.h" #include "../../Api/Include/Object.h" @@ -14,6 +15,7 @@ namespace Coplt ComPtr m_adapter{}; std::wstring m_name_string{}; std::wstring m_driver_string{}; + CD3DX12FeatureSupport m_feature_support{}; explicit D3d12GpuAdapter(Rc&& instance, ComPtr&& adapter); diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index 731c04f..f636f1e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -16,8 +16,8 @@ D3d12ShaderBinding::D3d12ShaderBinding( if (m_layout == nullptr) COPLT_THROW("Layout from different backends"); - const auto item_metas = m_layout->GetItemMetas(); - m_views = std::vector(item_metas.size(), {}); + const auto defs = m_layout->GetItemDefines(); + m_views = std::vector(defs.size(), {}); } FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept @@ -27,13 +27,14 @@ FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept void D3d12ShaderBinding::Set(const std::span bindings) { - auto item_metas = m_layout->GetItemMetas(); + auto infos = m_layout->GetItemInfos(); auto item_defines = m_layout->GetItemDefines(); for (const auto& [View, Index] : bindings) { if (Index >= m_views.size()) COPLT_THROW("Index out of bounds"); const auto& define = item_defines[Index]; + const auto info = infos[Index]; switch (View.Type) { case FViewType::None: @@ -44,10 +45,16 @@ void D3d12ShaderBinding::Set(const std::span bindings) break; } m_views[Index] = View; - m_changed.Add(Index); + m_changed_items.Add(Index); + m_changed_groups.Add(info.Group); } } +const Rc& D3d12ShaderBinding::Layout() noexcept +{ + return m_layout; +} + std::span D3d12ShaderBinding::Views() noexcept { return m_views; @@ -55,15 +62,21 @@ std::span D3d12ShaderBinding::Views() noexcept bool D3d12ShaderBinding::Changed() noexcept { - return !m_changed.IsEmpty(); + return !m_changed_items.IsEmpty() || !m_changed_groups.IsEmpty(); +} + +const HashSet& D3d12ShaderBinding::ChangedItems() noexcept +{ + return m_changed_items; } -const HashSet& D3d12ShaderBinding::ChangedIndexes() noexcept +const HashSet& D3d12ShaderBinding::ChangedGroups() noexcept { - return m_changed; + return m_changed_groups; } void D3d12ShaderBinding::ApplyChange() { - m_changed.Clear(); + m_changed_items.Clear(); + m_changed_groups.Clear(); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index 6dc0e79..000d895 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -11,9 +11,11 @@ namespace Coplt { COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "84f2b3e2-bb16-4276-ba3f-5da54eda462d", FD3d12ShaderBinding) { + virtual const Rc& Layout() noexcept = 0; virtual std::span Views() noexcept = 0; virtual bool Changed() noexcept = 0; - virtual const HashSet& ChangedIndexes() noexcept = 0; + virtual const HashSet& ChangedItems() noexcept = 0; + virtual const HashSet& ChangedGroups() noexcept = 0; virtual void Set(std::span bindings) = 0; @@ -26,7 +28,8 @@ namespace Coplt ComPtr m_dx_device{}; Rc m_layout{}; std::vector m_views{}; - HashSet m_changed{}; + HashSet m_changed_items{}; + HashSet m_changed_groups{}; explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); @@ -34,9 +37,11 @@ namespace Coplt void Set(std::span bindings) override; + const Rc& Layout() noexcept override; std::span Views() noexcept override; bool Changed() noexcept override; - const HashSet& ChangedIndexes() noexcept override; + const HashSet& ChangedItems() noexcept override; + const HashSet& ChangedGroups() noexcept override; void ApplyChange() override; }; diff --git a/Coplt.Graphics.Native/D3d12/Src/Command.cc b/Coplt.Graphics.Native/D3d12/Src/Command.cc index 47de7a1..6f19d8a 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Command.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Command.cc @@ -88,7 +88,11 @@ void D3d12CommandInterpreter::BarrierContext::BuildBarriers() void D3d12CommandInterpreter::Context::Reset() { Pipeline = nullptr; - D3dPipeline = nullptr; + Layout = nullptr; + GPipeline = nullptr; + Binding = nullptr; + PipelineChanged = false; + BindingChanged = false; } D3d12CommandInterpreter::D3d12CommandInterpreter(D3d12GpuQueue* queue) : m_queue(queue) @@ -105,6 +109,7 @@ void D3d12CommandInterpreter::Reset() { m_barrier_context.Reset(); m_context.Reset(); + m_bindings.Clear(); } void D3d12CommandInterpreter::Translate(const FCommandSubmit& submit) @@ -146,7 +151,8 @@ void D3d12CommandInterpreter::Translate(const FCommandSubmit& submit) Render(submit, i, item.Render); continue; case FCommandType::Compute: - COPLT_THROW("TODO"); + Compute(submit, i, item.Compute); + continue; // subcommands case FCommandType::SetPipeline: @@ -433,7 +439,8 @@ void D3d12CommandInterpreter::Render(const FCommandSubmit& submit, u32 i, const SetPipeline(m_queue->m_cmd, item.SetPipeline.Pipeline, j); continue; case FCommandType::SetBinding: - continue; // todo + SetBinding(item.SetBinding.Binding, j); + continue; case FCommandType::SetViewportScissor: RenderSetViewportScissor(submit, j, item.SetViewportScissor); continue; @@ -463,8 +470,9 @@ void D3d12CommandInterpreter::Render(const FCommandSubmit& submit, u32 i, const } } -void D3d12CommandInterpreter::RenderDraw(const FCommandSubmit& submit, u32 i, const FCommandDraw& cmd) const +void D3d12CommandInterpreter::RenderDraw(const FCommandSubmit& submit, u32 i, const FCommandDraw& cmd) { + SyncBinding(); if (cmd.Indexed) { m_queue->m_cmd->DrawIndexedInstanced(cmd.VertexOrIndexCount, cmd.InstanceCount, cmd.FirstVertexOrIndex, cmd.VertexOffset, cmd.FirstInstance); @@ -475,10 +483,11 @@ void D3d12CommandInterpreter::RenderDraw(const FCommandSubmit& submit, u32 i, co } } -void D3d12CommandInterpreter::RenderDispatch(const FCommandSubmit& submit, u32 i, const FCommandDispatch& cmd) const +void D3d12CommandInterpreter::RenderDispatch(const FCommandSubmit& submit, u32 i, const FCommandDispatch& cmd) { if (cmd.Type != FDispatchType::Mesh) COPLT_THROW_FMT("Render only supports DispatchMesh and does not support Dispatch for Compute at command {}", i); + SyncBinding(); m_queue->m_cmd.m_list6->DispatchMesh(cmd.GroupCountX, cmd.GroupCountY, cmd.GroupCountZ); } @@ -518,12 +527,68 @@ void D3d12CommandInterpreter::RenderSetMeshBuffers(const FCommandSubmit& submit, cmd_pack->IASetVertexBuffers(cmd.VertexStartSlot, buffers.VertexBufferCount, views); } +void D3d12CommandInterpreter::Compute(const FCommandSubmit& submit, u32 i, const FCommandCompute& cmd) +{ + m_context.Reset(); + const auto& _info = submit.ComputeInfos[cmd.InfoIndex]; + const auto commands = std::span(submit.ComputeCommands + cmd.CommandStartIndex, cmd.CommandCount); + for (u32 j = 0; j < commands.size(); j++) + { + const auto& item = commands[j]; + switch (item.Type) + { + case FCommandType::None: + continue; + case FCommandType::Label: + Label(submit, item.Label); + continue; + case FCommandType::BeginScope: + BeginScope(submit, item.BeginScope); + continue; + case FCommandType::EndScope: + EndScope(submit, item.EndScope); + continue; + case FCommandType::SetPipeline: + SetPipeline(m_queue->m_cmd, item.SetPipeline.Pipeline, j); + continue; + case FCommandType::SetBinding: + SetBinding(item.SetBinding.Binding, j); + continue; + case FCommandType::Dispatch: + ComputeDispatch(submit, j, item.Dispatch); + continue; + case FCommandType::SetViewportScissor: + case FCommandType::SetMeshBuffers: + case FCommandType::Draw: + COPLT_THROW("Compute commands cannot be placed in the render command list"); + case FCommandType::Present: + case FCommandType::Barrier: + case FCommandType::ClearColor: + case FCommandType::ClearDepthStencil: + case FCommandType::Bind: + case FCommandType::BufferCopy: + case FCommandType::Render: + case FCommandType::Compute: + COPLT_THROW("Main commands cannot be placed in the sub command list"); + } + COPLT_THROW_FMT("Unknown command type {}", static_cast(item.Type)); + } +} + +void D3d12CommandInterpreter::ComputeDispatch(const FCommandSubmit& submit, u32 i, const FCommandDispatch& cmd) +{ + SyncBinding(); + if (cmd.Type == FDispatchType::Mesh) + m_queue->m_cmd.m_list6->DispatchMesh(cmd.GroupCountX, cmd.GroupCountY, cmd.GroupCountZ); + else + m_queue->m_cmd->Dispatch(cmd.GroupCountX, cmd.GroupCountY, cmd.GroupCountZ); +} + void D3d12CommandInterpreter::SetPipelineContext(FShaderPipeline* pipeline, const u32 i) { if (pipeline == m_context.Pipeline) return; - m_context.Pipeline = pipeline; - m_context.D3dPipeline = pipeline->QueryInterface(); - if (!m_context.D3dPipeline) + m_context.Pipeline = pipeline->QueryInterface(); + if (!m_context.Pipeline) { COPLT_THROW_FMT( "Pipeline({:#x}) comes from different backends at cmd {}", @@ -541,6 +606,7 @@ void D3d12CommandInterpreter::SetPipelineContext(FShaderPipeline* pipeline, cons if (!m_context.GPipeline) COPLT_THROW("Pipeline from different backends or pipeline not a graphics pipeline"); } + m_context.PipelineChanged = true; } void D3d12CommandInterpreter::SetPipeline( @@ -560,7 +626,50 @@ void D3d12CommandInterpreter::SetPipeline( cmd_pack->IASetPrimitiveTopology(ToDx(states->Topology)); cmd_pack->SetGraphicsRootSignature(static_cast(m_context.Layout->GetRootSignaturePtr())); } - cmd_pack->SetPipelineState(static_cast(m_context.D3dPipeline->GetPipelineStatePtr())); + cmd_pack->SetPipelineState(static_cast(m_context.Pipeline->GetPipelineStatePtr())); +} + +void D3d12CommandInterpreter::SetBinding(FShaderBinding* binding, u32 i) +{ + if (binding == m_context.Binding) return; + m_context.Binding = binding->QueryInterface(); + if (!m_context.Binding) + COPLT_THROW_FMT("Shader bindings from different backend at command {}", i); + m_context.BindingChanged = true; +} + +void D3d12CommandInterpreter::SyncBinding() +{ + if (!(m_context.PipelineChanged || m_context.BindingChanged)) return; + if (m_context.Binding->Changed()) UpdateBinding(); + UseBinding(); +} + +void D3d12CommandInterpreter::UpdateBinding() +{ + auto& dm = m_queue->m_descriptor_manager; + auto binding = m_context.Binding; + auto first = m_bindings.Add(binding); + auto layout = binding->Layout().get(); + auto defs = layout->GetItemDefines(); + auto infos = layout->GetItemInfos(); + auto tables = layout->GetTableGroups(); + const auto& changed_tables = binding->ChangedGroups(); + const auto& changed_items = binding->ChangedItems(); + for (auto i : changed_tables) + { + const auto& table = tables[i]; + } + for (auto i : changed_items) + { + const auto& def = defs[i]; + const auto& info = infos[i]; + } +} + +void D3d12CommandInterpreter::UseBinding() +{ + // todo } ID3D12Resource* D3d12CommandInterpreter::GetResource(const FResourceMeta& meta) diff --git a/Coplt.Graphics.Native/D3d12/Src/Command.h b/Coplt.Graphics.Native/D3d12/Src/Command.h index dc2730e..88f7cd0 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Command.h +++ b/Coplt.Graphics.Native/D3d12/Src/Command.h @@ -2,6 +2,7 @@ #include +#include "Binding.h" #include "../../Api/FFI/States.h" #include "../../Api/FFI/Command.h" @@ -42,22 +43,22 @@ namespace Coplt struct Context { - FShaderPipeline* Pipeline{}; - FD3d12PipelineState* D3dPipeline{}; + FD3d12PipelineState* Pipeline{}; FD3d12ShaderLayout* Layout{}; // 如果不是图形管线将不会设置 FD3d12GraphicsShaderPipeline* GPipeline{}; + ID3d12ShaderBinding* Binding{}; + + bool PipelineChanged{}; + bool BindingChanged{}; + void Reset(); }; - // std::vector m_states{}; - // std::vector m_barriers{}; - // std::vector m_barrier_resources{}; - // std::vector m_items{}; - // u32 m_last_barrier_index{}; BarrierContext m_barrier_context{}; Context m_context{}; + HashSet m_bindings{}; public: explicit D3d12CommandInterpreter(D3d12GpuQueue* queue); @@ -81,17 +82,21 @@ namespace Coplt void BufferCopy(const FCommandSubmit& submit, u32 i, const FCommandBufferCopy& cmd) const; void Bind(const FCommandSubmit& submit, u32 i, const FCommandBind& cmd) const; void Render(const FCommandSubmit& submit, u32 i, const FCommandRender& cmd); - void RenderDraw(const FCommandSubmit& submit, u32 i, const FCommandDraw& cmd) const; - void RenderDispatch(const FCommandSubmit& submit, u32 i, const FCommandDispatch& cmd) const; + void RenderDraw(const FCommandSubmit& submit, u32 i, const FCommandDraw& cmd); + void RenderDispatch(const FCommandSubmit& submit, u32 i, const FCommandDispatch& cmd); void RenderSetViewportScissor(const FCommandSubmit& submit, u32 i, const FCommandSetViewportScissor& cmd) const; void RenderSetMeshBuffers(const FCommandSubmit& submit, u32 i, const FCommandSetMeshBuffers& cmd) const; + void Compute(const FCommandSubmit& submit, u32 i, const FCommandCompute& cmd); + void ComputeDispatch(const FCommandSubmit& submit, u32 i, const FCommandDispatch& cmd); + + void SetPipelineContext(FShaderPipeline* pipeline, u32 i); + void SetPipeline(const CmdListPack& cmd_pack, FShaderPipeline* pipeline, u32 i); + + void SetBinding(FShaderBinding* binding, u32 i); - void SetPipelineContext( - FShaderPipeline* pipeline, u32 i - ); - void SetPipeline( - const CmdListPack& cmd_pack, FShaderPipeline* pipeline, u32 i - ); + void SyncBinding(); + void UpdateBinding(); + void UseBinding(); static ID3D12Resource* GetResource(const FResourceMeta& meta); static ID3D12Resource* GetResource(FUnknown* object, FResourceRefType type); diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc index 7d1ed40..4ce1e36 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc @@ -2,34 +2,38 @@ using namespace Coplt; -CpuDescriptorSet::CpuDescriptorSet( - ComPtr device, const D3D12_DESCRIPTOR_HEAP_TYPE type, const u32 init_cap -) : m_device(std::move(device)), m_type(type), m_cap(init_cap) +DescriptorHeap::DescriptorHeap(ComPtr device, const D3D12_DESCRIPTOR_HEAP_TYPE type, u32 size, bool gpu) + : m_device(std::move(device)), m_type(type), m_size(size), m_gpu(gpu) { D3D12_DESCRIPTOR_HEAP_DESC desc{}; desc.Type = type; - desc.NumDescriptors = init_cap; + desc.NumDescriptors = size; + if (gpu) desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; chr | m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_heap)); } -GpuDescriptorSet::GpuDescriptorSet( +CpuDescriptorAllocator::CpuDescriptorAllocator( ComPtr device, const D3D12_DESCRIPTOR_HEAP_TYPE type, const u32 init_cap -) : m_device(std::move(device)), m_type(type), m_cap(init_cap) +) : m_device(std::move(device)), m_type(type) { - D3D12_DESCRIPTOR_HEAP_DESC desc{}; - desc.Type = type; - desc.NumDescriptors = init_cap; - chr | m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_Cpu_heap)); - desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - chr | m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_Gpu_heap)); + m_heap = new DescriptorHeap(m_device, type, init_cap, false); +} + +GpuDescriptorAllocator::GpuDescriptorAllocator( + ComPtr device, const D3D12_DESCRIPTOR_HEAP_TYPE type, const u32 init_cap +) : m_device(std::move(device)), m_type(type), m_cap((init_cap + BlockSize - 1) / BlockSize) +{ + m_heap = new DescriptorHeap(m_device, type, m_cap * BlockSize, true); } DescriptorManager::DescriptorManager(D3d12GpuDevice* device) : m_device(device) { m_dx_device = m_device->m_device; - m_rtv_set = box(m_dx_device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, RtvDsvInitCap); - m_dsv_set = box(m_dx_device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, RtvDsvInitCap); - m_cbv_srv_uav_set = box(m_dx_device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, CbvSrvUavInitCap); - m_sampler_set = box(m_dx_device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, SamplerInitCap); + m_rtv_HEAP = new DescriptorHeap(m_dx_device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV, RtvDsvInitCap, false); + m_dsv_HEAP = new DescriptorHeap(m_dx_device, D3D12_DESCRIPTOR_HEAP_TYPE_DSV, RtvDsvInitCap, false); + m_cbv_srv_uav_CPU = box(m_dx_device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, CbvSrvUavInitCap); + m_sampler_CPU = box(m_dx_device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, SamplerInitCap); + m_cbv_srv_uav_GPU = box(m_dx_device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, CbvSrvUavInitCap); + m_sampler_GPU = box(m_dx_device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, SamplerInitCap); } diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h index 0a59129..3a2d8c6 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h @@ -1,51 +1,67 @@ #pragma once #include +#include #include "Device.h" namespace Coplt { - struct CpuDescriptorSet + struct DescriptorHeap final : Object { ComPtr m_device{}; - - D3D12_DESCRIPTOR_HEAP_TYPE m_type{}; ComPtr m_heap{}; + D3D12_DESCRIPTOR_HEAP_TYPE m_type{}; + u32 m_size{}; + bool m_gpu{}; + volatile bool m_discarded{}; - u32 m_used{}; - u32 m_cap{}; + bool IsDiscarded() const { return m_discarded; } - explicit CpuDescriptorSet(ComPtr device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 init_cap); + explicit DescriptorHeap(ComPtr device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 size, bool gpu); }; - struct GpuDescriptorSet + struct CpuDescriptorAllocator { ComPtr m_device{}; - + Rc m_heap{}; D3D12_DESCRIPTOR_HEAP_TYPE m_type{}; - ComPtr m_Cpu_heap{}; - ComPtr m_Gpu_heap{}; + u32 m_used{}; + explicit CpuDescriptorAllocator(ComPtr device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 init_cap); + + // todo + }; + + struct GpuDescriptorAllocator + { + constexpr static u32 BlockSize = 8; + + RwLock m_grow_lock{}; + ComPtr m_device{}; + Rc m_heap{}; + D3D12_DESCRIPTOR_HEAP_TYPE m_type{}; u32 m_used{}; u32 m_cap{}; - explicit GpuDescriptorSet(ComPtr device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 init_cap); + explicit GpuDescriptorAllocator(ComPtr device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 init_cap); }; struct DescriptorManager final { - constexpr static u32 RtvDsvInitCap = 128; - constexpr static u32 SamplerInitCap = 128; + constexpr static u32 RtvDsvInitCap = 8; + constexpr static u32 SamplerInitCap = 8; constexpr static u32 CbvSrvUavInitCap = 1024; D3d12GpuDevice* m_device; ComPtr m_dx_device{}; - Box m_rtv_set{}; - Box m_dsv_set{}; - Box m_cbv_srv_uav_set{}; - Box m_sampler_set{}; + Rc m_rtv_HEAP{}; + Rc m_dsv_HEAP{}; + Box m_cbv_srv_uav_CPU{}; + Box m_sampler_CPU{}; + Box m_cbv_srv_uav_GPU{}; + Box m_sampler_GPU{}; explicit DescriptorManager(D3d12GpuDevice* device); }; diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 8e54792..131778f 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -76,8 +76,6 @@ D3d12GpuDevice::D3d12GpuDevice(Rc&& adapter, const FGpuDeviceCr } chr | m_device->QueryInterface(IID_PPV_ARGS(&m_device0)); - - m_descriptor_manager = box(this); } D3d12GpuDevice::~D3d12GpuDevice() diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index e7bd340..9de96a5 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -11,7 +11,6 @@ namespace Coplt { struct D3d12GpuAdapter; - struct DescriptorManager; struct D3d12ShaderLayout; struct D3d12MeshLayout; @@ -25,7 +24,6 @@ namespace Coplt ComPtr m_device0{}; ComPtr m_info_queue{}; ComPtr m_gpu_allocator{}; - Box m_descriptor_manager{}; Box m_empty_layouts{}; Rc m_empty_mesh_layout{}; DWORD m_callback_cookie{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.cc b/Coplt.Graphics.Native/D3d12/Src/Layout.cc index 31b0793..f0f8b8e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.cc @@ -1,9 +1,82 @@ #include "Layout.h" +#include + #include "../Include/ShaderVisibility.h" using namespace Coplt; +namespace +{ + struct TableKey + { + FShaderStage Stage{}; + FShaderLayoutGroupView View{}; + + TableKey() = default; + + explicit TableKey(const FShaderStage Stage, const FShaderLayoutGroupView View) : Stage(Stage), View(View) + { + } + + struct Hasher + { + size_t operator()(const TableKey& value) const + { + return std::hash{}(static_cast(value.Stage) | (static_cast(value.View) << 8)); + } + }; + + struct Eq + { + bool operator()(const TableKey& lhs, const TableKey& rhs) const + { + return lhs.Stage == rhs.Stage && lhs.View == rhs.View; + } + }; + }; + + using TableMeta = ID3d12ShaderLayout::TableMeta; + using TableScope = ID3d12ShaderLayout::TableScope; + + struct TableGroupKey + { + TableScope Scope{}; + bool Sampler{}; + + TableGroupKey() = default; + + explicit TableGroupKey(const TableScope Scope, const bool Sampler) : Scope(Scope), Sampler(Sampler) + { + } + + struct Hasher + { + size_t operator()(const TableGroupKey& value) const + { + return std::hash{}(static_cast(value.Scope) | (static_cast(value.Sampler) << 8)); + } + }; + + struct Eq + { + bool operator()(const TableGroupKey& lhs, const TableGroupKey& rhs) const + { + return lhs.Scope == rhs.Scope && lhs.Sampler == rhs.Sampler; + } + }; + }; + + struct TableDefine + { + u8 Index{}; + u32 IndexInc{}; + HashMap Map{}; + }; + + using TmpTableGroupMap = HashMap; +} + D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderLayoutCreateOptions& options) : m_device(std::move(device)) { @@ -12,12 +85,12 @@ D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderL Flags = options.Flags; m_layout_item_defines = std::vector(options.Items, options.Items + options.Count); - m_item_metas = std::vector(options.Count, {}); + m_item_infos = std::vector(options.Count, {}); std::vector root_parameters{}; - HashMap tables[2]{}; - u32 table_index[2]{}; + TmpTableGroupMap tables{}; + u8 TableGroupIndexInc{}; for (u32 i = 0; i < m_layout_item_defines.size(); i++) { @@ -34,7 +107,10 @@ D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderL param.Constants.RegisterSpace = item.Space; param.Constants.Num32BitValues = std::max(1u, item.CountOrIndex); param.ShaderVisibility = ToDxVisibility(item.Stage); - m_item_metas[i] = ItemMeta{.Index = static_cast(root_parameters.size()), .Type = ItemType::Const}; + m_item_infos[i] = FShaderLayoutItemInfo{ + .Index = static_cast(root_parameters.size()), + .Place = FShaderLayoutItemPlace::Const, + }; root_parameters.push_back(param); continue; } @@ -51,7 +127,7 @@ D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderL table_scope = TableScope::Material; goto DefineDescriptorTable; case FShaderLayoutItemUsage::Instant: - if (item.CountOrIndex > 1) + if (item.CountOrIndex > 1 || !IsBuffer(item.Type)) { table_scope = TableScope::Common; goto DefineDescriptorTable; @@ -86,70 +162,94 @@ D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderL param.Descriptor.RegisterSpace = item.Space; param.Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE; param.ShaderVisibility = ToDxVisibility(item.Stage); - m_item_metas[i] = ItemMeta{.Index = static_cast(root_parameters.size()), .Type = ItemType::Direct}; + m_item_infos[i] = FShaderLayoutItemInfo{ + .Index = static_cast(root_parameters.size()), + .Place = FShaderLayoutItemPlace::Direct, + }; root_parameters.push_back(param); continue; } DefineDescriptorTable: { - auto& table = tables[static_cast(table_scope)]; - RangeType range_type{}; + auto& table = tables.GetOrAdd(TableGroupKey(table_scope, item.View == FShaderLayoutItemView::Sampler), [&](auto& p) + { + p = TableDefine{.Index = TableGroupIndexInc++}; + }); + FShaderLayoutGroupView group_view{}; D3D12_DESCRIPTOR_RANGE1 range{}; switch (item.View) { case FShaderLayoutItemView::Cbv: range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV; - range_type = RangeType::Cbv; + group_view = FShaderLayoutGroupView::Cbv; break; case FShaderLayoutItemView::Srv: range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - range_type = RangeType::Srv; + group_view = FShaderLayoutGroupView::Srv; break; case FShaderLayoutItemView::Uav: range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; - range_type = RangeType::Uav; + group_view = FShaderLayoutGroupView::Uav; break; case FShaderLayoutItemView::Sampler: range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; - range_type = RangeType::Sampler; + group_view = FShaderLayoutGroupView::Sampler; break; default: COPLT_THROW_FMT("Unknown shader layout item type {}", static_cast(item.Type)); } - auto& meta = table.GetOrAdd(TableKey(item.Stage, range_type), [&](auto& p) + auto& meta = table.Map.GetOrAdd(TableKey(item.Stage, group_view), [&](auto& p) { - p = TableMeta(table_index[static_cast(table_scope)]++, item.Stage, range_type); + p = TableMeta(table.IndexInc++, item.Stage, group_view); }); range.NumDescriptors = std::max(1u, item.CountOrIndex); range.BaseShaderRegister = item.Slot; range.RegisterSpace = item.Space; range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND; - m_item_metas[i] = ItemMeta{ - .Index = static_cast(meta.ranges.size()), .Table = table_scope, - .Type = ItemType::InTable, .RangeType = range_type + m_item_infos[i] = FShaderLayoutItemInfo{ + .Index = static_cast(meta.Ranges.size()), + .Class = table.Index, + .Group = meta.Index, + .Place = FShaderLayoutItemPlace::Grouped, }; - meta.ranges.push_back(range); + meta.Ranges.push_back(range); continue; } } - for (u8 ts = 0; ts < 2; ++ts) + m_table_groups = std::vector(tables.Count(), {}); + m_group_classes = std::vector(tables.Count(), {}); + for (auto& [key, table] : tables) { - auto& table = tables[ts]; - auto& table_metas = m_table_metas[ts]; - table_metas = std::vector(table.Count(), {}); - for (auto& pair : table) + auto& table_groups = m_table_groups[table.Index]; + auto& group_class = m_group_classes[table.Index]; + table_groups = TableGroup{ + .Metas = std::vector(table.Map.Count(), {}), + .Infos = std::vector(table.Map.Count(), {}), + .Scope = key.Scope, .Sampler = key.Sampler + }; + group_class = FShaderLayoutGroupClass{ + .Infos = table_groups.Infos.data(), + .Size = static_cast(table_groups.Metas.size()), + .Sampler = key.Sampler + }; + for (auto& item : table.Map | std::views::values) { D3D12_ROOT_PARAMETER1 param{}; param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - auto& meta = table_metas[pair.second.Index]; - meta = std::move(pair.second); + auto& meta = table_groups.Metas[item.Index]; + auto& info = table_groups.Infos[item.Index]; + meta = std::move(item); meta.RootIndex = root_parameters.size(); + info.Index = meta.RootIndex; + info.Size = meta.Ranges.size(); + info.Stage = meta.Stage; + info.View = meta.View; param.ShaderVisibility = ToDxVisibility(meta.Stage); - param.DescriptorTable.NumDescriptorRanges = meta.ranges.size(); - param.DescriptorTable.pDescriptorRanges = meta.ranges.data(); + param.DescriptorTable.NumDescriptorRanges = meta.Ranges.size(); + param.DescriptorTable.pDescriptorRanges = meta.Ranges.data(); root_parameters.push_back(param); } @@ -213,14 +313,21 @@ const FShaderLayoutItemDefine* D3d12ShaderLayout::GetItemDefines(u32* out_count) return m_layout_item_defines.data(); } -std::span D3d12ShaderLayout::GetItemMetas() noexcept +const FShaderLayoutItemInfo* D3d12ShaderLayout::GetItemInfos(u32* out_count) noexcept +{ + *out_count = static_cast(m_item_infos.size()); + return m_item_infos.data(); +} + +const FShaderLayoutGroupClass* D3d12ShaderLayout::GetGroupClasses(u32* out_count) noexcept { - return m_item_metas; + *out_count = static_cast(m_group_classes.size()); + return m_group_classes.data(); } -std::array, 2> D3d12ShaderLayout::GetTableMetas() noexcept +std::span D3d12ShaderLayout::GetTableGroups() noexcept { - return std::array, 2>{m_table_metas[0], m_table_metas[1]}; + return m_table_groups; } D3d12ShaderInputLayout::D3d12ShaderInputLayout( diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.h b/Coplt.Graphics.Native/D3d12/Src/Layout.h index 7b5e2fd..b6168a0 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.h +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.h @@ -13,85 +13,39 @@ namespace Coplt { COPLT_INTERFACE_DEFINE(ID3d12ShaderLayout, "d8cea40e-7b0c-4a5f-98a9-88fd3abf9ddc", FD3d12ShaderLayout) { - enum class ItemType : u8 - { - None, - Const, - Direct, - InTable, - StaticSampler, - }; - enum class TableScope : u8 { Common, Material, }; - enum class RangeType : u8 - { - Cbv, - Srv, - Uav, - Sampler, - }; - - struct TableKey - { - FShaderStage Stage{}; - RangeType Type{}; - - TableKey() = default; - - explicit TableKey(const FShaderStage Stage, const RangeType Type) : Stage(Stage), Type(Type) - { - } - - struct Hasher - { - size_t operator()(const TableKey& value) const - { - return std::hash{}(static_cast(value.Stage) | (static_cast(value.Type) << 8)); - } - }; - - struct Eq - { - bool operator()(const TableKey& lhs, const TableKey& rhs) const - { - return lhs.Stage == rhs.Stage && lhs.Type == rhs.Type; - } - }; - }; - struct TableMeta { - std::vector ranges{}; + std::vector Ranges{}; u32 Index{}; u32 RootIndex{}; FShaderStage Stage{}; - RangeType Type{}; + FShaderLayoutGroupView View{}; TableMeta() = default; - explicit TableMeta(const u32 index, const FShaderStage stage, const RangeType type) - : Index(index), Stage(stage), Type(type) + explicit TableMeta(const u32 index, const FShaderStage stage, const FShaderLayoutGroupView view) { + Index = index; + Stage = stage; + View = view; } }; - struct ItemMeta + struct TableGroup { - // Const | Direct 时是 Root Index,InTable 时是 Table 内的 Index - u32 Index{}; - // InTable 时表示在哪个 Table - TableScope Table{}; - ItemType Type{}; - RangeType RangeType{}; + std::vector Metas{}; + std::vector Infos{}; + TableScope Scope{}; + bool Sampler{}; }; - virtual std::span GetItemMetas() noexcept = 0; - virtual std::array, 2> GetTableMetas() noexcept = 0; + virtual std::span GetTableGroups() noexcept = 0; }; struct D3d12ShaderLayout final : Object @@ -101,9 +55,9 @@ namespace Coplt ComPtr m_root_signature{}; std::vector m_layout_item_defines{}; // 长度和 m_layout_item_defines 相同 - std::vector m_item_metas{}; - // [Common, Material] - std::vector m_table_metas[2]{}; + std::vector m_item_infos{}; + std::vector m_group_classes{}; + std::vector m_table_groups{}; explicit D3d12ShaderLayout(Rc&& device, const FShaderLayoutCreateOptions& options); @@ -112,9 +66,10 @@ namespace Coplt void* GetRootSignaturePtr() noexcept override; const FShaderLayoutItemDefine* GetItemDefines(u32* out_count) noexcept override; + const FShaderLayoutItemInfo* GetItemInfos(u32* out_count) noexcept override; + const FShaderLayoutGroupClass* GetGroupClasses(u32* out_count) noexcept override; - std::span GetItemMetas() noexcept override; - std::array, 2> GetTableMetas() noexcept override; + std::span GetTableGroups() noexcept override; }; struct D3d12ShaderInputLayout final : Object diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.cc b/Coplt.Graphics.Native/D3d12/Src/Queue.cc index 02644e3..434dbea 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.cc @@ -9,7 +9,7 @@ using namespace Coplt; D3d12GpuQueue::D3d12GpuQueue( Rc&& device, const FMainQueueCreateOptions& options -) : m_device(std::move(device)), m_command_interpreter(this) +) : m_device(std::move(device)), m_descriptor_manager(m_device.get()), m_command_interpreter(this) { m_queue_type = FGpuQueueType::Direct; diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.h b/Coplt.Graphics.Native/D3d12/Src/Queue.h index 4208ae3..01a9543 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -9,6 +9,7 @@ #include "../../Api/Include/Object.h" #include "../FFI/Queue.h" #include "Command.h" +#include "DescriptorManager.h" #include "Executor.h" namespace Coplt @@ -21,6 +22,7 @@ namespace Coplt ComPtr m_dx_device{}; ComPtr m_queue{}; Rc m_frame_context{}; + DescriptorManager m_descriptor_manager; CmdListPack m_cmd{}; std::mutex m_mutex{}; From 915bf8d91b0906f881504e141086c24336cbf15d Mon Sep 17 00:00:00 2001 From: U2A5F Date: Fri, 7 Mar 2025 18:46:08 +0800 Subject: [PATCH 5/9] save --- .idea/editor.xml | 4 +- Coplt.Graphics.Core/Core/CommandList.cs | 291 ++++++++++-------- Coplt.Graphics.Core/Core/GpuOutput.cs | 2 +- Coplt.Graphics.Core/Core/GpuQueue.cs | 33 +- Coplt.Graphics.Core/Core/GpuView.cs | 2 +- Coplt.Graphics.Core/Core/IQueueOwned.cs | 17 + Coplt.Graphics.Core/Core/PipelineState.cs | 2 +- Coplt.Graphics.Core/Core/ShaderBinding.cs | 45 ++- Coplt.Graphics.Core/Core/Views.cs | 7 +- Coplt.Graphics.Core/Native/Native.cs | 5 +- Coplt.Graphics.Native/Api/FFI/Command.h | 3 +- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 62 +++- Coplt.Graphics.Native/D3d12/Src/Binding.h | 15 +- Coplt.Graphics.Native/D3d12/Src/Command.cc | 41 ++- Coplt.Graphics.Native/D3d12/Src/Command.h | 1 - .../D3d12/Src/DescriptorManager.cc | 122 +++++++- .../D3d12/Src/DescriptorManager.h | 87 ++++-- Coplt.Graphics.Native/D3d12/Src/Layout.cc | 1 + Coplt.Graphics.Native/D3d12/Src/Layout.h | 1 + 19 files changed, 518 insertions(+), 223 deletions(-) create mode 100644 Coplt.Graphics.Core/Core/IQueueOwned.cs diff --git a/.idea/editor.xml b/.idea/editor.xml index 9e1bfff..25fcf2b 100644 --- a/.idea/editor.xml +++ b/.idea/editor.xml @@ -2,6 +2,8 @@