From fc52935930e69e797b8d889ab2c9eb37322610bd Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 18 Mar 2025 16:36:50 +0800 Subject: [PATCH 01/46] save --- Coplt.Graphics.Core/Core/DeviceChild.cs | 18 ++ Coplt.Graphics.Core/Core/GpuDevice.cs | 101 ++++------ Coplt.Graphics.Core/Core/GpuIsolate.cs | 100 ++++++++++ Coplt.Graphics.Core/Core/GpuObject.cs | 8 +- Coplt.Graphics.Core/Core/GpuQueue.cs | 51 ++++- Coplt.Graphics.Core/Native/Native.cs | 221 ++++++++++++++++++++- Coplt.Graphics.Native/Api/CMakeLists.txt | 1 + Coplt.Graphics.Native/Api/FFI/Device.h | 2 + Coplt.Graphics.Native/Api/FFI/Isolate.h | 33 +++ Coplt.Graphics.Native/Api/FFI/Queue.h | 18 ++ Coplt.Graphics.Native/D3d12/CMakeLists.txt | 3 + Coplt.Graphics.Native/D3d12/FFI/Isolate.h | 10 + Coplt.Graphics.Native/D3d12/FFI/Queue.h | 5 + Coplt.Graphics.Native/D3d12/Src/Device.cc | 16 ++ Coplt.Graphics.Native/D3d12/Src/Device.h | 1 + Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 57 ++++++ Coplt.Graphics.Native/D3d12/Src/Isolate.h | 38 ++++ Coplt.Graphics.Native/D3d12/Src/Queue.cc | 47 ++++- Coplt.Graphics.Native/D3d12/Src/Queue.h | 21 ++ Examples/ExampleBase/ExampleBase.cs | 2 + 20 files changed, 675 insertions(+), 78 deletions(-) create mode 100644 Coplt.Graphics.Core/Core/GpuIsolate.cs create mode 100644 Coplt.Graphics.Native/Api/FFI/Isolate.h create mode 100644 Coplt.Graphics.Native/D3d12/FFI/Isolate.h create mode 100644 Coplt.Graphics.Native/D3d12/Src/Isolate.cc create mode 100644 Coplt.Graphics.Native/D3d12/Src/Isolate.h diff --git a/Coplt.Graphics.Core/Core/DeviceChild.cs b/Coplt.Graphics.Core/Core/DeviceChild.cs index 9ef473f..fb6d48f 100644 --- a/Coplt.Graphics.Core/Core/DeviceChild.cs +++ b/Coplt.Graphics.Core/Core/DeviceChild.cs @@ -19,3 +19,21 @@ internal DeviceChild(FGpuObject* ptr, string? name, GpuDevice device) : base(ptr #endregion } + +public abstract unsafe class IsolateChild : DeviceChild +{ + #region Props + + public GpuIsolate Isolate { get; } + + #endregion + + #region Ctor + + internal IsolateChild(FGpuObject* ptr, string? name, GpuIsolate isolate) : base(ptr, name, isolate.Device) + { + Isolate = isolate; + } + + #endregion +} diff --git a/Coplt.Graphics.Core/Core/GpuDevice.cs b/Coplt.Graphics.Core/Core/GpuDevice.cs index e18ed1e..5c7671e 100644 --- a/Coplt.Graphics.Core/Core/GpuDevice.cs +++ b/Coplt.Graphics.Core/Core/GpuDevice.cs @@ -11,14 +11,12 @@ namespace Coplt.Graphics.Core; [Dropping(Unmanaged = true)] -public sealed unsafe partial class GpuDevice +public sealed unsafe partial class GpuDevice : GpuObject { #region Fields - internal FGpuDevice* m_ptr; internal readonly GraphicsInstance m_instance; internal readonly GpuAdapter m_adapter; - internal string? m_name; [Drop] internal readonly GpuQueue m_main_queue; @@ -26,7 +24,7 @@ public sealed unsafe partial class GpuDevice #region Props - public FGpuDevice* Ptr => m_ptr; + public new FGpuDevice* Ptr => (FGpuDevice*)m_ptr; public GraphicsInstance Instance => m_instance; public GpuAdapter Adapter => m_adapter; public GpuQueue MainQueue => m_main_queue; @@ -39,74 +37,59 @@ public sealed unsafe partial class GpuDevice internal GpuDevice( FGpuDevice* ptr, GraphicsInstance instance, GpuAdapter? adapter, string? name, string? QueueName = null, ReadOnlySpan QueueName8 = default - ) + ) : base((FGpuObject*)ptr, name) { m_instance = instance; m_name = name; - m_ptr = ptr; - m_adapter = adapter ?? m_instance.m_ptr_to_adapters[(nuint)m_ptr->GetAdapter()]; + m_adapter = adapter ?? m_instance.m_ptr_to_adapters[(nuint)Ptr->GetAdapter()]; m_main_queue = CreateMainQueue(Name: QueueName, Name8: QueueName8); } #endregion - #region Drop + #region GetRawDevice - [Drop] - private void Drop() - { - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); - } + /// Dx12 返回 ID3D12Device* + public void* GetRawDevice() => Ptr->GetRawDevice(); + + #endregion + + #region Blob + + public Blob CreateBlob(nuint size) => m_instance.CreateBlob(size); #endregion - #region SetName + #region CreateIsolate - public void SetName(string name) + public GpuIsolate CreateIsolate(string? Name = null, ReadOnlySpan Name8 = default) { - m_name = name; - fixed (char* ptr = name) + FGpuIsolateCreateOptions f_options = new(); + FMainQueueCreateResult f_result; + Ptr->CreateIsolate(&f_options, &f_result).TryThrow(); + var queues = new GpuQueue2[f_result.NumQueues]; + var isolate = new GpuIsolate(f_result.Isolate, null, this, f_result.Data, queues); + for (var i = 0; i < queues.Length; i++) { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); + ref var q = ref f_result.Queues[i]; + queues[i] = new GpuQueue2(q.Queue, q.Data, null, isolate); } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) + if (Instance.DebugEnabled) { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); + if (Name8.Length > 0) + { + isolate.SetName(Name8, Name); + } + else if (Name != null) + { + isolate.SetName(Name); + } } + return isolate; } #endregion - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(GpuDevice)}(0x{(nuint)m_ptr:X})" - : $"{nameof(GpuDevice)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion - - #region GetRawDevice - - /// Dx12 返回 ID3D12Device* - public void* GetRawDevice() => m_ptr->GetRawDevice(); - - #endregion - - #region Blob - - public Blob CreateBlob(nuint size) => m_instance.CreateBlob(size); - - #endregion - #region CreateMainQueue public GpuQueue CreateMainQueue(string? Name = null, ReadOnlySpan Name8 = default) @@ -119,7 +102,7 @@ public GpuQueue CreateMainQueue(string? Name = null, ReadOnlySpan Name8 = Name = new(Name, Name8, p_name, p_name8), }; FGpuQueue* ptr; - m_ptr->CreateMainQueue(&f_options, &ptr).TryThrow(); + Ptr->CreateMainQueue(&f_options, &ptr).TryThrow(); return new(ptr, Name, this); } } @@ -147,7 +130,7 @@ public ShaderModule CreateShaderModule( Stage = Stage.ToFFI(), }; FShaderModule* ptr; - m_ptr->CreateShaderModule(&f_options, &ptr).TryThrow(); + Ptr->CreateShaderModule(&f_options, &ptr).TryThrow(); return new(ptr, Name, EntryPoint); } } @@ -176,7 +159,7 @@ public ShaderLayout CreateShaderLayout( Flags = (FShaderLayoutFlags)Flags, }; FShaderLayout* ptr; - m_ptr->CreateShaderLayout(&f_options, &ptr).TryThrow(); + Ptr->CreateShaderLayout(&f_options, &ptr).TryThrow(); return new(ptr, Name); } } @@ -193,7 +176,7 @@ public ShaderLayout GetEmptyShaderLayout(ShaderLayoutFlags Flags = ShaderLayoutF Flags = (FShaderLayoutFlags)flags, }; FShaderLayout* ptr; - self.m_ptr->GetEmptyShaderLayout(&f_options, &ptr).TryThrow(); + self.Ptr->GetEmptyShaderLayout(&f_options, &ptr).TryThrow(); return new(ptr, $"Empty Shader Layout ({flags})"); }, this ); @@ -247,7 +230,7 @@ public ShaderInputLayout CreateShaderInputLayout( Count = (uint)Elements.Length, }; FShaderInputLayout* ptr; - m_ptr->CreateShaderInputLayout(&f_options, &ptr).TryThrow(); + Ptr->CreateShaderInputLayout(&f_options, &ptr).TryThrow(); return new(ptr, meta, Name); } } @@ -290,7 +273,7 @@ public Shader CreateShader( Count = (byte)Modules.Length, }; FShader* ptr; - m_ptr->CreateShader(&f_options, &ptr).TryThrow(); + Ptr->CreateShader(&f_options, &ptr).TryThrow(); return new(ptr, arr, Layout, InputLayout, Name); } } @@ -328,7 +311,7 @@ public MeshLayout CreateMeshLayout( ElementCount = (uint)Elements.Length, }; FMeshLayout* ptr; - m_ptr->CreateMeshLayout(&f_options, &ptr).TryThrow(); + Ptr->CreateMeshLayout(&f_options, &ptr).TryThrow(); return new(ptr, Name); } } @@ -356,7 +339,7 @@ public GraphicsShaderPipeline CreateGraphicsShaderPipeline( GraphicsState = PipelineState.ToFFI(), }; FGraphicsShaderPipeline* ptr; - m_ptr->CreateGraphicsPipeline(&f_options, &ptr).TryThrow(); + Ptr->CreateGraphicsPipeline(&f_options, &ptr).TryThrow(); return new(ptr, Name, Shader, PipelineState, MeshLayout); } } @@ -397,7 +380,7 @@ public Sampler CreateSampler( Info = Unsafe.As(ref Unsafe.AsRef(in info)), }; FGpuSampler* ptr; - m_ptr->CreateSampler(&f_options, &ptr).TryThrow(); + Ptr->CreateSampler(&f_options, &ptr).TryThrow(); return new(ptr, Name, this); } } diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs new file mode 100644 index 0000000..707cba7 --- /dev/null +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -0,0 +1,100 @@ +using System.Buffers; +using Coplt.Dropping; +using Coplt.Graphics.Native; + +namespace Coplt.Graphics.Core; + +[Dropping(Unmanaged = true)] +public sealed unsafe partial class GpuIsolate : DeviceChild +{ + #region Fields + + internal FGpuIsolateData* m_data; + internal readonly GpuQueue2[] m_queues; + + #endregion + + #region Props + + public new FGpuIsolate* Ptr => (FGpuIsolate*)m_ptr; + public ref readonly FGpuIsolateData Data => ref *m_data; + public ReadOnlySpan Queues => m_queues; + + #endregion + + #region Ctor + + internal GpuIsolate(FGpuIsolate* ptr, string? name, GpuDevice device, FGpuIsolateData* data, GpuQueue2[] queues) + : base((FGpuObject*)ptr, name, device) + { + m_data = data; + m_queues = queues; + } + + #endregion + + #region Drop + + [Drop] + private void Drop() + { + m_data = null; + foreach (var queue in m_queues) + { + queue.Dispose(); + } + } + + #endregion + + #region SetName + + public override void SetName(string name) + { + m_name = name; + if (!Device.Instance.DebugEnabled) return; + for (var i = 0; i < Queues.Length; i++) + { + var queue = Queues[i]; + queue.SetName($"[{name}]::Queue {i} ({queue.QueueType})"); + } + } + + public override void SetName(ReadOnlySpan name, string? managed_version = null) + { + m_name = managed_version; + if (!Device.Instance.DebugEnabled) return; + for (var i = 0; i < Queues.Length; i++) + { + var queue = Queues[i]; + if (managed_version != null) queue.m_name = $"[{managed_version}]::Queue {i} ({queue.QueueType})"; + var tmp_bytes = ArrayPool.Shared.Rent(name.Length + 256); + try + { + tmp_bytes[0] = "["u8[0]; + name.CopyTo(tmp_bytes.AsSpan(1)); + var cur = name.Length + 1; + "]::Queue"u8.CopyTo(tmp_bytes.AsSpan(cur)); + cur += "]::Queue "u8.Length; + i.TryFormat(tmp_bytes.AsSpan(cur), out var len); + cur += len; + tmp_bytes[cur] = " "u8[0]; + cur++; + tmp_bytes[cur] = "("u8[0]; + cur++; + var qt = queue.QueueType.ToUtf8String(); + qt.CopyTo(tmp_bytes.AsSpan(cur)); + cur += qt.Length; + tmp_bytes[cur] = ")"u8[0]; + tmp_bytes[cur + 1] = 0; + queue.SetName(tmp_bytes.AsSpan(0, cur + 2)); + } + finally + { + ArrayPool.Shared.Return(tmp_bytes); + } + } + } + + #endregion +} diff --git a/Coplt.Graphics.Core/Core/GpuObject.cs b/Coplt.Graphics.Core/Core/GpuObject.cs index 81b89f7..03a4af1 100644 --- a/Coplt.Graphics.Core/Core/GpuObject.cs +++ b/Coplt.Graphics.Core/Core/GpuObject.cs @@ -28,7 +28,7 @@ internal GpuObject(FGpuObject* ptr, string? name) : base((FUnknown*)ptr) #region SetName - public void SetName(string name) + public virtual void SetName(string name) { m_name = name; fixed (char* ptr = name) @@ -38,7 +38,7 @@ public void SetName(string name) } } - public void SetName(ReadOnlySpan name, string? managed_version = null) + public virtual void SetName(ReadOnlySpan name, string? managed_version = null) { m_name = managed_version; fixed (byte* ptr = name) @@ -54,8 +54,8 @@ public void SetName(ReadOnlySpan name, string? managed_version = null) public override string ToString() => m_name is null - ? $"0x{GetType().Name}({(nuint)m_ptr:X})" - : $"0x{GetType().Name}({(nuint)m_ptr:X} \"{m_name}\")"; + ? $"{GetType().Name}(0x{(nuint)m_ptr:X})" + : $"{GetType().Name}(0x{(nuint)m_ptr:X} \"{m_name}\")"; #endregion } diff --git a/Coplt.Graphics.Core/Core/GpuQueue.cs b/Coplt.Graphics.Core/Core/GpuQueue.cs index 6a3d1e4..d4b7bec 100644 --- a/Coplt.Graphics.Core/Core/GpuQueue.cs +++ b/Coplt.Graphics.Core/Core/GpuQueue.cs @@ -19,6 +19,14 @@ public static partial class GraphicsExtensions public static FGpuQueueType ToFFI(this GpuQueueType value) => (FGpuQueueType)value; public static GpuQueueType FromFFI(this FGpuQueueType value) => (GpuQueueType)value; + + public static ReadOnlySpan ToUtf8String(this GpuQueueType value) => value switch + { + GpuQueueType.Direct => "Direct"u8, + GpuQueueType.Compute => "Compute"u8, + GpuQueueType.Copy => "Copy"u8, + _ => throw new ArgumentOutOfRangeException(nameof(value), value, null) + }; } [Dropping(Unmanaged = true)] @@ -186,7 +194,7 @@ public ShaderBinding CreateShaderBinding( Layout = Layout.m_ptr, }; FShaderBinding* ptr; - m_device.m_ptr->CreateShaderBinding(&f_options, &ptr).TryThrow(); + m_device.Ptr->CreateShaderBinding(&f_options, &ptr).TryThrow(); return new(ptr, Name, m_device, this, Layout); } } @@ -220,7 +228,7 @@ public GpuBuffer CreateBuffer( Usage = options.Usage.ToFFI(), }; FGpuBuffer* ptr; - m_device.m_ptr->CreateBuffer(&f_options, &ptr).TryThrow(); + m_device.Ptr->CreateBuffer(&f_options, &ptr).TryThrow(); return new(ptr, Name, this); } } @@ -277,7 +285,7 @@ public GpuImage CreateImage( f_options.OptimizedClearValue.Stencil = options.OptimizedClearColor.Depth.Stencil; } FGpuImage* ptr; - m_device.m_ptr->CreateImage(&f_options, &ptr).TryThrow(); + m_device.Ptr->CreateImage(&f_options, &ptr).TryThrow(); return new(ptr, Name, this); } } @@ -347,3 +355,40 @@ public ImageUploadBufferMemory AllocImageUploadMemory2D(uint PixelSize, uint Wid #endregion } + +[Dropping(Unmanaged = true)] +public sealed unsafe partial class GpuQueue2 : IsolateChild +{ + #region Fields + + internal FGpuQueueData* m_data; + + #endregion + + #region Props + + public new FGpuQueue2* Ptr => (FGpuQueue2*)m_ptr; + public ref readonly FGpuQueueData Data => ref *m_data; + public GpuQueueType QueueType => Data.m_queue_type.FromFFI(); + + #endregion + + #region Ctor + + internal GpuQueue2(FGpuQueue2* ptr, FGpuQueueData* data, string? name, GpuIsolate isolate) : base((FGpuObject*)ptr, name, isolate) + { + m_data = data; + } + + #endregion + + #region Drop + + [Drop] + private void Drop() + { + m_data = null; + } + + #endregion +} diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 037a7ec..5c0e601 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -821,12 +821,20 @@ public FResult CreateMainQueue([NativeTypeName("const FMainQueueCreateOptions &" return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &")] FGpuIsolateCreateOptions* options, [NativeTypeName("Coplt::FMainQueueCreateResult &")] FMainQueueCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, FShaderModule** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -834,7 +842,7 @@ public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOpti public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, FShaderLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -842,7 +850,7 @@ public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOpti public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, FShaderLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -850,7 +858,7 @@ public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayout public FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -858,7 +866,7 @@ public FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayout public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, FShader** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -866,7 +874,7 @@ public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FSh public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -874,7 +882,7 @@ public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOp public FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions &")] FMeshLayoutCreateOptions* options, FMeshLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[16]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -882,7 +890,7 @@ public FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[16]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[17]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -890,7 +898,7 @@ public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipe public FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] FGpuBufferCreateOptions* options, FGpuBuffer** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[17]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[18]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -898,7 +906,7 @@ public FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FGpuImageCreateOptions* options, FGpuImage** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[18]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -906,7 +914,7 @@ public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FG public FResult CreateSampler([NativeTypeName("const FGpuSamplerCreateOptions &")] FGpuSamplerCreateOptions* options, FGpuSampler** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[20]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } public interface Interface : FGpuObject.Interface @@ -919,6 +927,9 @@ public interface Interface : FGpuObject.Interface [return: NativeTypeName("Coplt::FResult")] FResult CreateMainQueue([NativeTypeName("const FMainQueueCreateOptions &")] FMainQueueCreateOptions* options, FGpuQueue** @out); + [return: NativeTypeName("Coplt::FResult")] + FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &")] FGpuIsolateCreateOptions* options, [NativeTypeName("Coplt::FMainQueueCreateResult &")] FMainQueueCreateResult* @out); + [return: NativeTypeName("Coplt::FResult")] FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, FShaderModule** @out); @@ -1205,6 +1216,104 @@ public partial struct FGpuDeviceCreateOptions public FStr8or16 Name; } + public partial struct FGpuIsolateCreateOptions + { + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; + } + + public partial struct FGpuIsolateData + { + } + + [Guid("777C5774-8EB8-4550-A977-62CCCD7BDDA6")] + [NativeTypeName("struct FGpuIsolate : Coplt::FGpuObject")] + public unsafe partial struct FGpuIsolate : FGpuIsolate.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuIsolate)); + + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuIsolate*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuIsolate*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuIsolate*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuIsolate*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuIsolate*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, name); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuQueueCreateResult *")] + public FGpuQueueCreateResult* GetQueues([NativeTypeName("Coplt::u32 *")] uint* OutNumQueues) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuIsolate*)Unsafe.AsPointer(ref this), OutNumQueues); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuIsolateData *")] + public FGpuIsolateData* GpuIsolateData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuIsolate*)Unsafe.AsPointer(ref this)); + } + + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FGpuQueueCreateResult *")] + FGpuQueueCreateResult* GetQueues([NativeTypeName("Coplt::u32 *")] uint* OutNumQueues); + + [return: NativeTypeName("Coplt::FGpuIsolateData *")] + FGpuIsolateData* GpuIsolateData(); + } + } + + public unsafe partial struct FMainQueueCreateResult + { + [NativeTypeName("Coplt::FGpuIsolate *")] + public FGpuIsolate* Isolate; + + [NativeTypeName("Coplt::FGpuIsolateData *")] + public FGpuIsolateData* Data; + + [NativeTypeName("Coplt::FGpuQueueCreateResult *")] + public FGpuQueueCreateResult* Queues; + + [NativeTypeName("Coplt::u32")] + public uint NumQueues; + } + [NativeTypeName("Coplt::u8")] public enum FShaderStage : byte { @@ -1897,6 +2006,92 @@ public interface Interface : FGpuObject.Interface } } + public partial struct FGpuQueueData + { + [NativeTypeName("Coplt::FGpuQueueType")] + public FGpuQueueType m_queue_type; + } + + [Guid("FC94E4D0-5F01-4D4F-894C-6AEFAAD90499")] + [NativeTypeName("struct FGpuQueue2 : Coplt::FGpuObject")] + public unsafe partial struct FGpuQueue2 : FGpuQueue2.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuQueue2)); + + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuQueue2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuQueue2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuQueue2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuQueue2*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuQueue2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuQueue2*)Unsafe.AsPointer(ref this), &result, name); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuQueueData *")] + public FGpuQueueData* GpuQueueData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuQueue2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* GetRawQueue() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuQueue2*)Unsafe.AsPointer(ref this)); + } + + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FGpuQueueData *")] + FGpuQueueData* GpuQueueData(); + + void* GetRawQueue(); + } + } + + public unsafe partial struct FGpuQueueCreateResult + { + [NativeTypeName("Coplt::FGpuQueue2 *")] + public FGpuQueue2* Queue; + + [NativeTypeName("Coplt::FGpuQueueData *")] + public FGpuQueueData* Data; + } + [Guid("EDAB0989-E0C2-4B1E-826F-C73380088FC6")] [NativeTypeName("struct FGpuExecutor : Coplt::FGpuObject")] public unsafe partial struct FGpuExecutor : FGpuExecutor.Interface, INativeGuid @@ -5673,6 +5868,8 @@ public static partial class Native public static readonly Guid IID_FGpuDevice = new Guid(0x557F032D, 0xED50, 0x403A, 0xAD, 0xC5, 0x21, 0x4F, 0xDD, 0xBE, 0x6C, 0x6B); + public static readonly Guid IID_FGpuIsolate = new Guid(0x777C5774, 0x8EB8, 0x4550, 0xA9, 0x77, 0x62, 0xCC, 0xCD, 0x7B, 0xDD, 0xA6); + public static readonly Guid IID_FShaderModule = new Guid(0x5C0E1FDB, 0x2ACD, 0x4FCE, 0xB9, 0x85, 0x09, 0xE1, 0x2A, 0x7A, 0x1A, 0xAD); public static readonly Guid IID_FShader = new Guid(0xDE1352D5, 0x023D, 0x42B0, 0xBE, 0xAC, 0x12, 0x2B, 0x3B, 0x29, 0x6C, 0x9C); @@ -5683,6 +5880,8 @@ public static partial class Native public static readonly Guid IID_FGpuQueue = new Guid(0x95E60E28, 0xE387, 0x4055, 0x9B, 0x33, 0x2D, 0x23, 0xAF, 0x90, 0x1F, 0x8A); + public static readonly Guid IID_FGpuQueue2 = new Guid(0xFC94E4D0, 0x5F01, 0x4D4F, 0x89, 0x4C, 0x6A, 0xEF, 0xAA, 0xD9, 0x04, 0x99); + public static readonly Guid IID_FGpuExecutor = new Guid(0xEDAB0989, 0xE0C2, 0x4B1E, 0x82, 0x6F, 0xC7, 0x33, 0x80, 0x08, 0x8F, 0xC6); public static readonly Guid IID_FGpuViewable = new Guid(0xB3AEB8A5, 0x1FA6, 0x4866, 0x97, 0xEF, 0x1A, 0x5F, 0xA4, 0x01, 0xE1, 0x8F); diff --git a/Coplt.Graphics.Native/Api/CMakeLists.txt b/Coplt.Graphics.Native/Api/CMakeLists.txt index 06b08c2..bf9172a 100644 --- a/Coplt.Graphics.Native/Api/CMakeLists.txt +++ b/Coplt.Graphics.Native/Api/CMakeLists.txt @@ -56,6 +56,7 @@ add_library(${target_name} STATIC Include/GpuObject.h Include/Option.h FFI/Sampler.h + FFI/Isolate.h ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) add_library(Coplt::Graphics::Api ALIAS ${target_name}) diff --git a/Coplt.Graphics.Native/Api/FFI/Device.h b/Coplt.Graphics.Native/Api/FFI/Device.h index a61919b..f500517 100644 --- a/Coplt.Graphics.Native/Api/FFI/Device.h +++ b/Coplt.Graphics.Native/Api/FFI/Device.h @@ -3,6 +3,7 @@ #include "Binding.h" #include "Features.h" #include "GpuObject.h" +#include "Isolate.h" #include "Layout.h" #include "Queue.h" #include "Shader.h" @@ -77,6 +78,7 @@ namespace Coplt virtual void* GetRawDevice() noexcept = 0; virtual FResult CreateMainQueue(const FMainQueueCreateOptions& options, FGpuQueue** out) noexcept = 0; + virtual FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FMainQueueCreateResult& out) noexcept = 0; virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModule** out) noexcept = 0; virtual FResult CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayout** out) noexcept = 0; diff --git a/Coplt.Graphics.Native/Api/FFI/Isolate.h b/Coplt.Graphics.Native/Api/FFI/Isolate.h new file mode 100644 index 0000000..ed15987 --- /dev/null +++ b/Coplt.Graphics.Native/Api/FFI/Isolate.h @@ -0,0 +1,33 @@ +#pragma once + +#include "GpuObject.h" +#include "Queue.h" + +namespace Coplt +{ + struct FGpuIsolateCreateOptions + { + // 可选 + FStr8or16 Name{}; + }; + + struct FGpuIsolateData + { + + }; + + COPLT_INTERFACE_DEFINE(FGpuIsolate, "777c5774-8eb8-4550-a977-62cccd7bdda6", FGpuObject) + { + // 返回的 FGpuQueueCreateResult 不会增加引用计数 + virtual FGpuQueueCreateResult* GetQueues(u32* OutNumQueues) noexcept = 0; + virtual FGpuIsolateData* GpuIsolateData() noexcept = 0; + }; + + struct FMainQueueCreateResult + { + FGpuIsolate* Isolate{}; + FGpuIsolateData* Data{}; + FGpuQueueCreateResult* Queues{}; + u32 NumQueues{}; + }; +} diff --git a/Coplt.Graphics.Native/Api/FFI/Queue.h b/Coplt.Graphics.Native/Api/FFI/Queue.h index 9c657c0..39a2f42 100644 --- a/Coplt.Graphics.Native/Api/FFI/Queue.h +++ b/Coplt.Graphics.Native/Api/FFI/Queue.h @@ -52,4 +52,22 @@ namespace Coplt // 提交命令但是不等待执行器可用,必须先等待才能重新使用此执行器提交 virtual FResult SubmitNoWait(FGpuExecutor* Executor, const FCommandSubmit* submit) noexcept = 0; }; + + struct FGpuQueueData + { + FGpuQueueType m_queue_type{}; + }; + + COPLT_INTERFACE_DEFINE(FGpuQueue2, "fc94e4d0-5f01-4d4f-894c-6aefaad90499", FGpuObject) + { + virtual FGpuQueueData* GpuQueueData() noexcept = 0; + // d3d12 返回 ID3D12CommandQueue* + virtual void* GetRawQueue() noexcept = 0; + }; + + struct FGpuQueueCreateResult + { + FGpuQueue2* Queue{}; + FGpuQueueData* Data{}; + }; } diff --git a/Coplt.Graphics.Native/D3d12/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index d68c01a..ee6e12e 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -55,6 +55,9 @@ add_library(${target_name} SHARED Src/Sampler.h Src/Sampler.cc Include/Sampler.h + Src/Isolate.h + Src/Isolate.cc + FFI/Isolate.h ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "Coplt.Graphics.Native.D3d12") diff --git a/Coplt.Graphics.Native/D3d12/FFI/Isolate.h b/Coplt.Graphics.Native/D3d12/FFI/Isolate.h new file mode 100644 index 0000000..83e839a --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/FFI/Isolate.h @@ -0,0 +1,10 @@ +#pragma once + +#include "../../Api/FFI/Isolate.h" + +namespace Coplt +{ + COPLT_INTERFACE_DEFINE(FD3d12GpuIsolate, "a5538b89-42fc-4aaa-9ea1-8ed957454a61", FGpuIsolate) + { + }; +} diff --git a/Coplt.Graphics.Native/D3d12/FFI/Queue.h b/Coplt.Graphics.Native/D3d12/FFI/Queue.h index 23c4e65..99252d5 100644 --- a/Coplt.Graphics.Native/D3d12/FFI/Queue.h +++ b/Coplt.Graphics.Native/D3d12/FFI/Queue.h @@ -8,4 +8,9 @@ namespace Coplt { }; + + COPLT_INTERFACE_DEFINE(FD3d12GpuQueue2, "43fe03f5-0b12-43e3-8550-2c7f82bf5224", FGpuQueue2) + { + + }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 41383b0..27abbaf 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -8,6 +8,7 @@ #include "Buffer.h" #include "GraphicsPipeline.h" #include "Image.h" +#include "Isolate.h" #include "Layout.h" #include "Queue.h" #include "Sampler.h" @@ -153,6 +154,21 @@ FResult D3d12GpuDevice::CreateMainQueue(const FMainQueueCreateOptions& options, }); } +FResult D3d12GpuDevice::CreateIsolate(const FGpuIsolateCreateOptions& options, FMainQueueCreateResult& out) noexcept +{ + return feb([&] + { + const auto ptr = new D3d12GpuIsolate(this->CloneThis(), options); + out.Isolate = ptr; + out.Data = ptr; + out.Queues = out.Isolate->GetQueues(&out.NumQueues); + for (u32 i = 0; i < out.NumQueues; ++i) + { + out.Queues[i].Queue->AddRef(); + } + }); +} + FResult D3d12GpuDevice::CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModule** out) noexcept { return feb([&] diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index 5540569..b2e4043 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -47,6 +47,7 @@ namespace Coplt const Rc& GetEmptyMeshLayout(); FResult CreateMainQueue(const FMainQueueCreateOptions& options, FGpuQueue** out) noexcept override; + FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FMainQueueCreateResult& out) noexcept override; FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModule** out) noexcept override; FResult CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayout** out) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc new file mode 100644 index 0000000..150036e --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -0,0 +1,57 @@ +#include "Isolate.h" + +using namespace Coplt; + +D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options) + : m_device(std::move(device)) +{ + m_main_queue = new D3d12GpuQueue2(this, FGpuQueueType::Direct); + m_back_queue = new D3d12GpuQueue2(this, FGpuQueueType::Compute); + m_copy_queue = new D3d12GpuQueue2(this, FGpuQueueType::Copy); + m_queues = { + FGpuQueueCreateResult{m_main_queue.get(), m_main_queue.get()}, + FGpuQueueCreateResult{m_back_queue.get(), m_back_queue.get()}, + FGpuQueueCreateResult{m_copy_queue.get(), m_copy_queue.get()}, + }; +} + +FResult D3d12GpuIsolate::SetName(const FStr8or16& name) noexcept +{ + return FResult::None(); +} + +const Rc& D3d12GpuIsolate::MainQueue() const noexcept +{ + return m_main_queue; +} + +const Rc& D3d12GpuIsolate::BackQueue() const noexcept +{ + return m_back_queue; +} + +const Rc& D3d12GpuIsolate::CopyQueue() const noexcept +{ + return m_copy_queue; +} + +FGpuQueueCreateResult* D3d12GpuIsolate::GetQueues(u32* OutNumQueues) noexcept +{ + *OutNumQueues = m_queues.size(); + return m_queues.data(); +} + +FGpuIsolateData* D3d12GpuIsolate::GpuIsolateData() noexcept +{ + return this; +} + +FGpuIsolateData& D3d12GpuIsolate::Data() noexcept +{ + return *this; +} + +const FGpuIsolateData& D3d12GpuIsolate::Data() const noexcept +{ + return *this; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h new file mode 100644 index 0000000..2416dcb --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -0,0 +1,38 @@ +#pragma once + +#include "Device.h" +#include "Queue.h" +#include "../FFI/Isolate.h" +#include "../../Api/Include/GpuObject.h" + +namespace Coplt +{ + COPLT_INTERFACE_DEFINE(ID3d12GpuIsolate, "1c507c7f-140a-4717-809e-88096b475fea", FD3d12GpuIsolate) + { + virtual FGpuIsolateData& Data() noexcept = 0; + virtual const FGpuIsolateData& Data() const noexcept = 0; + virtual const Rc& MainQueue() const noexcept = 0; + virtual const Rc& BackQueue() const noexcept = 0; + virtual const Rc& CopyQueue() const noexcept = 0; + }; + + struct D3d12GpuIsolate final : GpuObject, FGpuIsolateData + { + Rc m_device{}; + Rc m_main_queue{}; + Rc m_back_queue{}; + Rc m_copy_queue{}; + std::array m_queues{}; + + explicit D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options); + + FResult SetName(const FStr8or16& name) noexcept override; + const Rc& MainQueue() const noexcept override; + const Rc& BackQueue() const noexcept override; + const Rc& CopyQueue() const noexcept override; + FGpuQueueCreateResult* GetQueues(u32* OutNumQueues) noexcept override; + FGpuIsolateData* GpuIsolateData() noexcept override; + FGpuIsolateData& Data() noexcept override; + const FGpuIsolateData& Data() const noexcept override; + }; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.cc b/Coplt.Graphics.Native/D3d12/Src/Queue.cc index 0fe7933..1802bb4 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.cc @@ -1,8 +1,8 @@ #include "Queue.h" #include "Device.h" +#include "Isolate.h" #include "Output.h" -#include "../../Api/Include/AllocObjectId.h" #include "../../Api/Include/Error.h" using namespace Coplt; @@ -137,3 +137,48 @@ FResult D3d12GpuQueue::SubmitNoWait(FGpuExecutor* Executor, const FCommandSubmit executor->SubmitNoWait(this, submit); }); } + +D3d12GpuQueue2::D3d12GpuQueue2(const NonNull isolate, const FGpuQueueType type) + : m_device(isolate->m_device) +{ + m_queue_type = type; + + constexpr UINT node_mask = 0; + + D3D12_COMMAND_QUEUE_DESC desc{}; + desc.NodeMask = node_mask; + desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + desc.Type = ToDx(type); + desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + + chr | m_device->m_device->CreateCommandQueue(&desc, IID_PPV_ARGS(&m_queue)); +} + +FGpuQueueData* D3d12GpuQueue2::GpuQueueData() noexcept +{ + return this; +} + +FResult D3d12GpuQueue2::SetName(const FStr8or16& name) noexcept +{ + return feb([&] + { + if (!m_device->Debug()) return; + chr | m_queue >> SetNameEx(name); + }); +} + +void* D3d12GpuQueue2::GetRawQueue() noexcept +{ + return m_queue.Get(); +} + +const Rc& D3d12GpuQueue2::Device() const noexcept +{ + return m_device; +} + +const ComPtr& D3d12GpuQueue2::Queue() const noexcept +{ + return m_queue; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.h b/Coplt.Graphics.Native/D3d12/Src/Queue.h index f80769e..6e45f73 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -14,6 +14,7 @@ namespace Coplt { + struct D3d12GpuIsolate; struct D3d12FrameContext; struct D3d12GpuQueue final : GpuObject @@ -70,4 +71,24 @@ namespace Coplt return D3D12_COMMAND_LIST_TYPE_DIRECT; } } + + COPLT_INTERFACE_DEFINE(ID3d12GpuQueue, "a60df5da-ecff-4ae4-a38b-6ddef7db5922", FD3d12GpuQueue2) + { + virtual const Rc& Device() const noexcept = 0; + virtual const ComPtr& Queue() const noexcept = 0; + }; + + struct D3d12GpuQueue2 final : GpuObject, FGpuQueueData + { + Rc m_device{}; + ComPtr m_queue{}; + + explicit D3d12GpuQueue2(NonNull isolate, FGpuQueueType type); + + FGpuQueueData* GpuQueueData() noexcept override; + FResult SetName(const FStr8or16& name) noexcept override; + void* GetRawQueue() noexcept override; + const Rc& Device() const noexcept override; + const ComPtr& Queue() const noexcept override; + }; } // Coplt diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index 2ce86d1..7c6b87a 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -13,6 +13,7 @@ public abstract class ExampleBase(IntPtr Handle, uint Width, uint Height) public bool IsClosed = false; public GraphicsInstance Graphics = null!; public GpuDevice Device = null!; + public GpuIsolate Isolate = null!; public GpuOutput Output = null!; public IntPtr Handle = Handle; @@ -41,6 +42,7 @@ public void DoInitGraphics() Adapter.Features.ShaderModelLevel } ); + Isolate = Device.CreateIsolate(Name: "Main Isolate"); Output = Device.MainQueue.CreateOutputForHwnd( new() { From 04ec2cf576ed17b69fb536858b07ca6ad57f80e7 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Wed, 19 Mar 2025 00:41:19 +0800 Subject: [PATCH 02/46] swap chain --- Coplt.Graphics.Core/Core/GpuIsolate.cs | 37 ++ Coplt.Graphics.Core/Core/GpuOutput.cs | 80 ++++ Coplt.Graphics.Core/Core/GpuQueue.cs | 2 +- Coplt.Graphics.Core/Native/Native.cs | 379 +++++++++++++++++- Coplt.Graphics.Native/Api/CMakeLists.txt | 2 + Coplt.Graphics.Native/Api/FFI/Isolate.h | 11 +- Coplt.Graphics.Native/Api/FFI/Output.h | 68 ++++ Coplt.Graphics.Native/Api/FFI/Queue.h | 2 +- Coplt.Graphics.Native/Api/FFI/Record.h | 39 ++ Coplt.Graphics.Native/Api/FFI/String.h | 5 + Coplt.Graphics.Native/Api/Include/Finally.h | 26 ++ Coplt.Graphics.Native/D3d12/CMakeLists.txt | 5 +- Coplt.Graphics.Native/D3d12/FFI/Isolate.h | 10 - Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 50 ++- Coplt.Graphics.Native/D3d12/Src/Isolate.h | 27 +- Coplt.Graphics.Native/D3d12/Src/Queue.cc | 43 +- Coplt.Graphics.Native/D3d12/Src/Queue.h | 22 +- Coplt.Graphics.Native/D3d12/Src/Record.cc | 28 ++ Coplt.Graphics.Native/D3d12/Src/Record.h | 27 ++ Coplt.Graphics.Native/D3d12/Src/SwapChain.cc | 325 +++++++++++++++ Coplt.Graphics.Native/D3d12/Src/SwapChain.h | 79 ++++ Coplt.Graphics.sln | 7 + Examples/SwapChain/App.xaml | 9 + Examples/SwapChain/App.xaml.cs | 62 +++ Examples/SwapChain/AssemblyInfo.cs | 10 + Examples/SwapChain/ExampleBase.cs | 75 ++++ Examples/SwapChain/MainWindow.xaml | 11 + Examples/SwapChain/MainWindow.xaml.cs | 40 ++ .../SwapChain/Properties/launchSettings.json | 9 + Examples/SwapChain/Shaders/Shader.hlsl | 67 ++++ Examples/SwapChain/SwapChain.csproj | 75 ++++ 31 files changed, 1567 insertions(+), 65 deletions(-) create mode 100644 Coplt.Graphics.Native/Api/FFI/Record.h create mode 100644 Coplt.Graphics.Native/Api/Include/Finally.h delete mode 100644 Coplt.Graphics.Native/D3d12/FFI/Isolate.h create mode 100644 Coplt.Graphics.Native/D3d12/Src/Record.cc create mode 100644 Coplt.Graphics.Native/D3d12/Src/Record.h create mode 100644 Coplt.Graphics.Native/D3d12/Src/SwapChain.cc create mode 100644 Coplt.Graphics.Native/D3d12/Src/SwapChain.h create mode 100644 Examples/SwapChain/App.xaml create mode 100644 Examples/SwapChain/App.xaml.cs create mode 100644 Examples/SwapChain/AssemblyInfo.cs create mode 100644 Examples/SwapChain/ExampleBase.cs create mode 100644 Examples/SwapChain/MainWindow.xaml create mode 100644 Examples/SwapChain/MainWindow.xaml.cs create mode 100644 Examples/SwapChain/Properties/launchSettings.json create mode 100644 Examples/SwapChain/Shaders/Shader.hlsl create mode 100644 Examples/SwapChain/SwapChain.csproj diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 707cba7..f824853 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -97,4 +97,41 @@ public override void SetName(ReadOnlySpan name, string? managed_version = } #endregion + + #region CreateSwapChainForHwnd + + /// + /// Will fail on non Windows systems + /// + public GpuSwapChain CreateSwapChainForHwnd(IntPtr Hwnd, in GpuSwapChainCreateOptions Options, string? Name = null, ReadOnlySpan Name8 = default) + { + fixed (char* p_name = Name) + fixed (byte* p_name8 = Name8) + { + FGpuSwapChainCreateOptions f_options = new() + { + Base = new() + { + Name = new(Name, Name8, p_name, p_name8), + PresentMode = (FPresentMode)Options.PresentMode, + }, + Width = Options.Width, + Height = Options.Height, + Format = Options.Format.ToFFI(), + AlphaMode = (FOutputAlphaMode)Options.AlphaMode, + VSync = Options.VSync, + FormatSelector = + { + Specify = Options.FormatSelector.Specify, + Srgb = Options.FormatSelector.Srgb, + Hdr = (FHdrType)Options.FormatSelector.Hdr, + }, + }; + FGpuSwapChainCreateResult r; + Ptr->CreateSwapChainForHwnd(&f_options, (void*)Hwnd, &r).TryThrow(); + return new(r.SwapChain, r.Data, Name, this); + } + } + + #endregion } diff --git a/Coplt.Graphics.Core/Core/GpuOutput.cs b/Coplt.Graphics.Core/Core/GpuOutput.cs index 2415676..d1e5635 100644 --- a/Coplt.Graphics.Core/Core/GpuOutput.cs +++ b/Coplt.Graphics.Core/Core/GpuOutput.cs @@ -149,3 +149,83 @@ m_name is null #endregion } + +[Dropping(Unmanaged = true)] +public abstract unsafe partial class GpuOutput2 : IsolateChild +{ + #region Fields + + internal FGpuOutputData* m_data; + + #endregion + + #region Props + + public new FGpuOutput2* Ptr => (FGpuOutput2*)m_ptr; + public ref readonly FGpuOutputData Data => ref *m_data; + + #endregion + + #region Ctor + + internal GpuOutput2(FGpuOutput2* ptr, FGpuOutputData* data, string? name, GpuIsolate isolate) : base((FGpuObject*)ptr, name, isolate) + { + m_data = data; + } + + #endregion + + #region Drop + + [Drop] + private void Drop() + { + m_data = null; + } + + #endregion + + #region Methods + + public void Resize(uint Width, uint Height) => Ptr->Resize(Width, Height).TryThrow(); + + public void Present() => Ptr->Present().TryThrow(); + public void PresentNoWait() => Ptr->PresentNoWait().TryThrow(); + public void Wait() => Ptr->Wait().TryThrow(); + + #endregion +} + +public record struct GpuSwapChainCreateOptions() +{ + public required uint Width; + public required uint Height; + public GraphicsFormat Format = GraphicsFormat.R8G8B8A8_UNorm; + public PresentMode PresentMode = PresentMode.TripleBuffer; + public OutputAlphaMode AlphaMode = OutputAlphaMode.Opaque; + public bool VSync = false; + public GpuOutputFormatSelector FormatSelector; +} + +public sealed unsafe class GpuSwapChain : GpuOutput2 +{ + #region Props + + public new FGpuSwapChain* Ptr => (FGpuSwapChain*)m_ptr; + public new ref readonly FGpuSwapChainData Data => ref *(FGpuSwapChainData*)m_data; + + #endregion + + #region Ctor + + internal GpuSwapChain(FGpuSwapChain* ptr, FGpuSwapChainData* data, string? name, GpuIsolate isolate) + : base((FGpuOutput2*)ptr, (FGpuOutputData*)data, name, isolate) { } + + #endregion + + #region Methods + + public void SetVSync(bool Enable) => Ptr->SetVSync(Enable).TryThrow(); + + #endregion +} diff --git a/Coplt.Graphics.Core/Core/GpuQueue.cs b/Coplt.Graphics.Core/Core/GpuQueue.cs index d4b7bec..cac6a51 100644 --- a/Coplt.Graphics.Core/Core/GpuQueue.cs +++ b/Coplt.Graphics.Core/Core/GpuQueue.cs @@ -369,7 +369,7 @@ public sealed unsafe partial class GpuQueue2 : IsolateChild public new FGpuQueue2* Ptr => (FGpuQueue2*)m_ptr; public ref readonly FGpuQueueData Data => ref *m_data; - public GpuQueueType QueueType => Data.m_queue_type.FromFFI(); + public GpuQueueType QueueType => Data.QueueType.FromFFI(); #endregion diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 5c0e601..d98d33c 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1216,6 +1216,18 @@ public partial struct FGpuDeviceCreateOptions public FStr8or16 Name; } + public partial struct FGpuRecord + { + } + + public partial struct FGpuRecordCreateOptions + { + } + + public partial struct FGpuRecordCreateResult + { + } + public partial struct FGpuIsolateCreateOptions { [NativeTypeName("Coplt::FStr8or16")] @@ -1289,6 +1301,30 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuIsolate*)Unsafe.AsPointer(ref this)); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateRecord([NativeTypeName("const FGpuRecordCreateOptions &")] FGpuRecordCreateOptions* options, [NativeTypeName("Coplt::FGpuRecordCreateResult &")] FGpuRecordCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateSwapChainFromExists([NativeTypeName("const FGpuSwapChainFromExistsCreateOptions &")] FGpuSwapChainFromExistsCreateOptions* options, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateSwapChainForHwnd([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, void* hwnd, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, hwnd, @out); + } + public interface Interface : FGpuObject.Interface { [return: NativeTypeName("Coplt::FGpuQueueCreateResult *")] @@ -1296,9 +1332,22 @@ public interface Interface : FGpuObject.Interface [return: NativeTypeName("Coplt::FGpuIsolateData *")] FGpuIsolateData* GpuIsolateData(); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateRecord([NativeTypeName("const FGpuRecordCreateOptions &")] FGpuRecordCreateOptions* options, [NativeTypeName("Coplt::FGpuRecordCreateResult &")] FGpuRecordCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateSwapChainFromExists([NativeTypeName("const FGpuSwapChainFromExistsCreateOptions &")] FGpuSwapChainFromExistsCreateOptions* options, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateSwapChainForHwnd([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, void* hwnd, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out); } } + public partial struct FGpuIsolate + { + } + public unsafe partial struct FMainQueueCreateResult { [NativeTypeName("Coplt::FGpuIsolate *")] @@ -2009,7 +2058,7 @@ public interface Interface : FGpuObject.Interface public partial struct FGpuQueueData { [NativeTypeName("Coplt::FGpuQueueType")] - public FGpuQueueType m_queue_type; + public FGpuQueueType QueueType; } [Guid("FC94E4D0-5F01-4D4F-894C-6AEFAAD90499")] @@ -3070,6 +3119,330 @@ public interface Interface : FGpuExecutor.Interface } } + public partial struct FGpuOutputData + { + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat Format; + + [NativeTypeName("Coplt::u32")] + public uint Width; + + [NativeTypeName("Coplt::u32")] + public uint Height; + + [NativeTypeName("Coplt::FPresentMode")] + public FPresentMode PresentMode; + } + + public partial struct FGpuOutput2CreateOptions + { + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; + + [NativeTypeName("Coplt::FPresentMode")] + public FPresentMode PresentMode; + } + + [Guid("3F82BE7F-2CF5-48A9-8CA4-BB2F9CFE58B2")] + [NativeTypeName("struct FGpuOutput2 : Coplt::FGpuExecutor")] + public unsafe partial struct FGpuOutput2 : FGpuOutput2.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuOutput2)); + + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuOutput2*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result, name); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Wait() + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("const FGpuOutputData *")] + public FGpuOutputData* GpuOutputData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Resize([NativeTypeName("Coplt::u32")] uint Width, [NativeTypeName("Coplt::u32")] uint Height) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result, Width, Height); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Present() + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult PresentNoWait() + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool IsAvailable() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuOutput2*)Unsafe.AsPointer(ref this)) != 0; + } + + public interface Interface : FGpuExecutor.Interface + { + [return: NativeTypeName("const FGpuOutputData *")] + FGpuOutputData* GpuOutputData(); + + [return: NativeTypeName("Coplt::FResult")] + FResult Resize([NativeTypeName("Coplt::u32")] uint Width, [NativeTypeName("Coplt::u32")] uint Height); + + [return: NativeTypeName("Coplt::FResult")] + FResult Present(); + + [return: NativeTypeName("Coplt::FResult")] + FResult PresentNoWait(); + + bool IsAvailable(); + } + } + + [NativeTypeName("struct FGpuSwapChainData : Coplt::FGpuOutputData")] + public partial struct FGpuSwapChainData + { + public FGpuOutputData Base; + + [NativeTypeName("Coplt::FOutputAlphaMode")] + public FOutputAlphaMode AlphaMode; + + [NativeTypeName("Coplt::b8")] + public B8 VSync; + } + + [NativeTypeName("struct FGpuSwapChainCreateOptions : Coplt::FGpuOutput2CreateOptions")] + public partial struct FGpuSwapChainCreateOptions + { + public FGpuOutput2CreateOptions Base; + + [NativeTypeName("Coplt::u32")] + public uint Width; + + [NativeTypeName("Coplt::u32")] + public uint Height; + + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat Format; + + [NativeTypeName("Coplt::FGpuOutputFormatSelector")] + public FGpuOutputFormatSelector FormatSelector; + + [NativeTypeName("Coplt::FOutputAlphaMode")] + public FOutputAlphaMode AlphaMode; + + [NativeTypeName("Coplt::b8")] + public B8 VSync; + } + + [NativeTypeName("struct FGpuSwapChainFromExistsCreateOptions : Coplt::FGpuOutput2CreateOptions")] + public unsafe partial struct FGpuSwapChainFromExistsCreateOptions + { + public FGpuOutput2CreateOptions Base; + + public void* ExistsSwapChain; + + [NativeTypeName("Coplt::FOutputAlphaMode")] + public FOutputAlphaMode AlphaMode; + + [NativeTypeName("Coplt::b8")] + public B8 VSync; + } + + [Guid("2BC677A1-77FC-4540-89E2-1FB7E3417DC2")] + [NativeTypeName("struct FGpuSwapChain : Coplt::FGpuOutput2")] + public unsafe partial struct FGpuSwapChain : FGpuSwapChain.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuSwapChain)); + + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result, name); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Wait() + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("const FGpuOutputData *")] + public FGpuOutputData* GpuOutputData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Resize([NativeTypeName("Coplt::u32")] uint Width, [NativeTypeName("Coplt::u32")] uint Height) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result, Width, Height); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Present() + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult PresentNoWait() + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool IsAvailable() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)) != 0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("const FGpuSwapChainData *")] + public FGpuSwapChainData* GpuSwapChainData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuIsolate *")] + public FGpuIsolate* GetIsolate() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result, Enable); + } + + public interface Interface : FGpuOutput2.Interface + { + [return: NativeTypeName("const FGpuSwapChainData *")] + FGpuSwapChainData* GpuSwapChainData(); + + [return: NativeTypeName("Coplt::FGpuIsolate *")] + FGpuIsolate* GetIsolate(); + + [return: NativeTypeName("Coplt::FResult")] + FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable); + } + } + + public unsafe partial struct FGpuSwapChainCreateResult + { + [NativeTypeName("Coplt::FGpuSwapChain *")] + public FGpuSwapChain* SwapChain; + + [NativeTypeName("Coplt::FGpuSwapChainData *")] + public FGpuSwapChainData* Data; + } + [NativeTypeName("Coplt::u8")] public enum FImagePlane : byte { @@ -5894,6 +6267,10 @@ public static partial class Native public static readonly Guid IID_FGpuOutput = new Guid(0xF1C59CB4, 0x7EE6, 0x4EE2, 0x80, 0xF4, 0x07, 0xCC, 0x56, 0x89, 0x20, 0xD2); + public static readonly Guid IID_FGpuOutput2 = new Guid(0x3F82BE7F, 0x2CF5, 0x48A9, 0x8C, 0xA4, 0xBB, 0x2F, 0x9C, 0xFE, 0x58, 0xB2); + + public static readonly Guid IID_FGpuSwapChain = new Guid(0x2BC677A1, 0x77FC, 0x4540, 0x89, 0xE2, 0x1F, 0xB7, 0xE3, 0x41, 0x7D, 0xC2); + public static readonly Guid IID_FShaderLayout = new Guid(0x552A498E, 0x8F3A, 0x47FF, 0xA3, 0x35, 0x7A, 0xF2, 0xDE, 0x09, 0x01, 0xE8); public static readonly Guid IID_FShaderInputLayout = new Guid(0x70229C9A, 0xFB3D, 0x46B4, 0xB5, 0x34, 0x72, 0xFD, 0xB1, 0x67, 0xD8, 0x07); diff --git a/Coplt.Graphics.Native/Api/CMakeLists.txt b/Coplt.Graphics.Native/Api/CMakeLists.txt index bf9172a..1b00e28 100644 --- a/Coplt.Graphics.Native/Api/CMakeLists.txt +++ b/Coplt.Graphics.Native/Api/CMakeLists.txt @@ -57,6 +57,8 @@ add_library(${target_name} STATIC Include/Option.h FFI/Sampler.h FFI/Isolate.h + FFI/Record.h + Include/Finally.h ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) add_library(Coplt::Graphics::Api ALIAS ${target_name}) diff --git a/Coplt.Graphics.Native/Api/FFI/Isolate.h b/Coplt.Graphics.Native/Api/FFI/Isolate.h index ed15987..ec36b1f 100644 --- a/Coplt.Graphics.Native/Api/FFI/Isolate.h +++ b/Coplt.Graphics.Native/Api/FFI/Isolate.h @@ -5,6 +5,10 @@ namespace Coplt { + struct FGpuRecord; + struct FGpuRecordCreateOptions; + struct FGpuRecordCreateResult; + struct FGpuIsolateCreateOptions { // 可选 @@ -13,7 +17,6 @@ namespace Coplt struct FGpuIsolateData { - }; COPLT_INTERFACE_DEFINE(FGpuIsolate, "777c5774-8eb8-4550-a977-62cccd7bdda6", FGpuObject) @@ -21,6 +24,12 @@ namespace Coplt // 返回的 FGpuQueueCreateResult 不会增加引用计数 virtual FGpuQueueCreateResult* GetQueues(u32* OutNumQueues) noexcept = 0; virtual FGpuIsolateData* GpuIsolateData() noexcept = 0; + + virtual FResult CreateRecord(const FGpuRecordCreateOptions& options, FGpuRecordCreateResult& out) noexcept = 0; + + virtual FResult CreateSwapChainFromExists(const FGpuSwapChainFromExistsCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept = 0; + // 在非 windows 系统上会报错 + virtual FResult CreateSwapChainForHwnd(const FGpuSwapChainCreateOptions& options, void* hwnd, FGpuSwapChainCreateResult& out) noexcept = 0; }; struct FMainQueueCreateResult diff --git a/Coplt.Graphics.Native/Api/FFI/Output.h b/Coplt.Graphics.Native/Api/FFI/Output.h index 8f0cb88..d02c72c 100644 --- a/Coplt.Graphics.Native/Api/FFI/Output.h +++ b/Coplt.Graphics.Native/Api/FFI/Output.h @@ -77,4 +77,72 @@ namespace Coplt virtual FResult Resize(u32 Width, u32 Height) noexcept = 0; }; + + struct FGpuOutputData + { + FGraphicsFormat Format{}; + u32 Width{}; + u32 Height{}; + FPresentMode PresentMode{}; + }; + + struct FGpuOutput2CreateOptions + { + FStr8or16 Name{}; + // 呈现模式,实现可以选择忽略 + FPresentMode PresentMode{}; + }; + + COPLT_INTERFACE_DEFINE(FGpuOutput2, "3f82be7f-2cf5-48a9-8ca4-bb2f9cfe58b2", FGpuExecutor) + { + virtual const FGpuOutputData* GpuOutputData() noexcept = 0; + + virtual FResult Resize(u32 Width, u32 Height) noexcept = 0; + + virtual FResult Present() noexcept = 0; + virtual FResult PresentNoWait() noexcept = 0; + + virtual bool IsAvailable() noexcept = 0; + }; + + struct FGpuSwapChainData : FGpuOutputData + { + FOutputAlphaMode AlphaMode{}; + b8 VSync{}; + }; + + struct FGpuSwapChainCreateOptions : FGpuOutput2CreateOptions + { + u32 Width{}; + u32 Height{}; + FGraphicsFormat Format{}; + FGpuOutputFormatSelector FormatSelector{}; + FOutputAlphaMode AlphaMode{}; + b8 VSync{}; + }; + + struct FGpuSwapChainFromExistsCreateOptions : FGpuOutput2CreateOptions + { + // d3d12 是 IDXGISwapChain3* + void* ExistsSwapChain{}; + FOutputAlphaMode AlphaMode{}; + b8 VSync{}; + }; + + struct FGpuIsolate; + + COPLT_INTERFACE_DEFINE(FGpuSwapChain, "2bc677a1-77fc-4540-89e2-1fb7e3417dc2", FGpuOutput2) + { + virtual const FGpuSwapChainData* GpuSwapChainData() noexcept = 0; + virtual FGpuIsolate* GetIsolate() noexcept = 0; + + // 设置垂直同步,实现可以选择忽略 + virtual FResult SetVSync(b8 Enable) noexcept = 0; + }; + + struct FGpuSwapChainCreateResult + { + FGpuSwapChain* SwapChain{}; + FGpuSwapChainData* Data{}; + }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Queue.h b/Coplt.Graphics.Native/Api/FFI/Queue.h index 39a2f42..72c8793 100644 --- a/Coplt.Graphics.Native/Api/FFI/Queue.h +++ b/Coplt.Graphics.Native/Api/FFI/Queue.h @@ -55,7 +55,7 @@ namespace Coplt struct FGpuQueueData { - FGpuQueueType m_queue_type{}; + FGpuQueueType QueueType{}; }; COPLT_INTERFACE_DEFINE(FGpuQueue2, "fc94e4d0-5f01-4d4f-894c-6aefaad90499", FGpuObject) diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h new file mode 100644 index 0000000..8d18ec5 --- /dev/null +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -0,0 +1,39 @@ +#pragma once + +#include "GpuObject.h" +#include "Isolate.h" + +namespace Coplt +{ + struct FGpuRecordData; + + struct FGpuRecordCreateOptions + { + // 可选 + FStr8or16 Name{}; + }; + + COPLT_INTERFACE_DEFINE(FGpuRecord, "0ef83584-ca65-44de-b38a-648bfb3a85a6", FGpuObject) + { + virtual FGpuRecordData* GpuFGpuRecordData() noexcept = 0; + }; + + // 里面的 FList 的 T* 生命周期由 c# 部分保证 + struct FGpuRecordData + { + FList Outputs; + + #ifdef FFI_SRC + explicit FGpuRecordData(FAllocator* allocator) + : Outputs(allocator) + { + } + #endif + }; + + struct FGpuRecordCreateResult + { + FGpuRecord* Record{}; + FGpuRecordData* Data{}; + }; +} diff --git a/Coplt.Graphics.Native/Api/FFI/String.h b/Coplt.Graphics.Native/Api/FFI/String.h index 1e4202f..6c0d077 100644 --- a/Coplt.Graphics.Native/Api/FFI/String.h +++ b/Coplt.Graphics.Native/Api/FFI/String.h @@ -139,6 +139,11 @@ namespace Coplt { } + const wchar_t* wcstr() const + { + return reinterpret_cast(this->str16); + } + #endif bool is8() const diff --git a/Coplt.Graphics.Native/Api/Include/Finally.h b/Coplt.Graphics.Native/Api/Include/Finally.h new file mode 100644 index 0000000..6ddf10d --- /dev/null +++ b/Coplt.Graphics.Native/Api/Include/Finally.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Concepts.h" + +namespace Coplt +{ + template F> + class Finally + { + F f; + + public: + explicit Finally(F&& f) : f(std::forward(f)) + { + } + + explicit Finally(const F& f) : f(f) + { + } + + ~Finally() + { + f(); + } + }; +} diff --git a/Coplt.Graphics.Native/D3d12/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index ee6e12e..b2febce 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -57,7 +57,10 @@ add_library(${target_name} SHARED Include/Sampler.h Src/Isolate.h Src/Isolate.cc - FFI/Isolate.h + Src/Record.h + Src/Record.cc + Src/SwapChain.h + Src/SwapChain.cc ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "Coplt.Graphics.Native.D3d12") diff --git a/Coplt.Graphics.Native/D3d12/FFI/Isolate.h b/Coplt.Graphics.Native/D3d12/FFI/Isolate.h deleted file mode 100644 index 83e839a..0000000 --- a/Coplt.Graphics.Native/D3d12/FFI/Isolate.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "../../Api/FFI/Isolate.h" - -namespace Coplt -{ - COPLT_INTERFACE_DEFINE(FD3d12GpuIsolate, "a5538b89-42fc-4aaa-9ea1-8ed957454a61", FGpuIsolate) - { - }; -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index 150036e..e44565d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -1,10 +1,15 @@ #include "Isolate.h" +#include "Record.h" +#include "SwapChain.h" +#include "../../Api/FFI/Record.h" + using namespace Coplt; D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options) - : m_device(std::move(device)) + : FGpuIsolateData() { + m_device = std::move(device); m_main_queue = new D3d12GpuQueue2(this, FGpuQueueType::Direct); m_back_queue = new D3d12GpuQueue2(this, FGpuQueueType::Compute); m_copy_queue = new D3d12GpuQueue2(this, FGpuQueueType::Copy); @@ -20,21 +25,6 @@ FResult D3d12GpuIsolate::SetName(const FStr8or16& name) noexcept return FResult::None(); } -const Rc& D3d12GpuIsolate::MainQueue() const noexcept -{ - return m_main_queue; -} - -const Rc& D3d12GpuIsolate::BackQueue() const noexcept -{ - return m_back_queue; -} - -const Rc& D3d12GpuIsolate::CopyQueue() const noexcept -{ - return m_copy_queue; -} - FGpuQueueCreateResult* D3d12GpuIsolate::GetQueues(u32* OutNumQueues) noexcept { *OutNumQueues = m_queues.size(); @@ -46,12 +36,32 @@ FGpuIsolateData* D3d12GpuIsolate::GpuIsolateData() noexcept return this; } -FGpuIsolateData& D3d12GpuIsolate::Data() noexcept +FResult D3d12GpuIsolate::CreateRecord(const FGpuRecordCreateOptions& options, FGpuRecordCreateResult& out) noexcept +{ + return feb([&] + { + const auto ptr = new D3d12GpuRecord(this, options); + out.Record = ptr; + out.Data = ptr; + }); +} + +FResult D3d12GpuIsolate::CreateSwapChainFromExists(const FGpuSwapChainFromExistsCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept { - return *this; + return feb([&] + { + const auto ptr = new D3d12GpuSwapChain(this, options); + out.SwapChain = ptr; + out.Data = ptr; + }); } -const FGpuIsolateData& D3d12GpuIsolate::Data() const noexcept +FResult D3d12GpuIsolate::CreateSwapChainForHwnd(const FGpuSwapChainCreateOptions& options, void* hwnd, FGpuSwapChainCreateResult& out) noexcept { - return *this; + return feb([&] + { + const auto ptr = new D3d12GpuSwapChain(this, options, static_cast(hwnd)); + out.SwapChain = ptr; + out.Data = ptr; + }); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index 2416dcb..2ce9626 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -2,37 +2,32 @@ #include "Device.h" #include "Queue.h" -#include "../FFI/Isolate.h" +#include "../../Api/FFI/Isolate.h" #include "../../Api/Include/GpuObject.h" namespace Coplt { - COPLT_INTERFACE_DEFINE(ID3d12GpuIsolate, "1c507c7f-140a-4717-809e-88096b475fea", FD3d12GpuIsolate) - { - virtual FGpuIsolateData& Data() noexcept = 0; - virtual const FGpuIsolateData& Data() const noexcept = 0; - virtual const Rc& MainQueue() const noexcept = 0; - virtual const Rc& BackQueue() const noexcept = 0; - virtual const Rc& CopyQueue() const noexcept = 0; - }; - - struct D3d12GpuIsolate final : GpuObject, FGpuIsolateData + COPLT_INTERFACE_DEFINE(ID3d12GpuIsolate, "1c507c7f-140a-4717-809e-88096b475fea", FGpuIsolate) { Rc m_device{}; Rc m_main_queue{}; Rc m_back_queue{}; Rc m_copy_queue{}; std::array m_queues{}; + std::mutex m_mutex{}; + }; + struct D3d12GpuIsolate final : GpuObject, FGpuIsolateData + { explicit D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; - const Rc& MainQueue() const noexcept override; - const Rc& BackQueue() const noexcept override; - const Rc& CopyQueue() const noexcept override; FGpuQueueCreateResult* GetQueues(u32* OutNumQueues) noexcept override; FGpuIsolateData* GpuIsolateData() noexcept override; - FGpuIsolateData& Data() noexcept override; - const FGpuIsolateData& Data() const noexcept override; + + FResult CreateRecord(const FGpuRecordCreateOptions& options, FGpuRecordCreateResult& out) noexcept override; + + FResult CreateSwapChainFromExists(const FGpuSwapChainFromExistsCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept override; + FResult CreateSwapChainForHwnd(const FGpuSwapChainCreateOptions& options, void* hwnd, FGpuSwapChainCreateResult& out) noexcept override; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.cc b/Coplt.Graphics.Native/D3d12/Src/Queue.cc index 1802bb4..293f6cf 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.cc @@ -139,9 +139,11 @@ FResult D3d12GpuQueue::SubmitNoWait(FGpuExecutor* Executor, const FCommandSubmit } D3d12GpuQueue2::D3d12GpuQueue2(const NonNull isolate, const FGpuQueueType type) - : m_device(isolate->m_device) + : FGpuQueueData() { - m_queue_type = type; + m_device = isolate->m_device; + QueueType = type; + const NonNull device = m_device->m_device.Get(); constexpr UINT node_mask = 0; @@ -151,7 +153,10 @@ D3d12GpuQueue2::D3d12GpuQueue2(const NonNull isolate, const FGp desc.Type = ToDx(type); desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; - chr | m_device->m_device->CreateCommandQueue(&desc, IID_PPV_ARGS(&m_queue)); + chr | device->CreateCommandQueue(&desc, IID_PPV_ARGS(&m_queue)); + + chr | device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)); + m_fence_value = 1; } FGpuQueueData* D3d12GpuQueue2::GpuQueueData() noexcept @@ -164,7 +169,18 @@ FResult D3d12GpuQueue2::SetName(const FStr8or16& name) noexcept return feb([&] { if (!m_device->Debug()) return; + if (name.is_null()) return; chr | m_queue >> SetNameEx(name); + if (name.is8()) + { + const auto str = fmt::format("[{}]::Fence", name.str8); + chr | m_fence >> SetNameEx(FStr8or16(str)); + } + else + { + const auto str = fmt::format(L"[{}]::Fence", reinterpret_cast(name.str16)); + chr | m_fence >> SetNameEx(FStr8or16(str)); + } }); } @@ -173,12 +189,25 @@ void* D3d12GpuQueue2::GetRawQueue() noexcept return m_queue.Get(); } -const Rc& D3d12GpuQueue2::Device() const noexcept +u64 D3d12GpuQueue2::Signal() { - return m_device; + std::lock_guard lock(m_mutex); + return SignalNoLock(); } -const ComPtr& D3d12GpuQueue2::Queue() const noexcept +u64 D3d12GpuQueue2::SignalNoLock() { - return m_queue; + const auto fence_value = m_fence_value; + chr | m_queue->Signal(m_fence.Get(), fence_value); + m_fence_value++; + return fence_value; +} + +void D3d12GpuQueue2::WaitFenceValue(u64 fence_value, HANDLE event) +{ + if (m_fence->GetCompletedValue() < fence_value) + { + chr | m_fence->SetEventOnCompletion(fence_value, event); + WaitForSingleObject(event, INFINITE); + } } diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.h b/Coplt.Graphics.Native/D3d12/Src/Queue.h index 6e45f73..026fda4 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -74,21 +74,29 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12GpuQueue, "a60df5da-ecff-4ae4-a38b-6ddef7db5922", FD3d12GpuQueue2) { - virtual const Rc& Device() const noexcept = 0; - virtual const ComPtr& Queue() const noexcept = 0; + Rc m_device{}; + ComPtr m_queue{}; + ComPtr m_fence{}; + u64 m_fence_value{}; + std::mutex m_mutex{}; + + virtual u64 Signal() = 0; + virtual u64 SignalNoLock() = 0; + + virtual void WaitFenceValue(u64 fence_value, HANDLE event) = 0; }; struct D3d12GpuQueue2 final : GpuObject, FGpuQueueData { - Rc m_device{}; - ComPtr m_queue{}; - explicit D3d12GpuQueue2(NonNull isolate, FGpuQueueType type); FGpuQueueData* GpuQueueData() noexcept override; FResult SetName(const FStr8or16& name) noexcept override; void* GetRawQueue() noexcept override; - const Rc& Device() const noexcept override; - const ComPtr& Queue() const noexcept override; + + u64 Signal() override; + u64 SignalNoLock() override; + + void WaitFenceValue(u64 fence_value, HANDLE event) override; }; } // Coplt diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc new file mode 100644 index 0000000..c70cb80 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -0,0 +1,28 @@ +#include "Record.h" + +using namespace Coplt; + +D3d12GpuRecord::D3d12GpuRecord(NonNull isolate, const FGpuRecordCreateOptions& options) + : FGpuRecordData(isolate->m_device->m_instance->m_allocator.get()), m_device(isolate->m_device) +{ +} + +FResult D3d12GpuRecord::SetName(const FStr8or16& name) noexcept +{ + return FResult::None(); +} + +FGpuRecordData* D3d12GpuRecord::GpuFGpuRecordData() noexcept +{ + return this; +} + +FGpuRecordData* D3d12GpuRecord::Data() noexcept +{ + return this; +} + +const FGpuRecordData* D3d12GpuRecord::Data() const noexcept +{ + return this; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h new file mode 100644 index 0000000..f789309 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Isolate.h" +#include "../../Api/FFI/Record.h" +#include "../../Api/Include/GpuObject.h" + +namespace Coplt +{ + + COPLT_INTERFACE_DEFINE(ID3d12GpuRecord, "57a9c7f9-1ec0-4d78-89b9-e547667c50b3", FGpuRecord) + { + virtual FGpuRecordData* Data() noexcept = 0; + virtual const FGpuRecordData* Data() const noexcept = 0; + }; + + struct D3d12GpuRecord final : GpuObject, FGpuRecordData + { + Rc m_device{}; + + explicit D3d12GpuRecord(NonNull isolate, const FGpuRecordCreateOptions& options); + + FResult SetName(const FStr8or16& name) noexcept override; + FGpuRecordData* GpuFGpuRecordData() noexcept override; + FGpuRecordData* Data() noexcept override; + const FGpuRecordData* Data() const noexcept override; + }; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc new file mode 100644 index 0000000..5b233ae --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -0,0 +1,325 @@ +#include "SwapChain.h" + +#include "Isolate.h" +#include "../../Api/Include/Finally.h" +#include "../Include/GraphicsFormat.h" + +using namespace Coplt; + +D3d12GpuSwapChain::D3d12GpuSwapChain( + const NonNull isolate, const FGpuOutput2CreateOptions& options, + const FOutputAlphaMode AlphaMode, const b8 VSync +) +{ + m_isolate = isolate->CloneThis(); + m_device = m_isolate->m_device->m_device; + m_queue = m_isolate->m_main_queue->m_queue; + m_debug_enabled = m_isolate->m_device->Debug(); + this->VSync = VSync; + this->PresentMode = options.PresentMode; + this->AlphaMode = AlphaMode; + + if (m_debug_enabled && !options.Name.is_null()) + { + m_name = options.Name.ToString(); + } +} + +void D3d12GpuSwapChain::Initialize() +{ + m_frame_index = m_swap_chain->GetCurrentBackBufferIndex(); + + D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc{}; + rtv_heap_desc.NumDescriptors = m_frame_count; + rtv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + chr | m_device->CreateDescriptorHeap(&rtv_heap_desc, IID_PPV_ARGS(&m_rtv_heap)); + m_rtv_descriptor_size = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); +} + +D3d12GpuSwapChain::D3d12GpuSwapChain(const NonNull isolate, const FGpuSwapChainFromExistsCreateOptions& options) + : D3d12GpuSwapChain(isolate, options, options.AlphaMode, options.VSync) +{ + m_swap_chain = static_cast(options.ExistsSwapChain); + + DXGI_SWAP_CHAIN_DESC1 desc{}; + chr | m_swap_chain->GetDesc1(&desc); + + this->Format = FromDx(desc.Format); + this->Width = desc.Width; + this->Height = desc.Height; + m_frame_count = desc.BufferCount; + + Initialize(); +} + +D3d12GpuSwapChain::D3d12GpuSwapChain(const NonNull isolate, const FGpuSwapChainCreateOptions& options, HWND hwnd) + : D3d12GpuSwapChain(isolate, options, options.AlphaMode, options.VSync) +{ + bool is_hdr = false; + this->Format = SelectFormat(options, is_hdr); + + DXGI_SWAP_CHAIN_DESC1 desc{}; + desc.Width = this->Width = options.Width; + desc.Height = this->Height = options.Height; + desc.Format = ToDx(this->Format); + desc.SampleDesc.Count = 1; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; + switch (options.PresentMode) + { + case FPresentMode::NoBuffer: + if (is_hdr) + { + m_frame_count = desc.BufferCount = 2; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + } + else + { + m_frame_count = desc.BufferCount = 2; + desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + } + break; + case FPresentMode::DoubleBuffer: + m_frame_count = desc.BufferCount = 2; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + break; + case FPresentMode::TripleBuffer: + default: + m_frame_count = desc.BufferCount = 3; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + break; + } + switch (options.AlphaMode) + { + case FOutputAlphaMode::PrePremultiplied: + desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; + break; + case FOutputAlphaMode::PostPremultiplied: + desc.AlphaMode = DXGI_ALPHA_MODE_STRAIGHT; + break; + case FOutputAlphaMode::Opaque: + default: + desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + break; + } + + ComPtr swap_chain; + chr | m_isolate->m_device->m_instance->m_factory->CreateSwapChainForHwnd( + m_queue.Get(), + hwnd, + &desc, + nullptr, + nullptr, + &swap_chain + ); + + chr | swap_chain.As(&m_swap_chain); + + if (this->Format == FGraphicsFormat::R10G10B10A2_UNorm) + { + chr | m_swap_chain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020); + } + + Initialize(); +} + +FGraphicsFormat D3d12GpuSwapChain::SelectFormat(const FGpuSwapChainCreateOptions& options, bool& is_hdr) +{ + if (options.FormatSelector.Specify) return options.Format; + if (options.FormatSelector.Hdr == FHdrType::UNorm10 && options.AlphaMode == FOutputAlphaMode::Opaque) + { + is_hdr = true; + return FGraphicsFormat::R10G10B10A2_UNorm; + } + if (options.FormatSelector.Hdr == FHdrType::Float16) + { + is_hdr = true; + return FGraphicsFormat::R16G16B16A16_Float; + } + if (options.FormatSelector.Srgb) return FGraphicsFormat::R8G8B8A8_UNorm_sRGB; + return FGraphicsFormat::R8G8B8A8_UNorm; +} + +D3d12GpuSwapChain::~D3d12GpuSwapChain() +{ + WaitAll(); + CloseHandle(m_event); +} + +void D3d12GpuSwapChain::CreateRts() +{ + CD3DX12_CPU_DESCRIPTOR_HANDLE rtv_handle(m_rtv_heap->GetCPUDescriptorHandleForHeapStart()); + for (u32 i = 0; i < m_frame_count; ++i) + { + chr | m_swap_chain->GetBuffer(i, IID_PPV_ARGS(&m_buffers[i])); + m_device->CreateRenderTargetView(m_buffers[i].Get(), nullptr, rtv_handle); + rtv_handle.Offset(1, m_rtv_descriptor_size); + } +} + +void D3d12GpuSwapChain::SetRtNames() +{ + if (!m_debug_enabled || m_name == nullptr) return; + for (u32 i = 0; i < m_frame_count; ++i) + { + const auto str = m_name->GetStr(); + if (str.is8()) + { + const auto name = fmt::format("[{}]::Buffer {} ({}, {})", str.str8, i, this->Width, this->Height); + chr | m_buffers[i] >> SetNameEx(FStr8or16(name)); + } + else + { + const auto name = fmt::format(L"[{}]::Buffer {} ({}, {})", str.wcstr(), i, this->Width, this->Height); + chr | m_buffers[i] >> SetNameEx(FStr8or16(name)); + } + } +} + +FResult D3d12GpuSwapChain::SetName(const FStr8or16& name) noexcept +{ + return feb([&] + { + if (!m_debug_enabled || name.is_null()) return; + std::lock_guard lock(m_present_mutex); + m_name = name.ToString(); + SetRtNames(); + }); +} + +const FGpuOutputData* D3d12GpuSwapChain::GpuOutputData() noexcept +{ + return this; +} + +const FGpuSwapChainData* D3d12GpuSwapChain::GpuSwapChainData() noexcept +{ + return this; +} + +FGpuIsolate* D3d12GpuSwapChain::GetIsolate() noexcept +{ + return m_isolate.get(); +} + +FResult D3d12GpuSwapChain::Resize(const u32 Width, const u32 Height) noexcept +{ + return feb([&] + { + std::lock_guard lock(m_resize_mutex); + + m_new_width = Width; + m_new_height = Height; + if (this->Width != Width || this->Height != Height) + { + m_need_resize = true; + } + }); +} + +FResult D3d12GpuSwapChain::SetVSync(const b8 Enable) noexcept +{ + return feb([&] + { + this->VSync = Enable; + }); +} + +FResult D3d12GpuSwapChain::Present() noexcept +{ + return feb([&] + { + std::lock_guard lock(m_present_mutex); + PresentNoLock(); + WaitNextFrameNoLock(); + }); +} + +FResult D3d12GpuSwapChain::PresentNoWait() noexcept +{ + return feb([&] + { + std::lock_guard lock(m_present_mutex); + PresentNoLock(); + }); +} + +FResult D3d12GpuSwapChain::Wait() noexcept +{ + return feb([&] + { + std::lock_guard lock(m_present_mutex); + WaitNextFrameNoLock(); + }); +} + +bool D3d12GpuSwapChain::IsAvailable() noexcept +{ + return !m_waiting; +} + +void D3d12GpuSwapChain::PresentNoLock() +{ + chr | m_swap_chain->Present(this->VSync ? 1 : 0, 0); + const auto fence_value = m_isolate->m_main_queue->Signal(); + m_event_values[m_frame_index] = fence_value; +} + +void D3d12GpuSwapChain::WaitNextFrameNoLock() +{ + m_waiting = true; + Finally finally([&] { m_waiting = false; }); + + if (m_need_resize) + { + ResizeNoLock(m_new_width, m_new_height); + m_need_resize = false; + } + u64 fence_value = std::numeric_limits::max(); + for (u32 i = 0; i < m_frame_count; ++i) + { + const auto frame_fence_value = m_event_values[m_frame_index]; + if (frame_fence_value < fence_value) + fence_value = frame_fence_value; + } + WaitFenceValueNoLock(fence_value); + m_frame_index = m_swap_chain->GetCurrentBackBufferIndex(); +} + +void D3d12GpuSwapChain::ResizeNoLock(const u32 width, const u32 height) +{ + if (this->Width == width && this->Height == height) return; + WaitAllNoLock(); + for (u32 i = 0; i < m_frame_count; i++) + { + m_buffers[i] = nullptr; + } + chr | m_swap_chain->ResizeBuffers(m_frame_count, width, height, ToDx(this->Format), 0); + CreateRts(); + m_frame_index = m_swap_chain->GetCurrentBackBufferIndex(); + this->Width = width; + this->Height = height; +} + +void D3d12GpuSwapChain::WaitAll() +{ + std::lock_guard lock(m_present_mutex); + WaitAllNoLock(); +} + +void D3d12GpuSwapChain::WaitAllNoLock() const +{ + u64 fence_value = 0; + for (u32 i = 0; i < m_frame_count; ++i) + { + const auto frame_fence_value = m_event_values[m_frame_index]; + if (frame_fence_value > fence_value) + fence_value = frame_fence_value; + } + WaitFenceValueNoLock(fence_value); +} + +void D3d12GpuSwapChain::WaitFenceValueNoLock(const u64 fence_value) const +{ + m_isolate->m_main_queue->WaitFenceValue(fence_value, m_event); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.h b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h new file mode 100644 index 0000000..62443db --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h @@ -0,0 +1,79 @@ +#pragma once + +#include "Queue.h" +#include "../../Api/FFI/Output.h" +#include "../../Api/Include/GpuObject.h" + +namespace Coplt +{ + COPLT_INTERFACE_DEFINE(ID3d12GpuSwapChain, "d726caf3-41c4-4d60-895e-61c68a4dff98", FGpuSwapChain) + { + constexpr static UINT MaxBufferCount = 3; + + Rc m_isolate{}; + // 可空 + Rc m_name{}; + ComPtr m_device{}; + ComPtr m_queue{}; + ComPtr m_swap_chain{}; + ComPtr m_rtv_heap{}; + ComPtr m_buffers[MaxBufferCount]; + std::mutex m_resize_mutex{}; + std::mutex m_present_mutex{}; + HANDLE m_event{}; + u64 m_event_values[MaxBufferCount]{}; + u32 m_frame_count{}; + u32 m_frame_index{}; + u32 m_rtv_descriptor_size{}; + mutable u32 m_new_width{}; + mutable u32 m_new_height{}; + std::atomic_bool m_waiting{}; + std::atomic_bool m_need_resize{}; + b8 m_debug_enabled{}; + }; + + struct D3d12GpuSwapChain final : GpuObject, FGpuSwapChainData + { + private: + explicit D3d12GpuSwapChain( + NonNull isolate, const FGpuOutput2CreateOptions& options, + FOutputAlphaMode AlphaMode, b8 VSync + ); + void Initialize(); + + public: + explicit D3d12GpuSwapChain(NonNull isolate, const FGpuSwapChainFromExistsCreateOptions& options); + explicit D3d12GpuSwapChain(NonNull isolate, const FGpuSwapChainCreateOptions& options, HWND hwnd); + + static FGraphicsFormat SelectFormat(const FGpuSwapChainCreateOptions& options, bool& is_hdr); + + ~D3d12GpuSwapChain() override; + + void CreateRts(); + void SetRtNames(); + + FResult SetName(const FStr8or16& name) noexcept override; + const FGpuOutputData* GpuOutputData() noexcept override; + const FGpuSwapChainData* GpuSwapChainData() noexcept override; + FGpuIsolate* GetIsolate() noexcept override; + + FResult Resize(u32 Width, u32 Height) noexcept override; + FResult SetVSync(b8 Enable) noexcept override; + + FResult Present() noexcept override; + FResult PresentNoWait() noexcept override; + FResult Wait() noexcept override; + + bool IsAvailable() noexcept override; + + void PresentNoLock(); + void WaitNextFrameNoLock(); + + void ResizeNoLock(u32 width, u32 height); + + void WaitAll(); + void WaitAllNoLock() const; + + void WaitFenceValueNoLock(u64 fence_value) const; + }; +} diff --git a/Coplt.Graphics.sln b/Coplt.Graphics.sln index e1e2e11..fa52178 100644 --- a/Coplt.Graphics.sln +++ b/Coplt.Graphics.sln @@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Colorful", "Examples\Colorf EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Image", "Examples\Image\Image.csproj", "{DB8B374C-102E-4825-B51E-F2A9805847C5}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwapChain", "Examples\SwapChain\SwapChain.csproj", "{B2648CB7-DF8C-43CE-A814-46FFBEF9F12A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -50,6 +52,10 @@ Global {DB8B374C-102E-4825-B51E-F2A9805847C5}.Debug|Any CPU.Build.0 = Debug|Any CPU {DB8B374C-102E-4825-B51E-F2A9805847C5}.Release|Any CPU.ActiveCfg = Release|Any CPU {DB8B374C-102E-4825-B51E-F2A9805847C5}.Release|Any CPU.Build.0 = Release|Any CPU + {B2648CB7-DF8C-43CE-A814-46FFBEF9F12A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2648CB7-DF8C-43CE-A814-46FFBEF9F12A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2648CB7-DF8C-43CE-A814-46FFBEF9F12A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2648CB7-DF8C-43CE-A814-46FFBEF9F12A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {2ABF3CFF-8E44-4992-A633-491B2AAA5BFB} = {DBD91642-35A7-4287-9856-CA8E09605928} @@ -57,5 +63,6 @@ Global {1173C015-4D34-4DD1-85F6-98C68FDC50BB} = {DBD91642-35A7-4287-9856-CA8E09605928} {C4C82737-D197-447B-B663-2DEFE3CE6679} = {DBD91642-35A7-4287-9856-CA8E09605928} {DB8B374C-102E-4825-B51E-F2A9805847C5} = {DBD91642-35A7-4287-9856-CA8E09605928} + {B2648CB7-DF8C-43CE-A814-46FFBEF9F12A} = {DBD91642-35A7-4287-9856-CA8E09605928} EndGlobalSection EndGlobal diff --git a/Examples/SwapChain/App.xaml b/Examples/SwapChain/App.xaml new file mode 100644 index 0000000..76b7b05 --- /dev/null +++ b/Examples/SwapChain/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/Examples/SwapChain/App.xaml.cs b/Examples/SwapChain/App.xaml.cs new file mode 100644 index 0000000..2b631ed --- /dev/null +++ b/Examples/SwapChain/App.xaml.cs @@ -0,0 +1,62 @@ +using System.Configuration; +using System.Data; +using System.IO; +using System.Text; +using System.Windows; +using Serilog; +using Serilog.Exceptions; + +namespace Examples; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ + protected override void OnStartup(StartupEventArgs e) + { + Console.OutputEncoding = Encoding.UTF8; + + base.OnStartup(e); + + InitLogger(); + } + + private static void InitLogger() + { + if (File.Exists("./logs/latest.log")) + { + try + { + var time = File.GetCreationTime("./logs/latest.log"); + var time_name = $"{time:yyyy-MM-dd}"; + var max_count = Directory.GetFiles("./logs/") + .Where(static n => Path.GetExtension(n) == ".log") + .Select(static n => Path.GetFileName(n)) + .Where(n => n.StartsWith(time_name)) + .Select(n => n.Substring(time_name.Length)) + .Select(static n => (n, i: n.IndexOf('.'))) + .Where(static a => a.i > 1) + .Select(static a => (s: uint.TryParse(a.n.Substring(1, a.i - 1), out var n), n)) + .Where(static a => a.s) + .OrderByDescending(static a => a.n) + .Select(static a => a.n) + .FirstOrDefault(); + var count = max_count + 1; + File.Move("./logs/latest.log", $"./logs/{time_name}_{count}.log"); + } + catch (Exception e) + { + Log.Error(e, ""); + } + } + Log.Logger = new LoggerConfiguration() + .Enrich.WithThreadId() + .Enrich.WithThreadName() + .Enrich.WithExceptionDetails() + .WriteTo.Console() + .WriteTo.Debug() + .WriteTo.Async(c => c.File("./logs/latest.log")) + .CreateLogger(); + } +} diff --git a/Examples/SwapChain/AssemblyInfo.cs b/Examples/SwapChain/AssemblyInfo.cs new file mode 100644 index 0000000..b9d746b --- /dev/null +++ b/Examples/SwapChain/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/Examples/SwapChain/ExampleBase.cs b/Examples/SwapChain/ExampleBase.cs new file mode 100644 index 0000000..28fe11d --- /dev/null +++ b/Examples/SwapChain/ExampleBase.cs @@ -0,0 +1,75 @@ +using System.Diagnostics; +using System.Reflection; +using Coplt.Graphics; +using Coplt.Graphics.Core; +using Serilog; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; + +namespace Examples; + +public class Example(IntPtr Handle, uint Width, uint Height) +{ + public bool IsClosed = false; + public GraphicsInstance Graphics = null!; + public GpuDevice Device = null!; + public GpuIsolate Isolate = null!; + public GpuSwapChain SwapChain = null!; + public IntPtr Handle = Handle; + + #region InitGraphics + + public void DoInitGraphics() + { + try + { + Graphics = GraphicsInstance.LoadD3d12(Debug: true); + Graphics.SetLogger( + (level, _) => Log.IsEnabled(level.ToLogEventLevel()), + (level, scope, msg) => Log.Write(level.ToLogEventLevel(), "[{Scope}] {Msg}", scope, msg) + ); + Device = Graphics.CreateDevice(Name: "Main Device"); + var Adapter = Device.Adapter; + Log.Information( + "Selected device: {@Info}", + new + { + Adapter.Name, Adapter.VendorId, Adapter.DeviceId, Adapter.Driver, Adapter.Backend, + Adapter.Features.ShaderModelLevel + } + ); + Isolate = Device.CreateIsolate(Name: "Main Isolate"); + SwapChain = Isolate.CreateSwapChainForHwnd( + Handle, new() + { + Width = Width, + Height = Height, + // VSync = true, + }, Name: "Main Swap Chain" + ); + new Thread( + () => + { + Thread.CurrentThread.Name = "Render Thread"; + while (!IsClosed) + { + try + { + SwapChain.Present(); + } + catch (Exception e) + { + Log.Error(e, ""); + } + } + } + ).Start(); + } + catch (Exception e) + { + Log.Error(e, ""); + } + } + + #endregion +} diff --git a/Examples/SwapChain/MainWindow.xaml b/Examples/SwapChain/MainWindow.xaml new file mode 100644 index 0000000..8c3fd8b --- /dev/null +++ b/Examples/SwapChain/MainWindow.xaml @@ -0,0 +1,11 @@ + + \ No newline at end of file diff --git a/Examples/SwapChain/MainWindow.xaml.cs b/Examples/SwapChain/MainWindow.xaml.cs new file mode 100644 index 0000000..cef3a01 --- /dev/null +++ b/Examples/SwapChain/MainWindow.xaml.cs @@ -0,0 +1,40 @@ +using System.Windows; +using System.Windows.Interop; +using Serilog; + +namespace Examples; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public readonly Example Example; + + #region Ctor + + public MainWindow() + { + InitializeComponent(); + Example = new(new WindowInteropHelper(this).EnsureHandle(), (uint)Width, (uint)Height); + Title = "Swap Chain"; + Example.DoInitGraphics(); + } + + #endregion + + #region Misc + + protected override void OnClosed(EventArgs e) + { + Example.IsClosed = true; + } + + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) + { + Log.Information("OnRenderSizeChanged {NewSize}", sizeInfo.NewSize); + Example.SwapChain.Resize((uint)sizeInfo.NewSize.Width, (uint)sizeInfo.NewSize.Height); + } + + #endregion +} diff --git a/Examples/SwapChain/Properties/launchSettings.json b/Examples/SwapChain/Properties/launchSettings.json new file mode 100644 index 0000000..673c307 --- /dev/null +++ b/Examples/SwapChain/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "Launch": { + "commandName": "Project", + "nativeDebugging": true, + "commandLineArgs": "-D" + } + } +} \ No newline at end of file diff --git a/Examples/SwapChain/Shaders/Shader.hlsl b/Examples/SwapChain/Shaders/Shader.hlsl new file mode 100644 index 0000000..e3cf836 --- /dev/null +++ b/Examples/SwapChain/Shaders/Shader.hlsl @@ -0,0 +1,67 @@ +struct Attribute +{ + uint VertexID : SV_VertexID; +}; + +struct Varying +{ + float4 PositionCS : SV_Position; + float4 Color : Color; + float2 Uv : Uv; +}; + +static const float3 Vertexs[3] = { + float3(0.0, 0.5 * 1.7, 0), + float3(0.5, -0.5 * 1.7, 0), + float3(-0.5, -0.5 * 1.7, 0), +}; +static const float2 Uvs[3] = { + float2(0.0, 0.0), + float2(-1.0, 2.0), + float2(1.0, 2.0), +}; +static const float4 Colors[3] = { + float4(0.71, 0.22, 0.21, 1), + float4(0.34, 0.64, 0.31, 1), + float4(0.36, 0.42, 0.92, 1), +}; + +[shader("vertex")] +Varying Vertex(Attribute input) +{ + Varying output; + output.PositionCS = float4(Vertexs[input.VertexID % 3], 1); + output.Color = Colors[input.VertexID % 3]; + output.Uv = Uvs[input.VertexID % 3]; + return output; +} + +float dot2(in float2 v) { return dot(v, v); } + +float SdTriangle(float2 p, float2 p0, float2 p1, float2 p2) +{ + float2 e0 = p1 - p0, v0 = p - p0; + float d0 = dot2(v0 - e0 * clamp(dot(v0, e0) / dot(e0, e0), 0.0, 1.0)); + float2 e1 = p2 - p1, v1 = p - p1; + float d1 = dot2(v1 - e1 * clamp(dot(v1, e1) / dot(e1, e1), 0.0, 1.0)); + float2 e2 = p0 - p2, v2 = p - 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)) + ); + return -sqrt(d.x) * sign(d.y); +} + +[shader("pixel")] +float4 Pixel(Varying input) : SV_Target +{ + float d = SdTriangle(input.Uv, float2(0.0f, 0.5f), float2(-0.5f, 1.5f), float2(0.5f, 1.5f)); + float aa = sqrt(2.71) / 512; + return float4(input.Color.rgb * 1.2, lerp(0, 1, smoothstep(aa, -aa, d))); +} diff --git a/Examples/SwapChain/SwapChain.csproj b/Examples/SwapChain/SwapChain.csproj new file mode 100644 index 0000000..22e9c0f --- /dev/null +++ b/Examples/SwapChain/SwapChain.csproj @@ -0,0 +1,75 @@ + + + + WinExe + net9.0-windows + enable + enable + true + Examples + + + + 715 + D3D12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 11c8be331e52ce8a4534f9360e72b62c010c49d0 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Wed, 19 Mar 2025 15:52:17 +0800 Subject: [PATCH 03/46] save --- Coplt.Graphics.Core/Native/Native.cs | 173 +++++++++++++++++- Coplt.Graphics.Native/Api/FFI/Context.h | 11 ++ Coplt.Graphics.Native/Api/FFI/Isolate.h | 11 +- Coplt.Graphics.Native/Api/FFI/Record.h | 7 +- Coplt.Graphics.Native/D3d12/Src/Context.cc | 65 +++++++ Coplt.Graphics.Native/D3d12/Src/Context.h | 21 +++ .../D3d12/Src/DescriptorManager.h | 1 - Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 129 ++++++++++++- Coplt.Graphics.Native/D3d12/Src/Isolate.h | 27 ++- Coplt.Graphics.Native/D3d12/Src/Queue.cc | 31 ++++ Coplt.Graphics.Native/D3d12/Src/Queue.h | 25 +++ Coplt.Graphics.Native/D3d12/Src/Record.cc | 11 +- Coplt.Graphics.Native/D3d12/Src/Record.h | 11 +- Examples/SwapChain/ExampleBase.cs | 2 +- 14 files changed, 498 insertions(+), 27 deletions(-) diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index d98d33c..87681b7 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1220,10 +1220,6 @@ public partial struct FGpuRecord { } - public partial struct FGpuRecordCreateOptions - { - } - public partial struct FGpuRecordCreateResult { } @@ -1236,6 +1232,8 @@ public partial struct FGpuIsolateCreateOptions public partial struct FGpuIsolateData { + [NativeTypeName("Coplt::u64")] + public ulong FrameId; } [Guid("777C5774-8EB8-4550-A977-62CCCD7BDDA6")] @@ -1303,10 +1301,34 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateRecord([NativeTypeName("const FGpuRecordCreateOptions &")] FGpuRecordCreateOptions* options, [NativeTypeName("Coplt::FGpuRecordCreateResult &")] FGpuRecordCreateResult* @out) + public FResult RentRecords([NativeTypeName("Coplt::u32")] uint NumRecords, [NativeTypeName("Coplt::FGpuRecordCreateResult *")] FGpuRecordCreateResult* OutRecords) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, OutRecords); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult ReturnRecords([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Submit([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records, [NativeTypeName("Coplt::FGpuRecordCreateResult *")] FGpuRecordCreateResult* OutRecords) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records, OutRecords); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SubmitReturn([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1314,7 +1336,7 @@ public FResult CreateRecord([NativeTypeName("const FGpuRecordCreateOptions &")] public FResult CreateSwapChainFromExists([NativeTypeName("const FGpuSwapChainFromExistsCreateOptions &")] FGpuSwapChainFromExistsCreateOptions* options, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1322,7 +1344,7 @@ public FResult CreateSwapChainFromExists([NativeTypeName("const FGpuSwapChainFro public FResult CreateSwapChainForHwnd([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, void* hwnd, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, hwnd, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, hwnd, @out); } public interface Interface : FGpuObject.Interface @@ -1334,7 +1356,16 @@ public interface Interface : FGpuObject.Interface FGpuIsolateData* GpuIsolateData(); [return: NativeTypeName("Coplt::FResult")] - FResult CreateRecord([NativeTypeName("const FGpuRecordCreateOptions &")] FGpuRecordCreateOptions* options, [NativeTypeName("Coplt::FGpuRecordCreateResult &")] FGpuRecordCreateResult* @out); + FResult RentRecords([NativeTypeName("Coplt::u32")] uint NumRecords, [NativeTypeName("Coplt::FGpuRecordCreateResult *")] FGpuRecordCreateResult* OutRecords); + + [return: NativeTypeName("Coplt::FResult")] + FResult ReturnRecords([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records); + + [return: NativeTypeName("Coplt::FResult")] + FResult Submit([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records, [NativeTypeName("Coplt::FGpuRecordCreateResult *")] FGpuRecordCreateResult* OutRecords); + + [return: NativeTypeName("Coplt::FResult")] + FResult SubmitReturn([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records); [return: NativeTypeName("Coplt::FResult")] FResult CreateSwapChainFromExists([NativeTypeName("const FGpuSwapChainFromExistsCreateOptions &")] FGpuSwapChainFromExistsCreateOptions* options, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out); @@ -1926,6 +1957,126 @@ public interface Interface : FGpuObject.Interface } } + [Guid("FA9C7561-AB0B-4311-BB4C-C6BEF93F86FE")] + [NativeTypeName("struct FFrameContext2 : Coplt::FGpuObject")] + public unsafe partial struct FFrameContext2 : FFrameContext2.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FFrameContext2)); + + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FFrameContext2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FFrameContext2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FFrameContext2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FFrameContext2*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FFrameContext2*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FFrameContext2*)Unsafe.AsPointer(ref this), &result, name); + } + + public interface Interface : FGpuObject.Interface + { + } + } + + [Guid("15B4821D-0648-4B78-9C21-C6A5B6A5ED75")] + [NativeTypeName("struct FRecordContext : Coplt::FGpuObject")] + public unsafe partial struct FRecordContext : FRecordContext.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FRecordContext)); + + public void** lpVtbl; + + public FList m_upload_buffer; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FRecordContext*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FRecordContext*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FRecordContext*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FRecordContext*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FRecordContext*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FRecordContext*)Unsafe.AsPointer(ref this), &result, name); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult GrowUploadBuffer([NativeTypeName("Coplt::u64")] ulong min_required_size) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FRecordContext*)Unsafe.AsPointer(ref this), &result, min_required_size); + } + + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FResult")] + FResult GrowUploadBuffer([NativeTypeName("Coplt::u64")] ulong min_required_size); + } + } + public partial struct FMainQueueCreateOptions { [NativeTypeName("Coplt::FStr8or16")] @@ -6251,6 +6402,10 @@ public static partial class Native public static readonly Guid IID_FFrameContext = new Guid(0x3A22DE68, 0x8377, 0x4E57, 0xA1, 0x67, 0x3E, 0xFD, 0xB9, 0x7C, 0x10, 0x2A); + public static readonly Guid IID_FFrameContext2 = new Guid(0xFA9C7561, 0xAB0B, 0x4311, 0xBB, 0x4C, 0xC6, 0xBE, 0xF9, 0x3F, 0x86, 0xFE); + + public static readonly Guid IID_FRecordContext = new Guid(0x15B4821D, 0x0648, 0x4B78, 0x9C, 0x21, 0xC6, 0xA5, 0xB6, 0xA5, 0xED, 0x75); + public static readonly Guid IID_FGpuQueue = new Guid(0x95E60E28, 0xE387, 0x4055, 0x9B, 0x33, 0x2D, 0x23, 0xAF, 0x90, 0x1F, 0x8A); public static readonly Guid IID_FGpuQueue2 = new Guid(0xFC94E4D0, 0x5F01, 0x4D4F, 0x89, 0x4C, 0x6A, 0xEF, 0xAA, 0xD9, 0x04, 0x99); diff --git a/Coplt.Graphics.Native/Api/FFI/Context.h b/Coplt.Graphics.Native/Api/FFI/Context.h index 1a5849f..c070f54 100644 --- a/Coplt.Graphics.Native/Api/FFI/Context.h +++ b/Coplt.Graphics.Native/Api/FFI/Context.h @@ -20,4 +20,15 @@ namespace Coplt virtual FResult GrowUploadBuffer(u64 min_required_size) noexcept = 0; }; + + COPLT_INTERFACE_DEFINE(FFrameContext2, "fa9c7561-ab0b-4311-bb4c-c6bef93f86fe", FGpuObject) + { + }; + + COPLT_INTERFACE_DEFINE(FRecordContext, "15b4821d-0648-4b78-9c21-c6a5b6a5ed75", FGpuObject) + { + FList m_upload_buffer{}; + + virtual FResult GrowUploadBuffer(u64 min_required_size) noexcept = 0; + }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Isolate.h b/Coplt.Graphics.Native/Api/FFI/Isolate.h index ec36b1f..a6cb0cc 100644 --- a/Coplt.Graphics.Native/Api/FFI/Isolate.h +++ b/Coplt.Graphics.Native/Api/FFI/Isolate.h @@ -6,7 +6,6 @@ namespace Coplt { struct FGpuRecord; - struct FGpuRecordCreateOptions; struct FGpuRecordCreateResult; struct FGpuIsolateCreateOptions @@ -17,6 +16,7 @@ namespace Coplt struct FGpuIsolateData { + u64 FrameId{}; }; COPLT_INTERFACE_DEFINE(FGpuIsolate, "777c5774-8eb8-4550-a977-62cccd7bdda6", FGpuObject) @@ -25,7 +25,14 @@ namespace Coplt virtual FGpuQueueCreateResult* GetQueues(u32* OutNumQueues) noexcept = 0; virtual FGpuIsolateData* GpuIsolateData() noexcept = 0; - virtual FResult CreateRecord(const FGpuRecordCreateOptions& options, FGpuRecordCreateResult& out) noexcept = 0; + // 租用记录 + virtual FResult RentRecords(u32 NumRecords, FGpuRecordCreateResult* OutRecords) noexcept = 0; + // 归还记录,不会进行提交,记录内容将被丢弃,不要调用归还的 FGpuRecord* 的 Release + virtual FResult ReturnRecords(u32 NumRecords, FGpuRecord** Records) noexcept = 0; + // 提交记录,并用返回新的记录用于替换,旧的记录将被拿走加入等待队列 + virtual FResult Submit(u32 NumRecords, FGpuRecord** Records, FGpuRecordCreateResult* OutRecords) noexcept = 0; + // 提交记录,并归还记录,不要调用归还的 FGpuRecord* 的 Release + virtual FResult SubmitReturn(u32 NumRecords, FGpuRecord** Records) noexcept = 0; virtual FResult CreateSwapChainFromExists(const FGpuSwapChainFromExistsCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept = 0; // 在非 windows 系统上会报错 diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index 8d18ec5..e67fc2c 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -7,12 +7,6 @@ namespace Coplt { struct FGpuRecordData; - struct FGpuRecordCreateOptions - { - // 可选 - FStr8or16 Name{}; - }; - COPLT_INTERFACE_DEFINE(FGpuRecord, "0ef83584-ca65-44de-b38a-648bfb3a85a6", FGpuObject) { virtual FGpuRecordData* GpuFGpuRecordData() noexcept = 0; @@ -21,6 +15,7 @@ namespace Coplt // 里面的 FList 的 T* 生命周期由 c# 部分保证 struct FGpuRecordData { + FRecordContext* Context{}; FList Outputs; #ifdef FFI_SRC diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.cc b/Coplt.Graphics.Native/D3d12/Src/Context.cc index a7a7aa3..8429fe5 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Context.cc @@ -79,3 +79,68 @@ void D3d12FrameContext::Recycle() } } } + +D3d12RecordContext::D3d12RecordContext(NonNull isolate) +{ + m_device = isolate->m_device; + m_upload_buffer = FList(m_device->m_instance->m_allocator.get()); +} + +FResult D3d12RecordContext::SetName(const FStr8or16& name) noexcept +{ + return FResult::None(); +} + +FResult D3d12RecordContext::GrowUploadBuffer(u64 min_required_size) noexcept +{ + return feb([&] + { + const auto size = + std::max( + InitUploadBufferSize, + std::max(m_cur_upload_buffer_size * 2, std::bit_ceil(min_required_size)) + ); + m_cur_upload_buffer_index = m_upload_buffers.size(); + m_cur_upload_buffer_size = size; + m_upload_buffers.push_back( + BufferPack(m_device.get(), m_device->m_gpu_allocator.Get(), FCpuAccess::Write, m_cur_upload_buffer_size) + ); + const auto& upload_buffer = m_upload_buffers.back(); + void* mapped_ptr{}; + if (m_device->Debug()) + { + const auto name = fmt::format( + L"Frame Context ({}) Upload Buffer ({})", m_object_id, upload_buffer.m_size + ); + chr | upload_buffer.m_resource.m_resource >> SetNameEx(FStr8or16(name)); + } + constexpr D3D12_RANGE read_range{.Begin = 0, .End = 0}; + chr | upload_buffer.m_resource.m_resource->Map(0, &read_range, &mapped_ptr); + m_upload_buffer.Add(FUploadBufferBlock{ + .mapped_ptr = static_cast(mapped_ptr), + .cur_offset = 0, + .size = upload_buffer.m_size, + }); + }); +} + +void D3d12RecordContext::Recycle() +{ + m_command_allocators.clear(); + + if (!m_upload_buffers.empty()) + { + { + BufferPack last = std::move(m_upload_buffers.back()); + m_upload_buffers.clear(); + m_upload_buffers.push_back(std::move(last)); + m_cur_upload_buffer_index = 0; + } + { + auto last = m_upload_buffer[m_upload_buffer.size() - 1]; + last.cur_offset = 0; + m_upload_buffer.Clear(); + m_upload_buffer.Add(last); + } + } +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.h b/Coplt.Graphics.Native/D3d12/Src/Context.h index b766439..4238645 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.h +++ b/Coplt.Graphics.Native/D3d12/Src/Context.h @@ -4,6 +4,7 @@ #include "../../Api/Include/Object.h" #include "CmdListPack.h" #include "Device.h" +#include "Isolate.h" #include "Queue.h" #include "Resource.h" @@ -31,4 +32,24 @@ namespace Coplt // 回收帧使用的资源,重复使用,需要在队列中等待帧完成后调用 void Recycle(); }; + + struct D3d12RecordContext final : GpuObject + { + constexpr static u64 InitUploadBufferSize = 1024 * 1024; + + Rc m_device{}; + std::vector m_command_allocators{}; + std::vector m_upload_buffers{}; + usize m_cur_upload_buffer_index{}; + usize m_cur_upload_buffer_size{}; + + explicit D3d12RecordContext(NonNull isolate); + + FResult SetName(const FStr8or16& name) noexcept override; + + FResult GrowUploadBuffer(u64 min_required_size) noexcept override; + + // 回收帧使用的资源,重复使用,需要在队列中等待帧完成后调用 + void Recycle(); + }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h index f0cd7ea..3290395 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h @@ -3,7 +3,6 @@ #include "directx/d3dx12.h" #include -#include #include #include diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index e44565d..123b2c0 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -9,6 +9,8 @@ using namespace Coplt; D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options) : FGpuIsolateData() { + m_waiting_ctx = box(); + m_record_pool = box(); m_device = std::move(device); m_main_queue = new D3d12GpuQueue2(this, FGpuQueueType::Direct); m_back_queue = new D3d12GpuQueue2(this, FGpuQueueType::Compute); @@ -18,6 +20,31 @@ D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCre FGpuQueueCreateResult{m_back_queue.get(), m_back_queue.get()}, FGpuQueueCreateResult{m_copy_queue.get(), m_copy_queue.get()}, }; + + m_wait_thread = std::jthread([this] + { + while (!m_exited) + { + m_waiting_signal.acquire(); + Rc records[8]{}; + re: + if (const auto count = m_waiting_ctx->try_dequeue_bulk(records, 8); count > 0) + { + for (auto i = 0; i < count; ++i) + { + records[i]->Recycle(); + m_record_pool->enqueue(std::move(records[i])); + } + goto re; + } + } + }); +} + +D3d12GpuIsolate::~D3d12GpuIsolate() +{ + m_exited = true; + m_waiting_signal.release(1); } FResult D3d12GpuIsolate::SetName(const FStr8or16& name) noexcept @@ -36,13 +63,40 @@ FGpuIsolateData* D3d12GpuIsolate::GpuIsolateData() noexcept return this; } -FResult D3d12GpuIsolate::CreateRecord(const FGpuRecordCreateOptions& options, FGpuRecordCreateResult& out) noexcept +FResult D3d12GpuIsolate::RentRecords(const u32 NumRecords, FGpuRecordCreateResult* OutRecords) noexcept { return feb([&] { - const auto ptr = new D3d12GpuRecord(this, options); - out.Record = ptr; - out.Data = ptr; + const std::span out(OutRecords, NumRecords); + RentRecords(out); + }); +} + +FResult D3d12GpuIsolate::ReturnRecords(const u32 NumRecords, FGpuRecord** Records) noexcept +{ + return feb([&] + { + const std::span records(Records, NumRecords); + ReturnRecords(records); + }); +} + +FResult D3d12GpuIsolate::Submit(const u32 NumRecords, FGpuRecord** Records, FGpuRecordCreateResult* OutRecords) noexcept +{ + return feb([&] + { + const std::span records(Records, NumRecords); + const std::span out(OutRecords, NumRecords); + Submit(records, out); + }); +} + +FResult D3d12GpuIsolate::SubmitReturn(const u32 NumRecords, FGpuRecord** Records) noexcept +{ + return feb([&] + { + const std::span records(Records, NumRecords); + SubmitReturn(records); }); } @@ -65,3 +119,70 @@ FResult D3d12GpuIsolate::CreateSwapChainForHwnd(const FGpuSwapChainCreateOptions out.Data = ptr; }); } + +void D3d12GpuIsolate::RentRecords(const std::span out) +{ + const auto f = [&](const std::span> items) + { + const auto count = m_record_pool->try_dequeue_bulk(items.data(), out.size()); + for (u32 i = 0; i < out.size(); ++i) + { + ID3d12GpuRecord* ptr; + if (i < count) ptr = items[i].leak(); + else ptr = new D3d12GpuRecord(this); + out[i].Record = ptr; + out[i].Data = ptr->GpuFGpuRecordData(); + } + }; + if (out.size() < 16) + { + Rc items[out.size()]; + for (u32 i = 0; i < out.size(); ++i) items[i] = {}; + f(std::span(items, out.size())); + } + else + { + std::vector> items(out.size(), {}); + f(std::span(items)); + } +} + +void D3d12GpuIsolate::ReturnRecords(const std::span records) +{ + const auto f = [&](const std::span> items) + { + for (u32 i = 0; i < items.size(); ++i) + { + items[i] = records[i]->QueryInterface(); + } + for (u32 i = 0; i < items.size(); ++i) + { + if (items[i] == nullptr) + COPLT_THROW("Record from different backends"); + items[i]->Recycle(); + } + m_record_pool->enqueue_bulk(items.data(), items.size()); + }; + if (records.size() < 16) + { + Rc items[records.size()]; + for (u32 i = 0; i < records.size(); ++i) items[i] = {}; + f(std::span(items, records.size())); + } + else + { + std::vector> items(records.size(), {}); + f(std::span(items)); + } +} + +void D3d12GpuIsolate::Submit(std::span records, std::span out) +{ + SubmitReturn(records); + RentRecords(out); +} + +void D3d12GpuIsolate::SubmitReturn(std::span records) +{ + // todo +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index 2ce9626..3030362 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -1,5 +1,9 @@ #pragma once +#include + +#include "concurrentqueue.h" + #include "Device.h" #include "Queue.h" #include "../../Api/FFI/Isolate.h" @@ -17,17 +21,38 @@ namespace Coplt std::mutex m_mutex{}; }; + struct ID3d12GpuRecord; + struct D3d12GpuIsolate final : GpuObject, FGpuIsolateData { + using RecordQueue = moodycamel::ConcurrentQueue>; + + Box m_waiting_ctx{}; + Box m_record_pool{}; + std::binary_semaphore m_waiting_signal{0}; + std::jthread m_wait_thread{}; + std::atomic_bool m_exited{false}; + std::atomic m_record_inc{0}; + explicit D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options); + ~D3d12GpuIsolate() override; + FResult SetName(const FStr8or16& name) noexcept override; FGpuQueueCreateResult* GetQueues(u32* OutNumQueues) noexcept override; FGpuIsolateData* GpuIsolateData() noexcept override; - FResult CreateRecord(const FGpuRecordCreateOptions& options, FGpuRecordCreateResult& out) noexcept override; + FResult RentRecords(u32 NumRecords, FGpuRecordCreateResult* OutRecords) noexcept override; + FResult ReturnRecords(u32 NumRecords, FGpuRecord** Records) noexcept override; + FResult Submit(u32 NumRecords, FGpuRecord** Records, FGpuRecordCreateResult* OutRecords) noexcept override; + FResult SubmitReturn(u32 NumRecords, FGpuRecord** Records) noexcept override; FResult CreateSwapChainFromExists(const FGpuSwapChainFromExistsCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept override; FResult CreateSwapChainForHwnd(const FGpuSwapChainCreateOptions& options, void* hwnd, FGpuSwapChainCreateResult& out) noexcept override; + + void RentRecords(std::span out); + void ReturnRecords(std::span records); + void Submit(std::span records, std::span out); + void SubmitReturn(std::span records); }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.cc b/Coplt.Graphics.Native/D3d12/Src/Queue.cc index 293f6cf..1c99858 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.cc @@ -138,9 +138,22 @@ FResult D3d12GpuQueue::SubmitNoWait(FGpuExecutor* Executor, const FCommandSubmit }); } +RentedCommandAllocator::RentedCommandAllocator(Rc&& queue, ComPtr&& command_allocator) + : m_queue(std::move(queue)), m_command_allocator(std::move(command_allocator)) +{ +} + +RentedCommandAllocator::~RentedCommandAllocator() +{ + if (!m_queue) return; + m_queue->ReturnCommandAllocator(std::move(m_command_allocator)); +} + D3d12GpuQueue2::D3d12GpuQueue2(const NonNull isolate, const FGpuQueueType type) : FGpuQueueData() { + m_command_allocator_pool = box(); + m_device = isolate->m_device; QueueType = type; const NonNull device = m_device->m_device.Get(); @@ -211,3 +224,21 @@ void D3d12GpuQueue2::WaitFenceValue(u64 fence_value, HANDLE event) WaitForSingleObject(event, INFINITE); } } + +RentedCommandAllocator D3d12GpuQueue2::RentCommandAllocator() +{ + ComPtr command_allocator{}; + if (!m_command_allocator_pool->try_dequeue(command_allocator)) + { + chr | m_device->m_device->CreateCommandAllocator( + ToDx(this->QueueType), IID_PPV_ARGS(&command_allocator) + ); + } + return RentedCommandAllocator(this->CloneThis(), std::move(command_allocator)); +} + +void D3d12GpuQueue2::ReturnCommandAllocator(ComPtr&& command_allocator) +{ + chr | command_allocator->Reset(); + m_command_allocator_pool->enqueue(std::move(command_allocator)); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.h b/Coplt.Graphics.Native/D3d12/Src/Queue.h index 026fda4..370f630 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -3,6 +3,8 @@ #include #include +#include "concurrentqueue.h" + #include "CmdListPack.h" #include "Device.h" #include "../Include/Utils.h" @@ -72,6 +74,20 @@ namespace Coplt } } + struct D3d12GpuQueue2; + + // 必须等待队列 fence 完成才能析构,或者可以 move 走 + struct RentedCommandAllocator final + { + Rc m_queue{}; + ComPtr m_command_allocator{}; + + RentedCommandAllocator() = default; + explicit RentedCommandAllocator(Rc&& queue, ComPtr&& command_allocator); + + ~RentedCommandAllocator(); + }; + COPLT_INTERFACE_DEFINE(ID3d12GpuQueue, "a60df5da-ecff-4ae4-a38b-6ddef7db5922", FD3d12GpuQueue2) { Rc m_device{}; @@ -84,10 +100,16 @@ namespace Coplt virtual u64 SignalNoLock() = 0; virtual void WaitFenceValue(u64 fence_value, HANDLE event) = 0; + virtual RentedCommandAllocator RentCommandAllocator() = 0; + virtual void ReturnCommandAllocator(ComPtr&& command_allocator) = 0; }; struct D3d12GpuQueue2 final : GpuObject, FGpuQueueData { + using CommandAllocatorConcurrentQueue = moodycamel::ConcurrentQueue>; + + Box m_command_allocator_pool{}; + explicit D3d12GpuQueue2(NonNull isolate, FGpuQueueType type); FGpuQueueData* GpuQueueData() noexcept override; @@ -98,5 +120,8 @@ namespace Coplt u64 SignalNoLock() override; void WaitFenceValue(u64 fence_value, HANDLE event) override; + + RentedCommandAllocator RentCommandAllocator() override; + void ReturnCommandAllocator(ComPtr&& command_allocator) override; }; } // Coplt diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index c70cb80..364f677 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -2,9 +2,13 @@ using namespace Coplt; -D3d12GpuRecord::D3d12GpuRecord(NonNull isolate, const FGpuRecordCreateOptions& options) +D3d12GpuRecord::D3d12GpuRecord(NonNull isolate) : FGpuRecordData(isolate->m_device->m_instance->m_allocator.get()), m_device(isolate->m_device) { + m_isolate_id = isolate->m_object_id; + m_record_id = isolate->m_record_inc++; + m_context = new D3d12RecordContext(isolate); + Context = m_context.get(); } FResult D3d12GpuRecord::SetName(const FStr8or16& name) noexcept @@ -26,3 +30,8 @@ const FGpuRecordData* D3d12GpuRecord::Data() const noexcept { return this; } + +void D3d12GpuRecord::Recycle() const +{ + m_context->Recycle(); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index f789309..c84f3db 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -1,27 +1,34 @@ #pragma once +#include "Context.h" #include "Isolate.h" #include "../../Api/FFI/Record.h" #include "../../Api/Include/GpuObject.h" namespace Coplt { - COPLT_INTERFACE_DEFINE(ID3d12GpuRecord, "57a9c7f9-1ec0-4d78-89b9-e547667c50b3", FGpuRecord) { virtual FGpuRecordData* Data() noexcept = 0; virtual const FGpuRecordData* Data() const noexcept = 0; + + virtual void Recycle() const = 0; }; struct D3d12GpuRecord final : GpuObject, FGpuRecordData { + u64 m_isolate_id{}; + u64 m_record_id{}; Rc m_device{}; + Rc m_context{}; - explicit D3d12GpuRecord(NonNull isolate, const FGpuRecordCreateOptions& options); + explicit D3d12GpuRecord(NonNull isolate); FResult SetName(const FStr8or16& name) noexcept override; FGpuRecordData* GpuFGpuRecordData() noexcept override; FGpuRecordData* Data() noexcept override; const FGpuRecordData* Data() const noexcept override; + + void Recycle() const override; }; } diff --git a/Examples/SwapChain/ExampleBase.cs b/Examples/SwapChain/ExampleBase.cs index 28fe11d..edf8c5e 100644 --- a/Examples/SwapChain/ExampleBase.cs +++ b/Examples/SwapChain/ExampleBase.cs @@ -72,4 +72,4 @@ public void DoInitGraphics() } #endregion -} +} \ No newline at end of file From afc4bace504a34d5be192259724e020e6cbb9c12 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Wed, 19 Mar 2025 17:44:42 +0800 Subject: [PATCH 04/46] save --- Coplt.Graphics.Core/Core/FrameId.cs | 3 + Coplt.Graphics.Core/Core/GpuIsolate.cs | 93 +++++ Coplt.Graphics.Core/Core/GpuRecord.cs | 41 ++ Coplt.Graphics.Core/Native/Native.cs | 464 ++++++++++++++++++++-- Coplt.Graphics.Native/Api/CMakeLists.txt | 2 + Coplt.Graphics.Native/Api/FFI/Cmd.h | 128 ++++++ Coplt.Graphics.Native/Api/FFI/Command.h | 20 +- Coplt.Graphics.Native/Api/FFI/Record.h | 25 +- Coplt.Graphics.Native/Api/FFI/Structs.h | 30 ++ Coplt.Graphics.Native/D3d12/Src/Record.cc | 25 +- Coplt.Graphics.Native/D3d12/Src/Record.h | 13 +- Examples/Colorful/Example.cs | 100 ++--- Examples/ExampleBase/ExampleBase.cs | 19 +- Examples/HelloTriangle/Example.cs | 50 +-- Examples/HelloTriangleVertex/Example.cs | 158 ++++---- Examples/Image/Example.cs | 136 +++---- 16 files changed, 1012 insertions(+), 295 deletions(-) create mode 100644 Coplt.Graphics.Core/Core/FrameId.cs create mode 100644 Coplt.Graphics.Core/Core/GpuRecord.cs create mode 100644 Coplt.Graphics.Native/Api/FFI/Cmd.h create mode 100644 Coplt.Graphics.Native/Api/FFI/Structs.h diff --git a/Coplt.Graphics.Core/Core/FrameId.cs b/Coplt.Graphics.Core/Core/FrameId.cs new file mode 100644 index 0000000..8e25797 --- /dev/null +++ b/Coplt.Graphics.Core/Core/FrameId.cs @@ -0,0 +1,3 @@ +namespace Coplt.Graphics.Core; + +public readonly record struct FrameId(ulong Value); diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index f824853..7284841 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -1,4 +1,5 @@ using System.Buffers; +using System.Diagnostics.CodeAnalysis; using Coplt.Dropping; using Coplt.Graphics.Native; @@ -19,6 +20,7 @@ public sealed unsafe partial class GpuIsolate : DeviceChild public new FGpuIsolate* Ptr => (FGpuIsolate*)m_ptr; public ref readonly FGpuIsolateData Data => ref *m_data; public ReadOnlySpan Queues => m_queues; + public FrameId FrameId => new(Data.FrameId); #endregion @@ -134,4 +136,95 @@ public GpuSwapChain CreateSwapChainForHwnd(IntPtr Hwnd, in GpuSwapChainCreateOpt } #endregion + + #region Rent Reocrds + + public GpuRecord RentRecord() + { + GpuRecord? record = null; + RentRecords(new Span(ref record)); + return record!; + } + + public void RentRecords(Span records) + { + if (records.Length == 0) return; + if (records.Length < 8) + { + var p = stackalloc FGpuRecordCreateResult[records.Length]; + Ptr->RentRecords((uint)records.Length, p).TryThrow(); + for (var i = 0; i < records.Length; i++) + { + records[i] = new(p[i].Record, p[i].Data, null, this); + } + } + else + { + var arr = ArrayPool.Shared.Rent(records.Length); + try + { + fixed (FGpuRecordCreateResult* p = arr) + { + Ptr->RentRecords((uint)records.Length, p).TryThrow(); + for (var i = 0; i < records.Length; i++) + { + records[i] = new(p[i].Record, p[i].Data, null, this); + } + } + } + finally + { + ArrayPool.Shared.Return(arr); + } + } + } + + #endregion + + #region Return Reocrds + + public void ReturnRecords(ReadOnlySpan records) + { + if (records.Length == 0) return; + bool disposed = false; + if (records.Length < 8) + { + var p = stackalloc FGpuRecord*[records.Length]; + var c = 0u; + foreach (var t in records) + { + if (ExchangeUtils.ExchangePtr(ref t.m_ptr, null, out var ptr) is null) disposed = true; + else p[c++] = (FGpuRecord*)ptr; + } + if (c > 0) Ptr->ReturnRecords(c, p).TryThrow(); + if (disposed) throw new ObjectDisposedException(nameof(GpuRecord)); + } + else + { + var arr = ArrayPool.Shared.Rent(records.Length); + var c = 0u; + try + { + foreach (var t in records) + { + if (ExchangeUtils.ExchangePtr(ref t.m_ptr, null, out var ptr) is null) disposed = true; + else arr[c++] = (IntPtr)ptr; + } + if (c > 0) + { + fixed (IntPtr* p = arr) + { + Ptr->ReturnRecords(c, (FGpuRecord**)p).TryThrow(); + } + } + if (disposed) throw new ObjectDisposedException(nameof(GpuRecord)); + } + finally + { + ArrayPool.Shared.Return(arr); + } + } + } + + #endregion } diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs new file mode 100644 index 0000000..8acbac3 --- /dev/null +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -0,0 +1,41 @@ +using Coplt.Dropping; +using Coplt.Graphics.Native; + +namespace Coplt.Graphics.Core; + +public sealed unsafe class GpuRecord : IsolateChild +{ + #region Fields + + internal FGpuRecordData* m_data; + + #endregion + + #region Props + + public ref readonly FGpuRecordData Data => ref *m_data; + internal ref FGpuRecordData MutData => ref *m_data; + + #endregion + + #region Ctor + + internal GpuRecord(FGpuRecord* ptr, FGpuRecordData* data, string? name, GpuIsolate isolate) : base((FGpuObject*)ptr, name, isolate) + { + m_data = data; + } + + #endregion + + #region Dispose + + protected override void Dispose(bool disposing) + { + if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; + var p = (FGpuRecord*)ptr; + Isolate.Ptr->ReturnRecords(1, &p).TryThrow(); + m_data = null; + } + + #endregion +} diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 87681b7..8629699 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -6,6 +6,54 @@ namespace Coplt.Graphics.Native { + public partial struct FRect + { + [NativeTypeName("Coplt::u32")] + public uint Left; + + [NativeTypeName("Coplt::u32")] + public uint Top; + + [NativeTypeName("Coplt::u32")] + public uint Right; + + [NativeTypeName("Coplt::u32")] + public uint Bottom; + } + + public partial struct FViewport + { + [NativeTypeName("Coplt::f32")] + public float X; + + [NativeTypeName("Coplt::f32")] + public float Y; + + [NativeTypeName("Coplt::f32")] + public float Width; + + [NativeTypeName("Coplt::f32")] + public float Height; + + [NativeTypeName("Coplt::f32")] + public float MinDepth; + + [NativeTypeName("Coplt::f32")] + public float MaxDepth; + } + + [StructLayout(LayoutKind.Explicit)] + public partial struct FOrRectViewport + { + [FieldOffset(0)] + [NativeTypeName("Coplt::FRect")] + public FRect Rect; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FViewport")] + public FViewport Viewport; + } + public unsafe partial struct FObject : FObject.Interface { public void** lpVtbl; @@ -1220,10 +1268,93 @@ public partial struct FGpuRecord { } + [Guid("0EF83584-CA65-44DE-B38A-648BFB3A85A6")] + [NativeTypeName("struct FGpuRecord : Coplt::FGpuObject")] + public unsafe partial struct FGpuRecord : FGpuRecord.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuRecord)); + + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuRecord*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuRecord*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuRecord*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuRecord*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuRecord*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuRecord*)Unsafe.AsPointer(ref this), &result, name); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuRecordData *")] + public FGpuRecordData* GpuFGpuRecordData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuRecord*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult End() + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuRecord*)Unsafe.AsPointer(ref this), &result); + } + + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FGpuRecordData *")] + FGpuRecordData* GpuFGpuRecordData(); + + [return: NativeTypeName("Coplt::FResult")] + FResult End(); + } + } + public partial struct FGpuRecordCreateResult { } + public unsafe partial struct FGpuRecordCreateResult + { + [NativeTypeName("Coplt::FGpuRecord *")] + public FGpuRecord* Record; + + [NativeTypeName("Coplt::FGpuRecordData *")] + public FGpuRecordData* Data; + } + public partial struct FGpuIsolateCreateOptions { [NativeTypeName("Coplt::FStr8or16")] @@ -1394,6 +1525,293 @@ public unsafe partial struct FMainQueueCreateResult public uint NumQueues; } + public unsafe partial struct FGpuRecordData + { + [NativeTypeName("Coplt::FRecordContext *")] + public FRecordContext* Context; + + public FList Commands; + + public FList Resources; + + public FList Payload; + + [NativeTypeName("FList")] + public FList Blob; + + [NativeTypeName("Coplt::usize")] + public nuint OutputCount; + } + + [NativeTypeName("Coplt::u32")] + public enum FCmdType : uint + { + None = 0, + Label, + BeginScope, + EndScope, + ClearColor, + ClearDepthStencil, + } + + public enum FCmdResType + { + Image, + Buffer, + Output, + } + + public unsafe partial struct FCmdRes + { + [NativeTypeName("__AnonymousRecord_Cmd_L31_C9")] + public _Anonymous_e__Union Anonymous; + + [NativeTypeName("Coplt::FCmdResType")] + public FCmdResType Type; + + [UnscopedRef] + public ref FGpuOutput2* Output + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Output; + } + } + + [UnscopedRef] + public ref FGpuBuffer* Buffer + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Buffer; + } + } + + [UnscopedRef] + public ref FGpuImage* Image + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Image; + } + } + + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + [NativeTypeName("Coplt::FGpuOutput2 *")] + public FGpuOutput2* Output; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FGpuBuffer *")] + public FGpuBuffer* Buffer; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FGpuImage *")] + public FGpuImage* Image; + } + } + + public partial struct FCmdResRef + { + [NativeTypeName("Coplt::u32")] + public uint Index; + } + + public partial struct FCmdBase + { + [NativeTypeName("Coplt::FCmdType")] + public FCmdType Type; + } + + [NativeTypeName("struct FCmdLabel : Coplt::FCmdBase")] + public partial struct FCmdLabel + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint StringLength; + + [NativeTypeName("Coplt::usize")] + public nuint StringIndex; + + [NativeTypeName("Coplt::FStrType")] + public FStrType StrType; + + [NativeTypeName("u8[3]")] + public _Color_e__FixedBuffer Color; + + [NativeTypeName("Coplt::b8")] + public B8 HasColor; + + [InlineArray(3)] + public partial struct _Color_e__FixedBuffer + { + public byte e0; + } + } + + [NativeTypeName("struct FCmdBeginScope : Coplt::FCmdBase")] + public partial struct FCmdBeginScope + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint StringLength; + + [NativeTypeName("Coplt::usize")] + public nuint StringIndex; + + [NativeTypeName("Coplt::FStrType")] + public FStrType StrType; + + [NativeTypeName("u8[3]")] + public _Color_e__FixedBuffer Color; + + [NativeTypeName("Coplt::b8")] + public B8 HasColor; + + [InlineArray(3)] + public partial struct _Color_e__FixedBuffer + { + public byte e0; + } + } + + [NativeTypeName("struct FCmdEndScope : Coplt::FCmdBase")] + public partial struct FCmdEndScope + { + public FCmdBase Base; + } + + [NativeTypeName("struct FCmdClearColor : Coplt::FCmdBase")] + public partial struct FCmdClearColor + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint RectCount; + + [NativeTypeName("Coplt::u32")] + public uint RectIndex; + + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Image; + + [NativeTypeName("f32[4]")] + public _Color_e__FixedBuffer Color; + + [InlineArray(4)] + public partial struct _Color_e__FixedBuffer + { + public float e0; + } + } + + public partial struct FCmdItem + { + [NativeTypeName("__AnonymousRecord_Cmd_L115_C9")] + public _Anonymous_e__Union Anonymous; + + [UnscopedRef] + public ref FCmdType Type + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Type; + } + } + + [UnscopedRef] + public ref FCmdLabel Label + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Label; + } + } + + [UnscopedRef] + public ref FCmdBeginScope BeginScope + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.BeginScope; + } + } + + [UnscopedRef] + public ref FCmdEndScope EndScope + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.EndScope; + } + } + + [UnscopedRef] + public ref FCmdClearColor ClearColor + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.ClearColor; + } + } + + [UnscopedRef] + public Span _pad + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return Anonymous._pad; + } + } + + [StructLayout(LayoutKind.Explicit)] + public partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdType")] + public FCmdType Type; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdLabel")] + public FCmdLabel Label; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdBeginScope")] + public FCmdBeginScope BeginScope; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdEndScope")] + public FCmdEndScope EndScope; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdClearColor")] + public FCmdClearColor ClearColor; + + [FieldOffset(0)] + [NativeTypeName("u8[32]")] + public __pad_e__FixedBuffer _pad; + + [InlineArray(32)] + public partial struct __pad_e__FixedBuffer + { + public byte e0; + } + } + } + [NativeTypeName("Coplt::u8")] public enum FShaderStage : byte { @@ -3900,7 +4318,7 @@ public enum FResourceRefType : byte public unsafe partial struct FResourceMeta { - [NativeTypeName("__AnonymousRecord_Command_L64_C9")] + [NativeTypeName("__AnonymousRecord_Command_L65_C9")] public _Anonymous_e__Union Anonymous; [NativeTypeName("Coplt::FResourceRefType")] @@ -4133,42 +4551,6 @@ public partial struct _Anonymous_e__Union } } - public partial struct FRect - { - [NativeTypeName("Coplt::u32")] - public uint Left; - - [NativeTypeName("Coplt::u32")] - public uint Top; - - [NativeTypeName("Coplt::u32")] - public uint Right; - - [NativeTypeName("Coplt::u32")] - public uint Bottom; - } - - public partial struct FViewport - { - [NativeTypeName("Coplt::f32")] - public float X; - - [NativeTypeName("Coplt::f32")] - public float Y; - - [NativeTypeName("Coplt::f32")] - public float Width; - - [NativeTypeName("Coplt::f32")] - public float Height; - - [NativeTypeName("Coplt::f32")] - public float MinDepth; - - [NativeTypeName("Coplt::f32")] - public float MaxDepth; - } - [NativeTypeName("Coplt::u8")] public enum FDepthStencilClearFlags : byte { @@ -4777,7 +5159,7 @@ public partial struct FCommandSyncBinding public partial struct FCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L528_C9")] + [NativeTypeName("__AnonymousRecord_Command_L510_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -5003,7 +5385,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FRenderCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L559_C9")] + [NativeTypeName("__AnonymousRecord_Command_L541_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -5187,7 +5569,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FComputeCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L584_C9")] + [NativeTypeName("__AnonymousRecord_Command_L566_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -6394,6 +6776,8 @@ public static partial class Native public static readonly Guid IID_FGpuIsolate = new Guid(0x777C5774, 0x8EB8, 0x4550, 0xA9, 0x77, 0x62, 0xCC, 0xCD, 0x7B, 0xDD, 0xA6); + public static readonly Guid IID_FGpuRecord = new Guid(0x0EF83584, 0xCA65, 0x44DE, 0xB3, 0x8A, 0x64, 0x8B, 0xFB, 0x3A, 0x85, 0xA6); + public static readonly Guid IID_FShaderModule = new Guid(0x5C0E1FDB, 0x2ACD, 0x4FCE, 0xB9, 0x85, 0x09, 0xE1, 0x2A, 0x7A, 0x1A, 0xAD); public static readonly Guid IID_FShader = new Guid(0xDE1352D5, 0x023D, 0x42B0, 0xBE, 0xAC, 0x12, 0x2B, 0x3B, 0x29, 0x6C, 0x9C); diff --git a/Coplt.Graphics.Native/Api/CMakeLists.txt b/Coplt.Graphics.Native/Api/CMakeLists.txt index 1b00e28..3fef5b9 100644 --- a/Coplt.Graphics.Native/Api/CMakeLists.txt +++ b/Coplt.Graphics.Native/Api/CMakeLists.txt @@ -59,6 +59,8 @@ add_library(${target_name} STATIC FFI/Isolate.h FFI/Record.h Include/Finally.h + FFI/Cmd.h + FFI/Structs.h ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) add_library(Coplt::Graphics::Api ALIAS ${target_name}) diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h new file mode 100644 index 0000000..3fe4669 --- /dev/null +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -0,0 +1,128 @@ +#pragma once + +#include "Structs.h" +#include "Output.h" + +namespace Coplt +{ + enum class FCmdType : u32 + { + None = 0, + + Label, + BeginScope, + EndScope, + + ClearColor, + ClearDepthStencil, + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + enum class FCmdResType + { + Image, + Buffer, + Output, + }; + + struct FCmdRes + { + union + { + FGpuOutput2* Output{}; + FGpuBuffer* Buffer; + FGpuImage* Image; + }; + + FCmdResType Type{}; + + #ifdef FFI_SRC + FUnknown* GetObjectPtr() const + { + switch (Type) + { + case FCmdResType::Image: + return Image; + case FCmdResType::Buffer: + return Buffer; + case FCmdResType::Output: + return Output; + } + return nullptr; + } + #endif + }; + + struct FCmdResRef + { + u32 Index{}; + + #ifdef FFI_SRC + operator bool() const { return Index == 0; } + #endif + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdBase + { + FCmdType Type{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdLabel : FCmdBase + { + u32 StringLength{}; + // Blob 中的 index + usize StringIndex{}; + FStrType StrType{}; + u8 Color[3]{}; + b8 HasColor{}; + }; + + struct FCmdBeginScope : FCmdBase + { + u32 StringLength{}; + // Blob 中的 index + usize StringIndex{}; + FStrType StrType{}; + u8 Color[3]{}; + b8 HasColor{}; + }; + + struct FCmdEndScope : FCmdBase + { + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdClearColor : FCmdBase + { + // 有多少个 Rect + u32 RectCount{}; + // Payload 中的 Index, 类型为 Rect + u32 RectIndex{}; + FCmdResRef Image{}; + f32 Color[4]{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdItem + { + union + { + FCmdType Type{}; + + FCmdLabel Label; + FCmdBeginScope BeginScope; + FCmdEndScope EndScope; + + FCmdClearColor ClearColor; + + u8 _pad[32]; + }; + }; +} diff --git a/Coplt.Graphics.Native/Api/FFI/Command.h b/Coplt.Graphics.Native/Api/FFI/Command.h index 654d318..844cf9f 100644 --- a/Coplt.Graphics.Native/Api/FFI/Command.h +++ b/Coplt.Graphics.Native/Api/FFI/Command.h @@ -1,5 +1,6 @@ #pragma once +#include "Structs.h" #include "Binding.h" #include "Blob.h" #include "Output.h" @@ -89,7 +90,6 @@ namespace Coplt struct FResourceRef { - // u32::max 表示 empty u32 ResourceIndex{}; #ifdef FFI_SRC @@ -175,24 +175,6 @@ namespace Coplt }; }; - struct FRect - { - u32 Left; - u32 Top; - u32 Right; - u32 Bottom; - }; - - struct FViewport - { - f32 X; - f32 Y; - f32 Width; - f32 Height; - f32 MinDepth; - f32 MaxDepth; - }; - COPLT_ENUM_FLAGS(FDepthStencilClearFlags, u8) { None = 0, diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index e67fc2c..5bfe183 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -1,5 +1,6 @@ #pragma once +#include "Cmd.h" #include "GpuObject.h" #include "Isolate.h" @@ -10,18 +11,36 @@ namespace Coplt COPLT_INTERFACE_DEFINE(FGpuRecord, "0ef83584-ca65-44de-b38a-648bfb3a85a6", FGpuObject) { virtual FGpuRecordData* GpuFGpuRecordData() noexcept = 0; + + // 结束录制,并分析命令,可能是耗时任务,如果未调用将在 submit 时自动调用,未重置多次调用将报错 + virtual FResult End() noexcept = 0; }; // 里面的 FList 的 T* 生命周期由 c# 部分保证 struct FGpuRecordData { FRecordContext* Context{}; - FList Outputs; + FList Commands; + // 需要保证不重复,c# 部分需要使用 HashMap 去重 + FList Resources; + FList Payload; + FList Blob; + // 统计不重复的 Output 数量 + usize OutputCount{}; #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) - : Outputs(allocator) + : Commands(allocator), Resources(allocator), Payload(allocator), Blob(allocator) + { + } + + void ClearData() { + Commands.Clear(); + Resources.Clear(); + Payload.Clear(); + Blob.Clear(); + OutputCount = 0; } #endif }; @@ -31,4 +50,6 @@ namespace Coplt FGpuRecord* Record{}; FGpuRecordData* Data{}; }; + + } diff --git a/Coplt.Graphics.Native/Api/FFI/Structs.h b/Coplt.Graphics.Native/Api/FFI/Structs.h new file mode 100644 index 0000000..c379280 --- /dev/null +++ b/Coplt.Graphics.Native/Api/FFI/Structs.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Common.h" + +namespace Coplt +{ + struct FRect + { + u32 Left; + u32 Top; + u32 Right; + u32 Bottom; + }; + + struct FViewport + { + f32 X; + f32 Y; + f32 Width; + f32 Height; + f32 MinDepth; + f32 MaxDepth; + }; + + union FOrRectViewport + { + FRect Rect; + FViewport Viewport; + }; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 364f677..75bf449 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -31,7 +31,30 @@ const FGpuRecordData* D3d12GpuRecord::Data() const noexcept return this; } -void D3d12GpuRecord::Recycle() const +void D3d12GpuRecord::Recycle() { + ClearData(); m_context->Recycle(); } + +FResult D3d12GpuRecord::End() noexcept +{ + return feb([&] + { + DoEnd(); + }); +} + +void D3d12GpuRecord::EnsureEnd() +{ + if (m_ended) return; + DoEnd(); +} + +void D3d12GpuRecord::DoEnd() +{ + if (m_ended) + COPLT_THROW("End cannot be called multiple times"); + m_ended = true; + // todo +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index c84f3db..6b34548 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -9,10 +9,15 @@ namespace Coplt { COPLT_INTERFACE_DEFINE(ID3d12GpuRecord, "57a9c7f9-1ec0-4d78-89b9-e547667c50b3", FGpuRecord) { + std::vector> m_object_owner{}; + bool m_ended{}; + virtual FGpuRecordData* Data() noexcept = 0; virtual const FGpuRecordData* Data() const noexcept = 0; - virtual void Recycle() const = 0; + virtual void Recycle() = 0; + + virtual void EnsureEnd() = 0; }; struct D3d12GpuRecord final : GpuObject, FGpuRecordData @@ -29,6 +34,10 @@ namespace Coplt FGpuRecordData* Data() noexcept override; const FGpuRecordData* Data() const noexcept override; - void Recycle() const override; + void Recycle() override; + + FResult End() noexcept override; + void EnsureEnd() override; + void DoEnd(); }; } diff --git a/Examples/Colorful/Example.cs b/Examples/Colorful/Example.cs index 2d38465..73829bb 100644 --- a/Examples/Colorful/Example.cs +++ b/Examples/Colorful/Example.cs @@ -13,54 +13,54 @@ public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handl private GpuBuffer ArgBuffer = null!; public override string Name => "Colorful"; - protected override async Task LoadResources(CommandList cmd) - { - var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); - Layout = Device.CreateShaderLayout( - [ - new() - { - Slot = 0, - Stage = ShaderStage.Pixel, - View = ShaderLayoutItemView.Cbv, - Type = ShaderLayoutItemType.ConstantBuffer, - Usage = ShaderLayoutItemUsage.Persist, - } - ], - Name: Name - ); - Shader = Device.CreateShader(modules, Layout); - ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); - Pipeline = Device.CreateGraphicsShaderPipeline( - Shader, new() - { - DsvFormat = GraphicsFormat.Unknown, - BlendState = - { - Rt0 = - { - Src = BlendType.SrcAlpha, - Dst = BlendType.InvSrcAlpha, - Op = BlendOp.Add, - } - }, - Topology = PrimitiveTopologyType.TriangleStrip, - }, Name: Name - ); - ArgBuffer = Device.CreateBuffer( - new() - { - Purpose = ResourcePurpose.ConstantBuffer, - Size = sizeof(float), - }, - Name: "Args" - ); - 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 Color(0.83f, 0.8f, 0.97f))]); - render.Draw(Pipeline, 4, Binding: ShaderBinding); - } + // protected override async Task LoadResources(CommandList cmd) + // { + // var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); + // Layout = Device.CreateShaderLayout( + // [ + // new() + // { + // Slot = 0, + // Stage = ShaderStage.Pixel, + // View = ShaderLayoutItemView.Cbv, + // Type = ShaderLayoutItemType.ConstantBuffer, + // Usage = ShaderLayoutItemUsage.Persist, + // } + // ], + // Name: Name + // ); + // Shader = Device.CreateShader(modules, Layout); + // ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); + // Pipeline = Device.CreateGraphicsShaderPipeline( + // Shader, new() + // { + // DsvFormat = GraphicsFormat.Unknown, + // BlendState = + // { + // Rt0 = + // { + // Src = BlendType.SrcAlpha, + // Dst = BlendType.InvSrcAlpha, + // Op = BlendOp.Add, + // } + // }, + // Topology = PrimitiveTopologyType.TriangleStrip, + // }, Name: Name + // ); + // ArgBuffer = Device.CreateBuffer( + // new() + // { + // Purpose = ResourcePurpose.ConstantBuffer, + // Size = sizeof(float), + // }, + // Name: "Args" + // ); + // 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 Color(0.83f, 0.8f, 0.97f))]); + // render.Draw(Pipeline, 4, Binding: ShaderBinding); + // } } diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index 7c6b87a..7df7fa5 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -14,7 +14,8 @@ public abstract class ExampleBase(IntPtr Handle, uint Width, uint Height) public GraphicsInstance Graphics = null!; public GpuDevice Device = null!; public GpuIsolate Isolate = null!; - public GpuOutput Output = null!; + public GpuSwapChain Output = null!; + public GpuRecord Record = null!; public IntPtr Handle = Handle; public abstract string Name { get; } @@ -43,21 +44,21 @@ public void DoInitGraphics() } ); Isolate = Device.CreateIsolate(Name: "Main Isolate"); - Output = Device.MainQueue.CreateOutputForHwnd( - new() + Output = Isolate.CreateSwapChainForHwnd( + Handle, new() { Width = Width, Height = Height, // VSync = true, - }, Handle + } ); + Record = Isolate.RentRecord(); InitGraphics(); new Thread( () => { Thread.CurrentThread.Name = "Render Thread"; - var cmd = Device.MainCommandList; - LoadResources(cmd).Wait(); + LoadResources(Record).Wait(); var start_time = Stopwatch.GetTimestamp(); var last_time = start_time; while (!IsClosed) @@ -74,7 +75,7 @@ public void DoInitGraphics() Delta = delta_time }; - Render(cmd, time); + Render(Record, time); Output.Present(); } catch (Exception e) @@ -124,13 +125,13 @@ public static Task> LoadImage(string path) where T : unmanaged, IPix #region LoadResources - protected abstract Task LoadResources(CommandList cmd); + protected virtual Task LoadResources(GpuRecord cmd) => Task.CompletedTask; #endregion #region Render - protected abstract void Render(CommandList cmd, Time time); + protected virtual void Render(GpuRecord cmd, Time time) { } #endregion } diff --git a/Examples/HelloTriangle/Example.cs b/Examples/HelloTriangle/Example.cs index a8a4bcc..90ac236 100644 --- a/Examples/HelloTriangle/Example.cs +++ b/Examples/HelloTriangle/Example.cs @@ -6,33 +6,33 @@ namespace Examples; public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handle, Width, Height) { - private Shader Shader = null!; - private GraphicsShaderPipeline Pipeline = null!; + // private Shader Shader = null!; + // private GraphicsShaderPipeline Pipeline = null!; public override string Name => "Hello Triangle"; - protected override async Task LoadResources(CommandList cmd) + // protected override async Task LoadResources(GpuRecord cmd) + // { + // var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); + // Shader = Device.CreateShader(modules, null, Device.CreateShaderInputLayout([])); + // Pipeline = Device.CreateGraphicsShaderPipeline( + // Shader, new() + // { + // DsvFormat = GraphicsFormat.Unknown, + // BlendState = + // { + // Rt0 = + // { + // Src = BlendType.SrcAlpha, + // Dst = BlendType.InvSrcAlpha, + // Op = BlendOp.Add, + // } + // } + // }, Name: Name + // ); + // } + protected override void Render(GpuRecord cmd, Time time) { - var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); - Shader = Device.CreateShader(modules, null, Device.CreateShaderInputLayout([])); - Pipeline = Device.CreateGraphicsShaderPipeline( - Shader, new() - { - DsvFormat = GraphicsFormat.Unknown, - BlendState = - { - Rt0 = - { - Src = BlendType.SrcAlpha, - Dst = BlendType.InvSrcAlpha, - Op = BlendOp.Add, - } - } - }, Name: Name - ); - } - protected override void Render(CommandList cmd, Time time) - { - using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); - render.Draw(Pipeline, 3); + // using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); + // render.Draw(Pipeline, 3); } } diff --git a/Examples/HelloTriangleVertex/Example.cs b/Examples/HelloTriangleVertex/Example.cs index 534f583..7ed5bf6 100644 --- a/Examples/HelloTriangleVertex/Example.cs +++ b/Examples/HelloTriangleVertex/Example.cs @@ -13,83 +13,83 @@ public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handl private GpuBuffer UvBuffer = null!; public override string Name => "Hello Triangle Vertex"; - protected override async Task LoadResources(CommandList cmd) - { - var SlotId_Position = Graphics.GetSlotId("Position"); - var SlotId_Color = Graphics.GetSlotId("Color"); - var SlotId_Uv = Graphics.GetSlotId("Uv"); - var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); - Shader = Device.CreateShader( - modules, null, - Device.CreateShaderInputLayout( - [new(SlotId_Position), new(SlotId_Color), new(SlotId_Uv)] - ) - ); - MeshLayout = Device.CreateMeshLayout( - [ - new(Stride: sizeof(float) * 7), - new(Stride: sizeof(float) * 2), - ], - [ - new(SlotId_Position, GraphicsFormat.R32G32B32_Float), - new(SlotId_Color, GraphicsFormat.R32G32B32A32_Float, Offset: sizeof(float) * 3), - new(SlotId_Uv, GraphicsFormat.R32G32_Float, BufferIndex: 1), - ], - Name: "Mesh" - ); - Pipeline = Device.CreateGraphicsShaderPipeline( - Shader, new() - { - DsvFormat = GraphicsFormat.Unknown, - BlendState = - { - Rt0 = - { - Src = BlendType.SrcAlpha, - Dst = BlendType.InvSrcAlpha, - Op = BlendOp.Add, - } - } - }, MeshLayout, Name: Name - ); - PositionColorBuffer = Device.CreateBuffer( - new() - { - Purpose = ResourcePurpose.VertexBuffer, - Size = sizeof(float) * 4 * 6, - }, "Position and Color" - ); - UvBuffer = Device.CreateBuffer( - new() - { - Purpose = ResourcePurpose.VertexBuffer, - Size = sizeof(float) * 2 * 3, - }, "Uv" - ); - cmd.Upload( - PositionColorBuffer, [ - /* position */ 0.0f, 0.5f * 1.7f, 0f, /* color */ 0.71f, 0.22f, 0.21f, 1f, - /* position */ 0.5f, -0.5f * 1.7f, 0f, /* color */ 0.34f, 0.64f, 0.31f, 1f, - /* position */ -0.5f, -0.5f * 1.7f, 0f, /* color */ 0.36f, 0.42f, 0.92f, 1f, - ] - ); - cmd.Upload( - UvBuffer, [ - 0.0f, 0.0f, - -1.0f, 2.0f, - 1.0f, 2.0f, - ] - ); - } - protected override void Render(CommandList cmd, Time time) - { - using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); - render.SetMeshBuffers( - MeshLayout, [ - new(0, PositionColorBuffer), - new(1, UvBuffer), - ] - ); - render.Draw(Pipeline, 3); - } + // protected override async Task LoadResources(CommandList cmd) + // { + // var SlotId_Position = Graphics.GetSlotId("Position"); + // var SlotId_Color = Graphics.GetSlotId("Color"); + // var SlotId_Uv = Graphics.GetSlotId("Uv"); + // var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); + // Shader = Device.CreateShader( + // modules, null, + // Device.CreateShaderInputLayout( + // [new(SlotId_Position), new(SlotId_Color), new(SlotId_Uv)] + // ) + // ); + // MeshLayout = Device.CreateMeshLayout( + // [ + // new(Stride: sizeof(float) * 7), + // new(Stride: sizeof(float) * 2), + // ], + // [ + // new(SlotId_Position, GraphicsFormat.R32G32B32_Float), + // new(SlotId_Color, GraphicsFormat.R32G32B32A32_Float, Offset: sizeof(float) * 3), + // new(SlotId_Uv, GraphicsFormat.R32G32_Float, BufferIndex: 1), + // ], + // Name: "Mesh" + // ); + // Pipeline = Device.CreateGraphicsShaderPipeline( + // Shader, new() + // { + // DsvFormat = GraphicsFormat.Unknown, + // BlendState = + // { + // Rt0 = + // { + // Src = BlendType.SrcAlpha, + // Dst = BlendType.InvSrcAlpha, + // Op = BlendOp.Add, + // } + // } + // }, MeshLayout, Name: Name + // ); + // PositionColorBuffer = Device.CreateBuffer( + // new() + // { + // Purpose = ResourcePurpose.VertexBuffer, + // Size = sizeof(float) * 4 * 6, + // }, "Position and Color" + // ); + // UvBuffer = Device.CreateBuffer( + // new() + // { + // Purpose = ResourcePurpose.VertexBuffer, + // Size = sizeof(float) * 2 * 3, + // }, "Uv" + // ); + // cmd.Upload( + // PositionColorBuffer, [ + // /* position */ 0.0f, 0.5f * 1.7f, 0f, /* color */ 0.71f, 0.22f, 0.21f, 1f, + // /* position */ 0.5f, -0.5f * 1.7f, 0f, /* color */ 0.34f, 0.64f, 0.31f, 1f, + // /* position */ -0.5f, -0.5f * 1.7f, 0f, /* color */ 0.36f, 0.42f, 0.92f, 1f, + // ] + // ); + // cmd.Upload( + // UvBuffer, [ + // 0.0f, 0.0f, + // -1.0f, 2.0f, + // 1.0f, 2.0f, + // ] + // ); + // } + // protected override void Render(CommandList cmd, Time time) + // { + // using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); + // render.SetMeshBuffers( + // MeshLayout, [ + // new(0, PositionColorBuffer), + // new(1, UvBuffer), + // ] + // ); + // render.Draw(Pipeline, 3); + // } } diff --git a/Examples/Image/Example.cs b/Examples/Image/Example.cs index f58dbe7..04dfbc2 100644 --- a/Examples/Image/Example.cs +++ b/Examples/Image/Example.cs @@ -15,72 +15,72 @@ public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handl private ShaderBinding ShaderBinding = null!; public override string Name => "Image"; - protected override async Task LoadResources(CommandList cmd) - { - var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); - Layout = Device.CreateShaderLayout( - [ - new() - { - Slot = 0, - Stage = ShaderStage.Pixel, - View = ShaderLayoutItemView.Srv, - Type = ShaderLayoutItemType.Texture2D, - Usage = ShaderLayoutItemUsage.Persist, - }, - new() - { - Slot = 0, - Stage = ShaderStage.Pixel, - View = ShaderLayoutItemView.Sampler, - Type = ShaderLayoutItemType.Sampler, - Usage = ShaderLayoutItemUsage.Persist, - } - ], - Name: Name - ); - Shader = Device.CreateShader(modules, Layout); - ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); - Pipeline = Device.CreateGraphicsShaderPipeline( - Shader, new() - { - DsvFormat = GraphicsFormat.Unknown, - BlendState = - { - Rt0 = - { - Src = BlendType.SrcAlpha, - Dst = BlendType.InvSrcAlpha, - Op = BlendOp.Add, - } - }, - Topology = PrimitiveTopologyType.TriangleStrip, - }, Name: Name - ); - Sampler = Device.CreateSampler(SamplerInfo.LinearRepeat); - using var image_data = await LoadImage("./Image.png"); - var upload_memory = Device.MainQueue.AllocImageUploadMemory2D(4, (uint)image_data.Width, (uint)image_data.Height); - for (var row = 0u; row < upload_memory.RowCount; row++) - { - var row_span = image_data.Frames[0].PixelBuffer.DangerousGetRowSpan((int)row); - MemoryMarshal.AsBytes(row_span).CopyTo(upload_memory[row]); - } - var test_image = Device.CreateImage( - new() - { - Purpose = ResourcePurpose.ShaderResource, - Format = GraphicsFormat.R8G8B8A8_UNorm, - Width = (uint)image_data.Width, - Height = (uint)image_data.Height, - }, - Name: "Test Image" - ); - cmd.Upload(test_image, upload_memory); - cmd.Bind(ShaderBinding, [new(0, test_image), new(1, Sampler)]); - } - protected override void Render(CommandList cmd, Time time) - { - using var render = cmd.Render([new(Output, LoadOp.Discard)]); - render.Draw(Pipeline, 4, Binding: ShaderBinding); - } + // protected override async Task LoadResources(CommandList cmd) + // { + // var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); + // Layout = Device.CreateShaderLayout( + // [ + // new() + // { + // Slot = 0, + // Stage = ShaderStage.Pixel, + // View = ShaderLayoutItemView.Srv, + // Type = ShaderLayoutItemType.Texture2D, + // Usage = ShaderLayoutItemUsage.Persist, + // }, + // new() + // { + // Slot = 0, + // Stage = ShaderStage.Pixel, + // View = ShaderLayoutItemView.Sampler, + // Type = ShaderLayoutItemType.Sampler, + // Usage = ShaderLayoutItemUsage.Persist, + // } + // ], + // Name: Name + // ); + // Shader = Device.CreateShader(modules, Layout); + // ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); + // Pipeline = Device.CreateGraphicsShaderPipeline( + // Shader, new() + // { + // DsvFormat = GraphicsFormat.Unknown, + // BlendState = + // { + // Rt0 = + // { + // Src = BlendType.SrcAlpha, + // Dst = BlendType.InvSrcAlpha, + // Op = BlendOp.Add, + // } + // }, + // Topology = PrimitiveTopologyType.TriangleStrip, + // }, Name: Name + // ); + // Sampler = Device.CreateSampler(SamplerInfo.LinearRepeat); + // using var image_data = await LoadImage("./Image.png"); + // var upload_memory = Device.MainQueue.AllocImageUploadMemory2D(4, (uint)image_data.Width, (uint)image_data.Height); + // for (var row = 0u; row < upload_memory.RowCount; row++) + // { + // var row_span = image_data.Frames[0].PixelBuffer.DangerousGetRowSpan((int)row); + // MemoryMarshal.AsBytes(row_span).CopyTo(upload_memory[row]); + // } + // var test_image = Device.CreateImage( + // new() + // { + // Purpose = ResourcePurpose.ShaderResource, + // Format = GraphicsFormat.R8G8B8A8_UNorm, + // Width = (uint)image_data.Width, + // Height = (uint)image_data.Height, + // }, + // Name: "Test Image" + // ); + // cmd.Upload(test_image, upload_memory); + // cmd.Bind(ShaderBinding, [new(0, test_image), new(1, Sampler)]); + // } + // protected override void Render(CommandList cmd, Time time) + // { + // using var render = cmd.Render([new(Output, LoadOp.Discard)]); + // render.Draw(Pipeline, 4, Binding: ShaderBinding); + // } } From 2411f767d10c08e7bde994edeab96e4f8ab19555 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 20 Mar 2025 00:00:20 +0800 Subject: [PATCH 05/46] save --- Coplt.Graphics.Core/Core/DeviceChild.cs | 39 ---- Coplt.Graphics.Core/Core/GpuBuffer.cs | 12 ++ Coplt.Graphics.Core/Core/GpuImage.cs | 12 ++ Coplt.Graphics.Core/Core/GpuIsolate.cs | 180 +++++++++++++++---- Coplt.Graphics.Core/Core/GpuOutput.cs | 56 +++++- Coplt.Graphics.Core/Core/GpuRecord.cs | 108 ++++++++++- Coplt.Graphics.Core/Core/Views.cs | 3 +- Coplt.Graphics.Core/Core/XChild.cs | 60 +++++++ Coplt.Graphics.Core/Native/FList.cs | 20 +++ Coplt.Graphics.Core/Native/Native.cs | 7 +- Coplt.Graphics.Native/Api/FFI/Cmd.h | 6 +- Coplt.Graphics.Native/Api/FFI/Record.h | 1 + Coplt.Graphics.Native/Api/Include/Error.h | 45 +++++ Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 62 +++++-- Coplt.Graphics.Native/D3d12/Src/Isolate.h | 6 +- Coplt.Graphics.Native/D3d12/Src/Queue.cc | 14 ++ Coplt.Graphics.Native/D3d12/Src/Queue.h | 14 ++ Coplt.Graphics.Native/D3d12/Src/Record.cc | 31 +++- Coplt.Graphics.Native/D3d12/Src/Record.h | 10 +- Coplt.Graphics.Native/D3d12/Src/SwapChain.cc | 3 + Examples/ExampleBase/ExampleBase.cs | 1 + Examples/HelloTriangle/Example.cs | 1 + 22 files changed, 583 insertions(+), 108 deletions(-) delete mode 100644 Coplt.Graphics.Core/Core/DeviceChild.cs create mode 100644 Coplt.Graphics.Core/Core/XChild.cs diff --git a/Coplt.Graphics.Core/Core/DeviceChild.cs b/Coplt.Graphics.Core/Core/DeviceChild.cs deleted file mode 100644 index fb6d48f..0000000 --- a/Coplt.Graphics.Core/Core/DeviceChild.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Coplt.Graphics.Native; - -namespace Coplt.Graphics.Core; - -public abstract unsafe class DeviceChild : GpuObject -{ - #region Props - - public GpuDevice Device { get; } - - #endregion - - #region Ctor - - internal DeviceChild(FGpuObject* ptr, string? name, GpuDevice device) : base(ptr, name) - { - Device = device; - } - - #endregion -} - -public abstract unsafe class IsolateChild : DeviceChild -{ - #region Props - - public GpuIsolate Isolate { get; } - - #endregion - - #region Ctor - - internal IsolateChild(FGpuObject* ptr, string? name, GpuIsolate isolate) : base(ptr, name, isolate.Device) - { - Isolate = isolate; - } - - #endregion -} diff --git a/Coplt.Graphics.Core/Core/GpuBuffer.cs b/Coplt.Graphics.Core/Core/GpuBuffer.cs index 317aea9..cb604d1 100644 --- a/Coplt.Graphics.Core/Core/GpuBuffer.cs +++ b/Coplt.Graphics.Core/Core/GpuBuffer.cs @@ -64,6 +64,16 @@ m_name is null #endregion + #region Cmd + + FCmdRes IGpuResource.IntoCmd() => new() + { + Type = FCmdResType.Buffer, + Buffer = Ptr, + }; + + #endregion + #region View public bool TryVbv() => Purpose.HasFlags(ResourcePurpose.VertexBuffer); @@ -105,4 +115,6 @@ public Span EnsureMappedMemory() } #endregion + + public GpuIsolate Isolate => throw new NotImplementedException(); } diff --git a/Coplt.Graphics.Core/Core/GpuImage.cs b/Coplt.Graphics.Core/Core/GpuImage.cs index 644cf48..5d3564b 100644 --- a/Coplt.Graphics.Core/Core/GpuImage.cs +++ b/Coplt.Graphics.Core/Core/GpuImage.cs @@ -131,6 +131,16 @@ m_name is null #endregion + #region Cmd + + FCmdRes IGpuResource.IntoCmd() => new() + { + Type = FCmdResType.Image, + Image = Ptr, + }; + + #endregion + #region View public bool TryRtv() => Purpose.HasFlags(ResourcePurpose.RenderTarget); @@ -139,4 +149,6 @@ m_name is null public bool TrySrv() => Purpose.HasFlags(ResourcePurpose.ShaderResource); #endregion + + public GpuIsolate Isolate => throw new NotImplementedException(); } diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 7284841..9e217fd 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -18,7 +18,7 @@ public sealed unsafe partial class GpuIsolate : DeviceChild #region Props public new FGpuIsolate* Ptr => (FGpuIsolate*)m_ptr; - public ref readonly FGpuIsolateData Data => ref *m_data; + internal ref readonly FGpuIsolateData Data => ref *m_data; public ReadOnlySpan Queues => m_queues; public FrameId FrameId => new(Data.FrameId); @@ -100,43 +100,6 @@ public override void SetName(ReadOnlySpan name, string? managed_version = #endregion - #region CreateSwapChainForHwnd - - /// - /// Will fail on non Windows systems - /// - public GpuSwapChain CreateSwapChainForHwnd(IntPtr Hwnd, in GpuSwapChainCreateOptions Options, string? Name = null, ReadOnlySpan Name8 = default) - { - fixed (char* p_name = Name) - fixed (byte* p_name8 = Name8) - { - FGpuSwapChainCreateOptions f_options = new() - { - Base = new() - { - Name = new(Name, Name8, p_name, p_name8), - PresentMode = (FPresentMode)Options.PresentMode, - }, - Width = Options.Width, - Height = Options.Height, - Format = Options.Format.ToFFI(), - AlphaMode = (FOutputAlphaMode)Options.AlphaMode, - VSync = Options.VSync, - FormatSelector = - { - Specify = Options.FormatSelector.Specify, - Srgb = Options.FormatSelector.Srgb, - Hdr = (FHdrType)Options.FormatSelector.Hdr, - }, - }; - FGpuSwapChainCreateResult r; - Ptr->CreateSwapChainForHwnd(&f_options, (void*)Hwnd, &r).TryThrow(); - return new(r.SwapChain, r.Data, Name, this); - } - } - - #endregion - #region Rent Reocrds public GpuRecord RentRecord() @@ -183,7 +146,7 @@ public void RentRecords(Span records) #region Return Reocrds - public void ReturnRecords(ReadOnlySpan records) + public void ReturnRecords(params ReadOnlySpan records) { if (records.Length == 0) return; bool disposed = false; @@ -227,4 +190,143 @@ public void ReturnRecords(ReadOnlySpan records) } #endregion + + #region Submit + + public void Submit(params ReadOnlySpan records) + { + if (records.Length == 0) return; + if (records.Length < 8) + { + var p = stackalloc FGpuRecord*[records.Length]; + var o = stackalloc FGpuRecordCreateResult[records.Length]; + for (var i = 0; i < records.Length; i++) + { + if ((p[i] = records[i].Ptr) == null) throw new NullReferenceException(); + } + Ptr->Submit((uint)records.Length, p, o).TryThrow(); + for (var i = 0; i < records.Length; i++) + { + records[i].m_ptr = (FUnknown*)o[i].Record; + records[i].m_data = o[i].Data; + records[i].Reset(); + } + } + else + { + var arr = ArrayPool.Shared.Rent(records.Length); + var @out = ArrayPool.Shared.Rent(records.Length); + try + { + for (var i = 0; i < records.Length; i++) + { + if ((arr[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); + } + fixed (IntPtr* p = arr) + fixed (FGpuRecordCreateResult* o = @out) + { + Ptr->Submit((uint)records.Length, (FGpuRecord**)p, o).TryThrow(); + for (var i = 0; i < records.Length; i++) + { + records[i].m_ptr = (FUnknown*)o[i].Record; + records[i].m_data = o[i].Data; + records[i].Reset(); + } + } + } + finally + { + ArrayPool.Shared.Return(arr); + ArrayPool.Shared.Return(@out); + } + } + } + + #endregion + + #region Submit Return + + public void SubmitReturn(params ReadOnlySpan records) + { + if (records.Length == 0) return; + if (records.Length < 8) + { + var p = stackalloc FGpuRecord*[records.Length]; + for (var i = 0; i < records.Length; i++) + { + if ((p[i] = records[i].Ptr) == null) throw new NullReferenceException(); + } + Ptr->SubmitReturn((uint)records.Length, p).TryThrow(); + foreach (var a in records) + { + a.m_ptr = null; + a.m_data = null; + a.Reset(); + } + } + else + { + var arr = ArrayPool.Shared.Rent(records.Length); + try + { + for (var i = 0; i < records.Length; i++) + { + if ((arr[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); + } + fixed (IntPtr* p = arr) + { + Ptr->SubmitReturn((uint)records.Length, (FGpuRecord**)p).TryThrow(); + foreach (var a in records) + { + a.m_ptr = null; + a.m_data = null; + a.Reset(); + } + } + } + finally + { + ArrayPool.Shared.Return(arr); + } + } + } + + #endregion + + #region CreateSwapChainForHwnd + + /// + /// Will fail on non Windows systems + /// + public GpuSwapChain CreateSwapChainForHwnd(IntPtr Hwnd, in GpuSwapChainCreateOptions Options, string? Name = null, ReadOnlySpan Name8 = default) + { + fixed (char* p_name = Name) + fixed (byte* p_name8 = Name8) + { + FGpuSwapChainCreateOptions f_options = new() + { + Base = new() + { + Name = new(Name, Name8, p_name, p_name8), + PresentMode = (FPresentMode)Options.PresentMode, + }, + Width = Options.Width, + Height = Options.Height, + Format = Options.Format.ToFFI(), + AlphaMode = (FOutputAlphaMode)Options.AlphaMode, + VSync = Options.VSync, + FormatSelector = + { + Specify = Options.FormatSelector.Specify, + Srgb = Options.FormatSelector.Srgb, + Hdr = (FHdrType)Options.FormatSelector.Hdr, + }, + }; + FGpuSwapChainCreateResult r; + Ptr->CreateSwapChainForHwnd(&f_options, (void*)Hwnd, &r).TryThrow(); + return new(r.SwapChain, r.Data, Name, this); + } + } + + #endregion } diff --git a/Coplt.Graphics.Core/Core/GpuOutput.cs b/Coplt.Graphics.Core/Core/GpuOutput.cs index d1e5635..2f4cbfa 100644 --- a/Coplt.Graphics.Core/Core/GpuOutput.cs +++ b/Coplt.Graphics.Core/Core/GpuOutput.cs @@ -64,7 +64,7 @@ public record struct GpuOutputOptions() #endregion [Dropping(Unmanaged = true)] -public sealed unsafe partial class GpuOutput : GpuExecutor, IQueueOwned, IGpuResource, IRtv, ISrv +public sealed unsafe partial class GpuOutput : GpuExecutor, IGpuResource, IRtv, ISrv { #region Fields @@ -99,6 +99,7 @@ public ResState State Type = FResourceRefType.Output, Output = m_ptr, }; + public FCmdRes IntoCmd() => throw new NotImplementedException(); #endregion @@ -148,10 +149,12 @@ m_name is null public void Resize(uint width, uint height) => m_ptr->Resize(width, height).TryThrow(); #endregion + + public GpuIsolate Isolate => throw new NotImplementedException(); } [Dropping(Unmanaged = true)] -public abstract unsafe partial class GpuOutput2 : IsolateChild +public abstract unsafe partial class GpuOutput2 : IsolateChild, IGpuResource, IRtv, ISrv { #region Fields @@ -162,7 +165,19 @@ public abstract unsafe partial class GpuOutput2 : IsolateChild #region Props public new FGpuOutput2* Ptr => (FGpuOutput2*)m_ptr; - public ref readonly FGpuOutputData Data => ref *m_data; + internal ref readonly FGpuOutputData Data => ref *m_data; + GpuResourceType IGpuResource.Type => GpuResourceType.Image; + IGpuResource IGpuView.Resource => this; + public GraphicsFormat Format => Data.Format.FromFFI(); + ulong IGpuView.Size => (ulong)Width * Height; + public uint Width => Data.Width; + public uint Height => Data.Height; + uint IGpuView.DepthOrLength => 1; + uint IGpuView.MipLevels => 1; + uint IGpuView.Planes => 1; + uint IGpuView.Count => 0; + uint IGpuView.Stride => 0; + public PresentMode PresentMode => (PresentMode)Data.PresentMode; #endregion @@ -185,6 +200,23 @@ private void Drop() #endregion + #region Cmd + + FCmdRes IGpuResource.IntoCmd() => new() + { + Type = FCmdResType.Output, + Output = Ptr, + }; + + #endregion + + #region Views + + public bool TrySrv() => true; + public bool TryRtv() => true; + + #endregion + #region Methods public void Resize(uint Width, uint Height) => Ptr->Resize(Width, Height).TryThrow(); @@ -194,6 +226,15 @@ private void Drop() public void Wait() => Ptr->Wait().TryThrow(); #endregion + + public FResourceMeta GetMeta() => throw new NotSupportedException(); + public ResState State + { + get => throw new NotSupportedException(); + set => throw new NotSupportedException(); + } + public ref FResState NativeState => throw new NotSupportedException(); + public GpuQueue Queue => throw new NotSupportedException(); } public record struct GpuSwapChainCreateOptions() @@ -212,7 +253,14 @@ public sealed unsafe class GpuSwapChain : GpuOutput2 #region Props public new FGpuSwapChain* Ptr => (FGpuSwapChain*)m_ptr; - public new ref readonly FGpuSwapChainData Data => ref *(FGpuSwapChainData*)m_data; + internal new ref readonly FGpuSwapChainData Data => ref *(FGpuSwapChainData*)m_data; + + public OutputAlphaMode AlphaMode => (OutputAlphaMode)Data.AlphaMode; + public bool VSync + { + get => Data.VSync; + set => SetVSync(value); + } #endregion diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 8acbac3..ee6995f 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -1,4 +1,5 @@ -using Coplt.Dropping; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using Coplt.Graphics.Native; namespace Coplt.Graphics.Core; @@ -8,13 +9,14 @@ public sealed unsafe class GpuRecord : IsolateChild #region Fields internal FGpuRecordData* m_data; + internal readonly Dictionary m_resources = new(); #endregion #region Props - public ref readonly FGpuRecordData Data => ref *m_data; - internal ref FGpuRecordData MutData => ref *m_data; + public new FGpuRecord* Ptr => (FGpuRecord*)m_ptr; + internal ref FGpuRecordData Data => ref *m_data; #endregion @@ -38,4 +40,104 @@ protected override void Dispose(bool disposing) } #endregion + + #region Reset + + internal void Reset() + { + m_resources.Clear(); + } + + #endregion + + #region End + + public void AssertNotEnded() + { + if (Data.Ended) throw new InvalidOperationException("Gpu record is already ended"); + } + + public void End() + { + AssertNotEnded(); + Ptr->End().TryThrow(); + } + + public void EnsureEnded() + { + if (Data.Ended) return; + Ptr->End().TryThrow(); + } + + #endregion + + #region AddResource + + internal FCmdResRef AddResource(IGpuResource resource) + { + if (resource.Isolate != Isolate) + throw new ArgumentException($"Resource {resource} does not belong to isolate {Isolate}"); + ref var slot = ref CollectionsMarshal.GetValueRefOrAddDefault(m_resources, m_resources, out var exists); + if (!exists) + { + var len = Data.Resources.LongLength; + if (len + 1 >= uint.MaxValue) throw new IndexOutOfRangeException("Resources >= uint32 max are not supported"); + slot = (uint)len; + if (resource is GpuOutput) Data.OutputCount++; + Data.Resources.Add(resource.IntoCmd()); + } + return new() { IndexPlusOne = slot + 1 }; + } + + #endregion + + #region AddRects + + internal uint AddRects(ReadOnlySpan Rects) + { + var len = Data.Payload.LongLength; + if (len >= uint.MaxValue) throw new IndexOutOfRangeException("Payload >= uint32 max are not supported"); + Data.Payload.EnsureCap(len + (uint)Rects.Length); + foreach (var rect in Rects) + { + Data.Payload.Add( + new() + { + Rect = new() + { + Left = rect.Left, + Top = rect.Top, + Right = rect.Right, + Bottom = rect.Bottom, + } + } + ); + } + return (uint)len; + } + + #endregion + + #region ClearColor + + public void ClearColor(IRtv Image, ReadOnlySpan Rects = default) => + ClearColor(Image, new(0, 0, 0, 1), Rects); + + public void ClearColor(IRtv Image, Color Color, ReadOnlySpan Rects = default) + { + AssertNotEnded(); + Image.AssertSameIsolate(Isolate); + if (!Image.TryRtv()) throw new ArgumentException($"Resource {Image} cannot be used as Rtv"); + var cmd = new FCmdClearColor + { + Base = { Type = FCmdType.ClearColor }, + RectCount = (uint)Rects.Length, + RectIndex = Rects.Length <= 0 ? 0 : AddRects(Rects), + Image = AddResource(Image.Resource), + Color = Unsafe.BitCast(Color), + }; + Data.Commands.Add(new() { ClearColor = cmd }); + } + + #endregion } diff --git a/Coplt.Graphics.Core/Core/Views.cs b/Coplt.Graphics.Core/Core/Views.cs index dad0780..cabeaa9 100644 --- a/Coplt.Graphics.Core/Core/Views.cs +++ b/Coplt.Graphics.Core/Core/Views.cs @@ -2,7 +2,7 @@ namespace Coplt.Graphics.Core; -public interface IGpuView : IQueueOwned +public interface IGpuView : IQueueOwned, IIsolateChild { /// /// 视图所属资源 @@ -69,6 +69,7 @@ public interface IGpuResource : IGpuView public ref FResState NativeState { get; } public FResourceMeta GetMeta(); + public FCmdRes IntoCmd(); } public interface ICbv : IGpuView diff --git a/Coplt.Graphics.Core/Core/XChild.cs b/Coplt.Graphics.Core/Core/XChild.cs new file mode 100644 index 0000000..7a28d16 --- /dev/null +++ b/Coplt.Graphics.Core/Core/XChild.cs @@ -0,0 +1,60 @@ +using Coplt.Graphics.Native; + +namespace Coplt.Graphics.Core; + +public interface IDeviceChild +{ + public GpuDevice Device { get; } +} + +public abstract unsafe class DeviceChild : GpuObject, IDeviceChild +{ + #region Props + + public GpuDevice Device { get; } + + #endregion + + #region Ctor + + internal DeviceChild(FGpuObject* ptr, string? name, GpuDevice device) : base(ptr, name) + { + Device = device; + } + + #endregion +} + +public interface IIsolateChild : IDeviceChild +{ + public GpuIsolate Isolate { get; } +} + +public abstract unsafe class IsolateChild : DeviceChild, IIsolateChild +{ + #region Props + + public GpuIsolate Isolate { get; } + + #endregion + + #region Ctor + + internal IsolateChild(FGpuObject* ptr, string? name, GpuIsolate isolate) : base(ptr, name, isolate.Device) + { + Isolate = isolate; + } + + #endregion +} + +public static partial class GraphicsExtensions +{ + public static bool IsSameIsolate(this T obj, GpuIsolate isolate) where T : IIsolateChild => obj.Isolate == isolate; + + public static void AssertSameIsolate(this T obj, GpuIsolate isolate) where T : IIsolateChild + { + if (obj.Isolate != isolate) + throw new InvalidOperationException($"{obj} does not belong to {isolate}."); + } +} diff --git a/Coplt.Graphics.Core/Native/FList.cs b/Coplt.Graphics.Core/Native/FList.cs index 25c7568..ccfaf81 100644 --- a/Coplt.Graphics.Core/Native/FList.cs +++ b/Coplt.Graphics.Core/Native/FList.cs @@ -108,6 +108,26 @@ private void Grow() #endregion + #region EnsureCap + + public void EnsureCap(nuint cap) + { + if ((cap & 1) != 0) cap += 1; + if (m_ptr == null) + { + m_cap = cap; + m_ptr = (T*)m_allocator->MemoryAlloc(m_cap * (nuint)sizeof(T), (nuint)Utils.AlignOf()); + } + else if (m_cap < cap) + { + m_cap = cap; + m_ptr = (T*)m_allocator->MemoryReAlloc(m_ptr, m_cap * (nuint)sizeof(T), (nuint)Utils.AlignOf()); + } + + } + + #endregion + #region Add public ref T UnsafeAdd() diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 8629699..054f9c8 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1541,6 +1541,9 @@ public unsafe partial struct FGpuRecordData [NativeTypeName("Coplt::usize")] public nuint OutputCount; + + [NativeTypeName("Coplt::b8")] + public B8 Ended; } [NativeTypeName("Coplt::u32")] @@ -1619,7 +1622,7 @@ public unsafe partial struct _Anonymous_e__Union public partial struct FCmdResRef { [NativeTypeName("Coplt::u32")] - public uint Index; + public uint IndexPlusOne; } public partial struct FCmdBase @@ -1714,7 +1717,7 @@ public partial struct _Color_e__FixedBuffer public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L115_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L117_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index 3fe4669..594e15a 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -56,10 +56,12 @@ namespace Coplt struct FCmdResRef { - u32 Index{}; + u32 IndexPlusOne{}; #ifdef FFI_SRC - operator bool() const { return Index == 0; } + operator bool() const { return IndexPlusOne == 0; } + + FCmdRes& Get(FList& list) const { return list[IndexPlusOne - 1]; } #endif }; diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index 5bfe183..4bc31d5 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -27,6 +27,7 @@ namespace Coplt FList Blob; // 统计不重复的 Output 数量 usize OutputCount{}; + b8 Ended{}; #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) diff --git a/Coplt.Graphics.Native/Api/Include/Error.h b/Coplt.Graphics.Native/Api/Include/Error.h index 97a9913..d8da7d7 100644 --- a/Coplt.Graphics.Native/Api/Include/Error.h +++ b/Coplt.Graphics.Native/Api/Include/Error.h @@ -308,4 +308,49 @@ namespace Coplt } return r; } + + template F> + void feb(Logger& logger, F f) noexcept + { + CPPTRACE_TRY + { + try + { + f(); + } + catch (FResult& e) + { + logger.Log(FLogLevel::Error, FLogType::Common, e.msg); + e.Drop(); + } + catch (cpptrace::exception& e) + { + logger.Log(FLogLevel::Error, e.what()); + } + catch (Exception& e) + { + const auto& msg = e.what(); + logger.Log(FLogLevel::Error, msg); + } + #ifdef _WINDOWS + catch (WException& e) + { + const auto& msg = e.what(); + logger.LogW(FLogLevel::Error, msg); + } + #endif + } + CPPTRACE_CATCH(std::exception& ex) + { + const auto trace = to_string(cpptrace::from_current_exception()); + const auto msg = fmt::format("{}\r\n{}", ex.what(), trace.c_str()); + logger.Log(FLogLevel::Error, msg); + } + CPPTRACE_CATCH_ALT(...) + { + const auto trace = to_string(cpptrace::from_current_exception()); + const auto msg = fmt::format("Unknown failure occurred. Possible memory corruption\r\n{}", trace.c_str()); + logger.Log(FLogLevel::Error, msg); + } + } } diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index 123b2c0..f983202 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -9,7 +9,7 @@ using namespace Coplt; D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options) : FGpuIsolateData() { - m_waiting_ctx = box(); + m_waiting_record = box(); m_record_pool = box(); m_device = std::move(device); m_main_queue = new D3d12GpuQueue2(this, FGpuQueueType::Direct); @@ -21,22 +21,28 @@ D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCre FGpuQueueCreateResult{m_copy_queue.get(), m_copy_queue.get()}, }; - m_wait_thread = std::jthread([this] + m_event = CreateEventW(nullptr, false, false, nullptr); + if (m_event == nullptr) chr | HRESULT_FROM_WIN32(GetLastError()); + + m_wait_thread = std::thread([this] { while (!m_exited) { m_waiting_signal.acquire(); - Rc records[8]{}; - re: - if (const auto count = m_waiting_ctx->try_dequeue_bulk(records, 8); count > 0) + feb(m_device->m_instance->m_logger, [&] { - for (auto i = 0; i < count; ++i) + Rc records[8]{}; + re: + if (const auto count = m_waiting_record->try_dequeue_bulk(records, 8); count > 0) { - records[i]->Recycle(); - m_record_pool->enqueue(std::move(records[i])); + for (auto i = 0; i < count; ++i) + { + records[i]->WaitAndRecycle(m_event); + m_record_pool->enqueue(std::move(records[i])); + } + goto re; } - goto re; - } + }); } }); } @@ -45,6 +51,8 @@ D3d12GpuIsolate::~D3d12GpuIsolate() { m_exited = true; m_waiting_signal.release(1); + m_wait_thread.join(); + CloseHandle(m_event); } FResult D3d12GpuIsolate::SetName(const FStr8or16& name) noexcept @@ -184,5 +192,39 @@ void D3d12GpuIsolate::Submit(std::span records, std::span records) { + const auto f = [&](const std::span> items) + { + for (u32 i = 0; i < items.size(); ++i) + { + items[i] = records[i]->QueryInterface(); + } + for (u32 i = 0; i < items.size(); ++i) + { + if (items[i] == nullptr) + COPLT_THROW("Record from different backends"); + } + SubmitReturn(items); + }; + if (records.size() < 16) + { + Rc items[records.size()]; + for (u32 i = 0; i < records.size(); ++i) items[i] = {}; + f(std::span(items, records.size())); + } + else + { + std::vector> items(records.size(), {}); + f(std::span(items)); + } +} + +void D3d12GpuIsolate::SubmitReturn(std::span> records) +{ + for (u32 i = 0; i < records.size(); ++i) + { + records[i]->Analyze(); + } // todo + m_waiting_record->enqueue_bulk(records.data(), records.size()); + m_waiting_signal.release(1); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index 3030362..a1e1c7b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -27,10 +27,11 @@ namespace Coplt { using RecordQueue = moodycamel::ConcurrentQueue>; - Box m_waiting_ctx{}; + HANDLE m_event{}; + Box m_waiting_record{}; Box m_record_pool{}; std::binary_semaphore m_waiting_signal{0}; - std::jthread m_wait_thread{}; + std::thread m_wait_thread{}; std::atomic_bool m_exited{false}; std::atomic m_record_inc{0}; @@ -54,5 +55,6 @@ namespace Coplt void ReturnRecords(std::span records); void Submit(std::span records, std::span out); void SubmitReturn(std::span records); + void SubmitReturn(std::span> records); }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.cc b/Coplt.Graphics.Native/D3d12/Src/Queue.cc index 1c99858..7ba7a6a 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.cc @@ -149,6 +149,15 @@ RentedCommandAllocator::~RentedCommandAllocator() m_queue->ReturnCommandAllocator(std::move(m_command_allocator)); } +QueueWaitPoint::QueueWaitPoint(Rc&& queue, const u64 fence_value) : m_queue(std::move(queue)), m_fence_value(fence_value) +{ +} + +void QueueWaitPoint::Wait(const HANDLE event) const +{ + m_queue->WaitFenceValue(m_fence_value, event); +} + D3d12GpuQueue2::D3d12GpuQueue2(const NonNull isolate, const FGpuQueueType type) : FGpuQueueData() { @@ -208,6 +217,11 @@ u64 D3d12GpuQueue2::Signal() return SignalNoLock(); } +QueueWaitPoint D3d12GpuQueue2::SignalWaitPointer() +{ + return QueueWaitPoint(this->CloneThis(), Signal()); +} + u64 D3d12GpuQueue2::SignalNoLock() { const auto fence_value = m_fence_value; diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.h b/Coplt.Graphics.Native/D3d12/Src/Queue.h index 370f630..2a1cb7c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -74,6 +74,7 @@ namespace Coplt } } + struct ID3d12GpuQueue; struct D3d12GpuQueue2; // 必须等待队列 fence 完成才能析构,或者可以 move 走 @@ -88,6 +89,17 @@ namespace Coplt ~RentedCommandAllocator(); }; + struct QueueWaitPoint final + { + Rc m_queue{}; + u64 m_fence_value{}; + + QueueWaitPoint() = default; + explicit QueueWaitPoint(Rc&& queue, u64 fence_value); + + void Wait(HANDLE event) const; + }; + COPLT_INTERFACE_DEFINE(ID3d12GpuQueue, "a60df5da-ecff-4ae4-a38b-6ddef7db5922", FD3d12GpuQueue2) { Rc m_device{}; @@ -97,6 +109,7 @@ namespace Coplt std::mutex m_mutex{}; virtual u64 Signal() = 0; + virtual QueueWaitPoint SignalWaitPointer() = 0; virtual u64 SignalNoLock() = 0; virtual void WaitFenceValue(u64 fence_value, HANDLE event) = 0; @@ -117,6 +130,7 @@ namespace Coplt void* GetRawQueue() noexcept override; u64 Signal() override; + QueueWaitPoint SignalWaitPointer() override; u64 SignalNoLock() override; void WaitFenceValue(u64 fence_value, HANDLE event) override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 75bf449..1332320 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -31,10 +31,21 @@ const FGpuRecordData* D3d12GpuRecord::Data() const noexcept return this; } +void D3d12GpuRecord::WaitAndRecycle(const HANDLE event) +{ + for (auto& wait_point : m_queue_wait_points) + { + wait_point.Wait(event); + } + Recycle(); +} + void D3d12GpuRecord::Recycle() { - ClearData(); + m_queue_wait_points.clear(); m_context->Recycle(); + m_resources_owner.clear(); + ClearData(); } FResult D3d12GpuRecord::End() noexcept @@ -47,14 +58,26 @@ FResult D3d12GpuRecord::End() noexcept void D3d12GpuRecord::EnsureEnd() { - if (m_ended) return; + if (Ended) return; DoEnd(); } void D3d12GpuRecord::DoEnd() { - if (m_ended) + if (Ended) COPLT_THROW("End cannot be called multiple times"); - m_ended = true; + Ended = true; + m_resources_owner.reserve(Resources.size()); + for (usize i = 0; i < Resources.size(); ++i) + { + const auto& res = Resources[i]; + m_resources_owner.push_back(Rc::UnsafeClone(res.GetObjectPtr())); + } + // todo +} + +void D3d12GpuRecord::Analyze() +{ + EnsureEnd(); // todo } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 6b34548..634f638 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -9,15 +9,18 @@ namespace Coplt { COPLT_INTERFACE_DEFINE(ID3d12GpuRecord, "57a9c7f9-1ec0-4d78-89b9-e547667c50b3", FGpuRecord) { - std::vector> m_object_owner{}; - bool m_ended{}; + std::vector> m_resources_owner{}; + std::vector m_queue_wait_points{}; virtual FGpuRecordData* Data() noexcept = 0; virtual const FGpuRecordData* Data() const noexcept = 0; + virtual void WaitAndRecycle(HANDLE event) = 0; virtual void Recycle() = 0; virtual void EnsureEnd() = 0; + + virtual void Analyze() = 0; }; struct D3d12GpuRecord final : GpuObject, FGpuRecordData @@ -34,10 +37,13 @@ namespace Coplt FGpuRecordData* Data() noexcept override; const FGpuRecordData* Data() const noexcept override; + void WaitAndRecycle(HANDLE event) override; void Recycle() override; FResult End() noexcept override; void EnsureEnd() override; void DoEnd(); + + void Analyze() override; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc index 5b233ae..cd6603b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -23,6 +23,9 @@ D3d12GpuSwapChain::D3d12GpuSwapChain( { m_name = options.Name.ToString(); } + + m_event = CreateEventW(nullptr, false, false, nullptr); + if (m_event == nullptr) chr | HRESULT_FROM_WIN32(GetLastError()); } void D3d12GpuSwapChain::Initialize() diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index 7df7fa5..7241ce0 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -76,6 +76,7 @@ public void DoInitGraphics() }; Render(Record, time); + Isolate.Submit(Record); Output.Present(); } catch (Exception e) diff --git a/Examples/HelloTriangle/Example.cs b/Examples/HelloTriangle/Example.cs index 90ac236..8b9140f 100644 --- a/Examples/HelloTriangle/Example.cs +++ b/Examples/HelloTriangle/Example.cs @@ -32,6 +32,7 @@ public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handl // } protected override void Render(GpuRecord cmd, Time time) { + cmd.ClearColor(Output, new Color(0.83f, 0.8f, 0.97f)); // using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); // render.Draw(Pipeline, 3); } From 89dfc805a8ecf34abbb499fbb11116512952d44b Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 20 Mar 2025 17:12:16 +0800 Subject: [PATCH 06/46] save --- Coplt.Graphics.Native/Api/FFI/Cmd.h | 7 +- Coplt.Graphics.Native/Api/FFI/List.h | 19 +++- Coplt.Graphics.Native/Api/FFI/Types.h | 7 ++ Coplt.Graphics.Native/Api/Include/Utils.h | 19 ++++ Coplt.Graphics.Native/D3d12/CMakeLists.txt | 1 + Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 3 +- Coplt.Graphics.Native/D3d12/Src/Record.cc | 122 +++++++++++++++++++-- Coplt.Graphics.Native/D3d12/Src/Record.h | 61 ++++++++++- 8 files changed, 220 insertions(+), 19 deletions(-) diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index 594e15a..d805931 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -61,7 +61,12 @@ namespace Coplt #ifdef FFI_SRC operator bool() const { return IndexPlusOne == 0; } - FCmdRes& Get(FList& list) const { return list[IndexPlusOne - 1]; } + FCmdRes& Get(FList& list) const + { + const auto index = IndexPlusOne - 1; + if (index > list.m_len) COPLT_THROW("Index out of range"); + return list[index]; + } #endif }; diff --git a/Coplt.Graphics.Native/Api/FFI/List.h b/Coplt.Graphics.Native/Api/FFI/List.h index 1785bc2..0991120 100644 --- a/Coplt.Graphics.Native/Api/FFI/List.h +++ b/Coplt.Graphics.Native/Api/FFI/List.h @@ -5,14 +5,15 @@ #if FFI_SRC #include +#include #endif namespace Coplt { template -#ifdef FFI_SRC + #ifdef FFI_SRC requires std::is_trivially_copyable_v -#endif + #endif struct FList COPLT_FINAL { FAllocator* m_allocator{}; @@ -20,7 +21,7 @@ namespace Coplt size_t m_len{}; size_t m_cap{}; -#ifdef FFI_SRC + #ifdef FFI_SRC constexpr static size_t InitCapacity = 4; @@ -135,6 +136,16 @@ namespace Coplt { m_len = 0; } -#endif + + std::span AsSpan() + { + return std::span(data(), size()); + } + + std::span AsSpan() const + { + return std::span(data(), size()); + } + #endif }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Types.h b/Coplt.Graphics.Native/Api/FFI/Types.h index f440899..3528144 100644 --- a/Coplt.Graphics.Native/Api/FFI/Types.h +++ b/Coplt.Graphics.Native/Api/FFI/Types.h @@ -6,6 +6,7 @@ #ifdef FFI_SRC #include +#include #include #include @@ -63,7 +64,12 @@ namespace Coplt using RwLock = std::shared_mutex; using WriteLock = std::unique_lock; using ReadLock = std::shared_lock; + + template + using Ref = std::reference_wrapper; + #else + using f32 = float; using f64 = double; @@ -91,6 +97,7 @@ namespace Coplt using Char8 = u8; using Char16 = u16; + #endif struct Guid diff --git a/Coplt.Graphics.Native/Api/Include/Utils.h b/Coplt.Graphics.Native/Api/Include/Utils.h index fb864e6..41956f1 100644 --- a/Coplt.Graphics.Native/Api/Include/Utils.h +++ b/Coplt.Graphics.Native/Api/Include/Utils.h @@ -52,4 +52,23 @@ namespace Coplt { return (value & 0xFFu) == 0; } + + inline void hash_combine(std::size_t& seed) + { + } + + template + void hash_combine(std::size_t& seed, const T& v) + { + std::hash hasher; + seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + } + + template + size_t hash_multi(const T& v, const Rest&... rest) + { + auto seed = std::hash{}(v); + (hash_combine(seed, rest), ...); + return seed; + } } diff --git a/Coplt.Graphics.Native/D3d12/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index b2febce..31ad918 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -61,6 +61,7 @@ add_library(${target_name} SHARED Src/Record.cc Src/SwapChain.h Src/SwapChain.cc + Include/Access.h ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "Coplt.Graphics.Native.D3d12") diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index f983202..554ecca 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -220,9 +220,10 @@ void D3d12GpuIsolate::SubmitReturn(std::span records) void D3d12GpuIsolate::SubmitReturn(std::span> records) { + std::lock_guard lock(m_mutex); for (u32 i = 0; i < records.size(); ++i) { - records[i]->Analyze(); + records[i]->EnsureEnd(); } // todo m_waiting_record->enqueue_bulk(records.data(), records.size()); diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 1332320..d0d24bd 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -1,8 +1,64 @@ #include "Record.h" using namespace Coplt; +using namespace Recording; -D3d12GpuRecord::D3d12GpuRecord(NonNull isolate) +ResUseType Recording::GetUseType(const D3D12_BARRIER_ACCESS access, const ResUseType UavUse) +{ + if (access & D3D12_BARRIER_ACCESS_NO_ACCESS) return ResUseType::None; + if (access & D3D12_BARRIER_ACCESS_UNORDERED_ACCESS) return UavUse; + if ( + access & D3D12_BARRIER_ACCESS_RENDER_TARGET || access & D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE + || access & D3D12_BARRIER_ACCESS_STREAM_OUTPUT || access & D3D12_BARRIER_ACCESS_COPY_DEST + || access & D3D12_BARRIER_ACCESS_RESOLVE_DEST || access & D3D12_BARRIER_ACCESS_RAYTRACING_ACCELERATION_STRUCTURE_WRITE + || access & D3D12_BARRIER_ACCESS_VIDEO_DECODE_WRITE + || access & D3D12_BARRIER_ACCESS_VIDEO_PROCESS_WRITE + || access & D3D12_BARRIER_ACCESS_VIDEO_ENCODE_WRITE + ) + return ResUseType::Write; + return ResUseType::Read; +} + +ResInfo::ResInfo(Rc&& resource, const u32 res_index) : m_owner(std::move(resource)), m_res_index(res_index) +{ +} + +void ResInfo::MarkUse( + const NonNull self, const u32 index, + const D3D12_BARRIER_ACCESS Access, const D3D12_BARRIER_LAYOUT Layout, + const FShaderStageFlags Stages, const ResUseType UavUse +) +{ + const auto use_type = GetUseType(Access, UavUse); + ResUse use{}; + use.ResIndex = m_res_index; + use.CmdIndex = index; + use.Layout = Layout; + use.Access = Access; + use.Stages = Stages; + use.Type = use_type; + const auto cur = self->m_res_use.size(); + switch (use_type) + { + case ResUseType::None: + case ResUseType::Write: + case ResUseType::ReadWrite: + use.LastUse = m_last_use; + m_last_write_use = cur; + break; + case ResUseType::Read: + use.LastUse = std::max(m_last_read_use_after_write, m_last_write_use); + if (m_last_write_use > m_last_read_use_after_write) + { + m_last_read_use_after_write = cur; + } + break; + } + m_last_use = cur; + self->m_res_use.push_back(use); +} + +D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) : FGpuRecordData(isolate->m_device->m_instance->m_allocator.get()), m_device(isolate->m_device) { m_isolate_id = isolate->m_object_id; @@ -31,6 +87,11 @@ const FGpuRecordData* D3d12GpuRecord::Data() const noexcept return this; } +std::pair, NonNull> D3d12GpuRecord::Get(const FCmdResRef& ref) +{ + return {&ref.Get(Resources), &m_resources[ref.IndexPlusOne - 1]}; +} + void D3d12GpuRecord::WaitAndRecycle(const HANDLE event) { for (auto& wait_point : m_queue_wait_points) @@ -44,8 +105,11 @@ void D3d12GpuRecord::Recycle() { m_queue_wait_points.clear(); m_context->Recycle(); - m_resources_owner.clear(); + m_resources.clear(); + m_res_use.clear(); + m_outputs.clear(); ClearData(); + Ended = false; } FResult D3d12GpuRecord::End() noexcept @@ -66,18 +130,58 @@ void D3d12GpuRecord::DoEnd() { if (Ended) COPLT_THROW("End cannot be called multiple times"); - Ended = true; - m_resources_owner.reserve(Resources.size()); - for (usize i = 0; i < Resources.size(); ++i) + if (Resources.size() >= std::numeric_limits::max()) + COPLT_THROW("Too many resources"); + m_resources.reserve(Resources.size()); + for (u32 i = 0; i < Resources.size(); ++i) { const auto& res = Resources[i]; - m_resources_owner.push_back(Rc::UnsafeClone(res.GetObjectPtr())); + m_resources.push_back( + ResInfo(Rc::UnsafeClone(res.GetObjectPtr()), i) + ); + if (res.Type == FCmdResType::Output) + { + m_outputs.push_back(i); + } } - // todo + Analyze(); + Ended = true; } void D3d12GpuRecord::Analyze() { - EnsureEnd(); - // todo + const auto commands = Commands.AsSpan(); + if (commands.size() >= std::numeric_limits::max()) + COPLT_THROW("Too many commands"); + for (u32 i = 0; i < commands.size(); ++i) + { + const auto& command = commands[i]; + switch (command.Type) + { + case FCmdType::None: + continue; + case FCmdType::Label: + // todo + continue; + case FCmdType::BeginScope: + // todo + continue; + case FCmdType::EndScope: + // todo + continue; + case FCmdType::ClearColor: + Analyze_ClearColor(i, command.ClearColor); + continue; + case FCmdType::ClearDepthStencil: + // todo + continue; + } + COPLT_THROW_FMT("Unknown command type {}", static_cast(command.Type)); + } +} + +void D3d12GpuRecord::Analyze_ClearColor(u32 i, const FCmdClearColor& cmd) +{ + const auto [meta, info] = Get(cmd.Image); + info->MarkUse(this, i, D3D12_BARRIER_ACCESS_RENDER_TARGET, D3D12_BARRIER_LAYOUT_RENDER_TARGET, FShaderStageFlags::None); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 634f638..6fa6ec3 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -7,9 +7,61 @@ namespace Coplt { + struct D3d12GpuRecord; + + namespace Recording + { + enum class ResUseType : u8 + { + None, + Read, + Write, + ReadWrite, + }; + + struct ResUse + { + u32 LastUse{}; + u32 ResIndex{}; + u32 CmdIndex{}; + D3D12_BARRIER_LAYOUT Layout{}; + D3D12_BARRIER_ACCESS Access{}; + FShaderStageFlags Stages{}; + ResUseType Type{}; + }; + + ResUseType GetUseType(D3D12_BARRIER_ACCESS access, ResUseType UavUse = ResUseType::ReadWrite); + + struct ResInfo + { + Rc m_owner{}; + u32 m_res_index{}; + + u32 m_last_use{COPLT_U32_MAX}; + u32 m_last_write_use{COPLT_U32_MAX}; + u32 m_last_read_use_after_write{COPLT_U32_MAX}; + + ResInfo() = default; + + explicit ResInfo(Rc&& resource, u32 res_index); + + void MarkUse( + NonNull self, u32 index, + D3D12_BARRIER_ACCESS Access, D3D12_BARRIER_LAYOUT Layout, + FShaderStageFlags Stages, ResUseType UavUse = ResUseType::ReadWrite + ); + }; + } + COPLT_INTERFACE_DEFINE(ID3d12GpuRecord, "57a9c7f9-1ec0-4d78-89b9-e547667c50b3", FGpuRecord) { - std::vector> m_resources_owner{}; + using ResUseType = Recording::ResUseType; + using ResUse = Recording::ResUse; + using ResInfo = Recording::ResInfo; + + std::vector m_resources{}; + std::vector m_outputs{}; + std::vector m_res_use{}; std::vector m_queue_wait_points{}; virtual FGpuRecordData* Data() noexcept = 0; @@ -19,8 +71,6 @@ namespace Coplt virtual void Recycle() = 0; virtual void EnsureEnd() = 0; - - virtual void Analyze() = 0; }; struct D3d12GpuRecord final : GpuObject, FGpuRecordData @@ -37,6 +87,8 @@ namespace Coplt FGpuRecordData* Data() noexcept override; const FGpuRecordData* Data() const noexcept override; + std::pair, NonNull> Get(const FCmdResRef& ref); + void WaitAndRecycle(HANDLE event) override; void Recycle() override; @@ -44,6 +96,7 @@ namespace Coplt void EnsureEnd() override; void DoEnd(); - void Analyze() override; + void Analyze(); + void Analyze_ClearColor(u32 i, const FCmdClearColor& cmd); }; } From 8ff903658a83d350829359b98e52cf718370647b Mon Sep 17 00:00:00 2001 From: U2A5F Date: Fri, 21 Mar 2025 00:37:06 +0800 Subject: [PATCH 07/46] save --- Coplt.Graphics.Core/Core/GpuIsolate.cs | 2 + Coplt.Graphics.Core/Core/QueueConfig.cs | 14 ++++ Coplt.Graphics.Core/Native/Native.cs | 37 ++++++++-- Coplt.Graphics.Native/Api/FFI/Isolate.h | 14 ++++ Coplt.Graphics.Native/Api/FFI/Queue.h | 4 +- Coplt.Graphics.Native/Api/Include/Utils.h | 9 +++ Coplt.Graphics.Native/D3d12/Include/States.h | 4 +- Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 72 ++++++++++++++++++-- Coplt.Graphics.Native/D3d12/Src/Isolate.h | 11 ++- Coplt.Graphics.Native/D3d12/Src/Queue.h | 9 ++- Coplt.Graphics.Native/D3d12/Src/Record.cc | 57 ++++++++++------ Coplt.Graphics.Native/D3d12/Src/Record.h | 17 ++--- 12 files changed, 202 insertions(+), 48 deletions(-) create mode 100644 Coplt.Graphics.Core/Core/QueueConfig.cs diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 9e217fd..1dc479b 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -1,5 +1,6 @@ using System.Buffers; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using Coplt.Dropping; using Coplt.Graphics.Native; @@ -21,6 +22,7 @@ public sealed unsafe partial class GpuIsolate : DeviceChild internal ref readonly FGpuIsolateData Data => ref *m_data; public ReadOnlySpan Queues => m_queues; public FrameId FrameId => new(Data.FrameId); + public ref readonly QueueConfig QueueConfig => ref Unsafe.As(ref *m_data->QueueConfig); #endregion diff --git a/Coplt.Graphics.Core/Core/QueueConfig.cs b/Coplt.Graphics.Core/Core/QueueConfig.cs new file mode 100644 index 0000000..2998ed3 --- /dev/null +++ b/Coplt.Graphics.Core/Core/QueueConfig.cs @@ -0,0 +1,14 @@ +namespace Coplt.Graphics.Core; + +public record struct QueueConfig +{ + /// + /// 额外的直接队列,默认保证有一个主队列 + /// + public uint NumDirect; + public uint NumCompute; + public uint NumCopy; + public uint NumVideoEncode; + public uint NumVideoDecode; + public uint NumVideoProcess; +} diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 054f9c8..f204044 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1355,16 +1355,43 @@ public unsafe partial struct FGpuRecordCreateResult public FGpuRecordData* Data; } - public partial struct FGpuIsolateCreateOptions + public partial struct FQueueConfig + { + [NativeTypeName("Coplt::u32")] + public uint NumDirect; + + [NativeTypeName("Coplt::u32")] + public uint NumCompute; + + [NativeTypeName("Coplt::u32")] + public uint NumCopy; + + [NativeTypeName("Coplt::u32")] + public uint NumVideoEncode; + + [NativeTypeName("Coplt::u32")] + public uint NumVideoDecode; + + [NativeTypeName("Coplt::u32")] + public uint NumVideoProcess; + } + + public unsafe partial struct FGpuIsolateCreateOptions { [NativeTypeName("Coplt::FStr8or16")] public FStr8or16 Name; + + [NativeTypeName("Coplt::FQueueConfig *")] + public FQueueConfig* QueueConfig; } - public partial struct FGpuIsolateData + public unsafe partial struct FGpuIsolateData { [NativeTypeName("Coplt::u64")] public ulong FrameId; + + [NativeTypeName("Coplt::FQueueConfig *")] + public FQueueConfig* QueueConfig; } [Guid("777C5774-8EB8-4550-A977-62CCCD7BDDA6")] @@ -1717,7 +1744,7 @@ public partial struct _Color_e__FixedBuffer public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L117_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L122_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -2510,7 +2537,9 @@ public enum FGpuQueueType : byte Direct, Compute, Copy, - Video, + VideoEncode, + VideoDecode, + VideoProcess, } [Guid("95E60E28-E387-4055-9B33-2D23AF901F8A")] diff --git a/Coplt.Graphics.Native/Api/FFI/Isolate.h b/Coplt.Graphics.Native/Api/FFI/Isolate.h index a6cb0cc..9304c4f 100644 --- a/Coplt.Graphics.Native/Api/FFI/Isolate.h +++ b/Coplt.Graphics.Native/Api/FFI/Isolate.h @@ -8,15 +8,29 @@ namespace Coplt struct FGpuRecord; struct FGpuRecordCreateResult; + struct FQueueConfig + { + // 额外的直接队列,默认保证有一个主队列 + u32 NumDirect{0}; + u32 NumCompute{1}; + u32 NumCopy{1}; + u32 NumVideoEncode{0}; + u32 NumVideoDecode{0}; + u32 NumVideoProcess{0}; + }; + struct FGpuIsolateCreateOptions { // 可选 FStr8or16 Name{}; + // 可选 + FQueueConfig* QueueConfig{}; }; struct FGpuIsolateData { u64 FrameId{}; + FQueueConfig* QueueConfig{}; }; COPLT_INTERFACE_DEFINE(FGpuIsolate, "777c5774-8eb8-4550-a977-62cccd7bdda6", FGpuObject) diff --git a/Coplt.Graphics.Native/Api/FFI/Queue.h b/Coplt.Graphics.Native/Api/FFI/Queue.h index 72c8793..efb2d42 100644 --- a/Coplt.Graphics.Native/Api/FFI/Queue.h +++ b/Coplt.Graphics.Native/Api/FFI/Queue.h @@ -18,7 +18,9 @@ namespace Coplt Direct, Compute, Copy, - Video, + VideoEncode, + VideoDecode, + VideoProcess, }; COPLT_INTERFACE_DEFINE(FGpuQueue, "95e60e28-e387-4055-9b33-2d23af901f8a", FGpuObject) diff --git a/Coplt.Graphics.Native/Api/Include/Utils.h b/Coplt.Graphics.Native/Api/Include/Utils.h index 41956f1..557bcee 100644 --- a/Coplt.Graphics.Native/Api/Include/Utils.h +++ b/Coplt.Graphics.Native/Api/Include/Utils.h @@ -12,6 +12,15 @@ namespace Coplt return std::make_unique(std::forward(args)...); } + template + using SRc = std::shared_ptr; + + template + SRc src(Args&&... args) + { + return std::make_shared(std::forward(args)...); + } + // move or forward template std::remove_reference_t&& fove(T&& a) diff --git a/Coplt.Graphics.Native/D3d12/Include/States.h b/Coplt.Graphics.Native/D3d12/Include/States.h index 2f3b210..c68cf97 100644 --- a/Coplt.Graphics.Native/D3d12/Include/States.h +++ b/Coplt.Graphics.Native/D3d12/Include/States.h @@ -122,7 +122,9 @@ namespace Coplt break; case FGpuQueueType::Copy: break; - case FGpuQueueType::Video: + case FGpuQueueType::VideoEncode: + case FGpuQueueType::VideoDecode: + case FGpuQueueType::VideoProcess: switch (value) { case FResLayout::Common: diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index 554ecca..4f8d425 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -9,17 +9,75 @@ using namespace Coplt; D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options) : FGpuIsolateData() { + m_queue_config = std::make_shared(options.QueueConfig == nullptr ? FQueueConfig() : *options.QueueConfig); + this->QueueConfig = m_queue_config.get(); m_waiting_record = box(); m_record_pool = box(); m_device = std::move(device); + + #pragma region Create Queues + m_main_queue = new D3d12GpuQueue2(this, FGpuQueueType::Direct); - m_back_queue = new D3d12GpuQueue2(this, FGpuQueueType::Compute); - m_copy_queue = new D3d12GpuQueue2(this, FGpuQueueType::Copy); - m_queues = { - FGpuQueueCreateResult{m_main_queue.get(), m_main_queue.get()}, - FGpuQueueCreateResult{m_back_queue.get(), m_back_queue.get()}, - FGpuQueueCreateResult{m_copy_queue.get(), m_copy_queue.get()}, - }; + + m_direct_queues.reserve(m_queue_config->NumDirect); + for (u32 i = 0; i < m_queue_config->NumDirect; i++) + { + m_direct_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::Direct)); + } + m_compute_queues.reserve(m_queue_config->NumCompute); + for (u32 i = 0; i < m_queue_config->NumCompute; i++) + { + m_compute_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::Compute)); + } + m_copy_queues.reserve(m_queue_config->NumCopy); + for (u32 i = 0; i < m_queue_config->NumCopy; i++) + { + m_copy_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::Copy)); + } + m_video_encode_queues.reserve(m_queue_config->NumVideoEncode); + for (u32 i = 0; i < m_queue_config->NumVideoEncode; i++) + { + m_video_encode_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::VideoEncode)); + } + m_video_decode_queues.reserve(m_queue_config->NumVideoDecode); + for (u32 i = 0; i < m_queue_config->NumVideoDecode; i++) + { + m_video_decode_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::VideoDecode)); + } + m_video_process_queues.reserve(m_queue_config->NumVideoProcess); + for (u32 i = 0; i < m_queue_config->NumVideoProcess; i++) + { + m_video_process_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::VideoProcess)); + } + m_queues.reserve(1 + m_queue_config->NumDirect + m_queue_config->NumCompute + m_queue_config->NumCopy + + m_queue_config->NumVideoEncode + m_queue_config->NumVideoDecode + m_queue_config->NumVideoProcess); + m_queues.push_back(FGpuQueueCreateResult{m_main_queue.get(), m_main_queue.get()}); + for (auto& queue : m_direct_queues) + { + m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); + } + for (auto& queue : m_compute_queues) + { + m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); + } + for (auto& queue : m_copy_queues) + { + m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); + } + for (auto& queue : m_video_encode_queues) + { + m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); + } + for (auto& queue : m_video_decode_queues) + { + m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); + } + for (auto& queue : m_video_process_queues) + { + m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); + } + + #pragma endregion m_event = CreateEventW(nullptr, false, false, nullptr); if (m_event == nullptr) chr | HRESULT_FROM_WIN32(GetLastError()); diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index a1e1c7b..d3b3d13 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -13,11 +13,16 @@ namespace Coplt { COPLT_INTERFACE_DEFINE(ID3d12GpuIsolate, "1c507c7f-140a-4717-809e-88096b475fea", FGpuIsolate) { + SRc m_queue_config{}; Rc m_device{}; Rc m_main_queue{}; - Rc m_back_queue{}; - Rc m_copy_queue{}; - std::array m_queues{}; + std::vector> m_direct_queues{}; + std::vector> m_compute_queues{}; + std::vector> m_copy_queues{}; + std::vector> m_video_encode_queues{}; + std::vector> m_video_decode_queues{}; + std::vector> m_video_process_queues{}; + std::vector m_queues{}; std::mutex m_mutex{}; }; diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.h b/Coplt.Graphics.Native/D3d12/Src/Queue.h index 2a1cb7c..3e2dac8 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -69,9 +69,14 @@ namespace Coplt return D3D12_COMMAND_LIST_TYPE_COMPUTE; case FGpuQueueType::Copy: return D3D12_COMMAND_LIST_TYPE_COPY; - default: - return D3D12_COMMAND_LIST_TYPE_DIRECT; + case FGpuQueueType::VideoEncode: + return D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE; + case FGpuQueueType::VideoDecode: + return D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE; + case FGpuQueueType::VideoProcess: + return D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS; } + return D3D12_COMMAND_LIST_TYPE_DIRECT; } struct ID3d12GpuQueue; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index d0d24bd..67b090f 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -3,6 +3,17 @@ using namespace Coplt; using namespace Recording; +bool ResUse::IsReadCompatible(const D3D12_BARRIER_LAYOUT Layout) const +{ + return Type == ResUseType::Read && this->Layout == Layout; +} + +void ResUse::MergeRead(const D3D12_BARRIER_ACCESS Access, const FShaderStageFlags Stages) +{ + this->Access |= Access; + this->Stages |= Stages; +} + ResUseType Recording::GetUseType(const D3D12_BARRIER_ACCESS access, const ResUseType UavUse) { if (access & D3D12_BARRIER_ACCESS_NO_ACCESS) return ResUseType::None; @@ -23,44 +34,46 @@ ResInfo::ResInfo(Rc&& resource, const u32 res_index) : m_owner(std::mo { } -void ResInfo::MarkUse( - const NonNull self, const u32 index, - const D3D12_BARRIER_ACCESS Access, const D3D12_BARRIER_LAYOUT Layout, +u32 ResInfo::MarkUse( + const NonNull self, const D3D12_BARRIER_ACCESS Access, const D3D12_BARRIER_LAYOUT Layout, const FShaderStageFlags Stages, const ResUseType UavUse ) { const auto use_type = GetUseType(Access, UavUse); - ResUse use{}; - use.ResIndex = m_res_index; - use.CmdIndex = index; - use.Layout = Layout; - use.Access = Access; - use.Stages = Stages; - use.Type = use_type; - const auto cur = self->m_res_use.size(); switch (use_type) { case ResUseType::None: case ResUseType::Write: case ResUseType::ReadWrite: - use.LastUse = m_last_use; - m_last_write_use = cur; - break; + goto Add; case ResUseType::Read: - use.LastUse = std::max(m_last_read_use_after_write, m_last_write_use); - if (m_last_write_use > m_last_read_use_after_write) - { - m_last_read_use_after_write = cur; - } - break; + if (m_last_unique_use == COPLT_U32_MAX) goto Add; + goto TryMerge; } - m_last_use = cur; + COPLT_THROW_FMT("Unknown ResUseType {}", static_cast(use_type)); +Add: + ResUse use{}; + use.FromUse = m_last_unique_use; + use.ResIndex = m_res_index; + use.Layout = Layout; + use.Access = Access; + use.Stages = Stages; + use.Type = use_type; + const auto cur = self->m_res_use.size(); + m_last_unique_use = cur; self->m_res_use.push_back(use); + return cur; +TryMerge: + auto& last = self->m_res_use[m_last_unique_use]; + if (!last.IsReadCompatible(Layout)) goto Add; + last.MergeRead(Access, Stages); + return m_last_unique_use; } D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) : FGpuRecordData(isolate->m_device->m_instance->m_allocator.get()), m_device(isolate->m_device) { + m_queue_config = isolate->m_queue_config; m_isolate_id = isolate->m_object_id; m_record_id = isolate->m_record_inc++; m_context = new D3d12RecordContext(isolate); @@ -183,5 +196,5 @@ void D3d12GpuRecord::Analyze() void D3d12GpuRecord::Analyze_ClearColor(u32 i, const FCmdClearColor& cmd) { const auto [meta, info] = Get(cmd.Image); - info->MarkUse(this, i, D3D12_BARRIER_ACCESS_RENDER_TARGET, D3D12_BARRIER_LAYOUT_RENDER_TARGET, FShaderStageFlags::None); + const auto use = info->MarkUse(this, D3D12_BARRIER_ACCESS_RENDER_TARGET, D3D12_BARRIER_LAYOUT_RENDER_TARGET, FShaderStageFlags::None); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 6fa6ec3..f2e708e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -21,13 +21,16 @@ namespace Coplt struct ResUse { - u32 LastUse{}; + // u32::max 表示没有来源 + u32 FromUse{}; u32 ResIndex{}; - u32 CmdIndex{}; D3D12_BARRIER_LAYOUT Layout{}; D3D12_BARRIER_ACCESS Access{}; FShaderStageFlags Stages{}; ResUseType Type{}; + + bool IsReadCompatible(D3D12_BARRIER_LAYOUT Layout) const; + void MergeRead(D3D12_BARRIER_ACCESS Access, FShaderStageFlags Stages); }; ResUseType GetUseType(D3D12_BARRIER_ACCESS access, ResUseType UavUse = ResUseType::ReadWrite); @@ -37,17 +40,14 @@ namespace Coplt Rc m_owner{}; u32 m_res_index{}; - u32 m_last_use{COPLT_U32_MAX}; - u32 m_last_write_use{COPLT_U32_MAX}; - u32 m_last_read_use_after_write{COPLT_U32_MAX}; + u32 m_last_unique_use{COPLT_U32_MAX}; ResInfo() = default; explicit ResInfo(Rc&& resource, u32 res_index); - void MarkUse( - NonNull self, u32 index, - D3D12_BARRIER_ACCESS Access, D3D12_BARRIER_LAYOUT Layout, + u32 MarkUse( + NonNull self, D3D12_BARRIER_ACCESS Access, D3D12_BARRIER_LAYOUT Layout, FShaderStageFlags Stages, ResUseType UavUse = ResUseType::ReadWrite ); }; @@ -59,6 +59,7 @@ namespace Coplt using ResUse = Recording::ResUse; using ResInfo = Recording::ResInfo; + SRc m_queue_config{}; std::vector m_resources{}; std::vector m_outputs{}; std::vector m_res_use{}; From ce199d3c743238ad0595434210015ab9605c8a80 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Fri, 21 Mar 2025 17:38:57 +0800 Subject: [PATCH 08/46] save --- Coplt.Graphics.Core/Core/GpuRecord.cs | 18 +- Coplt.Graphics.Core/Native/Native.cs | 71 +++- Coplt.Graphics.Native/Api/FFI/Cmd.h | 36 +- Coplt.Graphics.Native/Api/FFI/Command.h | 7 - Coplt.Graphics.Native/Api/FFI/Record.h | 8 +- Coplt.Graphics.Native/Api/FFI/Structs.h | 7 + Coplt.Graphics.Native/D3d12/Include/States.h | 4 +- Coplt.Graphics.Native/D3d12/Src/Buffer.cc | 5 + Coplt.Graphics.Native/D3d12/Src/Buffer.h | 2 + Coplt.Graphics.Native/D3d12/Src/Command.cc | 2 +- Coplt.Graphics.Native/D3d12/Src/Image.cc | 4 +- Coplt.Graphics.Native/D3d12/Src/Image.h | 4 +- Coplt.Graphics.Native/D3d12/Src/Output.h | 9 + Coplt.Graphics.Native/D3d12/Src/Record.cc | 398 +++++++++++++++---- Coplt.Graphics.Native/D3d12/Src/Record.h | 159 ++++++-- Coplt.Graphics.Native/D3d12/Src/SwapChain.cc | 36 +- Coplt.Graphics.Native/D3d12/Src/SwapChain.h | 10 +- Examples/HelloTriangle/Example.cs | 44 +- 18 files changed, 645 insertions(+), 179 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index ee6995f..fa1d1e8 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -95,21 +95,19 @@ internal FCmdResRef AddResource(IGpuResource resource) internal uint AddRects(ReadOnlySpan Rects) { - var len = Data.Payload.LongLength; + var len = Data.PayloadRect.LongLength; if (len >= uint.MaxValue) throw new IndexOutOfRangeException("Payload >= uint32 max are not supported"); - Data.Payload.EnsureCap(len + (uint)Rects.Length); + Data.PayloadRect.EnsureCap(len + (uint)Rects.Length); foreach (var rect in Rects) { - Data.Payload.Add( + // todo add range + Data.PayloadRect.Add( new() { - Rect = new() - { - Left = rect.Left, - Top = rect.Top, - Right = rect.Right, - Bottom = rect.Bottom, - } + Left = rect.Left, + Top = rect.Top, + Right = rect.Right, + Bottom = rect.Bottom, } ); } diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index f204044..4d31d2a 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -54,6 +54,14 @@ public partial struct FOrRectViewport public FViewport Viewport; } + [NativeTypeName("Coplt::u8")] + public enum FDepthStencilClearFlags : byte + { + None = 0, + Depth = 1, + Stencil = 2, + } + public unsafe partial struct FObject : FObject.Interface { public void** lpVtbl; @@ -1561,7 +1569,9 @@ public unsafe partial struct FGpuRecordData public FList Resources; - public FList Payload; + public FList PayloadRect; + + public FList PayloadViewport; [NativeTypeName("FList")] public FList Blob; @@ -1584,7 +1594,8 @@ public enum FCmdType : uint ClearDepthStencil, } - public enum FCmdResType + [NativeTypeName("Coplt::u8")] + public enum FCmdResType : byte { Image, Buffer, @@ -1593,7 +1604,7 @@ public enum FCmdResType public unsafe partial struct FCmdRes { - [NativeTypeName("__AnonymousRecord_Cmd_L31_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L47_C9")] public _Anonymous_e__Union Anonymous; [NativeTypeName("Coplt::FCmdResType")] @@ -1742,9 +1753,33 @@ public partial struct _Color_e__FixedBuffer } } + [NativeTypeName("struct FCmdClearDepthStencil : Coplt::FCmdBase")] + public partial struct FCmdClearDepthStencil + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint RectCount; + + [NativeTypeName("Coplt::u32")] + public uint RectIndex; + + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Image; + + [NativeTypeName("Coplt::f32")] + public float Depth; + + [NativeTypeName("Coplt::u8")] + public byte Stencil; + + [NativeTypeName("Coplt::FDepthStencilClearFlags")] + public FDepthStencilClearFlags Clear; + } + public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L122_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L151_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -1797,6 +1832,16 @@ public ref FCmdClearColor ClearColor } } + [UnscopedRef] + public ref FCmdClearDepthStencil ClearDepthStencil + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.ClearDepthStencil; + } + } + [UnscopedRef] public Span _pad { @@ -1830,6 +1875,10 @@ public partial struct _Anonymous_e__Union [NativeTypeName("Coplt::FCmdClearColor")] public FCmdClearColor ClearColor; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdClearDepthStencil")] + public FCmdClearDepthStencil ClearDepthStencil; + [FieldOffset(0)] [NativeTypeName("u8[32]")] public __pad_e__FixedBuffer _pad; @@ -4583,14 +4632,6 @@ public partial struct _Anonymous_e__Union } } - [NativeTypeName("Coplt::u8")] - public enum FDepthStencilClearFlags : byte - { - None = 0, - Depth = 1, - Stencil = 2, - } - public partial struct FUploadLoc { [NativeTypeName("Coplt::u32")] @@ -5191,7 +5232,7 @@ public partial struct FCommandSyncBinding public partial struct FCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L510_C9")] + [NativeTypeName("__AnonymousRecord_Command_L503_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -5417,7 +5458,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FRenderCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L541_C9")] + [NativeTypeName("__AnonymousRecord_Command_L534_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -5601,7 +5642,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FComputeCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L566_C9")] + [NativeTypeName("__AnonymousRecord_Command_L559_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index d805931..ce86052 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -19,13 +19,29 @@ namespace Coplt //////////////////////////////////////////////////////////////////////////////////////////////////// - enum class FCmdResType + enum class FCmdResType : u8 { Image, Buffer, Output, }; + #ifdef FFI_SRC + inline bool IsBuffer(const FCmdResType Type) + { + switch (Type) + { + case FCmdResType::Image: + return false; + case FCmdResType::Buffer: + return true; + case FCmdResType::Output: + return false; + } + return false; + } + #endif + struct FCmdRes { union @@ -64,7 +80,8 @@ namespace Coplt FCmdRes& Get(FList& list) const { const auto index = IndexPlusOne - 1; - if (index > list.m_len) COPLT_THROW("Index out of range"); + if (index > list.m_len) + COPLT_THROW("Index out of range"); return list[index]; } #endif @@ -109,12 +126,24 @@ namespace Coplt { // 有多少个 Rect u32 RectCount{}; - // Payload 中的 Index, 类型为 Rect + // Payload 中的索引, 类型为 FRect u32 RectIndex{}; FCmdResRef Image{}; f32 Color[4]{}; }; + struct FCmdClearDepthStencil : FCmdBase + { + // 有多少个 Rect + u32 RectCount{}; + // Payload 内的索引, 类型为 FRect + u32 RectIndex{}; + FCmdResRef Image{}; + f32 Depth{}; + u8 Stencil{}; + FDepthStencilClearFlags Clear{}; + }; + //////////////////////////////////////////////////////////////////////////////////////////////////// struct FCmdItem @@ -128,6 +157,7 @@ namespace Coplt FCmdEndScope EndScope; FCmdClearColor ClearColor; + FCmdClearDepthStencil ClearDepthStencil; u8 _pad[32]; }; diff --git a/Coplt.Graphics.Native/Api/FFI/Command.h b/Coplt.Graphics.Native/Api/FFI/Command.h index 844cf9f..be51707 100644 --- a/Coplt.Graphics.Native/Api/FFI/Command.h +++ b/Coplt.Graphics.Native/Api/FFI/Command.h @@ -175,13 +175,6 @@ namespace Coplt }; }; - COPLT_ENUM_FLAGS(FDepthStencilClearFlags, u8) - { - None = 0, - Depth = 1, - Stencil = 2, - }; - struct FUploadLoc { u32 Index{}; diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index 4bc31d5..8c6c81c 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -23,7 +23,8 @@ namespace Coplt FList Commands; // 需要保证不重复,c# 部分需要使用 HashMap 去重 FList Resources; - FList Payload; + FList PayloadRect; + FList PayloadViewport; FList Blob; // 统计不重复的 Output 数量 usize OutputCount{}; @@ -31,7 +32,7 @@ namespace Coplt #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) - : Commands(allocator), Resources(allocator), Payload(allocator), Blob(allocator) + : Commands(allocator), Resources(allocator), PayloadRect(allocator), PayloadViewport(allocator), Blob(allocator) { } @@ -39,7 +40,8 @@ namespace Coplt { Commands.Clear(); Resources.Clear(); - Payload.Clear(); + PayloadRect.Clear(); + PayloadViewport.Clear(); Blob.Clear(); OutputCount = 0; } diff --git a/Coplt.Graphics.Native/Api/FFI/Structs.h b/Coplt.Graphics.Native/Api/FFI/Structs.h index c379280..f06fbfe 100644 --- a/Coplt.Graphics.Native/Api/FFI/Structs.h +++ b/Coplt.Graphics.Native/Api/FFI/Structs.h @@ -27,4 +27,11 @@ namespace Coplt FRect Rect; FViewport Viewport; }; + + COPLT_ENUM_FLAGS(FDepthStencilClearFlags, u8) + { + None = 0, + Depth = 1, + Stencil = 2, + }; } diff --git a/Coplt.Graphics.Native/D3d12/Include/States.h b/Coplt.Graphics.Native/D3d12/Include/States.h index c68cf97..e2cefbe 100644 --- a/Coplt.Graphics.Native/D3d12/Include/States.h +++ b/Coplt.Graphics.Native/D3d12/Include/States.h @@ -299,7 +299,7 @@ namespace Coplt return r; } - template F> + template F> inline D3D12_RENDER_PASS_BEGINNING_ACCESS ToDx(const FLoadOp load, F SetClearValue) { D3D12_RENDER_PASS_BEGINNING_ACCESS acc{}; @@ -322,7 +322,7 @@ namespace Coplt return acc; } - template F> + template F> D3D12_RENDER_PASS_ENDING_ACCESS ToDx(const FStoreOp store, F SetResolve) { D3D12_RENDER_PASS_ENDING_ACCESS acc{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Buffer.cc b/Coplt.Graphics.Native/D3d12/Src/Buffer.cc index ac037cb..28f8edf 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Buffer.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Buffer.cc @@ -75,6 +75,11 @@ FGpuBufferData* D3d12GpuBuffer::GpuBufferData() noexcept return this; } +NonNull D3d12GpuBuffer::Data() +{ + return this; +} + void* D3d12GpuBuffer::GetRawResourcePtr() noexcept { return GetResourcePtr(); diff --git a/Coplt.Graphics.Native/D3d12/Src/Buffer.h b/Coplt.Graphics.Native/D3d12/Src/Buffer.h index c2bfc29..0a049f1 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Buffer.h +++ b/Coplt.Graphics.Native/D3d12/Src/Buffer.h @@ -14,6 +14,7 @@ namespace Coplt { COPLT_INTERFACE_DEFINE(ID3d12GpuBuffer, "6edf3bc5-dfc7-461a-ab6b-0e5f5a9d71e7", FD3d12GpuBuffer) { + virtual NonNull Data() = 0; virtual NonNull GetResourcePtr() = 0; }; @@ -33,6 +34,7 @@ namespace Coplt FGpuViewableData* GpuViewableData() noexcept override; FGpuResourceData* GpuResourceData() noexcept override; FGpuBufferData* GpuBufferData() noexcept override; + NonNull Data() override; void* GetRawResourcePtr() noexcept override; NonNull GetResourcePtr() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Command.cc b/Coplt.Graphics.Native/D3d12/Src/Command.cc index 6133207..5fb7889 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Command.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Command.cc @@ -565,7 +565,7 @@ void D3d12CommandInterpreter::BufferImageCopy(const FCommandSubmit& submit, u32 if (image_obj_may == nullptr) COPLT_THROW_FMT("Image is null or resource is not image at command {}", i); const NonNull image_obj = image_obj_may; - const auto image_data = image_obj->GetDataPtr(); + const auto image_data = image_obj->Data(); const auto IsDsOrYCbCr = IsDepthStencil(image_data->m_format) || IsYCbCr(image_data->m_format); auto bytes_per_row = range.BytesPerRow; auto rows_per_image = range.RowsPerImage; diff --git a/Coplt.Graphics.Native/D3d12/Src/Image.cc b/Coplt.Graphics.Native/D3d12/Src/Image.cc index 195197b..95bfe92 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Image.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Image.cc @@ -123,9 +123,9 @@ FGpuImageData* D3d12GpuImage::GpuImageData() noexcept return this; } -NonNull D3d12GpuImage::GetDataPtr() noexcept +NonNull D3d12GpuImage::Data() { - return NonNull::Unchecked(this); + return this; } void* D3d12GpuImage::GetRawResourcePtr() noexcept diff --git a/Coplt.Graphics.Native/D3d12/Src/Image.h b/Coplt.Graphics.Native/D3d12/Src/Image.h index 9d0867e..50b7fd4 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Image.h +++ b/Coplt.Graphics.Native/D3d12/Src/Image.h @@ -15,8 +15,8 @@ namespace Coplt { COPLT_INTERFACE_DEFINE(ID3d12GpuImage, "12748625-44ab-48e0-a40f-9b1d5685ce88", FD3d12GpuImage) { + virtual NonNull Data() = 0; virtual NonNull GetResourcePtr() = 0; - virtual NonNull GetDataPtr() noexcept = 0; }; struct D3d12GpuImage final : GpuObject, FGpuImageData @@ -34,7 +34,7 @@ namespace Coplt FGpuViewableData* GpuViewableData() noexcept override; FGpuResourceData* GpuResourceData() noexcept override; FGpuImageData* GpuImageData() noexcept override; - NonNull GetDataPtr() noexcept override; + NonNull Data() override; void* GetRawResourcePtr() noexcept override; NonNull GetResourcePtr() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Output.h b/Coplt.Graphics.Native/D3d12/Src/Output.h index 9f7ad91..52feee4 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Output.h +++ b/Coplt.Graphics.Native/D3d12/Src/Output.h @@ -2,6 +2,7 @@ #include #include +#include #include "Context.h" #include "Executor.h" @@ -84,4 +85,12 @@ namespace Coplt FResult GetCurrentResourcePtr(void* out) const noexcept override; FResult GetCurrentRtv(void* out) noexcept override; }; + + COPLT_INTERFACE_DEFINE(ID3d12GpuOutput2, "59aa68d8-91bd-4032-ba51-6a05795945b6", FGpuOutput2) + { + virtual NonNull Data() = 0; + virtual NonNull ImageData() = 0; + virtual NonNull GetResourcePtr() = 0; + virtual CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv() = 0; + }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 67b090f..d06d3b2 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -1,19 +1,10 @@ #include "Record.h" +#include "Output.h" + using namespace Coplt; using namespace Recording; -bool ResUse::IsReadCompatible(const D3D12_BARRIER_LAYOUT Layout) const -{ - return Type == ResUseType::Read && this->Layout == Layout; -} - -void ResUse::MergeRead(const D3D12_BARRIER_ACCESS Access, const FShaderStageFlags Stages) -{ - this->Access |= Access; - this->Stages |= Stages; -} - ResUseType Recording::GetUseType(const D3D12_BARRIER_ACCESS access, const ResUseType UavUse) { if (access & D3D12_BARRIER_ACCESS_NO_ACCESS) return ResUseType::None; @@ -30,52 +21,12 @@ ResUseType Recording::GetUseType(const D3D12_BARRIER_ACCESS access, const ResUse return ResUseType::Read; } -ResInfo::ResInfo(Rc&& resource, const u32 res_index) : m_owner(std::move(resource)), m_res_index(res_index) -{ -} - -u32 ResInfo::MarkUse( - const NonNull self, const D3D12_BARRIER_ACCESS Access, const D3D12_BARRIER_LAYOUT Layout, - const FShaderStageFlags Stages, const ResUseType UavUse -) -{ - const auto use_type = GetUseType(Access, UavUse); - switch (use_type) - { - case ResUseType::None: - case ResUseType::Write: - case ResUseType::ReadWrite: - goto Add; - case ResUseType::Read: - if (m_last_unique_use == COPLT_U32_MAX) goto Add; - goto TryMerge; - } - COPLT_THROW_FMT("Unknown ResUseType {}", static_cast(use_type)); -Add: - ResUse use{}; - use.FromUse = m_last_unique_use; - use.ResIndex = m_res_index; - use.Layout = Layout; - use.Access = Access; - use.Stages = Stages; - use.Type = use_type; - const auto cur = self->m_res_use.size(); - m_last_unique_use = cur; - self->m_res_use.push_back(use); - return cur; -TryMerge: - auto& last = self->m_res_use[m_last_unique_use]; - if (!last.IsReadCompatible(Layout)) goto Add; - last.MergeRead(Access, Stages); - return m_last_unique_use; -} - D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) : FGpuRecordData(isolate->m_device->m_instance->m_allocator.get()), m_device(isolate->m_device) { - m_queue_config = isolate->m_queue_config; m_isolate_id = isolate->m_object_id; m_record_id = isolate->m_record_inc++; + m_barrier_analyzer = new D3d12BarrierAnalyzer(); m_context = new D3d12RecordContext(isolate); Context = m_context.get(); } @@ -100,11 +51,6 @@ const FGpuRecordData* D3d12GpuRecord::Data() const noexcept return this; } -std::pair, NonNull> D3d12GpuRecord::Get(const FCmdResRef& ref) -{ - return {&ref.Get(Resources), &m_resources[ref.IndexPlusOne - 1]}; -} - void D3d12GpuRecord::WaitAndRecycle(const HANDLE event) { for (auto& wait_point : m_queue_wait_points) @@ -118,9 +64,7 @@ void D3d12GpuRecord::Recycle() { m_queue_wait_points.clear(); m_context->Recycle(); - m_resources.clear(); - m_res_use.clear(); - m_outputs.clear(); + m_resources_owner.clear(); ClearData(); Ended = false; } @@ -145,29 +89,32 @@ void D3d12GpuRecord::DoEnd() COPLT_THROW("End cannot be called multiple times"); if (Resources.size() >= std::numeric_limits::max()) COPLT_THROW("Too many resources"); - m_resources.reserve(Resources.size()); + m_resources_owner.reserve(Resources.size()); for (u32 i = 0; i < Resources.size(); ++i) { const auto& res = Resources[i]; - m_resources.push_back( - ResInfo(Rc::UnsafeClone(res.GetObjectPtr()), i) - ); - if (res.Type == FCmdResType::Output) - { - m_outputs.push_back(i); - } + m_resources_owner.push_back(Rc::UnsafeClone(res.GetObjectPtr())); } Analyze(); Ended = true; } +FCmdRes& D3d12GpuRecord::GetRes(const FCmdResRef& ref) +{ + return ref.Get(Resources); +} + void D3d12GpuRecord::Analyze() +{ + m_barrier_analyzer->Analyzer(NonNull::Unchecked(this)); +} + +void D3d12GpuRecord::Interpret(const CmdListPack& clp, const u32 cmd_index, const u32 cmd_count) { const auto commands = Commands.AsSpan(); - if (commands.size() >= std::numeric_limits::max()) - COPLT_THROW("Too many commands"); - for (u32 i = 0; i < commands.size(); ++i) + for (u32 n = 0; n < cmd_count; ++n) { + const auto i = cmd_index + n; const auto& command = commands[i]; switch (command.Type) { @@ -183,18 +130,317 @@ void D3d12GpuRecord::Analyze() // todo continue; case FCmdType::ClearColor: - Analyze_ClearColor(i, command.ClearColor); + Interpret_ClearColor(clp, i, command.ClearColor); continue; case FCmdType::ClearDepthStencil: - // todo + Interpret_ClearDepthStencil(clp, i, command.ClearDepthStencil); continue; } + } +} + +void D3d12GpuRecord::Interpret_ClearColor(const CmdListPack& clp, u32 i, const FCmdClearColor& cmd) +{ + const auto rtv = GetRtv(GetRes(cmd.Image)); + clp->ClearRenderTargetView( + rtv, cmd.Color, cmd.RectCount, + cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) + ); +} + +void D3d12GpuRecord::Interpret_ClearDepthStencil(const CmdListPack& clp, u32 i, const FCmdClearDepthStencil& cmd) +{ + const auto dsv = GetDsv(GetRes(cmd.Image)); + D3D12_CLEAR_FLAGS flags{}; + if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Depth)) flags |= D3D12_CLEAR_FLAG_DEPTH; + if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Stencil)) flags |= D3D12_CLEAR_FLAG_STENCIL; + clp->ClearDepthStencilView( + dsv, flags, cmd.Depth, cmd.Stencil, cmd.RectCount, + cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) + ); +} + +D3d12BarrierAnalyzer::ResInfo::ResInfo(const FCmdResType ResType) : ResInfo() +{ + this->ResType = ResType; +} + +bool D3d12BarrierAnalyzer::ResInfo::IsReadCompatible(const D3D12_BARRIER_LAYOUT Layout) const +{ + return Type == ResUseType::Read && this->Layout == Layout; +} + +bool D3d12BarrierAnalyzer::ResInfo::MergeRead(const D3D12_BARRIER_ACCESS Access, const D3D12_BARRIER_SYNC Sync) +{ + const auto old_access = Access; + const auto old_sync = Sync; + this->Access |= Access; + this->Sync |= Sync; + return this->Access != old_access || this->Sync != old_sync; +} + +D3d12BarrierAnalyzer::D3d12BarrierAnalyzer() : m_record(NonNull::Unchecked(nullptr)) +{ +} + +void D3d12BarrierAnalyzer::Recycle() +{ + m_res_inputs.clear(); + m_res_outputs.clear(); + m_resources.clear(); + m_parts.clear(); + m_begin_global_barriers.clear(); + m_begin_texture_barriers.clear(); + m_begin_buffer_barriers.clear(); + m_end_global_barriers.clear(); + m_end_texture_barriers.clear(); + m_end_buffer_barriers.clear(); + m_current_barrier_begin_part = 0; + m_current_cmd_part = 0; +} + +void D3d12BarrierAnalyzer::Analyzer(const NonNull record) +{ + Recycle(); + m_record = record; + m_resources.reserve(m_record->Resources.size()); + for (u32 i = 0; i < m_record->Resources.size(); ++i) + { + const auto& res = m_record->Resources[i]; + m_resources.push_back(ResInfo(res.Type)); + } + m_parts.push_back(Part{.Barrier = {.Type = PartType::BarrierBegin}}); + m_parts.push_back(Part{.Cmd = {}}); + m_current_barrier_begin_part = 0; + m_current_cmd_part = 1; + const auto commands = m_record->Commands.AsSpan(); + if (commands.size() >= std::numeric_limits::max()) + COPLT_THROW("Too many commands"); + for (u32 i = 0; i < commands.size(); ++i) + { + const auto& command = commands[i]; + switch (command.Type) + { + case FCmdType::None: + case FCmdType::Label: + case FCmdType::BeginScope: + case FCmdType::EndScope: + goto CmdNext; + case FCmdType::ClearColor: + Analyze_ClearColor(i, command.ClearColor); + goto CmdNext; + case FCmdType::ClearDepthStencil: + Analyze_ClearDepthStencil(i, command.ClearDepthStencil); + goto CmdNext; + } COPLT_THROW_FMT("Unknown command type {}", static_cast(command.Type)); + CmdNext: + CmdNext(); + continue; } + BuildInputOutput(); } -void D3d12GpuRecord::Analyze_ClearColor(u32 i, const FCmdClearColor& cmd) +D3d12BarrierAnalyzer::ResInfo& D3d12BarrierAnalyzer::GetInfo(const FCmdResRef& ref) { - const auto [meta, info] = Get(cmd.Image); - const auto use = info->MarkUse(this, D3D12_BARRIER_ACCESS_RENDER_TARGET, D3D12_BARRIER_LAYOUT_RENDER_TARGET, FShaderStageFlags::None); + return m_resources[ref.IndexPlusOne - 1]; +} + +std::pair, NonNull> D3d12BarrierAnalyzer::Get(const FCmdResRef& ref) +{ + return {&ref.Get(m_record->Resources), &m_resources[ref.IndexPlusOne - 1]}; +} + +NonNull D3d12BarrierAnalyzer::GetResource(const u32 index) const +{ + const auto& res = m_record->Resources[index]; + return Coplt::GetResource(res); +} + +NonNull D3d12BarrierAnalyzer::GetBufferData(const u32 index) const +{ + const auto& res = m_record->Resources[index]; + return Coplt::GetBufferData(res); +} + +NonNull D3d12BarrierAnalyzer::GetImageData(u32 index) const +{ + const auto& res = m_record->Resources[index]; + return Coplt::GetImageData(res); +} + +void D3d12BarrierAnalyzer::MarkUse( + ResInfo& Info, const D3D12_BARRIER_ACCESS Access, const D3D12_BARRIER_LAYOUT Layout, D3D12_BARRIER_SYNC Sync, const ResUseType UavUse +) +{ + const auto type = GetUseType(Access, UavUse); + if (Info.First) + { + Info.First = false; + Info.Type = type; + Info.Access = Access; + Info.Layout = Layout; + Info.Sync = Sync; + return; + } + COPLT_THROW("TODO"); + // if (type == ResUseType::Read && Info.IsReadCompatible(Layout)) + // { + // Info.MergeRead(Access, Stages); + // return; + // } + // const auto& cur_barrier = m_parts[m_current_barrier_begin_part].Barrier; + // const auto& cur_cmd = m_parts[m_current_cmd_part].Cmd; + // if (Info.WasDefInput) + // { + // + // } + // else if (Info.CurrentBarrierPart == COPLT_U32_MAX) + // { + // + // } + // return; +} + +void D3d12BarrierAnalyzer::CmdNext() +{ + m_parts[m_current_cmd_part].Cmd.Count++; +} + +void D3d12BarrierAnalyzer::BuildInputOutput() +{ + for (u32 i = 0; i < m_resources.size(); ++i) + { + const auto& res = m_resources[i]; + const auto use = ResUse{ + .ResIndex = i, + .Layout = res.Layout, + .Access = res.Access, + .Sync = res.Sync, + .Type = res.Type, + }; + m_res_outputs.push_back(use); + if (res.WasDefInput) continue; + m_res_inputs.push_back(use); + } +} + +void D3d12BarrierAnalyzer::Analyze_ClearColor(const u32 i, const FCmdClearColor& cmd) +{ + auto& info = GetInfo(cmd.Image); + MarkUse(info, D3D12_BARRIER_ACCESS_RENDER_TARGET, D3D12_BARRIER_LAYOUT_RENDER_TARGET, D3D12_BARRIER_SYNC_RENDER_TARGET); +} + +void D3d12BarrierAnalyzer::Analyze_ClearDepthStencil(const u32 i, const FCmdClearDepthStencil& cmd) +{ + auto& info = GetInfo(cmd.Image); + MarkUse(info, D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE, D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE, D3D12_BARRIER_SYNC_DEPTH_STENCIL); +} + +void D3d12BarrierAnalyzer::Interpret(NonNull record, CmdListPack& cmd) +{ +} + +NonNull Coplt::GetResource(const FCmdRes& res) +{ + switch (res.Type) + { + case FCmdResType::Image: + { + const NonNull obj = res.Image->QueryInterface(); + return obj->GetResourcePtr(); + } + case FCmdResType::Buffer: + { + const NonNull obj = res.Image->QueryInterface(); + return obj->GetResourcePtr(); + } + case FCmdResType::Output: + { + const NonNull obj = res.Image->QueryInterface(); + return obj->GetResourcePtr(); + } + } + return nullptr; +} + +NonNull Coplt::GetBufferData(const FCmdRes& res) +{ + switch (res.Type) + { + case FCmdResType::Buffer: + { + const NonNull obj = res.Image->QueryInterface(); + return obj->Data(); + } + case FCmdResType::Image: + case FCmdResType::Output: + return nullptr; + } + return nullptr; +} + +NonNull Coplt::GetImageData(const FCmdRes& res) +{ + switch (res.Type) + { + case FCmdResType::Image: + { + const NonNull obj = res.Image->QueryInterface(); + return obj->Data(); + } + case FCmdResType::Output: + { + const NonNull obj = res.Image->QueryInterface(); + return obj->ImageData(); + } + case FCmdResType::Buffer: + return nullptr; + } + return nullptr; +} + +CD3DX12_CPU_DESCRIPTOR_HANDLE Coplt::GetRtv(const FCmdRes& res) +{ + switch (res.Type) + { + case FCmdResType::Image: + { + const NonNull obj = res.Image->QueryInterface(); + COPLT_THROW("TODO"); + } + case FCmdResType::Buffer: + { + const NonNull obj = res.Image->QueryInterface(); + COPLT_THROW("TODO"); + } + case FCmdResType::Output: + { + const NonNull obj = res.Image->QueryInterface(); + return obj->GetRtv(); + } + } + COPLT_THROW("Unreachable"); +} + +CD3DX12_CPU_DESCRIPTOR_HANDLE Coplt::GetDsv(const FCmdRes& res) +{ + switch (res.Type) + { + case FCmdResType::Image: + { + const NonNull obj = res.Image->QueryInterface(); + COPLT_THROW("TODO"); + } + case FCmdResType::Buffer: + { + const NonNull obj = res.Image->QueryInterface(); + COPLT_THROW("TODO"); + } + case FCmdResType::Output: + { + COPLT_THROW("Output dose not support Dsv"); + } + } + COPLT_THROW("Unreachable"); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index f2e708e..f758129 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -7,6 +7,8 @@ namespace Coplt { + struct I3d12BarrierAnalyzer; + struct D3d12BarrierAnalyzer; struct D3d12GpuRecord; namespace Recording @@ -19,50 +21,24 @@ namespace Coplt ReadWrite, }; + ResUseType GetUseType(D3D12_BARRIER_ACCESS access, ResUseType UavUse = ResUseType::ReadWrite); + struct ResUse { - // u32::max 表示没有来源 - u32 FromUse{}; u32 ResIndex{}; D3D12_BARRIER_LAYOUT Layout{}; D3D12_BARRIER_ACCESS Access{}; - FShaderStageFlags Stages{}; + D3D12_BARRIER_SYNC Sync{}; ResUseType Type{}; - - bool IsReadCompatible(D3D12_BARRIER_LAYOUT Layout) const; - void MergeRead(D3D12_BARRIER_ACCESS Access, FShaderStageFlags Stages); - }; - - ResUseType GetUseType(D3D12_BARRIER_ACCESS access, ResUseType UavUse = ResUseType::ReadWrite); - - struct ResInfo - { - Rc m_owner{}; - u32 m_res_index{}; - - u32 m_last_unique_use{COPLT_U32_MAX}; - - ResInfo() = default; - - explicit ResInfo(Rc&& resource, u32 res_index); - - u32 MarkUse( - NonNull self, D3D12_BARRIER_ACCESS Access, D3D12_BARRIER_LAYOUT Layout, - FShaderStageFlags Stages, ResUseType UavUse = ResUseType::ReadWrite - ); }; } COPLT_INTERFACE_DEFINE(ID3d12GpuRecord, "57a9c7f9-1ec0-4d78-89b9-e547667c50b3", FGpuRecord) { using ResUseType = Recording::ResUseType; - using ResUse = Recording::ResUse; - using ResInfo = Recording::ResInfo; - SRc m_queue_config{}; - std::vector m_resources{}; - std::vector m_outputs{}; - std::vector m_res_use{}; + Rc m_barrier_analyzer{}; + std::vector> m_resources_owner{}; std::vector m_queue_wait_points{}; virtual FGpuRecordData* Data() noexcept = 0; @@ -88,8 +64,6 @@ namespace Coplt FGpuRecordData* Data() noexcept override; const FGpuRecordData* Data() const noexcept override; - std::pair, NonNull> Get(const FCmdResRef& ref); - void WaitAndRecycle(HANDLE event) override; void Recycle() override; @@ -97,7 +71,126 @@ namespace Coplt void EnsureEnd() override; void DoEnd(); + FCmdRes& GetRes(const FCmdResRef& ref); + void Analyze(); + void Interpret(const CmdListPack& clp, u32 cmd_index, u32 cmd_count); + + void Interpret_ClearColor(const CmdListPack& clp, u32 i, const FCmdClearColor& cmd); + void Interpret_ClearDepthStencil(const CmdListPack& clp, u32 i, const FCmdClearDepthStencil& cmd); + }; + + COPLT_INTERFACE_DEFINE(I3d12BarrierAnalyzer, "80086589-a583-41de-9aec-205afc022cd9", FUnknown) + { + using ResUseType = Recording::ResUseType; + using ResUse = Recording::ResUse; + + std::vector m_res_inputs{}; + std::vector m_res_outputs{}; + + virtual void Recycle() = 0; + virtual void Analyzer(NonNull record) = 0; + virtual void Interpret(NonNull record, CmdListPack& cmd) = 0; + }; + + struct D3d12BarrierAnalyzer final : Object + { + private: + struct ResInfo + { + u32 CurrentBarrierPart{COPLT_U32_MAX}; + D3D12_BARRIER_LAYOUT Layout{}; + D3D12_BARRIER_ACCESS Access{}; + D3D12_BARRIER_SYNC Sync{}; + ResUseType Type{}; + FCmdResType ResType{}; + bool WasDefInput{}; + bool First{true}; + + ResInfo() = default; + explicit ResInfo(FCmdResType ResType); + + bool IsReadCompatible(D3D12_BARRIER_LAYOUT Layout) const; + // 返回是否改变 + bool MergeRead(D3D12_BARRIER_ACCESS Access, D3D12_BARRIER_SYNC Sync); + }; + + enum class PartType : u32 + { + Cmd, + BarrierBegin, + BarrierEnd, + }; + + struct BarrierPart + { + PartType Type{}; + u32 GlobalIndex{COPLT_U32_MAX}; + u32 GlobalCount{}; + u32 TextureIndex{COPLT_U32_MAX}; + u32 TextureCount{}; + u32 BufferIndex{COPLT_U32_MAX}; + u32 BufferCount{}; + }; + + struct CmdPart + { + PartType Type{PartType::Cmd}; + u32 Index{}; + u32 Count{}; + }; + + union Part + { + PartType Type{}; + BarrierPart Barrier; + CmdPart Cmd; + }; + + NonNull m_record; + std::vector m_resources{}; + std::vector m_parts{}; + u32 m_current_barrier_begin_part{}; + u32 m_current_cmd_part{}; + std::vector m_begin_global_barriers{}; + std::vector m_begin_texture_barriers{}; + std::vector m_begin_buffer_barriers{}; + std::vector m_end_global_barriers{}; + std::vector m_end_texture_barriers{}; + std::vector m_end_buffer_barriers{}; + + public: + explicit D3d12BarrierAnalyzer(); + + void Recycle() override; + void Analyzer(NonNull record) override; + + private: + ResInfo& GetInfo(const FCmdResRef& ref); + std::pair, NonNull> Get(const FCmdResRef& ref); + NonNull GetResource(u32 index) const; + NonNull GetBufferData(u32 index) const; + NonNull GetImageData(u32 index) const; + + void MarkUse( + ResInfo& Info, + D3D12_BARRIER_ACCESS Access, D3D12_BARRIER_LAYOUT Layout, D3D12_BARRIER_SYNC Sync, + ResUseType UavUse = ResUseType::ReadWrite + ); + void CmdNext(); + + void BuildInputOutput(); + void Analyze_ClearColor(u32 i, const FCmdClearColor& cmd); + void Analyze_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); + + public: + void Interpret(NonNull record, CmdListPack& cmd) override; }; + + NonNull GetResource(const FCmdRes& res); + NonNull GetBufferData(const FCmdRes& res); + NonNull GetImageData(const FCmdRes& res); + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv(const FCmdRes& res); + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv(const FCmdRes& res); } diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc index cd6603b..dcb3d89 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -53,6 +53,16 @@ D3d12GpuSwapChain::D3d12GpuSwapChain(const NonNull isolate, con this->Height = desc.Height; m_frame_count = desc.BufferCount; + m_image_data.m_format = this->Format; + m_image_data.m_width = this->Width; + m_image_data.m_height = this->Height; + m_image_data.m_depth_or_length = 1; + m_image_data.m_mip_levels = 1; + m_image_data.m_multisample_count = 1; + m_image_data.m_planes = 1; + m_image_data.m_dimension = FImageDimension::Two; + m_image_data.m_layout = FImageLayout::Undefined; + Initialize(); } @@ -205,6 +215,28 @@ FGpuIsolate* D3d12GpuSwapChain::GetIsolate() noexcept return m_isolate.get(); } +NonNull D3d12GpuSwapChain::Data() +{ + return this; +} + +NonNull D3d12GpuSwapChain::ImageData() +{ + return &m_image_data; +} + +NonNull D3d12GpuSwapChain::GetResourcePtr() +{ + return m_buffers[m_frame_index].Get(); +} + +CD3DX12_CPU_DESCRIPTOR_HANDLE D3d12GpuSwapChain::GetRtv() +{ + CD3DX12_CPU_DESCRIPTOR_HANDLE rtv_handle(m_rtv_heap->GetCPUDescriptorHandleForHeapStart()); + rtv_handle.Offset(static_cast(m_frame_index), m_rtv_descriptor_size); + return rtv_handle; +} + FResult D3d12GpuSwapChain::Resize(const u32 Width, const u32 Height) noexcept { return feb([&] @@ -300,8 +332,8 @@ void D3d12GpuSwapChain::ResizeNoLock(const u32 width, const u32 height) chr | m_swap_chain->ResizeBuffers(m_frame_count, width, height, ToDx(this->Format), 0); CreateRts(); m_frame_index = m_swap_chain->GetCurrentBackBufferIndex(); - this->Width = width; - this->Height = height; + m_image_data.m_width = this->Width = width; + m_image_data.m_height = this->Height = height; } void D3d12GpuSwapChain::WaitAll() diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.h b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h index 62443db..9b67752 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.h +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h @@ -1,5 +1,6 @@ #pragma once +#include "Output.h" #include "Queue.h" #include "../../Api/FFI/Output.h" #include "../../Api/Include/GpuObject.h" @@ -32,8 +33,10 @@ namespace Coplt b8 m_debug_enabled{}; }; - struct D3d12GpuSwapChain final : GpuObject, FGpuSwapChainData + struct D3d12GpuSwapChain final : GpuObject, FGpuSwapChainData { + FGpuImageData m_image_data{}; + private: explicit D3d12GpuSwapChain( NonNull isolate, const FGpuOutput2CreateOptions& options, @@ -57,6 +60,11 @@ namespace Coplt const FGpuSwapChainData* GpuSwapChainData() noexcept override; FGpuIsolate* GetIsolate() noexcept override; + NonNull Data() override; + NonNull ImageData() override; + NonNull GetResourcePtr() override; + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv() override; + FResult Resize(u32 Width, u32 Height) noexcept override; FResult SetVSync(b8 Enable) noexcept override; diff --git a/Examples/HelloTriangle/Example.cs b/Examples/HelloTriangle/Example.cs index 8b9140f..5a24f9d 100644 --- a/Examples/HelloTriangle/Example.cs +++ b/Examples/HelloTriangle/Example.cs @@ -6,30 +6,30 @@ namespace Examples; public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handle, Width, Height) { - // private Shader Shader = null!; - // private GraphicsShaderPipeline Pipeline = null!; + private Shader Shader = null!; + private GraphicsShaderPipeline Pipeline = null!; public override string Name => "Hello Triangle"; - // protected override async Task LoadResources(GpuRecord cmd) - // { - // var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); - // Shader = Device.CreateShader(modules, null, Device.CreateShaderInputLayout([])); - // Pipeline = Device.CreateGraphicsShaderPipeline( - // Shader, new() - // { - // DsvFormat = GraphicsFormat.Unknown, - // BlendState = - // { - // Rt0 = - // { - // Src = BlendType.SrcAlpha, - // Dst = BlendType.InvSrcAlpha, - // Op = BlendOp.Add, - // } - // } - // }, Name: Name - // ); - // } + protected override async Task LoadResources(GpuRecord cmd) + { + var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); + Shader = Device.CreateShader(modules, null, Device.CreateShaderInputLayout([])); + Pipeline = Device.CreateGraphicsShaderPipeline( + Shader, new() + { + DsvFormat = GraphicsFormat.Unknown, + BlendState = + { + Rt0 = + { + Src = BlendType.SrcAlpha, + Dst = BlendType.InvSrcAlpha, + Op = BlendOp.Add, + } + } + }, Name: Name + ); + } protected override void Render(GpuRecord cmd, Time time) { cmd.ClearColor(Output, new Color(0.83f, 0.8f, 0.97f)); From f6d6bbec0a66ba2b9f80d8040fa2ffa2ad411f3f Mon Sep 17 00:00:00 2001 From: U2A5F Date: Fri, 21 Mar 2025 23:18:35 +0800 Subject: [PATCH 09/46] save --- Coplt.Graphics.Core/Core/GpuRecord.cs | 1 - Coplt.Graphics.Core/Native/Native.cs | 14 +- Coplt.Graphics.Native/Api/FFI/Record.h | 13 +- Coplt.Graphics.Native/D3d12/Src/Context.cc | 238 ++++++++++++++++++++- Coplt.Graphics.Native/D3d12/Src/Context.h | 118 +++++++++- Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 3 + Coplt.Graphics.Native/D3d12/Src/Isolate.h | 2 + Coplt.Graphics.Native/D3d12/Src/Queue.cc | 31 --- Coplt.Graphics.Native/D3d12/Src/Queue.h | 21 -- Coplt.Graphics.Native/D3d12/Src/Record.cc | 58 ++++- Coplt.Graphics.Native/D3d12/Src/Record.h | 14 +- 11 files changed, 436 insertions(+), 77 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index fa1d1e8..b3641c2 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -83,7 +83,6 @@ internal FCmdResRef AddResource(IGpuResource resource) var len = Data.Resources.LongLength; if (len + 1 >= uint.MaxValue) throw new IndexOutOfRangeException("Resources >= uint32 max are not supported"); slot = (uint)len; - if (resource is GpuOutput) Data.OutputCount++; Data.Resources.Add(resource.IntoCmd()); } return new() { IndexPlusOne = slot + 1 }; diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 4d31d2a..e40d248 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1560,6 +1560,14 @@ public unsafe partial struct FMainQueueCreateResult public uint NumQueues; } + [NativeTypeName("Coplt::u8")] + public enum FGpuRecordMode : byte + { + Direct = 0, + Compute = 1, + Copy = 2, + } + public unsafe partial struct FGpuRecordData { [NativeTypeName("Coplt::FRecordContext *")] @@ -1576,11 +1584,11 @@ public unsafe partial struct FGpuRecordData [NativeTypeName("FList")] public FList Blob; - [NativeTypeName("Coplt::usize")] - public nuint OutputCount; - [NativeTypeName("Coplt::b8")] public B8 Ended; + + [NativeTypeName("Coplt::FGpuRecordMode")] + public FGpuRecordMode Mode; } [NativeTypeName("Coplt::u32")] diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index 8c6c81c..36979e3 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -6,6 +6,13 @@ namespace Coplt { + enum class FGpuRecordMode : u8 + { + Direct = 0, + Compute = 1, + Copy = 2, + }; + struct FGpuRecordData; COPLT_INTERFACE_DEFINE(FGpuRecord, "0ef83584-ca65-44de-b38a-648bfb3a85a6", FGpuObject) @@ -26,9 +33,8 @@ namespace Coplt FList PayloadRect; FList PayloadViewport; FList Blob; - // 统计不重复的 Output 数量 - usize OutputCount{}; b8 Ended{}; + FGpuRecordMode Mode{}; #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) @@ -43,7 +49,6 @@ namespace Coplt PayloadRect.Clear(); PayloadViewport.Clear(); Blob.Clear(); - OutputCount = 0; } #endif }; @@ -53,6 +58,4 @@ namespace Coplt FGpuRecord* Record{}; FGpuRecordData* Data{}; }; - - } diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.cc b/Coplt.Graphics.Native/D3d12/Src/Context.cc index 8429fe5..f29d3a9 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Context.cc @@ -83,6 +83,7 @@ void D3d12FrameContext::Recycle() D3d12RecordContext::D3d12RecordContext(NonNull isolate) { m_device = isolate->m_device; + m_cmd_alloc_pool = isolate->m_cmd_alloc_pool; m_upload_buffer = FList(m_device->m_instance->m_allocator.get()); } @@ -126,7 +127,7 @@ FResult D3d12RecordContext::GrowUploadBuffer(u64 min_required_size) noexcept void D3d12RecordContext::Recycle() { - m_command_allocators.clear(); + m_recycled_command_allocators.clear(); if (!m_upload_buffers.empty()) { @@ -144,3 +145,238 @@ void D3d12RecordContext::Recycle() } } } + +D3d12CommandPool::D3d12CommandPool(const Rc& device, const D3D12_COMMAND_LIST_TYPE type) + : m_device(device), m_type(type) +{ + m_command_allocator_pool = box(); +} + +D3d12RentedCommandAllocator D3d12CommandPool::RentCommandAllocator() +{ + ComPtr allocator{}; + if (!m_command_allocator_pool->try_dequeue(allocator)) + { + chr | m_device->m_device->CreateCommandAllocator(m_type, IID_PPV_ARGS(&allocator)); + } + return D3d12RentedCommandAllocator(this->CloneThis(), std::move(allocator)); +} + +void D3d12CommandPool::ReturnCommandAllocator(ComPtr&& allocator) const +{ + chr | allocator->Reset(); + m_command_allocator_pool->enqueue(std::move(allocator)); +} + +void D3d12CommandPool::ReturnCommandList(Rc&& list) const +{ + m_command_list_pool->enqueue(std::move(list)); +} + +D3d12CommandListPoolCluster::D3d12CommandListPoolCluster(const Rc& device) + : m_device(device) +{ + m_direct = new D3d12CommandPool(m_device, D3D12_COMMAND_LIST_TYPE_DIRECT); + m_compute = new D3d12CommandPool(m_device, D3D12_COMMAND_LIST_TYPE_COMPUTE); + m_copy = new D3d12CommandPool(m_device, D3D12_COMMAND_LIST_TYPE_COPY); + m_video_decode = new D3d12CommandPool(m_device, D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE); + m_video_process = new D3d12CommandPool(m_device, D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS); + m_video_encode = new D3d12CommandPool(m_device, D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE); +} + +D3d12RentedCommandAllocator D3d12CommandListPoolCluster::RentCommandAllocator(const D3D12_COMMAND_LIST_TYPE type) const +{ + switch (type) + { + case D3D12_COMMAND_LIST_TYPE_DIRECT: + return m_direct->RentCommandAllocator(); + case D3D12_COMMAND_LIST_TYPE_COMPUTE: + return m_compute->RentCommandAllocator(); + case D3D12_COMMAND_LIST_TYPE_COPY: + return m_copy->RentCommandAllocator(); + case D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE: + return m_video_decode->RentCommandAllocator(); + case D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS: + return m_video_process->RentCommandAllocator(); + case D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE: + return m_video_encode->RentCommandAllocator(); + case D3D12_COMMAND_LIST_TYPE_BUNDLE: + case D3D12_COMMAND_LIST_TYPE_NONE: + break; + } + COPLT_THROW_FMT("Unknown or unsupported command list type {}", static_cast(type)); +} + +D3d12CommandList::D3d12CommandList(const D3d12RentedCommandAllocator& allocator) +{ + type = allocator.m_pool->m_type; + switch (type) + { + case D3D12_COMMAND_LIST_TYPE_DIRECT: + case D3D12_COMMAND_LIST_TYPE_COMPUTE: + case D3D12_COMMAND_LIST_TYPE_COPY: + { + chr | allocator.m_pool->m_device->m_device->CreateCommandList( + 0, type, allocator.m_allocator.Get(), nullptr, IID_PPV_ARGS(&g0) + ); + if (SUCCEEDED(g0->QueryInterface(&g10))) goto _9; + if (SUCCEEDED(g0->QueryInterface(&g9))) goto _8; + if (SUCCEEDED(g0->QueryInterface(&g8))) goto _7; + if (SUCCEEDED(g0->QueryInterface(&g7))) goto _6; + if (SUCCEEDED(g0->QueryInterface(&g6))) goto _5; + if (SUCCEEDED(g0->QueryInterface(&g5))) goto _4; + if (SUCCEEDED(g0->QueryInterface(&g4))) goto _3; + if (SUCCEEDED(g0->QueryInterface(&g3))) goto _2; + if (SUCCEEDED(g0->QueryInterface(&g2))) goto _1; + if (SUCCEEDED(g0->QueryInterface(&g1))) goto _0; + return; + _9: + g9 = g10; + _8: + g8 = g9; + _7: + g7 = g8; + _6: + g6 = g7; + _5: + g5 = g6; + _4: + g4 = g5; + _3: + g3 = g4; + _2: + g2 = g3; + _1: + g1 = g2; + _0: + return; + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE: + COPLT_THROW("TODO"); + case D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS: + COPLT_THROW("TODO"); + case D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE: + COPLT_THROW("TODO"); + case D3D12_COMMAND_LIST_TYPE_NONE: + case D3D12_COMMAND_LIST_TYPE_BUNDLE: + std::unreachable(); + } + std::unreachable(); +} + +void D3d12CommandList::Reset(const D3d12RentedCommandAllocator& allocator) const +{ + switch (type) + { + case D3D12_COMMAND_LIST_TYPE_DIRECT: + case D3D12_COMMAND_LIST_TYPE_COMPUTE: + case D3D12_COMMAND_LIST_TYPE_COPY: + { + chr | g0->Reset(allocator.m_allocator.Get(), nullptr); + return; + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE: + { + chr | vd0->Reset(allocator.m_allocator.Get()); + return; + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS: + { + chr | vp0->Reset(allocator.m_allocator.Get()); + return; + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE: + { + chr | ve0->Reset(allocator.m_allocator.Get()); + return; + } + case D3D12_COMMAND_LIST_TYPE_NONE: + case D3D12_COMMAND_LIST_TYPE_BUNDLE: + std::unreachable(); + } + std::unreachable(); +} + +void D3d12CommandList::Close() const +{ + switch (type) + { + case D3D12_COMMAND_LIST_TYPE_DIRECT: + case D3D12_COMMAND_LIST_TYPE_COMPUTE: + case D3D12_COMMAND_LIST_TYPE_COPY: + { + chr | g0->Close(); + return; + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE: + { + chr | vd0->Close(); + return; + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS: + { + chr | vp0->Close(); + return; + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE: + { + chr | ve0->Close(); + return; + } + case D3D12_COMMAND_LIST_TYPE_NONE: + case D3D12_COMMAND_LIST_TYPE_BUNDLE: + std::unreachable(); + } + std::unreachable(); +} + +D3d12RentedCommandList::D3d12RentedCommandList(const Rc& pool, Rc&& list) + : m_pool(pool), m_list(std::move(list)) +{ +} + +D3d12RentedCommandList::~D3d12RentedCommandList() +{ + if (!m_pool) return; + m_pool->ReturnCommandList(std::move(m_list)); +} + +D3d12CommandList* D3d12RentedCommandList::operator->() const noexcept +{ + return m_list.get(); +} + +D3d12CommandList& D3d12RentedCommandList::operator*() const noexcept +{ + return *m_list.get(); +} + +D3d12RentedCommandList::operator bool() const noexcept +{ + return static_cast(m_pool); +} + +D3d12RentedCommandAllocator::D3d12RentedCommandAllocator(const Rc& pool, ComPtr&& allocator) + : m_pool(pool), m_allocator(std::move(allocator)) +{ +} + +D3d12RentedCommandAllocator::~D3d12RentedCommandAllocator() +{ + if (!m_pool) return; + m_pool->ReturnCommandAllocator(std::move(m_allocator)); +} + +D3d12RentedCommandList D3d12RentedCommandAllocator::RentCommandList() const +{ + Rc list{}; + if (m_pool->m_command_list_pool->try_dequeue(list)) + { + list->Reset(*this); + } + else + { + list = new D3d12CommandList(*this); + } + return D3d12RentedCommandList(m_pool, std::move(list)); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.h b/Coplt.Graphics.Native/D3d12/Src/Context.h index 4238645..a1420a6 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.h +++ b/Coplt.Graphics.Native/D3d12/Src/Context.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "../../Api/FFI/Context.h" #include "../../Api/Include/Object.h" #include "CmdListPack.h" @@ -33,12 +35,17 @@ namespace Coplt void Recycle(); }; + struct D3d12CommandList; + struct D3d12RentedCommandList; + struct D3d12RentedCommandAllocator; + struct D3d12RecordContext final : GpuObject { constexpr static u64 InitUploadBufferSize = 1024 * 1024; Rc m_device{}; - std::vector m_command_allocators{}; + Rc m_cmd_alloc_pool{}; + std::vector m_recycled_command_allocators{}; std::vector m_upload_buffers{}; usize m_cur_upload_buffer_index{}; usize m_cur_upload_buffer_size{}; @@ -52,4 +59,113 @@ namespace Coplt // 回收帧使用的资源,重复使用,需要在队列中等待帧完成后调用 void Recycle(); }; + + struct D3d12CommandPool final : Object + { + using CommandAllocatorConcurrentQueue = moodycamel::ConcurrentQueue>; + using CommandListConcurrentQueue = moodycamel::ConcurrentQueue>; + + Rc m_device{}; + Box m_command_allocator_pool{}; + Box m_command_list_pool{}; + D3D12_COMMAND_LIST_TYPE m_type{}; + + explicit D3d12CommandPool(const Rc& device, D3D12_COMMAND_LIST_TYPE type); + + D3d12RentedCommandAllocator RentCommandAllocator(); + void ReturnCommandAllocator(ComPtr&& allocator) const; + void ReturnCommandList(Rc&& list) const; + }; + + struct D3d12CommandListPoolCluster final : Object + { + Rc m_device{}; + Rc m_direct{}; + Rc m_compute{}; + Rc m_copy{}; + Rc m_video_decode{}; + Rc m_video_process{}; + Rc m_video_encode{}; + + explicit D3d12CommandListPoolCluster(const Rc& device); + + D3d12RentedCommandAllocator RentCommandAllocator(D3D12_COMMAND_LIST_TYPE type) const; + }; + + struct D3d12CommandList final : Object + { + D3D12_COMMAND_LIST_TYPE type{}; + + ComPtr g10{}; + ComPtr g9{}; + ComPtr g8{}; + ComPtr g7{}; + ComPtr g6{}; + ComPtr g5{}; + ComPtr g4{}; + ComPtr g3{}; + ComPtr g2{}; + ComPtr g1{}; + ComPtr g0{}; + + ComPtr vd3{}; + ComPtr vd2{}; + ComPtr vd1{}; + ComPtr vd0{}; + + ComPtr ve4{}; + ComPtr ve3{}; + ComPtr ve2{}; + ComPtr ve1{}; + ComPtr ve0{}; + + ComPtr vp3{}; + ComPtr vp2{}; + ComPtr vp1{}; + ComPtr vp0{}; + + explicit D3d12CommandList(const D3d12RentedCommandAllocator& allocator); + + void Reset(const D3d12RentedCommandAllocator& allocator) const; + void Close() const; + }; + + struct D3d12RentedCommandList final + { + Rc m_pool{}; + Rc m_list{}; + + D3d12RentedCommandList() = default; + explicit D3d12RentedCommandList(const Rc& pool, Rc&& list); + ~D3d12RentedCommandList(); + + D3d12RentedCommandList(D3d12RentedCommandList&&) = default; + D3d12RentedCommandList& operator=(D3d12RentedCommandList&&) = default; + + D3d12RentedCommandList(const D3d12RentedCommandList&) = delete; + D3d12RentedCommandList& operator=(const D3d12RentedCommandList&) = delete; + + D3d12CommandList* operator->() const noexcept; + D3d12CommandList& operator*() const noexcept; + + operator bool() const noexcept; + }; + + // 必须等待队列 fence 完成才能析构,或者可以 move 走 + struct D3d12RentedCommandAllocator final + { + Rc m_pool{}; + ComPtr m_allocator{}; + + explicit D3d12RentedCommandAllocator(const Rc& pool, ComPtr&& allocator); + ~D3d12RentedCommandAllocator(); + + D3d12RentedCommandAllocator(D3d12RentedCommandAllocator&& other) = default; + D3d12RentedCommandAllocator& operator=(D3d12RentedCommandAllocator&& other) = default; + + D3d12RentedCommandAllocator(const D3d12RentedCommandAllocator&) = delete; + D3d12RentedCommandAllocator& operator=(const D3d12RentedCommandAllocator&) = delete; + + D3d12RentedCommandList RentCommandList() const; + }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index 4f8d425..eb57e82 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -2,6 +2,7 @@ #include "Record.h" #include "SwapChain.h" +#include "Context.h" #include "../../Api/FFI/Record.h" using namespace Coplt; @@ -79,6 +80,8 @@ D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCre #pragma endregion + m_cmd_alloc_pool = new D3d12CommandListPoolCluster(m_device); + m_event = CreateEventW(nullptr, false, false, nullptr); if (m_event == nullptr) chr | HRESULT_FROM_WIN32(GetLastError()); diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index d3b3d13..22df136 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -11,6 +11,7 @@ namespace Coplt { + struct D3d12CommandListPoolCluster; COPLT_INTERFACE_DEFINE(ID3d12GpuIsolate, "1c507c7f-140a-4717-809e-88096b475fea", FGpuIsolate) { SRc m_queue_config{}; @@ -35,6 +36,7 @@ namespace Coplt HANDLE m_event{}; Box m_waiting_record{}; Box m_record_pool{}; + Rc m_cmd_alloc_pool{}; std::binary_semaphore m_waiting_signal{0}; std::thread m_wait_thread{}; std::atomic_bool m_exited{false}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.cc b/Coplt.Graphics.Native/D3d12/Src/Queue.cc index 7ba7a6a..42f2ae2 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.cc @@ -138,17 +138,6 @@ FResult D3d12GpuQueue::SubmitNoWait(FGpuExecutor* Executor, const FCommandSubmit }); } -RentedCommandAllocator::RentedCommandAllocator(Rc&& queue, ComPtr&& command_allocator) - : m_queue(std::move(queue)), m_command_allocator(std::move(command_allocator)) -{ -} - -RentedCommandAllocator::~RentedCommandAllocator() -{ - if (!m_queue) return; - m_queue->ReturnCommandAllocator(std::move(m_command_allocator)); -} - QueueWaitPoint::QueueWaitPoint(Rc&& queue, const u64 fence_value) : m_queue(std::move(queue)), m_fence_value(fence_value) { } @@ -161,8 +150,6 @@ void QueueWaitPoint::Wait(const HANDLE event) const D3d12GpuQueue2::D3d12GpuQueue2(const NonNull isolate, const FGpuQueueType type) : FGpuQueueData() { - m_command_allocator_pool = box(); - m_device = isolate->m_device; QueueType = type; const NonNull device = m_device->m_device.Get(); @@ -238,21 +225,3 @@ void D3d12GpuQueue2::WaitFenceValue(u64 fence_value, HANDLE event) WaitForSingleObject(event, INFINITE); } } - -RentedCommandAllocator D3d12GpuQueue2::RentCommandAllocator() -{ - ComPtr command_allocator{}; - if (!m_command_allocator_pool->try_dequeue(command_allocator)) - { - chr | m_device->m_device->CreateCommandAllocator( - ToDx(this->QueueType), IID_PPV_ARGS(&command_allocator) - ); - } - return RentedCommandAllocator(this->CloneThis(), std::move(command_allocator)); -} - -void D3d12GpuQueue2::ReturnCommandAllocator(ComPtr&& command_allocator) -{ - chr | command_allocator->Reset(); - m_command_allocator_pool->enqueue(std::move(command_allocator)); -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.h b/Coplt.Graphics.Native/D3d12/Src/Queue.h index 3e2dac8..c2f19aa 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -82,18 +82,6 @@ namespace Coplt struct ID3d12GpuQueue; struct D3d12GpuQueue2; - // 必须等待队列 fence 完成才能析构,或者可以 move 走 - struct RentedCommandAllocator final - { - Rc m_queue{}; - ComPtr m_command_allocator{}; - - RentedCommandAllocator() = default; - explicit RentedCommandAllocator(Rc&& queue, ComPtr&& command_allocator); - - ~RentedCommandAllocator(); - }; - struct QueueWaitPoint final { Rc m_queue{}; @@ -118,16 +106,10 @@ namespace Coplt virtual u64 SignalNoLock() = 0; virtual void WaitFenceValue(u64 fence_value, HANDLE event) = 0; - virtual RentedCommandAllocator RentCommandAllocator() = 0; - virtual void ReturnCommandAllocator(ComPtr&& command_allocator) = 0; }; struct D3d12GpuQueue2 final : GpuObject, FGpuQueueData { - using CommandAllocatorConcurrentQueue = moodycamel::ConcurrentQueue>; - - Box m_command_allocator_pool{}; - explicit D3d12GpuQueue2(NonNull isolate, FGpuQueueType type); FGpuQueueData* GpuQueueData() noexcept override; @@ -139,8 +121,5 @@ namespace Coplt u64 SignalNoLock() override; void WaitFenceValue(u64 fence_value, HANDLE event) override; - - RentedCommandAllocator RentCommandAllocator() override; - void ReturnCommandAllocator(ComPtr&& command_allocator) override; }; } // Coplt diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index d06d3b2..7a67bc0 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -63,6 +63,7 @@ void D3d12GpuRecord::WaitAndRecycle(const HANDLE event) void D3d12GpuRecord::Recycle() { m_queue_wait_points.clear(); + m_list = {}; m_context->Recycle(); m_resources_owner.clear(); ClearData(); @@ -96,6 +97,7 @@ void D3d12GpuRecord::DoEnd() m_resources_owner.push_back(Rc::UnsafeClone(res.GetObjectPtr())); } Analyze(); + Interpret(); Ended = true; } @@ -106,10 +108,19 @@ FCmdRes& D3d12GpuRecord::GetRes(const FCmdResRef& ref) void D3d12GpuRecord::Analyze() { - m_barrier_analyzer->Analyzer(NonNull::Unchecked(this)); + m_barrier_analyzer->Analyzer(this); } -void D3d12GpuRecord::Interpret(const CmdListPack& clp, const u32 cmd_index, const u32 cmd_count) +void D3d12GpuRecord::Interpret() +{ + auto allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(ToListType(Mode)); + m_list = allocator.RentCommandList(); + m_context->m_recycled_command_allocators.push_back(std::move(allocator)); + m_barrier_analyzer->Interpret(this); + m_list->Close(); +} + +void D3d12GpuRecord::Interpret(const u32 cmd_index, const u32 cmd_count) { const auto commands = Commands.AsSpan(); for (u32 n = 0; n < cmd_count; ++n) @@ -130,31 +141,31 @@ void D3d12GpuRecord::Interpret(const CmdListPack& clp, const u32 cmd_index, cons // todo continue; case FCmdType::ClearColor: - Interpret_ClearColor(clp, i, command.ClearColor); + Interpret_ClearColor(i, command.ClearColor); continue; case FCmdType::ClearDepthStencil: - Interpret_ClearDepthStencil(clp, i, command.ClearDepthStencil); + Interpret_ClearDepthStencil(i, command.ClearDepthStencil); continue; } } } -void D3d12GpuRecord::Interpret_ClearColor(const CmdListPack& clp, u32 i, const FCmdClearColor& cmd) +void D3d12GpuRecord::Interpret_ClearColor(u32 i, const FCmdClearColor& cmd) { const auto rtv = GetRtv(GetRes(cmd.Image)); - clp->ClearRenderTargetView( + m_list->g0->ClearRenderTargetView( rtv, cmd.Color, cmd.RectCount, cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) ); } -void D3d12GpuRecord::Interpret_ClearDepthStencil(const CmdListPack& clp, u32 i, const FCmdClearDepthStencil& cmd) +void D3d12GpuRecord::Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd) { const auto dsv = GetDsv(GetRes(cmd.Image)); D3D12_CLEAR_FLAGS flags{}; if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Depth)) flags |= D3D12_CLEAR_FLAG_DEPTH; if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Stencil)) flags |= D3D12_CLEAR_FLAG_STENCIL; - clp->ClearDepthStencilView( + m_list->g0->ClearDepthStencilView( dsv, flags, cmd.Depth, cmd.Stencil, cmd.RectCount, cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) ); @@ -337,8 +348,23 @@ void D3d12BarrierAnalyzer::Analyze_ClearDepthStencil(const u32 i, const FCmdClea MarkUse(info, D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE, D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE, D3D12_BARRIER_SYNC_DEPTH_STENCIL); } -void D3d12BarrierAnalyzer::Interpret(NonNull record, CmdListPack& cmd) +void D3d12BarrierAnalyzer::Interpret(NonNull record) { + for (auto& part : m_parts) + { + switch (part.Type) + { + case PartType::Cmd: + record->Interpret(part.Cmd.Index, part.Cmd.Count); + break; + case PartType::BarrierBegin: + // todo + break; + case PartType::BarrierEnd: + // todo + break; + } + } } NonNull Coplt::GetResource(const FCmdRes& res) @@ -444,3 +470,17 @@ CD3DX12_CPU_DESCRIPTOR_HANDLE Coplt::GetDsv(const FCmdRes& res) } COPLT_THROW("Unreachable"); } + +D3D12_COMMAND_LIST_TYPE Coplt::ToListType(const FGpuRecordMode value) +{ + switch (value) + { + case FGpuRecordMode::Direct: + return D3D12_COMMAND_LIST_TYPE_DIRECT; + case FGpuRecordMode::Compute: + return D3D12_COMMAND_LIST_TYPE_COMPUTE; + case FGpuRecordMode::Copy: + return D3D12_COMMAND_LIST_TYPE_COPY; + } + return D3D12_COMMAND_LIST_TYPE_DIRECT; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index f758129..c80d682 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -56,6 +56,7 @@ namespace Coplt u64 m_record_id{}; Rc m_device{}; Rc m_context{}; + D3d12RentedCommandList m_list{}; explicit D3d12GpuRecord(NonNull isolate); @@ -74,10 +75,11 @@ namespace Coplt FCmdRes& GetRes(const FCmdResRef& ref); void Analyze(); - void Interpret(const CmdListPack& clp, u32 cmd_index, u32 cmd_count); + void Interpret(); + void Interpret(u32 cmd_index, u32 cmd_count); - void Interpret_ClearColor(const CmdListPack& clp, u32 i, const FCmdClearColor& cmd); - void Interpret_ClearDepthStencil(const CmdListPack& clp, u32 i, const FCmdClearDepthStencil& cmd); + void Interpret_ClearColor(u32 i, const FCmdClearColor& cmd); + void Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); }; COPLT_INTERFACE_DEFINE(I3d12BarrierAnalyzer, "80086589-a583-41de-9aec-205afc022cd9", FUnknown) @@ -90,7 +92,7 @@ namespace Coplt virtual void Recycle() = 0; virtual void Analyzer(NonNull record) = 0; - virtual void Interpret(NonNull record, CmdListPack& cmd) = 0; + virtual void Interpret(NonNull record) = 0; }; struct D3d12BarrierAnalyzer final : Object @@ -185,7 +187,7 @@ namespace Coplt void Analyze_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); public: - void Interpret(NonNull record, CmdListPack& cmd) override; + void Interpret(NonNull record) override; }; NonNull GetResource(const FCmdRes& res); @@ -193,4 +195,6 @@ namespace Coplt NonNull GetImageData(const FCmdRes& res); CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv(const FCmdRes& res); CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv(const FCmdRes& res); + + D3D12_COMMAND_LIST_TYPE ToListType(const FGpuRecordMode value); } From d7c388f374346a4323549e4952a676ca06eb9189 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Mon, 24 Mar 2025 23:02:50 +0800 Subject: [PATCH 10/46] save --- Coplt.Graphics.Native/Api/FFI/Cmd.h | 4 +- Coplt.Graphics.Native/Api/FFI/Common.h | 5 + Coplt.Graphics.Native/D3d12/CMakeLists.txt | 7 +- .../D3d12/Include/ResState.h | 103 +++++ Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 69 ++++ Coplt.Graphics.Native/D3d12/Src/Barrier.h | 68 +++ Coplt.Graphics.Native/D3d12/Src/Context.cc | 19 + Coplt.Graphics.Native/D3d12/Src/Context.h | 9 + Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 3 + Coplt.Graphics.Native/D3d12/Src/Isolate.h | 2 + Coplt.Graphics.Native/D3d12/Src/Record.cc | 278 ++----------- Coplt.Graphics.Native/D3d12/Src/Record.h | 157 +------ .../D3d12/Src/RecordStorage.cc | 63 +++ .../D3d12/Src/RecordStorage.h | 47 +++ Coplt.Graphics.Native/D3d12/Src/ResState.cc | 386 ++++++++++++++++++ 15 files changed, 823 insertions(+), 397 deletions(-) create mode 100644 Coplt.Graphics.Native/D3d12/Include/ResState.h create mode 100644 Coplt.Graphics.Native/D3d12/Src/Barrier.cc create mode 100644 Coplt.Graphics.Native/D3d12/Src/Barrier.h create mode 100644 Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc create mode 100644 Coplt.Graphics.Native/D3d12/Src/RecordStorage.h create mode 100644 Coplt.Graphics.Native/D3d12/Src/ResState.cc diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index ce86052..d6d54ee 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -77,9 +77,11 @@ namespace Coplt #ifdef FFI_SRC operator bool() const { return IndexPlusOne == 0; } + u32 ResIndex() const { return IndexPlusOne - 1; } + FCmdRes& Get(FList& list) const { - const auto index = IndexPlusOne - 1; + const auto index = ResIndex(); if (index > list.m_len) COPLT_THROW("Index out of range"); return list[index]; diff --git a/Coplt.Graphics.Native/Api/FFI/Common.h b/Coplt.Graphics.Native/Api/FFI/Common.h index 370da4c..13de548 100644 --- a/Coplt.Graphics.Native/Api/FFI/Common.h +++ b/Coplt.Graphics.Native/Api/FFI/Common.h @@ -63,6 +63,7 @@ #endif #define COPLT_U32_MAX 4294967295 +#define COPLT_U64_MAX 18446744073709551615 #ifdef FFI_SRC #define COPLT_ENUM_FLAGS(Name, Type) enum class Name : Type;\ @@ -118,6 +119,10 @@ inline constexpr bool HasAnyFlags(Name a, Name b)\ {\ return (a & b) != 0;\ }\ +inline constexpr bool HasFlagsOnly(Name a, Name b)\ +{\ +return (a & ~(b)) == 0;\ +}\ enum class Name : Type #else #define COPLT_ENUM_FLAGS(Name, Type) enum class Name : Type diff --git a/Coplt.Graphics.Native/D3d12/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index 31ad918..62309ce 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -61,7 +61,12 @@ add_library(${target_name} SHARED Src/Record.cc Src/SwapChain.h Src/SwapChain.cc - Include/Access.h + Src/Barrier.h + Src/Barrier.cc + Include/ResState.h + Src/ResState.cc + Src/RecordStorage.h + Src/RecordStorage.cc ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "Coplt.Graphics.Native.D3d12") diff --git a/Coplt.Graphics.Native/D3d12/Include/ResState.h b/Coplt.Graphics.Native/D3d12/Include/ResState.h new file mode 100644 index 0000000..f0af867 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Include/ResState.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include "../../Api/FFI/Common.h" +#include "../../Api/FFI/Queue.h" + +namespace Coplt +{ + COPLT_ENUM_FLAGS(ResUseType, u8) + { + None, + Read = 1 << 0, + Write = 1 << 1, + ReadWrite = Read | Write, + }; + + COPLT_ENUM_FLAGS(ResAccess, u32) + { + None, + Common = COPLT_U32_MAX, + VertexBufferRead = 1 << 0, + ConstantBufferRead = 1 << 1, + IndexBufferRead = 1 << 2, + RenderTargetWrite = 1 << 3, + UnorderedAccessRead = 1 << 4, + UnorderedAccessWrite = 1 << 5, + DepthStencilRead = 1 << 6, + DepthStencilWrite = 1 << 7, + ShaderResourceRead = 1 << 8, + StreamOutputWrite = 1 << 9, + IndirectArgumentRead = 1 << 10, + CopySourceRead = 1 << 11, + CopyDestWrite = 1 << 12, + ResolveSourceRead = 1 << 13, + ResolveDestWrite = 1 << 14, + RayTracingAccelerationStructureRead = 1 << 15, + RayTracingAccelerationStructureWrite = 1 << 16, + ShadingRateSourceRead = 1 << 17, + VideoEncodeRead = 1 << 18, + VideoEncodeWrite = 1 << 19, + VideoDecodeRead = 1 << 20, + VideoDecodeWrite = 1 << 21, + VideoProcessRead = 1 << 22, + VideoProcessWrite = 1 << 23, + }; + + COPLT_ENUM_FLAGS(ResUsage, u16) + { + Common = 0, + VertexOrMesh = 1 << 0, + Pixel = 1 << 1, + Compute = 1 << 2, + RayTracing = 1 << 3, + BuildRayTracingAccelerationStructure = 1 << 4, + CopyRayTracingAccelerationStructure = 1 << 5, + EmitRayTracingAccelerationStructurePostBuildInfo = 1 << 6, + ClearUav = 1 << 7, + }; + + enum class ResLayout : u16 + { + Undefined = COPLT_U32_MAX, + Common = 0, + GenericRead, + RenderTarget, + UnorderedAccess, + DepthStencilWrite, + DepthStencilRead, + ShaderResource, + CopySource, + CopyDest, + ResolveSource, + ResolveDest, + ShaderRateSource, + VideoEncodeRead, + VideoEncodeWrite, + VideoDecodeRead, + VideoDecodeWrite, + VideoProcessRead, + VideoProcessWrite, + }; + + struct ResState + { + ResAccess Access{}; + ResUsage Usage{}; + ResLayout Layout{}; + }; + + bool IsValid(ResAccess access); + + ResUseType GetUseType(ResAccess access); + + bool IsReadOnly(ResAccess access); + + D3D12_RESOURCE_STATES GetResourceState(ResAccess access); + + D3D12_BARRIER_ACCESS GetBarrierAccess(ResAccess access); + + D3D12_BARRIER_LAYOUT GetBarrierLayout(ResLayout layout, FGpuQueueType queue, bool cross_queue); + + D3D12_BARRIER_SYNC GetBarrierSync(ResAccess access, ResUsage usage); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc new file mode 100644 index 0000000..15831c4 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -0,0 +1,69 @@ +#include "Barrier.h" + +using namespace Coplt; + +namespace Coplt::Enhanced +{ + EnhancedBarrierAnalyzer::EnhancedBarrierAnalyzer(const Rc& device) + : m_device(device) + { + } + + Rc EnhancedBarrierAnalyzer::CreateRecorder(const Rc& storage) + { + return new EnhancedBarrierRecorder(m_device, storage); + } + + EnhancedBarrierRecorder::ResInfo::ResInfo(const FCmdResType ResType) : ResType(ResType) + { + } + + EnhancedBarrierRecorder::EnhancedBarrierRecorder(const Rc& device, const Rc& storage) + : m_device(device), m_storage(storage) + { + } + + void EnhancedBarrierRecorder::Clear() + { + m_resources.clear(); + } + + void EnhancedBarrierRecorder::StartRecord(const std::span resources) + { + Clear(); + m_resources.reserve(resources.size()); + for (usize i = 0; i < resources.size(); ++i) + { + const auto& res = resources[i]; + m_resources.push_back(ResInfo(res.Type)); + } + } + + void EnhancedBarrierRecorder::EndRecord() + { + } + + void EnhancedBarrierRecorder::OnUse(const FCmdResRef ResRef, const ResAccess Access, const ResUsage Usage, const ResLayout Layout) + { + const auto ResIndex = ResRef.ResIndex(); + auto& info = m_resources[ResIndex]; + if (info.InfoState == InfoState::Unused) + { + info.InfoState = InfoState::Input; + info.State = ResState{ + .Access = Access, + .Usage = Usage, + .Layout = Layout, + }; + return; + } + else if (info.InfoState == InfoState::Input) + { + // todo + } + else + { + // todo + } + } +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h new file mode 100644 index 0000000..47e804a --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -0,0 +1,68 @@ +#pragma once + +#include "Device.h" +#include "RecordStorage.h" +#include "../../Api/Include/Object.h" +#include "../../Api/FFI/Cmd.h" +#include "../Include/ResState.h" + +namespace Coplt +{ + struct I3d12BarrierRecorder; + + COPLT_INTERFACE_DEFINE(I3d12BarrierAnalyzer, "792f273c-376d-4027-af99-0d14d3d71302", FUnknown) + { + virtual Rc CreateRecorder(const Rc& storage) = 0; + }; + + COPLT_INTERFACE_DEFINE(I3d12BarrierRecorder, "115741ea-2138-4c92-9f4f-94f91d254587", FUnknown) + { + virtual void Clear() = 0; + virtual void StartRecord(std::span resources) = 0; + virtual void EndRecord() = 0; + + virtual void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) = 0; + }; + + namespace Enhanced + { + struct EnhancedBarrierAnalyzer final : Object + { + Rc m_device; + + explicit EnhancedBarrierAnalyzer(const Rc& device); + + Rc CreateRecorder(const Rc& storage) override; + }; + + struct EnhancedBarrierRecorder final : Object + { + enum class InfoState : u8 + { + Unused, + Input, + Used, + }; + + struct ResInfo + { + ResState State{}; + const FCmdResType ResType{}; + InfoState InfoState{}; + + explicit ResInfo(FCmdResType ResType); + }; + + Rc m_device{}; + Rc m_storage{}; + std::vector m_resources{}; + + explicit EnhancedBarrierRecorder(const Rc& device, const Rc& storage); + + void Clear() override; + void StartRecord(std::span resources) override; + void EndRecord() override; + void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) override; + }; + } +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.cc b/Coplt.Graphics.Native/D3d12/Src/Context.cc index f29d3a9..23a87e8 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Context.cc @@ -356,6 +356,20 @@ D3d12RentedCommandList::operator bool() const noexcept return static_cast(m_pool); } +void D3d12RentedCommandList::Close() +{ + try + { + m_list->Close(); + } + catch (...) + { + m_pool = {}; + m_list = {}; + std::rethrow_exception(std::current_exception()); + } +} + D3d12RentedCommandAllocator::D3d12RentedCommandAllocator(const Rc& pool, ComPtr&& allocator) : m_pool(pool), m_allocator(std::move(allocator)) { @@ -380,3 +394,8 @@ D3d12RentedCommandList D3d12RentedCommandAllocator::RentCommandList() const } return D3d12RentedCommandList(m_pool, std::move(list)); } + +D3d12RentedCommandAllocator::operator bool() const noexcept +{ + return static_cast(m_pool); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.h b/Coplt.Graphics.Native/D3d12/Src/Context.h index a1420a6..9fd6489 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.h +++ b/Coplt.Graphics.Native/D3d12/Src/Context.h @@ -126,6 +126,10 @@ namespace Coplt explicit D3d12CommandList(const D3d12RentedCommandAllocator& allocator); + private: + friend struct D3d12RentedCommandList; + friend struct D3d12RentedCommandAllocator; + void Reset(const D3d12RentedCommandAllocator& allocator) const; void Close() const; }; @@ -149,6 +153,8 @@ namespace Coplt D3d12CommandList& operator*() const noexcept; operator bool() const noexcept; + + void Close(); }; // 必须等待队列 fence 完成才能析构,或者可以 move 走 @@ -157,6 +163,7 @@ namespace Coplt Rc m_pool{}; ComPtr m_allocator{}; + D3d12RentedCommandAllocator() = default; explicit D3d12RentedCommandAllocator(const Rc& pool, ComPtr&& allocator); ~D3d12RentedCommandAllocator(); @@ -167,5 +174,7 @@ namespace Coplt D3d12RentedCommandAllocator& operator=(const D3d12RentedCommandAllocator&) = delete; D3d12RentedCommandList RentCommandList() const; + + operator bool() const noexcept; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index eb57e82..df8c1ce 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -4,6 +4,7 @@ #include "SwapChain.h" #include "Context.h" #include "../../Api/FFI/Record.h" +#include "Barrier.h" using namespace Coplt; @@ -80,6 +81,8 @@ D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCre #pragma endregion + m_barrier_analyzer = new Enhanced::EnhancedBarrierAnalyzer(m_device); + m_cmd_alloc_pool = new D3d12CommandListPoolCluster(m_device); m_event = CreateEventW(nullptr, false, false, nullptr); diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index 22df136..3682713 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -28,11 +28,13 @@ namespace Coplt }; struct ID3d12GpuRecord; + struct I3d12BarrierAnalyzer; struct D3d12GpuIsolate final : GpuObject, FGpuIsolateData { using RecordQueue = moodycamel::ConcurrentQueue>; + Rc m_barrier_analyzer{}; HANDLE m_event{}; Box m_waiting_record{}; Box m_record_pool{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 7a67bc0..fedeb32 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -3,31 +3,15 @@ #include "Output.h" using namespace Coplt; -using namespace Recording; - -ResUseType Recording::GetUseType(const D3D12_BARRIER_ACCESS access, const ResUseType UavUse) -{ - if (access & D3D12_BARRIER_ACCESS_NO_ACCESS) return ResUseType::None; - if (access & D3D12_BARRIER_ACCESS_UNORDERED_ACCESS) return UavUse; - if ( - access & D3D12_BARRIER_ACCESS_RENDER_TARGET || access & D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE - || access & D3D12_BARRIER_ACCESS_STREAM_OUTPUT || access & D3D12_BARRIER_ACCESS_COPY_DEST - || access & D3D12_BARRIER_ACCESS_RESOLVE_DEST || access & D3D12_BARRIER_ACCESS_RAYTRACING_ACCELERATION_STRUCTURE_WRITE - || access & D3D12_BARRIER_ACCESS_VIDEO_DECODE_WRITE - || access & D3D12_BARRIER_ACCESS_VIDEO_PROCESS_WRITE - || access & D3D12_BARRIER_ACCESS_VIDEO_ENCODE_WRITE - ) - return ResUseType::Write; - return ResUseType::Read; -} D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) : FGpuRecordData(isolate->m_device->m_instance->m_allocator.get()), m_device(isolate->m_device) { m_isolate_id = isolate->m_object_id; m_record_id = isolate->m_record_inc++; - m_barrier_analyzer = new D3d12BarrierAnalyzer(); m_context = new D3d12RecordContext(isolate); + m_storage = new D3d12RecordStorage(isolate, m_context); + m_barrier_recorder = isolate->m_barrier_analyzer->CreateRecorder(m_storage); Context = m_context.get(); } @@ -51,6 +35,11 @@ const FGpuRecordData* D3d12GpuRecord::Data() const noexcept return this; } +void D3d12GpuRecord::RegisterWaitPoint(QueueWaitPoint&& wait_point) +{ + m_queue_wait_points.push_back(std::move(wait_point)); +} + void D3d12GpuRecord::WaitAndRecycle(const HANDLE event) { for (auto& wait_point : m_queue_wait_points) @@ -63,7 +52,8 @@ void D3d12GpuRecord::WaitAndRecycle(const HANDLE event) void D3d12GpuRecord::Recycle() { m_queue_wait_points.clear(); - m_list = {}; + m_barrier_recorder->Clear(); + m_storage->Clear(); m_context->Recycle(); m_resources_owner.clear(); ClearData(); @@ -90,13 +80,7 @@ void D3d12GpuRecord::DoEnd() COPLT_THROW("End cannot be called multiple times"); if (Resources.size() >= std::numeric_limits::max()) COPLT_THROW("Too many resources"); - m_resources_owner.reserve(Resources.size()); - for (u32 i = 0; i < Resources.size(); ++i) - { - const auto& res = Resources[i]; - m_resources_owner.push_back(Rc::UnsafeClone(res.GetObjectPtr())); - } - Analyze(); + ReadyResource(); Interpret(); Ended = true; } @@ -106,26 +90,28 @@ FCmdRes& D3d12GpuRecord::GetRes(const FCmdResRef& ref) return ref.Get(Resources); } -void D3d12GpuRecord::Analyze() +D3d12RentedCommandList& D3d12GpuRecord::CurList() const { - m_barrier_analyzer->Analyzer(this); + return m_storage->CurList(); } -void D3d12GpuRecord::Interpret() +void D3d12GpuRecord::ReadyResource() { - auto allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(ToListType(Mode)); - m_list = allocator.RentCommandList(); - m_context->m_recycled_command_allocators.push_back(std::move(allocator)); - m_barrier_analyzer->Interpret(this); - m_list->Close(); + m_resources_owner.reserve(Resources.size()); + for (u32 i = 0; i < Resources.size(); ++i) + { + const auto& res = Resources[i]; + m_resources_owner.push_back(Rc::UnsafeClone(res.GetObjectPtr())); + } } -void D3d12GpuRecord::Interpret(const u32 cmd_index, const u32 cmd_count) +void D3d12GpuRecord::Interpret() { + m_storage->StartRecord(Mode); + m_barrier_recorder->StartRecord(Resources.AsSpan()); const auto commands = Commands.AsSpan(); - for (u32 n = 0; n < cmd_count; ++n) + for (u32 i = 0; i < commands.size(); ++i) { - const auto i = cmd_index + n; const auto& command = commands[i]; switch (command.Type) { @@ -148,12 +134,15 @@ void D3d12GpuRecord::Interpret(const u32 cmd_index, const u32 cmd_count) continue; } } + m_barrier_recorder->EndRecord(); + m_storage->EndRecord(); } void D3d12GpuRecord::Interpret_ClearColor(u32 i, const FCmdClearColor& cmd) { + m_barrier_recorder->OnUse(cmd.Image, ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); const auto rtv = GetRtv(GetRes(cmd.Image)); - m_list->g0->ClearRenderTargetView( + CurList()->g0->ClearRenderTargetView( rtv, cmd.Color, cmd.RectCount, cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) ); @@ -161,212 +150,17 @@ void D3d12GpuRecord::Interpret_ClearColor(u32 i, const FCmdClearColor& cmd) void D3d12GpuRecord::Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd) { + m_barrier_recorder->OnUse(cmd.Image, ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); const auto dsv = GetDsv(GetRes(cmd.Image)); D3D12_CLEAR_FLAGS flags{}; if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Depth)) flags |= D3D12_CLEAR_FLAG_DEPTH; if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Stencil)) flags |= D3D12_CLEAR_FLAG_STENCIL; - m_list->g0->ClearDepthStencilView( + CurList()->g0->ClearDepthStencilView( dsv, flags, cmd.Depth, cmd.Stencil, cmd.RectCount, cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) ); } -D3d12BarrierAnalyzer::ResInfo::ResInfo(const FCmdResType ResType) : ResInfo() -{ - this->ResType = ResType; -} - -bool D3d12BarrierAnalyzer::ResInfo::IsReadCompatible(const D3D12_BARRIER_LAYOUT Layout) const -{ - return Type == ResUseType::Read && this->Layout == Layout; -} - -bool D3d12BarrierAnalyzer::ResInfo::MergeRead(const D3D12_BARRIER_ACCESS Access, const D3D12_BARRIER_SYNC Sync) -{ - const auto old_access = Access; - const auto old_sync = Sync; - this->Access |= Access; - this->Sync |= Sync; - return this->Access != old_access || this->Sync != old_sync; -} - -D3d12BarrierAnalyzer::D3d12BarrierAnalyzer() : m_record(NonNull::Unchecked(nullptr)) -{ -} - -void D3d12BarrierAnalyzer::Recycle() -{ - m_res_inputs.clear(); - m_res_outputs.clear(); - m_resources.clear(); - m_parts.clear(); - m_begin_global_barriers.clear(); - m_begin_texture_barriers.clear(); - m_begin_buffer_barriers.clear(); - m_end_global_barriers.clear(); - m_end_texture_barriers.clear(); - m_end_buffer_barriers.clear(); - m_current_barrier_begin_part = 0; - m_current_cmd_part = 0; -} - -void D3d12BarrierAnalyzer::Analyzer(const NonNull record) -{ - Recycle(); - m_record = record; - m_resources.reserve(m_record->Resources.size()); - for (u32 i = 0; i < m_record->Resources.size(); ++i) - { - const auto& res = m_record->Resources[i]; - m_resources.push_back(ResInfo(res.Type)); - } - m_parts.push_back(Part{.Barrier = {.Type = PartType::BarrierBegin}}); - m_parts.push_back(Part{.Cmd = {}}); - m_current_barrier_begin_part = 0; - m_current_cmd_part = 1; - const auto commands = m_record->Commands.AsSpan(); - if (commands.size() >= std::numeric_limits::max()) - COPLT_THROW("Too many commands"); - for (u32 i = 0; i < commands.size(); ++i) - { - const auto& command = commands[i]; - switch (command.Type) - { - case FCmdType::None: - case FCmdType::Label: - case FCmdType::BeginScope: - case FCmdType::EndScope: - goto CmdNext; - case FCmdType::ClearColor: - Analyze_ClearColor(i, command.ClearColor); - goto CmdNext; - case FCmdType::ClearDepthStencil: - Analyze_ClearDepthStencil(i, command.ClearDepthStencil); - goto CmdNext; - } - COPLT_THROW_FMT("Unknown command type {}", static_cast(command.Type)); - CmdNext: - CmdNext(); - continue; - } - BuildInputOutput(); -} - -D3d12BarrierAnalyzer::ResInfo& D3d12BarrierAnalyzer::GetInfo(const FCmdResRef& ref) -{ - return m_resources[ref.IndexPlusOne - 1]; -} - -std::pair, NonNull> D3d12BarrierAnalyzer::Get(const FCmdResRef& ref) -{ - return {&ref.Get(m_record->Resources), &m_resources[ref.IndexPlusOne - 1]}; -} - -NonNull D3d12BarrierAnalyzer::GetResource(const u32 index) const -{ - const auto& res = m_record->Resources[index]; - return Coplt::GetResource(res); -} - -NonNull D3d12BarrierAnalyzer::GetBufferData(const u32 index) const -{ - const auto& res = m_record->Resources[index]; - return Coplt::GetBufferData(res); -} - -NonNull D3d12BarrierAnalyzer::GetImageData(u32 index) const -{ - const auto& res = m_record->Resources[index]; - return Coplt::GetImageData(res); -} - -void D3d12BarrierAnalyzer::MarkUse( - ResInfo& Info, const D3D12_BARRIER_ACCESS Access, const D3D12_BARRIER_LAYOUT Layout, D3D12_BARRIER_SYNC Sync, const ResUseType UavUse -) -{ - const auto type = GetUseType(Access, UavUse); - if (Info.First) - { - Info.First = false; - Info.Type = type; - Info.Access = Access; - Info.Layout = Layout; - Info.Sync = Sync; - return; - } - COPLT_THROW("TODO"); - // if (type == ResUseType::Read && Info.IsReadCompatible(Layout)) - // { - // Info.MergeRead(Access, Stages); - // return; - // } - // const auto& cur_barrier = m_parts[m_current_barrier_begin_part].Barrier; - // const auto& cur_cmd = m_parts[m_current_cmd_part].Cmd; - // if (Info.WasDefInput) - // { - // - // } - // else if (Info.CurrentBarrierPart == COPLT_U32_MAX) - // { - // - // } - // return; -} - -void D3d12BarrierAnalyzer::CmdNext() -{ - m_parts[m_current_cmd_part].Cmd.Count++; -} - -void D3d12BarrierAnalyzer::BuildInputOutput() -{ - for (u32 i = 0; i < m_resources.size(); ++i) - { - const auto& res = m_resources[i]; - const auto use = ResUse{ - .ResIndex = i, - .Layout = res.Layout, - .Access = res.Access, - .Sync = res.Sync, - .Type = res.Type, - }; - m_res_outputs.push_back(use); - if (res.WasDefInput) continue; - m_res_inputs.push_back(use); - } -} - -void D3d12BarrierAnalyzer::Analyze_ClearColor(const u32 i, const FCmdClearColor& cmd) -{ - auto& info = GetInfo(cmd.Image); - MarkUse(info, D3D12_BARRIER_ACCESS_RENDER_TARGET, D3D12_BARRIER_LAYOUT_RENDER_TARGET, D3D12_BARRIER_SYNC_RENDER_TARGET); -} - -void D3d12BarrierAnalyzer::Analyze_ClearDepthStencil(const u32 i, const FCmdClearDepthStencil& cmd) -{ - auto& info = GetInfo(cmd.Image); - MarkUse(info, D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE, D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE, D3D12_BARRIER_SYNC_DEPTH_STENCIL); -} - -void D3d12BarrierAnalyzer::Interpret(NonNull record) -{ - for (auto& part : m_parts) - { - switch (part.Type) - { - case PartType::Cmd: - record->Interpret(part.Cmd.Index, part.Cmd.Count); - break; - case PartType::BarrierBegin: - // todo - break; - case PartType::BarrierEnd: - // todo - break; - } - } -} - NonNull Coplt::GetResource(const FCmdRes& res) { switch (res.Type) @@ -470,17 +264,3 @@ CD3DX12_CPU_DESCRIPTOR_HANDLE Coplt::GetDsv(const FCmdRes& res) } COPLT_THROW("Unreachable"); } - -D3D12_COMMAND_LIST_TYPE Coplt::ToListType(const FGpuRecordMode value) -{ - switch (value) - { - case FGpuRecordMode::Direct: - return D3D12_COMMAND_LIST_TYPE_DIRECT; - case FGpuRecordMode::Compute: - return D3D12_COMMAND_LIST_TYPE_COMPUTE; - case FGpuRecordMode::Copy: - return D3D12_COMMAND_LIST_TYPE_COPY; - } - return D3D12_COMMAND_LIST_TYPE_DIRECT; -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index c80d682..9e04cbd 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -1,49 +1,20 @@ #pragma once +#include "Barrier.h" #include "Context.h" #include "Isolate.h" +#include "RecordStorage.h" #include "../../Api/FFI/Record.h" #include "../../Api/Include/GpuObject.h" namespace Coplt { - struct I3d12BarrierAnalyzer; - struct D3d12BarrierAnalyzer; - struct D3d12GpuRecord; - - namespace Recording - { - enum class ResUseType : u8 - { - None, - Read, - Write, - ReadWrite, - }; - - ResUseType GetUseType(D3D12_BARRIER_ACCESS access, ResUseType UavUse = ResUseType::ReadWrite); - - struct ResUse - { - u32 ResIndex{}; - D3D12_BARRIER_LAYOUT Layout{}; - D3D12_BARRIER_ACCESS Access{}; - D3D12_BARRIER_SYNC Sync{}; - ResUseType Type{}; - }; - } - COPLT_INTERFACE_DEFINE(ID3d12GpuRecord, "57a9c7f9-1ec0-4d78-89b9-e547667c50b3", FGpuRecord) { - using ResUseType = Recording::ResUseType; - - Rc m_barrier_analyzer{}; - std::vector> m_resources_owner{}; - std::vector m_queue_wait_points{}; - virtual FGpuRecordData* Data() noexcept = 0; virtual const FGpuRecordData* Data() const noexcept = 0; + virtual void RegisterWaitPoint(QueueWaitPoint&& wait_point) = 0; virtual void WaitAndRecycle(HANDLE event) = 0; virtual void Recycle() = 0; @@ -56,7 +27,10 @@ namespace Coplt u64 m_record_id{}; Rc m_device{}; Rc m_context{}; - D3d12RentedCommandList m_list{}; + Rc m_storage{}; + Rc m_barrier_recorder{}; + std::vector> m_resources_owner{}; + std::vector m_queue_wait_points{}; explicit D3d12GpuRecord(NonNull isolate); @@ -65,6 +39,7 @@ namespace Coplt FGpuRecordData* Data() noexcept override; const FGpuRecordData* Data() const noexcept override; + void RegisterWaitPoint(QueueWaitPoint&& wait_point) override; void WaitAndRecycle(HANDLE event) override; void Recycle() override; @@ -74,127 +49,17 @@ namespace Coplt FCmdRes& GetRes(const FCmdResRef& ref); - void Analyze(); - void Interpret(); - void Interpret(u32 cmd_index, u32 cmd_count); + D3d12RentedCommandList& CurList() const; + void ReadyResource(); + void Interpret(); void Interpret_ClearColor(u32 i, const FCmdClearColor& cmd); void Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); }; - COPLT_INTERFACE_DEFINE(I3d12BarrierAnalyzer, "80086589-a583-41de-9aec-205afc022cd9", FUnknown) - { - using ResUseType = Recording::ResUseType; - using ResUse = Recording::ResUse; - - std::vector m_res_inputs{}; - std::vector m_res_outputs{}; - - virtual void Recycle() = 0; - virtual void Analyzer(NonNull record) = 0; - virtual void Interpret(NonNull record) = 0; - }; - - struct D3d12BarrierAnalyzer final : Object - { - private: - struct ResInfo - { - u32 CurrentBarrierPart{COPLT_U32_MAX}; - D3D12_BARRIER_LAYOUT Layout{}; - D3D12_BARRIER_ACCESS Access{}; - D3D12_BARRIER_SYNC Sync{}; - ResUseType Type{}; - FCmdResType ResType{}; - bool WasDefInput{}; - bool First{true}; - - ResInfo() = default; - explicit ResInfo(FCmdResType ResType); - - bool IsReadCompatible(D3D12_BARRIER_LAYOUT Layout) const; - // 返回是否改变 - bool MergeRead(D3D12_BARRIER_ACCESS Access, D3D12_BARRIER_SYNC Sync); - }; - - enum class PartType : u32 - { - Cmd, - BarrierBegin, - BarrierEnd, - }; - - struct BarrierPart - { - PartType Type{}; - u32 GlobalIndex{COPLT_U32_MAX}; - u32 GlobalCount{}; - u32 TextureIndex{COPLT_U32_MAX}; - u32 TextureCount{}; - u32 BufferIndex{COPLT_U32_MAX}; - u32 BufferCount{}; - }; - - struct CmdPart - { - PartType Type{PartType::Cmd}; - u32 Index{}; - u32 Count{}; - }; - - union Part - { - PartType Type{}; - BarrierPart Barrier; - CmdPart Cmd; - }; - - NonNull m_record; - std::vector m_resources{}; - std::vector m_parts{}; - u32 m_current_barrier_begin_part{}; - u32 m_current_cmd_part{}; - std::vector m_begin_global_barriers{}; - std::vector m_begin_texture_barriers{}; - std::vector m_begin_buffer_barriers{}; - std::vector m_end_global_barriers{}; - std::vector m_end_texture_barriers{}; - std::vector m_end_buffer_barriers{}; - - public: - explicit D3d12BarrierAnalyzer(); - - void Recycle() override; - void Analyzer(NonNull record) override; - - private: - ResInfo& GetInfo(const FCmdResRef& ref); - std::pair, NonNull> Get(const FCmdResRef& ref); - NonNull GetResource(u32 index) const; - NonNull GetBufferData(u32 index) const; - NonNull GetImageData(u32 index) const; - - void MarkUse( - ResInfo& Info, - D3D12_BARRIER_ACCESS Access, D3D12_BARRIER_LAYOUT Layout, D3D12_BARRIER_SYNC Sync, - ResUseType UavUse = ResUseType::ReadWrite - ); - void CmdNext(); - - void BuildInputOutput(); - - void Analyze_ClearColor(u32 i, const FCmdClearColor& cmd); - void Analyze_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); - - public: - void Interpret(NonNull record) override; - }; - NonNull GetResource(const FCmdRes& res); NonNull GetBufferData(const FCmdRes& res); NonNull GetImageData(const FCmdRes& res); CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv(const FCmdRes& res); CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv(const FCmdRes& res); - - D3D12_COMMAND_LIST_TYPE ToListType(const FGpuRecordMode value); } diff --git a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc new file mode 100644 index 0000000..77781eb --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc @@ -0,0 +1,63 @@ +#include "RecordStorage.h" + +using namespace Coplt; + +D3d12RecordStorage::D3d12RecordStorage(NonNull isolate, const Rc& context) + : m_device(isolate->m_device), m_context(context) +{ +} + +void D3d12RecordStorage::Clear() +{ + m_cur_list = {}; + m_result_lists.clear(); +} + +void D3d12RecordStorage::StartRecord(const FGpuRecordMode Mode) +{ + m_cmd_allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(ToListType(Mode)); + m_cur_list = m_cmd_allocator.RentCommandList(); +} + +void D3d12RecordStorage::EndRecord() +{ + m_result_lists.push_back(std::move(m_cur_list)); + for (auto& list : m_result_lists) + { + list.Close(); + } +} + +void D3d12RecordStorage::AfterSubmit() +{ + m_context->m_recycled_command_allocators.push_back(std::move(m_cmd_allocator)); +} + +void D3d12RecordStorage::Split() +{ + m_result_lists.push_back(std::exchange(m_cur_list, m_cmd_allocator.RentCommandList())); +} + +D3d12RentedCommandList& D3d12RecordStorage::CurList() +{ + return m_cur_list; +} + +std::span D3d12RecordStorage::Lists() +{ + return m_result_lists; +} + +D3D12_COMMAND_LIST_TYPE Coplt::ToListType(const FGpuRecordMode value) +{ + switch (value) + { + case FGpuRecordMode::Direct: + return D3D12_COMMAND_LIST_TYPE_DIRECT; + case FGpuRecordMode::Compute: + return D3D12_COMMAND_LIST_TYPE_COMPUTE; + case FGpuRecordMode::Copy: + return D3D12_COMMAND_LIST_TYPE_COPY; + } + return D3D12_COMMAND_LIST_TYPE_DIRECT; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h new file mode 100644 index 0000000..eae8037 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h @@ -0,0 +1,47 @@ +#pragma once + +#include "Context.h" +#include "../../Api/Include/Object.h" +#include "../../Api/FFI/Record.h" +#include "Isolate.h" + +namespace Coplt +{ + COPLT_INTERFACE_DEFINE(ID3d12RecordStorage, "ba14d287-5cea-4715-b655-7ad81184fd84", FUnknown) + { + virtual void Clear() = 0; + + virtual void StartRecord(FGpuRecordMode Mode) = 0; + virtual void EndRecord() = 0; + virtual void AfterSubmit() = 0; + + virtual void Split() = 0; + virtual D3d12RentedCommandList& CurList() = 0; + + virtual std::span Lists() = 0; + }; + + struct D3d12RecordStorage final : Object + { + Rc m_device{}; + Rc m_context{}; + D3d12RentedCommandAllocator m_cmd_allocator{}; + D3d12RentedCommandList m_cur_list{}; + std::vector m_result_lists{}; + + explicit D3d12RecordStorage(NonNull isolate, const Rc& context); + + void Clear() override; + + void StartRecord(FGpuRecordMode Mode) override; + void EndRecord() override; + void AfterSubmit() override; + + void Split() override; + D3d12RentedCommandList& CurList() override; + + std::span Lists() override; + }; + + D3D12_COMMAND_LIST_TYPE ToListType(FGpuRecordMode value); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/ResState.cc b/Coplt.Graphics.Native/D3d12/Src/ResState.cc new file mode 100644 index 0000000..220852a --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/ResState.cc @@ -0,0 +1,386 @@ +#include "../Include/ResState.h" + +using namespace Coplt; + +bool Coplt::IsValid(const ResAccess access) +{ + switch (access) + { + case ResAccess::None: + case ResAccess::Common: + return true; + case ResAccess::UnorderedAccessRead: + case ResAccess::UnorderedAccessWrite: + case ResAccess::UnorderedAccessRead | ResAccess::UnorderedAccessWrite: + return HasFlagsOnly(access, ResAccess::UnorderedAccessRead | ResAccess::UnorderedAccessWrite); + case ResAccess::RayTracingAccelerationStructureRead | ResAccess::RayTracingAccelerationStructureWrite: + return false; + case ResAccess::RayTracingAccelerationStructureRead: + case ResAccess::RayTracingAccelerationStructureWrite: + return HasFlagsOnly(access, ResAccess::RayTracingAccelerationStructureRead | ResAccess::RayTracingAccelerationStructureWrite); + case ResAccess::RenderTargetWrite: + case ResAccess::DepthStencilWrite: + case ResAccess::StreamOutputWrite: + case ResAccess::CopyDestWrite: + case ResAccess::ResolveDestWrite: + case ResAccess::VideoEncodeWrite: + case ResAccess::VideoDecodeWrite: + case ResAccess::VideoProcessWrite: + return true; + default: + break; + } + if (HasFlagsOnly( + access, + ResAccess::VertexBufferRead | ResAccess::ConstantBufferRead | ResAccess::IndexBufferRead | + ResAccess::DepthStencilRead | ResAccess::ShaderResourceRead | ResAccess::IndirectArgumentRead | + ResAccess::CopySourceRead | ResAccess::ResolveSourceRead | ResAccess::ShadingRateSourceRead | + ResAccess::VideoEncodeRead | ResAccess::VideoDecodeRead | ResAccess::VideoProcessRead + )) + return true; + return false; +} + +ResUseType Coplt::GetUseType(const ResAccess access) +{ + auto usage = ResUseType::None; + if (access == ResAccess::Common) return ResUseType::ReadWrite; + if (HasAnyFlags( + access, + ResAccess::VertexBufferRead | ResAccess::ConstantBufferRead | ResAccess::IndexBufferRead | ResAccess::UnorderedAccessRead | + ResAccess::DepthStencilRead | ResAccess::ShaderResourceRead | ResAccess::IndirectArgumentRead | ResAccess::CopySourceRead | + ResAccess::ResolveSourceRead | ResAccess::RayTracingAccelerationStructureRead | ResAccess::ShadingRateSourceRead | + ResAccess::VideoEncodeRead | ResAccess::VideoDecodeRead | ResAccess::VideoProcessRead + )) + usage = ResUseType::Read; + if (HasAnyFlags( + access, + ResAccess::RenderTargetWrite | ResAccess::UnorderedAccessWrite | ResAccess::DepthStencilWrite | ResAccess::StreamOutputWrite | + ResAccess::CopyDestWrite | ResAccess::ResolveDestWrite | ResAccess::RayTracingAccelerationStructureWrite | + ResAccess::VideoEncodeWrite | ResAccess::VideoDecodeWrite | ResAccess::VideoProcessWrite + )) + usage = ResUseType::Write; + return usage; +} + +bool Coplt::IsReadOnly(const ResAccess access) +{ + return HasFlagsOnly( + access, + ResAccess::VertexBufferRead | ResAccess::ConstantBufferRead | ResAccess::IndexBufferRead | ResAccess::UnorderedAccessRead | + ResAccess::DepthStencilRead | ResAccess::ShaderResourceRead | ResAccess::IndirectArgumentRead | ResAccess::CopySourceRead | + ResAccess::ResolveSourceRead | ResAccess::RayTracingAccelerationStructureRead | ResAccess::ShadingRateSourceRead | + ResAccess::VideoEncodeRead | ResAccess::VideoDecodeRead | ResAccess::VideoProcessRead + ); +} + +D3D12_RESOURCE_STATES Coplt::GetResourceState(const ResAccess access) +{ + D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COMMON; + switch (access) + { + case ResAccess::None: + case ResAccess::Common: + return D3D12_RESOURCE_STATE_COMMON; + case ResAccess::RenderTargetWrite: + return D3D12_RESOURCE_STATE_RENDER_TARGET; + case ResAccess::DepthStencilWrite: + return D3D12_RESOURCE_STATE_DEPTH_WRITE; + case ResAccess::UnorderedAccessRead | ResAccess::UnorderedAccessWrite: + case ResAccess::UnorderedAccessRead: + case ResAccess::UnorderedAccessWrite: + return D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + case ResAccess::StreamOutputWrite: + return D3D12_RESOURCE_STATE_STREAM_OUT; + case ResAccess::CopyDestWrite: + return D3D12_RESOURCE_STATE_COPY_DEST; + case ResAccess::ResolveDestWrite: + return D3D12_RESOURCE_STATE_RESOLVE_DEST; + case ResAccess::RayTracingAccelerationStructureRead: + case ResAccess::RayTracingAccelerationStructureWrite: + return D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE; + case ResAccess::VideoEncodeWrite: + return D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE; + case ResAccess::VideoDecodeWrite: + return D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE; + case ResAccess::VideoProcessWrite: + return D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE; + default: + break; + } + if (HasAnyFlags(access, ResAccess::VertexBufferRead | ResAccess::ConstantBufferRead)) + state |= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; + if (HasAnyFlags(access, ResAccess::IndexBufferRead)) + state |= D3D12_RESOURCE_STATE_INDEX_BUFFER; + if (HasAnyFlags(access, ResAccess::DepthStencilRead)) + state |= D3D12_RESOURCE_STATE_DEPTH_READ; + if (HasAnyFlags(access, ResAccess::ShaderResourceRead)) + state |= D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE; + if (HasAnyFlags(access, ResAccess::IndirectArgumentRead)) + state |= D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT; + if (HasAnyFlags(access, ResAccess::CopySourceRead)) + state |= D3D12_RESOURCE_STATE_COPY_SOURCE; + if (HasAnyFlags(access, ResAccess::ResolveSourceRead)) + state |= D3D12_RESOURCE_STATE_RESOLVE_SOURCE; + if (HasAnyFlags(access, ResAccess::ShadingRateSourceRead)) + state |= D3D12_RESOURCE_STATE_SHADING_RATE_SOURCE; + if (HasAnyFlags(access, ResAccess::VideoEncodeRead)) + state |= D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ; + if (HasAnyFlags(access, ResAccess::VideoDecodeRead)) + state |= D3D12_RESOURCE_STATE_VIDEO_DECODE_READ; + if (HasAnyFlags(access, ResAccess::VideoProcessRead)) + state |= D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ; + return state; +} + +D3D12_BARRIER_ACCESS Coplt::GetBarrierAccess(const ResAccess access) +{ + D3D12_BARRIER_ACCESS ba = D3D12_BARRIER_ACCESS_COMMON; + switch (access) + { + case ResAccess::None: + return D3D12_BARRIER_ACCESS_NO_ACCESS; + case ResAccess::Common: + return D3D12_BARRIER_ACCESS_COMMON; + case ResAccess::RenderTargetWrite: + return D3D12_BARRIER_ACCESS_RENDER_TARGET; + case ResAccess::DepthStencilWrite: + return D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE; + case ResAccess::UnorderedAccessRead | ResAccess::UnorderedAccessWrite: + case ResAccess::UnorderedAccessRead: + case ResAccess::UnorderedAccessWrite: + return D3D12_BARRIER_ACCESS_UNORDERED_ACCESS; + case ResAccess::StreamOutputWrite: + return D3D12_BARRIER_ACCESS_STREAM_OUTPUT; + case ResAccess::CopyDestWrite: + return D3D12_BARRIER_ACCESS_COPY_DEST; + case ResAccess::ResolveDestWrite: + return D3D12_BARRIER_ACCESS_RESOLVE_DEST; + case ResAccess::RayTracingAccelerationStructureRead: + return D3D12_BARRIER_ACCESS_RAYTRACING_ACCELERATION_STRUCTURE_READ; + case ResAccess::RayTracingAccelerationStructureWrite: + return D3D12_BARRIER_ACCESS_RAYTRACING_ACCELERATION_STRUCTURE_WRITE; + case ResAccess::VideoEncodeWrite: + return D3D12_BARRIER_ACCESS_VIDEO_ENCODE_WRITE; + case ResAccess::VideoDecodeWrite: + return D3D12_BARRIER_ACCESS_VIDEO_DECODE_WRITE; + case ResAccess::VideoProcessWrite: + return D3D12_BARRIER_ACCESS_VIDEO_PROCESS_WRITE; + default: + break; + } + if (HasAnyFlags(access, ResAccess::VertexBufferRead)) + ba |= D3D12_BARRIER_ACCESS_VERTEX_BUFFER; + if (HasAnyFlags(access, ResAccess::ConstantBufferRead)) + ba |= D3D12_BARRIER_ACCESS_CONSTANT_BUFFER; + if (HasAnyFlags(access, ResAccess::IndexBufferRead)) + ba |= D3D12_BARRIER_ACCESS_INDEX_BUFFER; + if (HasAnyFlags(access, ResAccess::DepthStencilRead)) + ba |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_READ; + if (HasAnyFlags(access, ResAccess::ShaderResourceRead)) + ba |= D3D12_BARRIER_ACCESS_SHADER_RESOURCE; + if (HasAnyFlags(access, ResAccess::IndirectArgumentRead)) + ba |= D3D12_BARRIER_ACCESS_INDIRECT_ARGUMENT; + if (HasAnyFlags(access, ResAccess::CopySourceRead)) + ba |= D3D12_BARRIER_ACCESS_COPY_SOURCE; + if (HasAnyFlags(access, ResAccess::ResolveSourceRead)) + ba |= D3D12_BARRIER_ACCESS_RESOLVE_SOURCE; + if (HasAnyFlags(access, ResAccess::ShadingRateSourceRead)) + ba |= D3D12_BARRIER_ACCESS_SHADING_RATE_SOURCE; + if (HasAnyFlags(access, ResAccess::VideoEncodeRead)) + ba |= D3D12_BARRIER_ACCESS_VIDEO_ENCODE_READ; + if (HasAnyFlags(access, ResAccess::VideoDecodeRead)) + ba |= D3D12_BARRIER_ACCESS_VIDEO_DECODE_READ; + if (HasAnyFlags(access, ResAccess::VideoProcessRead)) + ba |= D3D12_BARRIER_ACCESS_VIDEO_PROCESS_READ; + return ba; +} + +D3D12_BARRIER_LAYOUT Coplt::GetBarrierLayout(const ResLayout layout, const FGpuQueueType queue, const bool cross_queue) +{ + switch (layout) + { + case ResLayout::Undefined: + return D3D12_BARRIER_LAYOUT_UNDEFINED; + case ResLayout::RenderTarget: + return D3D12_BARRIER_LAYOUT_RENDER_TARGET; + case ResLayout::DepthStencilWrite: + return D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE; + case ResLayout::DepthStencilRead: + return D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_READ; + case ResLayout::ResolveSource: + return D3D12_BARRIER_LAYOUT_RESOLVE_SOURCE; + case ResLayout::ResolveDest: + return D3D12_BARRIER_LAYOUT_RESOLVE_DEST; + case ResLayout::ShaderRateSource: + return D3D12_BARRIER_LAYOUT_SHADING_RATE_SOURCE; + case ResLayout::VideoEncodeRead: + return D3D12_BARRIER_LAYOUT_VIDEO_ENCODE_READ; + case ResLayout::VideoEncodeWrite: + return D3D12_BARRIER_LAYOUT_VIDEO_ENCODE_WRITE; + case ResLayout::VideoDecodeRead: + return D3D12_BARRIER_LAYOUT_VIDEO_DECODE_READ; + case ResLayout::VideoDecodeWrite: + return D3D12_BARRIER_LAYOUT_VIDEO_DECODE_WRITE; + case ResLayout::VideoProcessRead: + return D3D12_BARRIER_LAYOUT_VIDEO_PROCESS_READ; + case ResLayout::VideoProcessWrite: + return D3D12_BARRIER_LAYOUT_VIDEO_PROCESS_WRITE; + case ResLayout::GenericRead: + if (!cross_queue) + { + switch (queue) + { + case FGpuQueueType::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ; + case FGpuQueueType::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_GENERIC_READ; + default: + break; + } + } + return D3D12_BARRIER_LAYOUT_GENERIC_READ; + case ResLayout::UnorderedAccess: + if (!cross_queue) + { + switch (queue) + { + case FGpuQueueType::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS; + case FGpuQueueType::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_UNORDERED_ACCESS; + default: + break; + } + } + return D3D12_BARRIER_LAYOUT_UNORDERED_ACCESS; + case ResLayout::ShaderResource: + if (!cross_queue) + { + switch (queue) + { + case FGpuQueueType::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE; + case FGpuQueueType::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_SHADER_RESOURCE; + default: + break; + } + } + return D3D12_BARRIER_LAYOUT_SHADER_RESOURCE; + case ResLayout::CopySource: + if (!cross_queue) + { + switch (queue) + { + case FGpuQueueType::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE; + case FGpuQueueType::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_SOURCE; + default: + break; + } + } + return D3D12_BARRIER_LAYOUT_COPY_SOURCE; + case ResLayout::CopyDest: + if (!cross_queue) + { + switch (queue) + { + case FGpuQueueType::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_DEST; + case FGpuQueueType::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_DEST; + default: + break; + } + } + return D3D12_BARRIER_LAYOUT_COPY_DEST; + case ResLayout::Common: + default: + if (!cross_queue) + { + switch (queue) + { + case FGpuQueueType::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON; + case FGpuQueueType::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COMMON; + case FGpuQueueType::VideoEncode: + case FGpuQueueType::VideoDecode: + case FGpuQueueType::VideoProcess: + return D3D12_BARRIER_LAYOUT_VIDEO_QUEUE_COMMON; + default: + break; + } + } + return D3D12_BARRIER_LAYOUT_COMMON; + } +} + +D3D12_BARRIER_SYNC Coplt::GetBarrierSync(const ResAccess access, const ResUsage usage) +{ + D3D12_BARRIER_SYNC sync = D3D12_BARRIER_SYNC_NONE; + switch (access) + { + case ResAccess::None: + return D3D12_BARRIER_SYNC_NONE; + case ResAccess::Common: + return D3D12_BARRIER_SYNC_ALL; + default: + break; + } + + if (HasAnyFlags(access, ResAccess::IndexBufferRead)) + sync |= D3D12_BARRIER_SYNC_INDEX_INPUT; + + if (HasAnyFlags(usage, ResUsage::VertexOrMesh)) + sync |= D3D12_BARRIER_SYNC_VERTEX_SHADING; + + if (HasAnyFlags(usage, ResUsage::Pixel)) + sync |= D3D12_BARRIER_SYNC_PIXEL_SHADING; + + if (HasAnyFlags(access, ResAccess::RenderTargetWrite)) + sync |= D3D12_BARRIER_SYNC_RENDER_TARGET; + + if (HasAnyFlags(access, ResAccess::DepthStencilRead | ResAccess::DepthStencilWrite)) + sync |= D3D12_BARRIER_SYNC_DEPTH_STENCIL; + + if (HasAnyFlags(usage, ResUsage::Compute)) + sync |= D3D12_BARRIER_SYNC_COMPUTE_SHADING; + + if (HasAnyFlags(usage, ResUsage::RayTracing)) + sync |= D3D12_BARRIER_SYNC_RAYTRACING; + + if (HasAnyFlags(access, ResAccess::CopySourceRead | ResAccess::CopyDestWrite)) + sync |= D3D12_BARRIER_SYNC_COPY; + + if (HasAnyFlags(access, ResAccess::ResolveSourceRead | ResAccess::ResolveDestWrite)) + sync |= D3D12_BARRIER_SYNC_RESOLVE; + + if (HasAnyFlags(access, ResAccess::IndirectArgumentRead)) + sync |= D3D12_BARRIER_SYNC_EXECUTE_INDIRECT; + + if (HasAnyFlags(access, ResAccess::VideoEncodeRead | ResAccess::VideoEncodeWrite)) + sync |= D3D12_BARRIER_SYNC_VIDEO_ENCODE; + + if (HasAnyFlags(access, ResAccess::VideoDecodeRead | ResAccess::VideoDecodeWrite)) + sync |= D3D12_BARRIER_SYNC_VIDEO_DECODE; + + if (HasAnyFlags(access, ResAccess::VideoProcessRead | ResAccess::VideoProcessWrite)) + sync |= D3D12_BARRIER_SYNC_VIDEO_PROCESS; + + if (HasAnyFlags(usage, ResUsage::BuildRayTracingAccelerationStructure)) + sync |= D3D12_BARRIER_SYNC_BUILD_RAYTRACING_ACCELERATION_STRUCTURE; + + if (HasAnyFlags(usage, ResUsage::CopyRayTracingAccelerationStructure)) + sync |= D3D12_BARRIER_SYNC_COPY_RAYTRACING_ACCELERATION_STRUCTURE; + + if (HasAnyFlags(usage, ResUsage::EmitRayTracingAccelerationStructurePostBuildInfo)) + sync |= D3D12_BARRIER_SYNC_EMIT_RAYTRACING_ACCELERATION_STRUCTURE_POSTBUILD_INFO; + + if (HasAnyFlags(usage, ResUsage::ClearUav)) + sync |= D3D12_BARRIER_SYNC_CLEAR_UNORDERED_ACCESS_VIEW; + + return sync; +} From 0bf4bbe434c6a9170f559928ae97b16e7011b992 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 25 Mar 2025 16:04:21 +0800 Subject: [PATCH 11/46] save --- Coplt.Graphics.Core/Native/Native.cs | 2 +- Coplt.Graphics.Native/Api/FFI/Cmd.h | 2 +- Coplt.Graphics.Native/Api/Include/Object.h | 10 ++ .../D3d12/Include/ResState.h | 9 ++ Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 144 +++++++++++++++++- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 90 ++++++++++- Coplt.Graphics.Native/D3d12/Src/Context.cc | 1 + Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 42 ++++- Coplt.Graphics.Native/D3d12/Src/Isolate.h | 23 ++- Coplt.Graphics.Native/D3d12/Src/Queue.cc | 7 +- Coplt.Graphics.Native/D3d12/Src/Queue.h | 4 + Coplt.Graphics.Native/D3d12/Src/Record.cc | 12 +- Coplt.Graphics.Native/D3d12/Src/Record.h | 12 +- .../D3d12/Src/RecordStorage.cc | 8 +- .../D3d12/Src/RecordStorage.h | 7 +- Coplt.Graphics.Native/D3d12/Src/ResState.cc | 35 +++++ Coplt.Graphics.Native/D3d12/Src/SwapChain.cc | 8 +- 17 files changed, 385 insertions(+), 31 deletions(-) diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index e40d248..159bc2d 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1787,7 +1787,7 @@ public partial struct FCmdClearDepthStencil public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L151_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L153_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index d6d54ee..5590c5a 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -54,7 +54,7 @@ namespace Coplt FCmdResType Type{}; #ifdef FFI_SRC - FUnknown* GetObjectPtr() const + FGpuObject* GetObjectPtr() const { switch (Type) { diff --git a/Coplt.Graphics.Native/Api/Include/Object.h b/Coplt.Graphics.Native/Api/Include/Object.h index 58f8f04..d6f4b7e 100644 --- a/Coplt.Graphics.Native/Api/Include/Object.h +++ b/Coplt.Graphics.Native/Api/Include/Object.h @@ -602,6 +602,16 @@ namespace Coplt } }; + template + struct SubObject : Base + { + void* ObjectStart() noexcept override + { + This* self = static_cast(this); + return self; + } + }; + template using Object = std::conditional_t< std::is_base_of_v, diff --git a/Coplt.Graphics.Native/D3d12/Include/ResState.h b/Coplt.Graphics.Native/D3d12/Include/ResState.h index f0af867..27da84d 100644 --- a/Coplt.Graphics.Native/D3d12/Include/ResState.h +++ b/Coplt.Graphics.Native/D3d12/Include/ResState.h @@ -85,6 +85,13 @@ namespace Coplt ResAccess Access{}; ResUsage Usage{}; ResLayout Layout{}; + + ResState() = default; + explicit ResState(ResAccess Access, ResUsage Usage, ResLayout Layout); + + bool IsCompatible(const ResState& New, bool Enhanced) const; + ResState Merge(const ResState& New) const; + ResState Split() const; }; bool IsValid(ResAccess access); @@ -93,6 +100,8 @@ namespace Coplt bool IsReadOnly(ResAccess access); + bool IsCompatible(ResAccess Old, ResAccess New); + D3D12_RESOURCE_STATES GetResourceState(ResAccess access); D3D12_BARRIER_ACCESS GetBarrierAccess(ResAccess access); diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index 15831c4..9b81508 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -1,5 +1,7 @@ #include "Barrier.h" +#include "Record.h" + using namespace Coplt; namespace Coplt::Enhanced @@ -9,11 +11,16 @@ namespace Coplt::Enhanced { } - Rc EnhancedBarrierAnalyzer::CreateRecorder(const Rc& storage) + Rc EnhancedBarrierAnalyzer::CreateRecorder(const Rc& storage) { return new EnhancedBarrierRecorder(m_device, storage); } + Rc EnhancedBarrierAnalyzer::CreateCombiner() + { + return new EnhancedBarrierCombiner(m_device); + } + EnhancedBarrierRecorder::ResInfo::ResInfo(const FCmdResType ResType) : ResType(ResType) { } @@ -23,9 +30,22 @@ namespace Coplt::Enhanced { } + std::span EnhancedBarrierRecorder::Inputs() const + { + return m_inputs; + } + void EnhancedBarrierRecorder::Clear() { m_resources.clear(); + m_inputs.clear(); + m_groups.clear(); + m_begin_buffer_barriers.clear(); + m_begin_texture_barriers.clear(); + m_end_buffer_barriers.clear(); + m_end_texture_barriers.clear(); + m_current_begin_barrier_group_index = 0; + m_current_end_barrier_group_index = 0; } void EnhancedBarrierRecorder::StartRecord(const std::span resources) @@ -37,6 +57,7 @@ namespace Coplt::Enhanced const auto& res = resources[i]; m_resources.push_back(ResInfo(res.Type)); } + m_groups.push_back({}); } void EnhancedBarrierRecorder::EndRecord() @@ -47,23 +68,134 @@ namespace Coplt::Enhanced { const auto ResIndex = ResRef.ResIndex(); auto& info = m_resources[ResIndex]; + const auto new_state = ResState(Access, Usage, Layout); if (info.InfoState == InfoState::Unused) { info.InfoState = InfoState::Input; - info.State = ResState{ - .Access = Access, - .Usage = Usage, - .Layout = Layout, - }; + info.State = new_state; return; } else if (info.InfoState == InfoState::Input) { + if (info.State.IsCompatible(new_state, true)) + { + info.State = info.State.Merge(new_state); + return; + } + const auto list_index = m_storage->Split(); + m_inputs.push_back(InputResState{.ResIndex = ResIndex, .ListIndex = list_index, .State = info.State}); + info.State = new_state; + info.InfoState = InfoState::Used; // todo + return; } else { + if (info.State.IsCompatible(new_state, true)) + { + info.State = info.State.Merge(new_state); + return; + } // todo } } + + EnhancedBarrierCombiner::EnhancedBarrierCombiner(const Rc& device) + { + m_device = device; + } + + void EnhancedBarrierCombiner::Process(NonNull isolate, std::span> records) + { + for (const auto& record : records) + { + const NonNull data = record->Data(); + const auto& barrier_recorder = record->BarrierRecorder(); + for (const auto& input : barrier_recorder->Inputs()) + { + const auto& res = data->Resources[input.ResIndex]; + bool exist; + auto& sr = m_submit_resources.GetOrAdd(res.GetObjectPtr()->ObjectId(), exist, [&](auto& p) + { + p.put(ResInfo{ + .Res = res, + }); + }); + // todo + } + } + } +} + +void AD3d12BarrierCombiner::StartSubmit() +{ +} + +void AD3d12BarrierCombiner::EndSubmit() +{ + m_submit_lists.clear(); + m_list_ranges.clear(); + m_fence_info.clear(); + m_used_queues.clear(); + m_submit_resources.Clear(); +} + +bool AD3d12BarrierCombiner::Submit(NonNull isolate, std::span> records) +{ + StartSubmit(); + Process(isolate, records); + for (const auto& record : records) + { + const auto& storage = record->Storage(); + storage->BeforeSubmit(); + } + const auto has_submit = m_list_ranges.size() > 0; + if (has_submit) + { + const auto& main_queue = isolate->m_main_queue; + + #pragma region 提交命令列表 + + for (const auto& range : m_list_ranges) + { + const auto& queue = isolate->GetQueue(range.QueueAt); + for (u32 i = 0; i < range.FenceCount; ++i) + { + const auto& at = m_fence_info[i + range.FenceIndex]; + const auto& dep_queue = isolate->GetQueue(at); + queue->Wait(*dep_queue, dep_queue->Signal()); + } + queue->m_queue->ExecuteCommandLists(range.ListCount, m_submit_lists.data() + range.ListIndex); + } + + #pragma endregion + + #pragma region 在主队列中等待其他队列 + + for (auto& at : m_used_queues) + { + if (at.IsMain()) continue; + const auto& dep_queue = isolate->GetQueue(at); + main_queue->Wait(*dep_queue, dep_queue->Signal()); + } + + #pragma endregion + + #pragma region 所有录制都在主队列中等待执行结束 + + const auto fence_value = main_queue->Signal(); + for (const auto& record : records) + { + record->RegisterWaitPoint(QueueWaitPoint(main_queue, fence_value)); + } + + #pragma endregion + } + for (const auto& record : records) + { + const auto& storage = record->Storage(); + storage->AfterSubmit(); + } + EndSubmit(); + return has_submit; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index 47e804a..365fb3d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -8,15 +8,26 @@ namespace Coplt { - struct I3d12BarrierRecorder; + struct InputResState + { + u32 ResIndex{}; + u32 ListIndex{}; + ResState State{}; + }; - COPLT_INTERFACE_DEFINE(I3d12BarrierAnalyzer, "792f273c-376d-4027-af99-0d14d3d71302", FUnknown) + struct ID3d12BarrierRecorder; + struct ID3d12BarrierCombiner; + + COPLT_INTERFACE_DEFINE(ID3d12BarrierAnalyzer, "792f273c-376d-4027-af99-0d14d3d71302", FUnknown) { - virtual Rc CreateRecorder(const Rc& storage) = 0; + virtual Rc CreateRecorder(const Rc& storage) = 0; + virtual Rc CreateCombiner() = 0; }; - COPLT_INTERFACE_DEFINE(I3d12BarrierRecorder, "115741ea-2138-4c92-9f4f-94f91d254587", FUnknown) + COPLT_INTERFACE_DEFINE(ID3d12BarrierRecorder, "115741ea-2138-4c92-9f4f-94f91d254587", FUnknown) { + virtual std::span Inputs() const = 0; + virtual void Clear() = 0; virtual void StartRecord(std::span resources) = 0; virtual void EndRecord() = 0; @@ -24,18 +35,56 @@ namespace Coplt virtual void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) = 0; }; + COPLT_INTERFACE_DEFINE(ID3d12BarrierCombiner, "e1e15444-6369-4d8a-90b3-153672abca39", FUnknown) + { + // 返回是否有实际提交,如果没有实际提交可以直接回收录制,不然就需要等待提交执行完成 + virtual bool Submit(NonNull isolate, std::span> records) = 0; + }; + + struct AD3d12BarrierCombiner : Object + { + struct ResInfo + { + FCmdRes Res{}; + }; + + struct ListRange + { + u32 FenceIndex{}; + u32 FenceCount{}; + u32 ListIndex{}; + u32 ListCount{}; + QueueAt QueueAt{}; + }; + + Rc m_device{}; + std::vector m_submit_lists{}; + std::vector m_list_ranges{}; + std::vector m_fence_info{}; + std::vector m_used_queues{}; + HashMap m_submit_resources{}; + + virtual void StartSubmit(); + virtual void EndSubmit(); + + // 返回是否有实际提交,如果没有实际提交可以直接回收录制,不然就需要等待提交执行完成 + bool Submit(NonNull isolate, std::span> records) override; + virtual void Process(NonNull isolate, std::span> records) = 0; + }; + namespace Enhanced { - struct EnhancedBarrierAnalyzer final : Object + struct EnhancedBarrierAnalyzer final : Object { Rc m_device; explicit EnhancedBarrierAnalyzer(const Rc& device); - Rc CreateRecorder(const Rc& storage) override; + Rc CreateRecorder(const Rc& storage) override; + Rc CreateCombiner() override; }; - struct EnhancedBarrierRecorder final : Object + struct EnhancedBarrierRecorder final : Object { enum class InfoState : u8 { @@ -47,22 +96,49 @@ namespace Coplt struct ResInfo { ResState State{}; + u32 CurrentBeginBarrierGroupIndex{}; + u32 CurrentEndBarrierGroupIndex{}; const FCmdResType ResType{}; InfoState InfoState{}; explicit ResInfo(FCmdResType ResType); }; + struct BarrierGroupRange + { + u32 BufferIndex{}; + u32 BufferCount{}; + u32 TextureIndex{}; + u32 TextureCount{}; + }; + Rc m_device{}; Rc m_storage{}; std::vector m_resources{}; + std::vector m_inputs{}; + std::vector m_groups{}; + std::vector m_begin_buffer_barriers{}; + std::vector m_begin_texture_barriers{}; + std::vector m_end_buffer_barriers{}; + std::vector m_end_texture_barriers{}; + u32 m_current_begin_barrier_group_index{}; + u32 m_current_end_barrier_group_index{}; explicit EnhancedBarrierRecorder(const Rc& device, const Rc& storage); + std::span Inputs() const override; + void Clear() override; void StartRecord(std::span resources) override; void EndRecord() override; void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) override; }; + + struct EnhancedBarrierCombiner final : Object + { + explicit EnhancedBarrierCombiner(const Rc& device); + + void Process(NonNull isolate, std::span> records) override; + }; } } diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.cc b/Coplt.Graphics.Native/D3d12/Src/Context.cc index 23a87e8..00d176f 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Context.cc @@ -150,6 +150,7 @@ D3d12CommandPool::D3d12CommandPool(const Rc& device, const D3D12 : m_device(device), m_type(type) { m_command_allocator_pool = box(); + m_command_list_pool = box(); } D3d12RentedCommandAllocator D3d12CommandPool::RentCommandAllocator() diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index df8c1ce..3439c71 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -8,6 +8,15 @@ using namespace Coplt; +QueueAt::QueueAt(const u32 index, const FGpuQueueType type) : Index(index), Type(type) +{ +} + +bool QueueAt::IsMain() const +{ + return Type == FGpuQueueType::Direct && Index == 0; +} + D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options) : FGpuIsolateData() { @@ -82,6 +91,7 @@ D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCre #pragma endregion m_barrier_analyzer = new Enhanced::EnhancedBarrierAnalyzer(m_device); + m_barrier_combiner = m_barrier_analyzer->CreateCombiner(); m_cmd_alloc_pool = new D3d12CommandListPoolCluster(m_device); @@ -135,6 +145,27 @@ FGpuIsolateData* D3d12GpuIsolate::GpuIsolateData() noexcept return this; } +const Rc& D3d12GpuIsolate::GetQueue(const QueueAt at) +{ + switch (at.Type) + { + case FGpuQueueType::Direct: + if (at.Index == 0) return m_main_queue; + return m_direct_queues[at.Index - 1]; + case FGpuQueueType::Compute: + return m_compute_queues[at.Index]; + case FGpuQueueType::Copy: + return m_copy_queues[at.Index]; + case FGpuQueueType::VideoEncode: + return m_video_encode_queues[at.Index]; + case FGpuQueueType::VideoDecode: + return m_video_decode_queues[at.Index]; + case FGpuQueueType::VideoProcess: + return m_video_process_queues[at.Index]; + } + return m_main_queue; +} + FResult D3d12GpuIsolate::RentRecords(const u32 NumRecords, FGpuRecordCreateResult* OutRecords) noexcept { return feb([&] @@ -285,11 +316,16 @@ void D3d12GpuIsolate::SubmitReturn(std::span records) void D3d12GpuIsolate::SubmitReturn(std::span> records) { std::lock_guard lock(m_mutex); - for (u32 i = 0; i < records.size(); ++i) + SubmitNoLock(records); +} + +void D3d12GpuIsolate::SubmitNoLock(std::span> records) +{ + for (const auto& record : records) { - records[i]->EnsureEnd(); + record->EnsureEnd(); } - // todo + m_barrier_combiner->Submit(this, records); m_waiting_record->enqueue_bulk(records.data(), records.size()); m_waiting_signal.release(1); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index 3682713..c5d6cdb 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -8,6 +8,7 @@ #include "Queue.h" #include "../../Api/FFI/Isolate.h" #include "../../Api/Include/GpuObject.h" +#include "../../Api/FFI/Cmd.h" namespace Coplt { @@ -28,13 +29,27 @@ namespace Coplt }; struct ID3d12GpuRecord; - struct I3d12BarrierAnalyzer; + struct ID3d12BarrierAnalyzer; + struct ID3d12BarrierCombiner; + + struct QueueAt + { + u32 Index{}; + FGpuQueueType Type{}; + + QueueAt() = default; + + explicit QueueAt(u32 index, FGpuQueueType type); + + bool IsMain() const; + }; struct D3d12GpuIsolate final : GpuObject, FGpuIsolateData { using RecordQueue = moodycamel::ConcurrentQueue>; - Rc m_barrier_analyzer{}; + Rc m_barrier_analyzer{}; + Rc m_barrier_combiner{}; HANDLE m_event{}; Box m_waiting_record{}; Box m_record_pool{}; @@ -52,6 +67,8 @@ namespace Coplt FGpuQueueCreateResult* GetQueues(u32* OutNumQueues) noexcept override; FGpuIsolateData* GpuIsolateData() noexcept override; + const Rc& GetQueue(QueueAt at); + FResult RentRecords(u32 NumRecords, FGpuRecordCreateResult* OutRecords) noexcept override; FResult ReturnRecords(u32 NumRecords, FGpuRecord** Records) noexcept override; FResult Submit(u32 NumRecords, FGpuRecord** Records, FGpuRecordCreateResult* OutRecords) noexcept override; @@ -65,5 +82,7 @@ namespace Coplt void Submit(std::span records, std::span out); void SubmitReturn(std::span records); void SubmitReturn(std::span> records); + + void SubmitNoLock(std::span> records); }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.cc b/Coplt.Graphics.Native/D3d12/Src/Queue.cc index 42f2ae2..0dff6ba 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.cc @@ -217,7 +217,7 @@ u64 D3d12GpuQueue2::SignalNoLock() return fence_value; } -void D3d12GpuQueue2::WaitFenceValue(u64 fence_value, HANDLE event) +void D3d12GpuQueue2::WaitFenceValue(const u64 fence_value, const HANDLE event) { if (m_fence->GetCompletedValue() < fence_value) { @@ -225,3 +225,8 @@ void D3d12GpuQueue2::WaitFenceValue(u64 fence_value, HANDLE event) WaitForSingleObject(event, INFINITE); } } + +void D3d12GpuQueue2::Wait(D3d12GpuQueue2& other, const u64 fence_value) +{ + chr | m_queue->Wait(other.m_fence.Get(), fence_value); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.h b/Coplt.Graphics.Native/D3d12/Src/Queue.h index c2f19aa..955b15d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -93,6 +93,8 @@ namespace Coplt void Wait(HANDLE event) const; }; + struct D3d12GpuQueue2; + COPLT_INTERFACE_DEFINE(ID3d12GpuQueue, "a60df5da-ecff-4ae4-a38b-6ddef7db5922", FD3d12GpuQueue2) { Rc m_device{}; @@ -106,6 +108,7 @@ namespace Coplt virtual u64 SignalNoLock() = 0; virtual void WaitFenceValue(u64 fence_value, HANDLE event) = 0; + virtual void Wait(D3d12GpuQueue2& other, u64 fence_value) = 0; }; struct D3d12GpuQueue2 final : GpuObject, FGpuQueueData @@ -121,5 +124,6 @@ namespace Coplt u64 SignalNoLock() override; void WaitFenceValue(u64 fence_value, HANDLE event) override; + void Wait(D3d12GpuQueue2& other, u64 fence_value) override; }; } // Coplt diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index fedeb32..1f8210d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -35,6 +35,16 @@ const FGpuRecordData* D3d12GpuRecord::Data() const noexcept return this; } +const Rc& D3d12GpuRecord::Storage() +{ + return m_storage; +} + +const Rc& D3d12GpuRecord::BarrierRecorder() +{ + return m_barrier_recorder; +} + void D3d12GpuRecord::RegisterWaitPoint(QueueWaitPoint&& wait_point) { m_queue_wait_points.push_back(std::move(wait_point)); @@ -101,7 +111,7 @@ void D3d12GpuRecord::ReadyResource() for (u32 i = 0; i < Resources.size(); ++i) { const auto& res = Resources[i]; - m_resources_owner.push_back(Rc::UnsafeClone(res.GetObjectPtr())); + m_resources_owner.push_back(Rc::UnsafeClone(res.GetObjectPtr())); } } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 9e04cbd..ce2dedc 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -19,6 +19,9 @@ namespace Coplt virtual void Recycle() = 0; virtual void EnsureEnd() = 0; + + virtual const Rc& Storage() = 0; + virtual const Rc& BarrierRecorder() = 0; }; struct D3d12GpuRecord final : GpuObject, FGpuRecordData @@ -27,9 +30,9 @@ namespace Coplt u64 m_record_id{}; Rc m_device{}; Rc m_context{}; - Rc m_storage{}; - Rc m_barrier_recorder{}; - std::vector> m_resources_owner{}; + Rc m_storage{}; + Rc m_barrier_recorder{}; + std::vector> m_resources_owner{}; std::vector m_queue_wait_points{}; explicit D3d12GpuRecord(NonNull isolate); @@ -39,6 +42,9 @@ namespace Coplt FGpuRecordData* Data() noexcept override; const FGpuRecordData* Data() const noexcept override; + const Rc& Storage() override; + const Rc& BarrierRecorder() override; + void RegisterWaitPoint(QueueWaitPoint&& wait_point) override; void WaitAndRecycle(HANDLE event) override; void Recycle() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc index 77781eb..9049587 100644 --- a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc +++ b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc @@ -22,6 +22,10 @@ void D3d12RecordStorage::StartRecord(const FGpuRecordMode Mode) void D3d12RecordStorage::EndRecord() { m_result_lists.push_back(std::move(m_cur_list)); +} + +void D3d12RecordStorage::BeforeSubmit() +{ for (auto& list : m_result_lists) { list.Close(); @@ -33,9 +37,11 @@ void D3d12RecordStorage::AfterSubmit() m_context->m_recycled_command_allocators.push_back(std::move(m_cmd_allocator)); } -void D3d12RecordStorage::Split() +u32 D3d12RecordStorage::Split() { + const auto i = m_result_lists.size(); m_result_lists.push_back(std::exchange(m_cur_list, m_cmd_allocator.RentCommandList())); + return i; } D3d12RentedCommandList& D3d12RecordStorage::CurList() diff --git a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h index eae8037..23b2887 100644 --- a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h +++ b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h @@ -13,9 +13,11 @@ namespace Coplt virtual void StartRecord(FGpuRecordMode Mode) = 0; virtual void EndRecord() = 0; + virtual void BeforeSubmit() = 0; virtual void AfterSubmit() = 0; - virtual void Split() = 0; + // 返回当前 List 的 index + virtual u32 Split() = 0; virtual D3d12RentedCommandList& CurList() = 0; virtual std::span Lists() = 0; @@ -35,9 +37,10 @@ namespace Coplt void StartRecord(FGpuRecordMode Mode) override; void EndRecord() override; + void BeforeSubmit() override; void AfterSubmit() override; - void Split() override; + u32 Split() override; D3d12RentedCommandList& CurList() override; std::span Lists() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/ResState.cc b/Coplt.Graphics.Native/D3d12/Src/ResState.cc index 220852a..8ebec9b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/ResState.cc +++ b/Coplt.Graphics.Native/D3d12/Src/ResState.cc @@ -2,6 +2,26 @@ using namespace Coplt; +ResState::ResState(const ResAccess Access, const ResUsage Usage, const ResLayout Layout) : Access(Access), Usage(Usage), Layout(Layout) +{ +} + +bool ResState::IsCompatible(const ResState& New, const bool Enhanced) const +{ + if (Enhanced && Layout != New.Layout) return false; + return Coplt::IsCompatible(Access, New.Access); +} + +ResState ResState::Merge(const ResState& New) const +{ + return ResState(Access | New.Access, Usage | New.Usage, New.Layout); +} + +ResState ResState::Split() const +{ + return ResState(Access, ResUsage::Common, Layout); +} + bool Coplt::IsValid(const ResAccess access) { switch (access) @@ -74,6 +94,21 @@ bool Coplt::IsReadOnly(const ResAccess access) ); } +bool Coplt::IsCompatible(const ResAccess Old, const ResAccess New) +{ + switch (Old) + { + case ResAccess::None: + return true; + case ResAccess::UnorderedAccessRead: + case ResAccess::RayTracingAccelerationStructureRead: + return false; + default: + if (IsReadOnly(Old) && IsReadOnly(New)) return true; + return false; + } +} + D3D12_RESOURCE_STATES Coplt::GetResourceState(const ResAccess access) { D3D12_RESOURCE_STATES state = D3D12_RESOURCE_STATE_COMMON; diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc index dcb3d89..95171cc 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -23,9 +23,6 @@ D3d12GpuSwapChain::D3d12GpuSwapChain( { m_name = options.Name.ToString(); } - - m_event = CreateEventW(nullptr, false, false, nullptr); - if (m_event == nullptr) chr | HRESULT_FROM_WIN32(GetLastError()); } void D3d12GpuSwapChain::Initialize() @@ -38,6 +35,11 @@ void D3d12GpuSwapChain::Initialize() rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; chr | m_device->CreateDescriptorHeap(&rtv_heap_desc, IID_PPV_ARGS(&m_rtv_heap)); m_rtv_descriptor_size = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + CreateRts(); + + m_event = CreateEventW(nullptr, false, false, nullptr); + if (m_event == nullptr) chr | HRESULT_FROM_WIN32(GetLastError()); } D3d12GpuSwapChain::D3d12GpuSwapChain(const NonNull isolate, const FGpuSwapChainFromExistsCreateOptions& options) From 0071ac47e626165f02709c0054325981fb8129d8 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 25 Mar 2025 22:03:19 +0800 Subject: [PATCH 12/46] save --- Coplt.Graphics.Core/Core/GpuRecord.cs | 16 +++ Coplt.Graphics.Core/Native/Native.cs | 28 ++++- Coplt.Graphics.Native/Api/FFI/Cmd.h | 25 ++++ Coplt.Graphics.Native/Api/Include/Object.h | 12 +- .../D3d12/Include/ResState.h | 7 ++ Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 107 +++++++++++++++++- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 10 +- Coplt.Graphics.Native/D3d12/Src/Context.cc | 70 ++++++++++++ Coplt.Graphics.Native/D3d12/Src/Context.h | 4 + Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 18 +++ Coplt.Graphics.Native/D3d12/Src/Isolate.h | 2 + Coplt.Graphics.Native/D3d12/Src/Output.h | 2 + Coplt.Graphics.Native/D3d12/Src/Record.cc | 59 +++++++++- Coplt.Graphics.Native/D3d12/Src/Record.h | 3 + .../D3d12/Src/RecordStorage.cc | 17 ++- .../D3d12/Src/RecordStorage.h | 7 +- Coplt.Graphics.Native/D3d12/Src/SwapChain.cc | 9 ++ Coplt.Graphics.Native/D3d12/Src/SwapChain.h | 2 + Examples/ExampleBase/ExampleBase.cs | 1 + 19 files changed, 376 insertions(+), 23 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index b3641c2..0ee2a06 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -115,6 +115,22 @@ internal uint AddRects(ReadOnlySpan Rects) #endregion + #region PreparePresent + + public void PreparePresent(GpuOutput2 Output) + { + AssertNotEnded(); + Output.AssertSameIsolate(Isolate); + var cmd = new FCmdPreparePresent + { + Base = { Type = FCmdType.PreparePresent }, + Output = AddResource(Output), + }; + Data.Commands.Add(new() { PreparePresent = cmd }); + } + + #endregion + #region ClearColor public void ClearColor(IRtv Image, ReadOnlySpan Rects = default) => diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 159bc2d..8b49919 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1598,6 +1598,7 @@ public enum FCmdType : uint Label, BeginScope, EndScope, + PreparePresent, ClearColor, ClearDepthStencil, } @@ -1612,7 +1613,7 @@ public enum FCmdResType : byte public unsafe partial struct FCmdRes { - [NativeTypeName("__AnonymousRecord_Cmd_L47_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L49_C9")] public _Anonymous_e__Union Anonymous; [NativeTypeName("Coplt::FCmdResType")] @@ -1737,6 +1738,15 @@ public partial struct FCmdEndScope public FCmdBase Base; } + [NativeTypeName("struct FCmdPreparePresent : Coplt::FCmdBase")] + public partial struct FCmdPreparePresent + { + public FCmdBase Base; + + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Output; + } + [NativeTypeName("struct FCmdClearColor : Coplt::FCmdBase")] public partial struct FCmdClearColor { @@ -1787,7 +1797,7 @@ public partial struct FCmdClearDepthStencil public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L153_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L176_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -1830,6 +1840,16 @@ public ref FCmdEndScope EndScope } } + [UnscopedRef] + public ref FCmdPreparePresent PreparePresent + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.PreparePresent; + } + } + [UnscopedRef] public ref FCmdClearColor ClearColor { @@ -1879,6 +1899,10 @@ public partial struct _Anonymous_e__Union [NativeTypeName("Coplt::FCmdEndScope")] public FCmdEndScope EndScope; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdPreparePresent")] + public FCmdPreparePresent PreparePresent; + [FieldOffset(0)] [NativeTypeName("Coplt::FCmdClearColor")] public FCmdClearColor ClearColor; diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index 5590c5a..b7ae187 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -13,6 +13,8 @@ namespace Coplt BeginScope, EndScope, + PreparePresent, + ClearColor, ClearDepthStencil, }; @@ -67,6 +69,20 @@ namespace Coplt } return nullptr; } + + bool IsImage() const + { + switch (Type) + { + case FCmdResType::Image: + return true; + case FCmdResType::Buffer: + return false; + case FCmdResType::Output: + return true; + } + return false; + } #endif }; @@ -124,6 +140,13 @@ namespace Coplt //////////////////////////////////////////////////////////////////////////////////////////////////// + struct FCmdPreparePresent : FCmdBase + { + FCmdResRef Output{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + struct FCmdClearColor : FCmdBase { // 有多少个 Rect @@ -158,6 +181,8 @@ namespace Coplt FCmdBeginScope BeginScope; FCmdEndScope EndScope; + FCmdPreparePresent PreparePresent; + FCmdClearColor ClearColor; FCmdClearDepthStencil ClearDepthStencil; diff --git a/Coplt.Graphics.Native/Api/Include/Object.h b/Coplt.Graphics.Native/Api/Include/Object.h index d6f4b7e..78e340d 100644 --- a/Coplt.Graphics.Native/Api/Include/Object.h +++ b/Coplt.Graphics.Native/Api/Include/Object.h @@ -577,9 +577,11 @@ namespace Coplt }; // 对象不允许多继承,只允许具有多个接口 - template - struct ObjectImpl : Base, _internal::MergeInterface::Output + template + struct ObjectImpl : TBase, _internal::MergeInterface::Output { + using Base = ObjectImpl; + void* ObjectStart() noexcept override { This* self = static_cast(this); @@ -588,17 +590,17 @@ namespace Coplt size_t Release() noexcept override { - return Base::Release(); + return TBase::Release(); } size_t AddRef() noexcept override { - return Base::AddRef(); + return TBase::AddRef(); } void* QueryInterface(const Guid& id) noexcept override { - return Base::QueryInterface(id); + return TBase::QueryInterface(id); } }; diff --git a/Coplt.Graphics.Native/D3d12/Include/ResState.h b/Coplt.Graphics.Native/D3d12/Include/ResState.h index 27da84d..f366561 100644 --- a/Coplt.Graphics.Native/D3d12/Include/ResState.h +++ b/Coplt.Graphics.Native/D3d12/Include/ResState.h @@ -94,6 +94,13 @@ namespace Coplt ResState Split() const; }; + struct ResourceState + { + ResState State{}; + FGpuQueueType QueueType{}; + bool CrossQueue{}; + }; + bool IsValid(ResAccess access); ResUseType GetUseType(ResAccess access); diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index 9b81508..e5eeab2 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -62,6 +62,16 @@ namespace Coplt::Enhanced void EnhancedBarrierRecorder::EndRecord() { + for (u32 i = 0; i < m_resources.size(); ++i) + { + auto& info = m_resources[i]; + if (info.InfoState == InfoState::Unused) continue; + if (info.InfoState == InfoState::Input) + { + m_inputs.push_back(InputResState{.ResIndex = i, .BeforeUseListIndex = info.CurrentBeforeUseListIndex, .State = info.State}); + } + // todo output + } } void EnhancedBarrierRecorder::OnUse(const FCmdResRef ResRef, const ResAccess Access, const ResUsage Usage, const ResLayout Layout) @@ -73,6 +83,7 @@ namespace Coplt::Enhanced { info.InfoState = InfoState::Input; info.State = new_state; + info.CurrentBeforeUseListIndex = m_storage->CurrentListIndex() - 1; return; } else if (info.InfoState == InfoState::Input) @@ -82,11 +93,12 @@ namespace Coplt::Enhanced info.State = info.State.Merge(new_state); return; } - const auto list_index = m_storage->Split(); - m_inputs.push_back(InputResState{.ResIndex = ResIndex, .ListIndex = list_index, .State = info.State}); + m_inputs.push_back(InputResState{.ResIndex = ResIndex, .BeforeUseListIndex = info.CurrentBeforeUseListIndex, .State = info.State}); info.State = new_state; info.InfoState = InfoState::Used; - // todo + info.CurrentBeforeUseListIndex = m_storage->CurrentListIndex(); + m_storage->Split(); + // todo 记录屏障 return; } else @@ -105,12 +117,21 @@ namespace Coplt::Enhanced m_device = device; } + void EnhancedBarrierCombiner::EndSubmit() + { + m_buffer_barriers.clear(); + m_texture_barriers.clear(); + Base::EndSubmit(); + } + void EnhancedBarrierCombiner::Process(NonNull isolate, std::span> records) { for (const auto& record : records) { const NonNull data = record->Data(); const auto& barrier_recorder = record->BarrierRecorder(); + const auto& storage = record->Storage(); + u32 buffer_barrier_index = m_buffer_barriers.size(), texture_barrier_index = m_texture_barriers.size(); for (const auto& input : barrier_recorder->Inputs()) { const auto& res = data->Resources[input.ResIndex]; @@ -119,10 +140,90 @@ namespace Coplt::Enhanced { p.put(ResInfo{ .Res = res, + .State = GetState(res), }); }); + if (!exist) + { + if (res.IsImage()) + { + const auto img_data = GetImageData(res); + D3D12_TEXTURE_BARRIER barrier{ + .SyncBefore = D3D12_BARRIER_SYNC_NONE, + .SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage), + // .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, // todo 拆分屏障 + .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, + .AccessAfter = GetBarrierAccess(input.State.Access), + .LayoutBefore = GetBarrierLayout(sr.State->State.Layout, ToQueueType(data->Mode), sr.State->CrossQueue), + .LayoutAfter = GetBarrierLayout(input.State.Layout, ToQueueType(data->Mode), false), + .pResource = GetResource(res), + .Subresources = { + .IndexOrFirstMipLevel = 0, + .NumMipLevels = img_data->m_mip_levels, + .FirstArraySlice = 0, + .NumArraySlices = img_data->m_depth_or_length, + .FirstPlane = 0, + .NumPlanes = img_data->m_planes, + }, + .Flags = D3D12_TEXTURE_BARRIER_FLAG_NONE, + }; + m_texture_barriers.push_back(barrier); + } + else + { + //todo + } + } // todo } + + #pragma region 插入输入屏障 + + const u32 buffer_barrier_count = m_buffer_barriers.size() - buffer_barrier_index; + const u32 texture_barrier_count = m_texture_barriers.size() - texture_barrier_index; + if (buffer_barrier_count > 0 || texture_barrier_count > 0) + { + D3D12_BARRIER_GROUP groups[2]; + u32 group_count = 0; + if (buffer_barrier_count > 0) + { + groups[group_count++] = D3D12_BARRIER_GROUP{ + .Type = D3D12_BARRIER_TYPE_BUFFER, + .NumBarriers = buffer_barrier_count, + .pBufferBarriers = m_buffer_barriers.data() + buffer_barrier_index, + }; + } + if (texture_barrier_count > 0) + { + groups[group_count++] = D3D12_BARRIER_GROUP{ + .Type = D3D12_BARRIER_TYPE_TEXTURE, + .NumBarriers = texture_barrier_count, + .pTextureBarriers = m_texture_barriers.data() + texture_barrier_index, + }; + } + // 第一个列表是保留的用于屏障的 + storage->Lists()[0]->Barrier(group_count, groups); + } + + #pragma endregion + + #pragma region 完成录制 记录 list 范围 + + { + ListRange range{}; + // todo fence + range.ListIndex = m_submit_lists.size(); + const auto lists = storage->Lists(); + range.ListCount = lists.size(); + range.QueueAt = QueueAt(0, FGpuQueueType::Direct); // todo 选择队列 + for (const auto& list : lists) + { + m_submit_lists.push_back(list->ToCommandList()); + } + m_list_ranges.push_back(range); + } + + #pragma endregion } } } diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index 365fb3d..bdb5b95 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -11,7 +11,7 @@ namespace Coplt struct InputResState { u32 ResIndex{}; - u32 ListIndex{}; + u32 BeforeUseListIndex{}; ResState State{}; }; @@ -46,6 +46,7 @@ namespace Coplt struct ResInfo { FCmdRes Res{}; + NonNull State; }; struct ListRange @@ -96,6 +97,8 @@ namespace Coplt struct ResInfo { ResState State{}; + // 在使用前的,可以插入屏障的 list 的 index + u32 CurrentBeforeUseListIndex{}; u32 CurrentBeginBarrierGroupIndex{}; u32 CurrentEndBarrierGroupIndex{}; const FCmdResType ResType{}; @@ -138,6 +141,11 @@ namespace Coplt { explicit EnhancedBarrierCombiner(const Rc& device); + std::vector m_buffer_barriers{}; + std::vector m_texture_barriers{}; + + void EndSubmit() override; + void Process(NonNull isolate, std::span> records) override; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.cc b/Coplt.Graphics.Native/D3d12/Src/Context.cc index 00d176f..b20d361 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Context.cc @@ -331,6 +331,76 @@ void D3d12CommandList::Close() const std::unreachable(); } +ID3D12CommandList* D3d12CommandList::ToCommandList() const +{ + switch (type) + { + case D3D12_COMMAND_LIST_TYPE_DIRECT: + case D3D12_COMMAND_LIST_TYPE_COMPUTE: + case D3D12_COMMAND_LIST_TYPE_COPY: + { + return g0.Get(); + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE: + { + return vd0.Get(); + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS: + { + return vp0.Get(); + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE: + { + return ve0.Get(); + } + case D3D12_COMMAND_LIST_TYPE_NONE: + case D3D12_COMMAND_LIST_TYPE_BUNDLE: + std::unreachable(); + } + std::unreachable(); +} + +void D3d12CommandList::Barrier(const UINT32 NumBarrierGroups, const D3D12_BARRIER_GROUP* pBarrierGroups) const +{ + switch (type) + { + case D3D12_COMMAND_LIST_TYPE_DIRECT: + case D3D12_COMMAND_LIST_TYPE_COMPUTE: + case D3D12_COMMAND_LIST_TYPE_COPY: + { + if (g7 == nullptr) + COPLT_THROW("Does not support enhanced barriers"); + g7->Barrier(NumBarrierGroups, pBarrierGroups); + return; + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_DECODE: + { + if (vd3 == nullptr) + COPLT_THROW("Does not support enhanced barriers"); + vd3->Barrier(NumBarrierGroups, pBarrierGroups); + return; + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS: + { + if (vp3 == nullptr) + COPLT_THROW("Does not support enhanced barriers"); + vp3->Barrier(NumBarrierGroups, pBarrierGroups); + return; + } + case D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE: + { + if (ve3 == nullptr) + COPLT_THROW("Does not support enhanced barriers"); + ve3->Barrier(NumBarrierGroups, pBarrierGroups); + return; + } + case D3D12_COMMAND_LIST_TYPE_NONE: + case D3D12_COMMAND_LIST_TYPE_BUNDLE: + std::unreachable(); + } + std::unreachable(); +} + D3d12RentedCommandList::D3d12RentedCommandList(const Rc& pool, Rc&& list) : m_pool(pool), m_list(std::move(list)) { diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.h b/Coplt.Graphics.Native/D3d12/Src/Context.h index 9fd6489..a8b444b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.h +++ b/Coplt.Graphics.Native/D3d12/Src/Context.h @@ -132,6 +132,10 @@ namespace Coplt void Reset(const D3d12RentedCommandAllocator& allocator) const; void Close() const; + + public: + ID3D12CommandList* ToCommandList() const; + void Barrier(UINT32 NumBarrierGroups, const D3D12_BARRIER_GROUP* pBarrierGroups) const; }; struct D3d12RentedCommandList final diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index 3439c71..701a152 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -250,6 +250,15 @@ void D3d12GpuIsolate::RentRecords(const std::span out) } } +void D3d12GpuIsolate::RentRecords(std::span> out) +{ + const auto count = m_record_pool->try_dequeue_bulk(out.data(), out.size()); + for (u32 i = count; i < out.size(); ++i) + { + out[i] = new D3d12GpuRecord(this); + } +} + void D3d12GpuIsolate::ReturnRecords(const std::span records) { const auto f = [&](const std::span> items) @@ -279,6 +288,15 @@ void D3d12GpuIsolate::ReturnRecords(const std::span records) } } +void D3d12GpuIsolate::ReturnRecords(std::span> records) +{ + for (const auto& item : records) + { + item->Recycle(); + } + m_record_pool->enqueue_bulk(records.data(), records.size()); +} + void D3d12GpuIsolate::Submit(std::span records, std::span out) { SubmitReturn(records); diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index c5d6cdb..0e04488 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -78,7 +78,9 @@ namespace Coplt FResult CreateSwapChainForHwnd(const FGpuSwapChainCreateOptions& options, void* hwnd, FGpuSwapChainCreateResult& out) noexcept override; void RentRecords(std::span out); + void RentRecords(std::span> out); void ReturnRecords(std::span records); + void ReturnRecords(std::span> records); void Submit(std::span records, std::span out); void SubmitReturn(std::span records); void SubmitReturn(std::span> records); diff --git a/Coplt.Graphics.Native/D3d12/Src/Output.h b/Coplt.Graphics.Native/D3d12/Src/Output.h index 52feee4..9aeea4b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Output.h +++ b/Coplt.Graphics.Native/D3d12/Src/Output.h @@ -9,6 +9,7 @@ #include "Queue.h" #include "../FFI/Output.h" #include "../../Api/Include/Object.h" +#include "../Include/ResState.h" namespace Coplt { @@ -88,6 +89,7 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12GpuOutput2, "59aa68d8-91bd-4032-ba51-6a05795945b6", FGpuOutput2) { + virtual NonNull State() = 0; virtual NonNull Data() = 0; virtual NonNull ImageData() = 0; virtual NonNull GetResourcePtr() = 0; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 1f8210d..f5d7d25 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -126,28 +126,38 @@ void D3d12GpuRecord::Interpret() switch (command.Type) { case FCmdType::None: - continue; + break; case FCmdType::Label: // todo - continue; + break; case FCmdType::BeginScope: // todo - continue; + break; case FCmdType::EndScope: // todo - continue; + break; + case FCmdType::PreparePresent: + Interpret_PreparePresent(i, command.PreparePresent); + break; case FCmdType::ClearColor: Interpret_ClearColor(i, command.ClearColor); - continue; + break; case FCmdType::ClearDepthStencil: Interpret_ClearDepthStencil(i, command.ClearDepthStencil); - continue; + break; } } m_barrier_recorder->EndRecord(); m_storage->EndRecord(); } +void D3d12GpuRecord::Interpret_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const +{ + if (Mode != FGpuRecordMode::Direct) + COPLT_THROW("Can only present on the direct mode"); + m_barrier_recorder->OnUse(cmd.Output, ResAccess::None, ResUsage::Common, ResLayout::Common); +} + void D3d12GpuRecord::Interpret_ClearColor(u32 i, const FCmdClearColor& cmd) { m_barrier_recorder->OnUse(cmd.Image, ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); @@ -171,6 +181,20 @@ void D3d12GpuRecord::Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthSten ); } +FGpuQueueType Coplt::ToQueueType(const FGpuRecordMode mode) +{ + switch (mode) + { + case FGpuRecordMode::Direct: + return FGpuQueueType::Direct; + case FGpuRecordMode::Compute: + return FGpuQueueType::Compute; + case FGpuRecordMode::Copy: + return FGpuQueueType::Copy; + } + return FGpuQueueType::Direct; +} + NonNull Coplt::GetResource(const FCmdRes& res) { switch (res.Type) @@ -274,3 +298,26 @@ CD3DX12_CPU_DESCRIPTOR_HANDLE Coplt::GetDsv(const FCmdRes& res) } COPLT_THROW("Unreachable"); } + +NonNull Coplt::GetState(const FCmdRes& res) +{ + switch (res.Type) + { + case FCmdResType::Image: + { + const NonNull obj = res.Image->QueryInterface(); + COPLT_THROW("TODO"); + } + case FCmdResType::Buffer: + { + const NonNull obj = res.Image->QueryInterface(); + COPLT_THROW("TODO"); + } + case FCmdResType::Output: + { + const NonNull obj = res.Image->QueryInterface(); + return obj->State(); + } + } + COPLT_THROW("Unreachable"); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index ce2dedc..06d9b36 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -59,13 +59,16 @@ namespace Coplt void ReadyResource(); void Interpret(); + void Interpret_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const; void Interpret_ClearColor(u32 i, const FCmdClearColor& cmd); void Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); }; + FGpuQueueType ToQueueType(FGpuRecordMode mode); NonNull GetResource(const FCmdRes& res); NonNull GetBufferData(const FCmdRes& res); NonNull GetImageData(const FCmdRes& res); CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv(const FCmdRes& res); CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv(const FCmdRes& res); + NonNull GetState(const FCmdRes& res); } diff --git a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc index 9049587..dca9344 100644 --- a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc +++ b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc @@ -15,8 +15,11 @@ void D3d12RecordStorage::Clear() void D3d12RecordStorage::StartRecord(const FGpuRecordMode Mode) { - m_cmd_allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(ToListType(Mode)); - m_cur_list = m_cmd_allocator.RentCommandList(); + m_list_type = ToListType(Mode); + auto cmd_allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(m_list_type); + m_cur_list = cmd_allocator.RentCommandList(); + m_context->m_recycled_command_allocators.push_back(std::move(cmd_allocator)); + Split(); } void D3d12RecordStorage::EndRecord() @@ -34,13 +37,14 @@ void D3d12RecordStorage::BeforeSubmit() void D3d12RecordStorage::AfterSubmit() { - m_context->m_recycled_command_allocators.push_back(std::move(m_cmd_allocator)); } u32 D3d12RecordStorage::Split() { const auto i = m_result_lists.size(); - m_result_lists.push_back(std::exchange(m_cur_list, m_cmd_allocator.RentCommandList())); + auto cmd_allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(m_list_type); + m_result_lists.push_back(std::exchange(m_cur_list, cmd_allocator.RentCommandList())); + m_context->m_recycled_command_allocators.push_back(std::move(cmd_allocator)); return i; } @@ -54,6 +58,11 @@ std::span D3d12RecordStorage::Lists() return m_result_lists; } +u32 D3d12RecordStorage::CurrentListIndex() +{ + return m_result_lists.size(); +} + D3D12_COMMAND_LIST_TYPE Coplt::ToListType(const FGpuRecordMode value) { switch (value) diff --git a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h index 23b2887..ecba23d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h +++ b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h @@ -16,20 +16,22 @@ namespace Coplt virtual void BeforeSubmit() = 0; virtual void AfterSubmit() = 0; - // 返回当前 List 的 index + // 返回当前 List 的 index,是拆分后的新 list virtual u32 Split() = 0; virtual D3d12RentedCommandList& CurList() = 0; + // 永远在前面保留一个空的 list 用于插入屏障 virtual std::span Lists() = 0; + virtual u32 CurrentListIndex() = 0; }; struct D3d12RecordStorage final : Object { Rc m_device{}; Rc m_context{}; - D3d12RentedCommandAllocator m_cmd_allocator{}; D3d12RentedCommandList m_cur_list{}; std::vector m_result_lists{}; + D3D12_COMMAND_LIST_TYPE m_list_type{}; explicit D3d12RecordStorage(NonNull isolate, const Rc& context); @@ -44,6 +46,7 @@ namespace Coplt D3d12RentedCommandList& CurList() override; std::span Lists() override; + u32 CurrentListIndex() override; }; D3D12_COMMAND_LIST_TYPE ToListType(FGpuRecordMode value); diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc index 95171cc..b0a85f7 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -19,6 +19,10 @@ D3d12GpuSwapChain::D3d12GpuSwapChain( this->PresentMode = options.PresentMode; this->AlphaMode = AlphaMode; + m_res_state.State = ResState(ResAccess::None, ResUsage::Common, ResLayout::Common); + m_res_state.QueueType = FGpuQueueType::Direct; + m_res_state.CrossQueue = true; + if (m_debug_enabled && !options.Name.is_null()) { m_name = options.Name.ToString(); @@ -217,6 +221,11 @@ FGpuIsolate* D3d12GpuSwapChain::GetIsolate() noexcept return m_isolate.get(); } +NonNull D3d12GpuSwapChain::State() +{ + return &m_res_state; +} + NonNull D3d12GpuSwapChain::Data() { return this; diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.h b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h index 9b67752..2fd49eb 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.h +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h @@ -36,6 +36,7 @@ namespace Coplt struct D3d12GpuSwapChain final : GpuObject, FGpuSwapChainData { FGpuImageData m_image_data{}; + ResourceState m_res_state{}; private: explicit D3d12GpuSwapChain( @@ -60,6 +61,7 @@ namespace Coplt const FGpuSwapChainData* GpuSwapChainData() noexcept override; FGpuIsolate* GetIsolate() noexcept override; + NonNull State() override; NonNull Data() override; NonNull ImageData() override; NonNull GetResourcePtr() override; diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index 7241ce0..b6f0c78 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -76,6 +76,7 @@ public void DoInitGraphics() }; Render(Record, time); + Record.PreparePresent(Output); Isolate.Submit(Record); Output.Present(); } From fa33b578e3337ccbfd321711fef08206ea3656a5 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Wed, 26 Mar 2025 15:10:30 +0800 Subject: [PATCH 13/46] save --- Coplt.Graphics.Core/Core/GpuDevice.cs | 20 +- Coplt.Graphics.Core/Core/GpuIsolate.cs | 61 +----- Coplt.Graphics.Core/Core/GpuQueue.cs | 37 ---- Coplt.Graphics.Core/Core/QueueConfig.cs | 14 -- Coplt.Graphics.Core/Native/FChunked.cs | 71 +++++++ Coplt.Graphics.Core/Native/Native.cs | 73 +++----- Coplt.Graphics.Native/Api/CMakeLists.txt | 1 + Coplt.Graphics.Native/Api/FFI/Chunked.h | 174 ++++++++++++++++++ Coplt.Graphics.Native/Api/FFI/Common.h | 16 ++ Coplt.Graphics.Native/Api/FFI/Isolate.h | 22 +-- Coplt.Graphics.Native/Api/FFI/List.h | 6 +- Coplt.Graphics.Native/Api/FFI/Queue.h | 11 ++ .../D3d12/Include/ResState.h | 22 ++- Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 32 ++-- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 12 +- Coplt.Graphics.Native/D3d12/Src/Device.cc | 5 - Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 98 +--------- Coplt.Graphics.Native/D3d12/Src/Isolate.h | 28 +-- Coplt.Graphics.Native/D3d12/Src/Output.h | 2 +- Coplt.Graphics.Native/D3d12/Src/Record.cc | 14 +- Coplt.Graphics.Native/D3d12/Src/Record.h | 4 +- Coplt.Graphics.Native/D3d12/Src/ResState.cc | 157 +++++++++------- Coplt.Graphics.Native/D3d12/Src/SwapChain.cc | 9 +- Coplt.Graphics.Native/D3d12/Src/SwapChain.h | 4 +- 24 files changed, 472 insertions(+), 421 deletions(-) delete mode 100644 Coplt.Graphics.Core/Core/QueueConfig.cs create mode 100644 Coplt.Graphics.Core/Native/FChunked.cs create mode 100644 Coplt.Graphics.Native/Api/FFI/Chunked.h diff --git a/Coplt.Graphics.Core/Core/GpuDevice.cs b/Coplt.Graphics.Core/Core/GpuDevice.cs index 5c7671e..de5ee7d 100644 --- a/Coplt.Graphics.Core/Core/GpuDevice.cs +++ b/Coplt.Graphics.Core/Core/GpuDevice.cs @@ -67,25 +67,7 @@ public GpuIsolate CreateIsolate(string? Name = null, ReadOnlySpan Name8 = FGpuIsolateCreateOptions f_options = new(); FMainQueueCreateResult f_result; Ptr->CreateIsolate(&f_options, &f_result).TryThrow(); - var queues = new GpuQueue2[f_result.NumQueues]; - var isolate = new GpuIsolate(f_result.Isolate, null, this, f_result.Data, queues); - for (var i = 0; i < queues.Length; i++) - { - ref var q = ref f_result.Queues[i]; - queues[i] = new GpuQueue2(q.Queue, q.Data, null, isolate); - } - if (Instance.DebugEnabled) - { - if (Name8.Length > 0) - { - isolate.SetName(Name8, Name); - } - else if (Name != null) - { - isolate.SetName(Name); - } - } - return isolate; + return new GpuIsolate(f_result.Isolate, null, this, f_result.Data); } #endregion diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 1dc479b..74f4386 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -12,7 +12,6 @@ public sealed unsafe partial class GpuIsolate : DeviceChild #region Fields internal FGpuIsolateData* m_data; - internal readonly GpuQueue2[] m_queues; #endregion @@ -20,19 +19,16 @@ public sealed unsafe partial class GpuIsolate : DeviceChild public new FGpuIsolate* Ptr => (FGpuIsolate*)m_ptr; internal ref readonly FGpuIsolateData Data => ref *m_data; - public ReadOnlySpan Queues => m_queues; public FrameId FrameId => new(Data.FrameId); - public ref readonly QueueConfig QueueConfig => ref Unsafe.As(ref *m_data->QueueConfig); #endregion #region Ctor - internal GpuIsolate(FGpuIsolate* ptr, string? name, GpuDevice device, FGpuIsolateData* data, GpuQueue2[] queues) + internal GpuIsolate(FGpuIsolate* ptr, string? name, GpuDevice device, FGpuIsolateData* data) : base((FGpuObject*)ptr, name, device) { m_data = data; - m_queues = queues; } #endregion @@ -43,61 +39,6 @@ internal GpuIsolate(FGpuIsolate* ptr, string? name, GpuDevice device, FGpuIsolat private void Drop() { m_data = null; - foreach (var queue in m_queues) - { - queue.Dispose(); - } - } - - #endregion - - #region SetName - - public override void SetName(string name) - { - m_name = name; - if (!Device.Instance.DebugEnabled) return; - for (var i = 0; i < Queues.Length; i++) - { - var queue = Queues[i]; - queue.SetName($"[{name}]::Queue {i} ({queue.QueueType})"); - } - } - - public override void SetName(ReadOnlySpan name, string? managed_version = null) - { - m_name = managed_version; - if (!Device.Instance.DebugEnabled) return; - for (var i = 0; i < Queues.Length; i++) - { - var queue = Queues[i]; - if (managed_version != null) queue.m_name = $"[{managed_version}]::Queue {i} ({queue.QueueType})"; - var tmp_bytes = ArrayPool.Shared.Rent(name.Length + 256); - try - { - tmp_bytes[0] = "["u8[0]; - name.CopyTo(tmp_bytes.AsSpan(1)); - var cur = name.Length + 1; - "]::Queue"u8.CopyTo(tmp_bytes.AsSpan(cur)); - cur += "]::Queue "u8.Length; - i.TryFormat(tmp_bytes.AsSpan(cur), out var len); - cur += len; - tmp_bytes[cur] = " "u8[0]; - cur++; - tmp_bytes[cur] = "("u8[0]; - cur++; - var qt = queue.QueueType.ToUtf8String(); - qt.CopyTo(tmp_bytes.AsSpan(cur)); - cur += qt.Length; - tmp_bytes[cur] = ")"u8[0]; - tmp_bytes[cur + 1] = 0; - queue.SetName(tmp_bytes.AsSpan(0, cur + 2)); - } - finally - { - ArrayPool.Shared.Return(tmp_bytes); - } - } } #endregion diff --git a/Coplt.Graphics.Core/Core/GpuQueue.cs b/Coplt.Graphics.Core/Core/GpuQueue.cs index cac6a51..0d95d92 100644 --- a/Coplt.Graphics.Core/Core/GpuQueue.cs +++ b/Coplt.Graphics.Core/Core/GpuQueue.cs @@ -355,40 +355,3 @@ public ImageUploadBufferMemory AllocImageUploadMemory2D(uint PixelSize, uint Wid #endregion } - -[Dropping(Unmanaged = true)] -public sealed unsafe partial class GpuQueue2 : IsolateChild -{ - #region Fields - - internal FGpuQueueData* m_data; - - #endregion - - #region Props - - public new FGpuQueue2* Ptr => (FGpuQueue2*)m_ptr; - public ref readonly FGpuQueueData Data => ref *m_data; - public GpuQueueType QueueType => Data.QueueType.FromFFI(); - - #endregion - - #region Ctor - - internal GpuQueue2(FGpuQueue2* ptr, FGpuQueueData* data, string? name, GpuIsolate isolate) : base((FGpuObject*)ptr, name, isolate) - { - m_data = data; - } - - #endregion - - #region Drop - - [Drop] - private void Drop() - { - m_data = null; - } - - #endregion -} diff --git a/Coplt.Graphics.Core/Core/QueueConfig.cs b/Coplt.Graphics.Core/Core/QueueConfig.cs deleted file mode 100644 index 2998ed3..0000000 --- a/Coplt.Graphics.Core/Core/QueueConfig.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Coplt.Graphics.Core; - -public record struct QueueConfig -{ - /// - /// 额外的直接队列,默认保证有一个主队列 - /// - public uint NumDirect; - public uint NumCompute; - public uint NumCopy; - public uint NumVideoEncode; - public uint NumVideoDecode; - public uint NumVideoProcess; -} diff --git a/Coplt.Graphics.Core/Native/FChunked.cs b/Coplt.Graphics.Core/Native/FChunked.cs new file mode 100644 index 0000000..8bc3092 --- /dev/null +++ b/Coplt.Graphics.Core/Native/FChunked.cs @@ -0,0 +1,71 @@ +using System.Runtime.InteropServices; +using Coplt.Dropping; +using Coplt.Graphics.Utilities; + +namespace Coplt.Graphics.Native; + +[StructLayout(LayoutKind.Sequential)] +public unsafe struct FChunkedMemory where T : unmanaged +{ + #region Fields + + public T* m_ptr; + + #endregion +} + +[Dropping(Unmanaged = true)] +[StructLayout(LayoutKind.Sequential)] +public unsafe partial struct FChunkedAllocator where T : unmanaged +{ + #region Fields + + [Drop] + public FList> m_list; + public nuint m_cur; + public nuint m_chunk_size; + + #endregion + + #region Drop + + [Drop(Order = -1)] + private void Drop() + { + if (m_list.m_allocator != null && m_list.m_ptr != null) + { + for (nuint i = 0; i < m_list.m_len; ++i) + { + var chunk = m_list[i]; + m_list.m_allocator->MemoryFree(chunk.m_ptr, (nuint)Utils.AlignOf()); + } + } + } + + #endregion + + #region Alloc + + public FChunkedMemory Alloc() + { + if (m_cur >= m_list.m_len) + { + if (m_list.m_allocator == null) throw new NullReferenceException(); + FChunkedMemory chunk = new() { m_ptr = (T*)m_list.m_allocator->MemoryAlloc(m_chunk_size, (nuint)Utils.AlignOf()) }; + m_list.Add(chunk); + return chunk; + } + return m_list[m_cur++]; + } + + #endregion + + #region Reset + + public void Reset() + { + m_cur = 0; + } + + #endregion +} diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 8b49919..87a3b4a 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1363,43 +1363,22 @@ public unsafe partial struct FGpuRecordCreateResult public FGpuRecordData* Data; } - public partial struct FQueueConfig + public enum FGpuIsolateType { - [NativeTypeName("Coplt::u32")] - public uint NumDirect; - - [NativeTypeName("Coplt::u32")] - public uint NumCompute; - - [NativeTypeName("Coplt::u32")] - public uint NumCopy; - - [NativeTypeName("Coplt::u32")] - public uint NumVideoEncode; - - [NativeTypeName("Coplt::u32")] - public uint NumVideoDecode; - - [NativeTypeName("Coplt::u32")] - public uint NumVideoProcess; + Main, + BackgroundCopy, } - public unsafe partial struct FGpuIsolateCreateOptions + public partial struct FGpuIsolateCreateOptions { [NativeTypeName("Coplt::FStr8or16")] public FStr8or16 Name; - - [NativeTypeName("Coplt::FQueueConfig *")] - public FQueueConfig* QueueConfig; } - public unsafe partial struct FGpuIsolateData + public partial struct FGpuIsolateData { [NativeTypeName("Coplt::u64")] public ulong FrameId; - - [NativeTypeName("Coplt::FQueueConfig *")] - public FQueueConfig* QueueConfig; } [Guid("777C5774-8EB8-4550-A977-62CCCD7BDDA6")] @@ -1451,18 +1430,11 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, name); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuQueueCreateResult *")] - public FGpuQueueCreateResult* GetQueues([NativeTypeName("Coplt::u32 *")] uint* OutNumQueues) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuIsolate*)Unsafe.AsPointer(ref this), OutNumQueues); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FGpuIsolateData *")] public FGpuIsolateData* GpuIsolateData() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuIsolate*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuIsolate*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1470,7 +1442,7 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) public FResult RentRecords([NativeTypeName("Coplt::u32")] uint NumRecords, [NativeTypeName("Coplt::FGpuRecordCreateResult *")] FGpuRecordCreateResult* OutRecords) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, OutRecords); + return *((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, OutRecords); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1478,7 +1450,7 @@ public FResult RentRecords([NativeTypeName("Coplt::u32")] uint NumRecords, [Nati public FResult ReturnRecords([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records); + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1486,7 +1458,7 @@ public FResult ReturnRecords([NativeTypeName("Coplt::u32")] uint NumRecords, FGp public FResult Submit([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records, [NativeTypeName("Coplt::FGpuRecordCreateResult *")] FGpuRecordCreateResult* OutRecords) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records, OutRecords); + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records, OutRecords); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1494,7 +1466,7 @@ public FResult Submit([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord public FResult SubmitReturn([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records); + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1502,7 +1474,7 @@ public FResult SubmitReturn([NativeTypeName("Coplt::u32")] uint NumRecords, FGpu public FResult CreateSwapChainFromExists([NativeTypeName("const FGpuSwapChainFromExistsCreateOptions &")] FGpuSwapChainFromExistsCreateOptions* options, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1510,14 +1482,11 @@ public FResult CreateSwapChainFromExists([NativeTypeName("const FGpuSwapChainFro public FResult CreateSwapChainForHwnd([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, void* hwnd, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, hwnd, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, hwnd, @out); } public interface Interface : FGpuObject.Interface { - [return: NativeTypeName("Coplt::FGpuQueueCreateResult *")] - FGpuQueueCreateResult* GetQueues([NativeTypeName("Coplt::u32 *")] uint* OutNumQueues); - [return: NativeTypeName("Coplt::FGpuIsolateData *")] FGpuIsolateData* GpuIsolateData(); @@ -1552,12 +1521,6 @@ public unsafe partial struct FMainQueueCreateResult [NativeTypeName("Coplt::FGpuIsolateData *")] public FGpuIsolateData* Data; - - [NativeTypeName("Coplt::FGpuQueueCreateResult *")] - public FGpuQueueCreateResult* Queues; - - [NativeTypeName("Coplt::u32")] - public uint NumQueues; } [NativeTypeName("Coplt::u8")] @@ -2623,6 +2586,18 @@ public enum FGpuQueueType : byte VideoProcess, } + [NativeTypeName("Coplt::u8")] + public enum FGpuQueueFlags : byte + { + None = 0, + Direct = 1 << 0, + Compute = 1 << 1, + Copy = 1 << 2, + VideoEncode = 1 << 3, + VideoDecode = 1 << 4, + VideoProcess = 1 << 5, + } + [Guid("95E60E28-E387-4055-9B33-2D23AF901F8A")] [NativeTypeName("struct FGpuQueue : Coplt::FGpuObject")] public unsafe partial struct FGpuQueue : FGpuQueue.Interface, INativeGuid diff --git a/Coplt.Graphics.Native/Api/CMakeLists.txt b/Coplt.Graphics.Native/Api/CMakeLists.txt index 3fef5b9..e5d83ed 100644 --- a/Coplt.Graphics.Native/Api/CMakeLists.txt +++ b/Coplt.Graphics.Native/Api/CMakeLists.txt @@ -61,6 +61,7 @@ add_library(${target_name} STATIC Include/Finally.h FFI/Cmd.h FFI/Structs.h + FFI/Chunked.h ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) add_library(Coplt::Graphics::Api ALIAS ${target_name}) diff --git a/Coplt.Graphics.Native/Api/FFI/Chunked.h b/Coplt.Graphics.Native/Api/FFI/Chunked.h new file mode 100644 index 0000000..28b808f --- /dev/null +++ b/Coplt.Graphics.Native/Api/FFI/Chunked.h @@ -0,0 +1,174 @@ +#pragma once +#include + +#include "List.h" + +#ifdef FFI_SRC +#include +#endif + +namespace Coplt +{ + template + COPLT_REQUIRES COPLT_POD(T) + struct FChunkedMemory COPLT_FINAL + { + T* m_ptr{}; + }; + + template + COPLT_REQUIRES COPLT_POD(T) + struct FChunkedAllocator COPLT_FINAL + { + FList> m_list{}; + usize m_cur{}; + usize m_chunk_size{}; + + #ifdef FFI_SRC + + FChunkedAllocator() = default; + + explicit FChunkedAllocator(FAllocator* allocator) : m_list(allocator), m_chunk_size(128) + { + } + + explicit FChunkedAllocator(FAllocator* allocator, const usize chunk_size) : m_list(allocator), m_chunk_size(chunk_size) + { + if (!std::has_single_bit(chunk_size)) throw std::invalid_argument("Chunk size must be a power of 2"); + } + + void Swap(FChunkedAllocator& other) + { + std::swap(m_list, other.m_list); + std::swap(m_cur, other.m_cur); + std::swap(m_chunk_size, other.m_chunk_size); + } + + FChunkedAllocator(FChunkedAllocator&& other) noexcept + : m_list(std::exchange(other.m_list, {})), + m_cur(std::exchange(other.m_cur, 0)), + m_chunk_size(std::exchange(other.m_chunk_size, 0)) + { + } + + FChunkedAllocator& operator=(FChunkedAllocator&& other) noexcept + { + if (&m_list == &other.m_list) return *this; + FChunkedAllocator(std::forward(other)).Swap(*this); + return *this; + } + + FChunkedAllocator(FChunkedAllocator& other) = delete; + + FChunkedAllocator& operator=(FChunkedAllocator& other) = delete; + + ~FChunkedAllocator() + { + if (m_list.m_allocator && m_list.m_ptr) + { + for (usize i = 0; i < m_list.m_len; ++i) + { + auto chunk = m_list[i]; + m_list.m_allocator->MemoryFree(chunk.m_ptr, alignof(T)); + } + } + } + + FChunkedMemory Alloc() + { + if (m_cur >= m_list.m_len) + { + if (m_list.m_allocator == nullptr) throw std::bad_alloc(); + FChunkedMemory chunk{m_list.m_allocator->MemoryAlloc(m_chunk_size, alignof(T))}; + m_list.Add(chunk); + return chunk; + } + return m_list[m_cur++]; + } + + void Reset() + { + m_cur = 0; + } + + #endif + }; + + // 持有分块内存的 list,分块大小以 16 为起点,每次扩容翻倍 + // 可以随机访问,但是比较慢,适合录制命令这种只写和只顺序遍历的场景 + // 对比普通 list 只能减少扩容复制的开销,用处不是很大 + template + COPLT_REQUIRES COPLT_POD(T) + struct FGrowthChunkedList COPLT_FINAL + { + FList> m_chunks{}; + usize m_len{}; + usize m_cap{}; + usize m_cur_chunk_size{}; + + #ifdef FFI_SRC + + constexpr static usize InitChunkSize = 16; + constexpr static usize ChunkOffset = std::countr_zero(InitChunkSize); + + FGrowthChunkedList() = default; + + explicit FGrowthChunkedList(FAllocator* allocator) : m_chunks(allocator) + { + } + + void Swap(FGrowthChunkedList& other) + { + std::swap(m_chunks, other.m_chunks); + std::swap(m_len, other.m_len); + std::swap(m_cap, other.m_cap); + std::swap(m_cur_chunk_size, other.m_cur_chunk_size); + } + + FGrowthChunkedList(FGrowthChunkedList&& other) noexcept + : m_chunks(std::exchange(other.m_chunks, nullptr)), + m_len(other.m_len), m_cap(other.m_cap), m_cur_chunk_size(other.m_cur_chunk_size) + { + } + + FGrowthChunkedList& operator=(FGrowthChunkedList&& other) noexcept + { + if (&m_chunks == &other.m_chunks) return *this; + FGrowthChunkedList(std::forward(other)).Swap(*this); + return *this; + } + + FGrowthChunkedList(FGrowthChunkedList& other) = delete; + + FGrowthChunkedList& operator=(FGrowthChunkedList& other) = delete; + + ~FGrowthChunkedList() + { + if (m_chunks.m_allocator && m_chunks.m_ptr) + { + for (usize i = 0; i < m_chunks.m_len; ++i) + { + m_chunks.m_allocator.MemoryFree(m_chunks[i].m_ptr, alignof(T)); + } + } + } + + T& operator[](const usize index) + { + if (index >= m_len) throw std::out_of_range("FGrowthChunkedList::operator[]"); + const auto chunk_size = std::max(std::bit_ceil(index + 1), InitChunkSize); + const auto chunk_index = std::countr_zero(chunk_size >> ChunkOffset); + const auto index_in_chunk = index - (chunk_size - InitChunkSize); + return m_chunks[chunk_index][index_in_chunk]; + } + + usize Size() const + { + return m_len; + } + + // todo 优化用,暂时用不上先不写了 + + #endif + }; +} diff --git a/Coplt.Graphics.Native/Api/FFI/Common.h b/Coplt.Graphics.Native/Api/FFI/Common.h index 13de548..57e4b8e 100644 --- a/Coplt.Graphics.Native/Api/FFI/Common.h +++ b/Coplt.Graphics.Native/Api/FFI/Common.h @@ -8,6 +8,22 @@ #endif #endif +#ifndef COPLT_REQUIRES +#ifdef FFI_SRC +#define COPLT_REQUIRES requires +#else +#define COPLT_REQUIRES +#endif +#endif + +#ifndef COPLT_POD +#ifdef FFI_SRC +#define COPLT_POD(T) std::is_trivially_copyable_v +#else +#define COPLT_POD(T) +#endif +#endif + #ifndef COPLT_CDECL #ifdef _MSC_VER #define COPLT_CDECL __cdecl diff --git a/Coplt.Graphics.Native/Api/FFI/Isolate.h b/Coplt.Graphics.Native/Api/FFI/Isolate.h index 9304c4f..fe8efc0 100644 --- a/Coplt.Graphics.Native/Api/FFI/Isolate.h +++ b/Coplt.Graphics.Native/Api/FFI/Isolate.h @@ -8,35 +8,29 @@ namespace Coplt struct FGpuRecord; struct FGpuRecordCreateResult; - struct FQueueConfig + enum class FGpuIsolateType { - // 额外的直接队列,默认保证有一个主队列 - u32 NumDirect{0}; - u32 NumCompute{1}; - u32 NumCopy{1}; - u32 NumVideoEncode{0}; - u32 NumVideoDecode{0}; - u32 NumVideoProcess{0}; + // 包含 direct compute copy 队列,最多同时具有这3个队列 + // 可以提交异步任务自动调度到队列上,同时如果不支持多队列将回退到主 direct 队列 + Main, + // 仅包含 copy 队列,不一定有 + BackgroundCopy, + // todo video }; struct FGpuIsolateCreateOptions { // 可选 FStr8or16 Name{}; - // 可选 - FQueueConfig* QueueConfig{}; }; struct FGpuIsolateData { u64 FrameId{}; - FQueueConfig* QueueConfig{}; }; COPLT_INTERFACE_DEFINE(FGpuIsolate, "777c5774-8eb8-4550-a977-62cccd7bdda6", FGpuObject) { - // 返回的 FGpuQueueCreateResult 不会增加引用计数 - virtual FGpuQueueCreateResult* GetQueues(u32* OutNumQueues) noexcept = 0; virtual FGpuIsolateData* GpuIsolateData() noexcept = 0; // 租用记录 @@ -57,7 +51,5 @@ namespace Coplt { FGpuIsolate* Isolate{}; FGpuIsolateData* Data{}; - FGpuQueueCreateResult* Queues{}; - u32 NumQueues{}; }; } diff --git a/Coplt.Graphics.Native/Api/FFI/List.h b/Coplt.Graphics.Native/Api/FFI/List.h index 0991120..8e1b4ff 100644 --- a/Coplt.Graphics.Native/Api/FFI/List.h +++ b/Coplt.Graphics.Native/Api/FFI/List.h @@ -11,9 +11,7 @@ namespace Coplt { template - #ifdef FFI_SRC - requires std::is_trivially_copyable_v - #endif + COPLT_REQUIRES COPLT_POD(T) struct FList COPLT_FINAL { FAllocator* m_allocator{}; @@ -92,11 +90,13 @@ namespace Coplt { if (m_ptr == nullptr) { + if (m_allocator == nullptr) throw std::bad_alloc(); m_cap = InitCapacity; m_ptr = static_cast(m_allocator->MemoryAlloc(m_cap * sizeof(T), alignof(T))); } else { + if (m_allocator == nullptr) throw std::bad_alloc(); m_cap *= 2; m_ptr = static_cast(m_allocator->MemoryReAlloc(m_ptr, m_cap * sizeof(T), alignof(T))); } diff --git a/Coplt.Graphics.Native/Api/FFI/Queue.h b/Coplt.Graphics.Native/Api/FFI/Queue.h index efb2d42..82414d8 100644 --- a/Coplt.Graphics.Native/Api/FFI/Queue.h +++ b/Coplt.Graphics.Native/Api/FFI/Queue.h @@ -23,6 +23,17 @@ namespace Coplt VideoProcess, }; + COPLT_ENUM_FLAGS(FGpuQueueFlags, u8) + { + None = 0, + Direct = 1 << 0, + Compute = 1 << 1, + Copy = 1 << 2, + VideoEncode = 1 << 3, + VideoDecode = 1 << 4, + VideoProcess = 1 << 5, + }; + COPLT_INTERFACE_DEFINE(FGpuQueue, "95e60e28-e387-4055-9b33-2d23af901f8a", FGpuObject) { // 不安全的内存暴露,外部不能修改,每帧必须保证当前指向可用的帧上下文 diff --git a/Coplt.Graphics.Native/D3d12/Include/ResState.h b/Coplt.Graphics.Native/D3d12/Include/ResState.h index f366561..ad28a26 100644 --- a/Coplt.Graphics.Native/D3d12/Include/ResState.h +++ b/Coplt.Graphics.Native/D3d12/Include/ResState.h @@ -71,7 +71,7 @@ namespace Coplt CopyDest, ResolveSource, ResolveDest, - ShaderRateSource, + ShadingRateSource, VideoEncodeRead, VideoEncodeWrite, VideoDecodeRead, @@ -80,11 +80,20 @@ namespace Coplt VideoProcessWrite, }; + enum class ResQueue : u16 + { + Common = 0, + Direct = 1, + Compute = 2, + Video = 3, + }; + struct ResState { ResAccess Access{}; ResUsage Usage{}; ResLayout Layout{}; + ResQueue Queue{}; ResState() = default; explicit ResState(ResAccess Access, ResUsage Usage, ResLayout Layout); @@ -94,11 +103,10 @@ namespace Coplt ResState Split() const; }; - struct ResourceState + struct LayoutState { - ResState State{}; - FGpuQueueType QueueType{}; - bool CrossQueue{}; + ResLayout Layout{}; + ResQueue Queue{}; }; bool IsValid(ResAccess access); @@ -111,9 +119,11 @@ namespace Coplt D3D12_RESOURCE_STATES GetResourceState(ResAccess access); + D3D12_RESOURCE_STATES GetResourceState(ResLayout layout); + D3D12_BARRIER_ACCESS GetBarrierAccess(ResAccess access); - D3D12_BARRIER_LAYOUT GetBarrierLayout(ResLayout layout, FGpuQueueType queue, bool cross_queue); + D3D12_BARRIER_LAYOUT GetBarrierLayout(ResLayout layout, ResQueue queue); D3D12_BARRIER_SYNC GetBarrierSync(ResAccess access, ResUsage usage); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index e5eeab2..4015baf 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -154,8 +154,8 @@ namespace Coplt::Enhanced // .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, // todo 拆分屏障 .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, .AccessAfter = GetBarrierAccess(input.State.Access), - .LayoutBefore = GetBarrierLayout(sr.State->State.Layout, ToQueueType(data->Mode), sr.State->CrossQueue), - .LayoutAfter = GetBarrierLayout(input.State.Layout, ToQueueType(data->Mode), false), + .LayoutBefore = GetBarrierLayout(sr.State->Layout, sr.State->Queue), + .LayoutAfter = GetBarrierLayout(input.State.Layout, ToResQueue(data->Mode)), .pResource = GetResource(res), .Subresources = { .IndexOrFirstMipLevel = 0, @@ -215,7 +215,7 @@ namespace Coplt::Enhanced range.ListIndex = m_submit_lists.size(); const auto lists = storage->Lists(); range.ListCount = lists.size(); - range.QueueAt = QueueAt(0, FGpuQueueType::Direct); // todo 选择队列 + range.Queue = FGpuQueueType::Direct; // todo 选择队列 for (const auto& list : lists) { m_submit_lists.push_back(list->ToCommandList()); @@ -236,9 +236,9 @@ void AD3d12BarrierCombiner::EndSubmit() { m_submit_lists.clear(); m_list_ranges.clear(); - m_fence_info.clear(); - m_used_queues.clear(); + m_queue_deps.clear(); m_submit_resources.Clear(); + m_used_queues = FGpuQueueFlags::None; } bool AD3d12BarrierCombiner::Submit(NonNull isolate, std::span> records) @@ -259,11 +259,11 @@ bool AD3d12BarrierCombiner::Submit(NonNull isolate, std::spanGetQueue(range.QueueAt); - for (u32 i = 0; i < range.FenceCount; ++i) + const auto& queue = isolate->GetQueue(range.Queue); + for (u32 i = 0; i < range.DepCount; ++i) { - const auto& at = m_fence_info[i + range.FenceIndex]; - const auto& dep_queue = isolate->GetQueue(at); + const auto& dep = m_queue_deps[i + range.DepIndex]; + const auto& dep_queue = isolate->GetQueue(dep); queue->Wait(*dep_queue, dep_queue->Signal()); } queue->m_queue->ExecuteCommandLists(range.ListCount, m_submit_lists.data() + range.ListIndex); @@ -273,11 +273,17 @@ bool AD3d12BarrierCombiner::Submit(NonNull isolate, std::spanGetQueue(at); - main_queue->Wait(*dep_queue, dep_queue->Signal()); + if (HasFlags(m_used_queues, FGpuQueueFlags::Compute)) + { + const auto& dep_queue = isolate->GetQueue(FGpuQueueType::Compute); + main_queue->Wait(*dep_queue, dep_queue->Signal()); + } + if (HasFlags(m_used_queues, FGpuQueueFlags::Copy)) + { + const auto& dep_queue = isolate->GetQueue(FGpuQueueType::Copy); + main_queue->Wait(*dep_queue, dep_queue->Signal()); + } } #pragma endregion diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index bdb5b95..dc95023 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -46,23 +46,23 @@ namespace Coplt struct ResInfo { FCmdRes Res{}; - NonNull State; + NonNull State; }; struct ListRange { - u32 FenceIndex{}; - u32 FenceCount{}; + u32 DepIndex{}; + u32 DepCount{}; u32 ListIndex{}; u32 ListCount{}; - QueueAt QueueAt{}; + FGpuQueueType Queue{}; }; Rc m_device{}; std::vector m_submit_lists{}; std::vector m_list_ranges{}; - std::vector m_fence_info{}; - std::vector m_used_queues{}; + std::vector m_queue_deps{}; + FGpuQueueFlags m_used_queues{}; HashMap m_submit_resources{}; virtual void StartSubmit(); diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 27abbaf..0be659b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -161,11 +161,6 @@ FResult D3d12GpuDevice::CreateIsolate(const FGpuIsolateCreateOptions& options, F const auto ptr = new D3d12GpuIsolate(this->CloneThis(), options); out.Isolate = ptr; out.Data = ptr; - out.Queues = out.Isolate->GetQueues(&out.NumQueues); - for (u32 i = 0; i < out.NumQueues; ++i) - { - out.Queues[i].Queue->AddRef(); - } }); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index 701a152..54a9656 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -8,85 +8,18 @@ using namespace Coplt; -QueueAt::QueueAt(const u32 index, const FGpuQueueType type) : Index(index), Type(type) -{ -} - -bool QueueAt::IsMain() const -{ - return Type == FGpuQueueType::Direct && Index == 0; -} - D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options) : FGpuIsolateData() { - m_queue_config = std::make_shared(options.QueueConfig == nullptr ? FQueueConfig() : *options.QueueConfig); - this->QueueConfig = m_queue_config.get(); m_waiting_record = box(); m_record_pool = box(); m_device = std::move(device); - #pragma region Create Queues + #pragma region 创建队列 m_main_queue = new D3d12GpuQueue2(this, FGpuQueueType::Direct); - - m_direct_queues.reserve(m_queue_config->NumDirect); - for (u32 i = 0; i < m_queue_config->NumDirect; i++) - { - m_direct_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::Direct)); - } - m_compute_queues.reserve(m_queue_config->NumCompute); - for (u32 i = 0; i < m_queue_config->NumCompute; i++) - { - m_compute_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::Compute)); - } - m_copy_queues.reserve(m_queue_config->NumCopy); - for (u32 i = 0; i < m_queue_config->NumCopy; i++) - { - m_copy_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::Copy)); - } - m_video_encode_queues.reserve(m_queue_config->NumVideoEncode); - for (u32 i = 0; i < m_queue_config->NumVideoEncode; i++) - { - m_video_encode_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::VideoEncode)); - } - m_video_decode_queues.reserve(m_queue_config->NumVideoDecode); - for (u32 i = 0; i < m_queue_config->NumVideoDecode; i++) - { - m_video_decode_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::VideoDecode)); - } - m_video_process_queues.reserve(m_queue_config->NumVideoProcess); - for (u32 i = 0; i < m_queue_config->NumVideoProcess; i++) - { - m_video_process_queues.push_back(new D3d12GpuQueue2(this, FGpuQueueType::VideoProcess)); - } - m_queues.reserve(1 + m_queue_config->NumDirect + m_queue_config->NumCompute + m_queue_config->NumCopy - + m_queue_config->NumVideoEncode + m_queue_config->NumVideoDecode + m_queue_config->NumVideoProcess); - m_queues.push_back(FGpuQueueCreateResult{m_main_queue.get(), m_main_queue.get()}); - for (auto& queue : m_direct_queues) - { - m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); - } - for (auto& queue : m_compute_queues) - { - m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); - } - for (auto& queue : m_copy_queues) - { - m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); - } - for (auto& queue : m_video_encode_queues) - { - m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); - } - for (auto& queue : m_video_decode_queues) - { - m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); - } - for (auto& queue : m_video_process_queues) - { - m_queues.push_back(FGpuQueueCreateResult{queue.get(), queue.get()}); - } + m_compute_queue = new D3d12GpuQueue2(this, FGpuQueueType::Compute); + m_copy_queue = new D3d12GpuQueue2(this, FGpuQueueType::Copy); #pragma endregion @@ -134,34 +67,23 @@ FResult D3d12GpuIsolate::SetName(const FStr8or16& name) noexcept return FResult::None(); } -FGpuQueueCreateResult* D3d12GpuIsolate::GetQueues(u32* OutNumQueues) noexcept -{ - *OutNumQueues = m_queues.size(); - return m_queues.data(); -} - FGpuIsolateData* D3d12GpuIsolate::GpuIsolateData() noexcept { return this; } -const Rc& D3d12GpuIsolate::GetQueue(const QueueAt at) +const Rc& D3d12GpuIsolate::GetQueue(const FGpuQueueType type) { - switch (at.Type) + switch (type) { case FGpuQueueType::Direct: - if (at.Index == 0) return m_main_queue; - return m_direct_queues[at.Index - 1]; + return m_main_queue; case FGpuQueueType::Compute: - return m_compute_queues[at.Index]; + return m_compute_queue; case FGpuQueueType::Copy: - return m_copy_queues[at.Index]; - case FGpuQueueType::VideoEncode: - return m_video_encode_queues[at.Index]; - case FGpuQueueType::VideoDecode: - return m_video_decode_queues[at.Index]; - case FGpuQueueType::VideoProcess: - return m_video_process_queues[at.Index]; + return m_copy_queue; + default: + break; } return m_main_queue; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index 0e04488..1cc2a34 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -13,18 +13,10 @@ namespace Coplt { struct D3d12CommandListPoolCluster; + COPLT_INTERFACE_DEFINE(ID3d12GpuIsolate, "1c507c7f-140a-4717-809e-88096b475fea", FGpuIsolate) { - SRc m_queue_config{}; Rc m_device{}; - Rc m_main_queue{}; - std::vector> m_direct_queues{}; - std::vector> m_compute_queues{}; - std::vector> m_copy_queues{}; - std::vector> m_video_encode_queues{}; - std::vector> m_video_decode_queues{}; - std::vector> m_video_process_queues{}; - std::vector m_queues{}; std::mutex m_mutex{}; }; @@ -32,22 +24,13 @@ namespace Coplt struct ID3d12BarrierAnalyzer; struct ID3d12BarrierCombiner; - struct QueueAt - { - u32 Index{}; - FGpuQueueType Type{}; - - QueueAt() = default; - - explicit QueueAt(u32 index, FGpuQueueType type); - - bool IsMain() const; - }; - struct D3d12GpuIsolate final : GpuObject, FGpuIsolateData { using RecordQueue = moodycamel::ConcurrentQueue>; + Rc m_main_queue{}; + Rc m_compute_queue{}; + Rc m_copy_queue{}; Rc m_barrier_analyzer{}; Rc m_barrier_combiner{}; HANDLE m_event{}; @@ -64,10 +47,9 @@ namespace Coplt ~D3d12GpuIsolate() override; FResult SetName(const FStr8or16& name) noexcept override; - FGpuQueueCreateResult* GetQueues(u32* OutNumQueues) noexcept override; FGpuIsolateData* GpuIsolateData() noexcept override; - const Rc& GetQueue(QueueAt at); + const Rc& GetQueue(FGpuQueueType type); FResult RentRecords(u32 NumRecords, FGpuRecordCreateResult* OutRecords) noexcept override; FResult ReturnRecords(u32 NumRecords, FGpuRecord** Records) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Output.h b/Coplt.Graphics.Native/D3d12/Src/Output.h index 9aeea4b..9b4b757 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Output.h +++ b/Coplt.Graphics.Native/D3d12/Src/Output.h @@ -89,7 +89,7 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12GpuOutput2, "59aa68d8-91bd-4032-ba51-6a05795945b6", FGpuOutput2) { - virtual NonNull State() = 0; + virtual NonNull State() = 0; virtual NonNull Data() = 0; virtual NonNull ImageData() = 0; virtual NonNull GetResourcePtr() = 0; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index f5d7d25..3248843 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -181,18 +181,18 @@ void D3d12GpuRecord::Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthSten ); } -FGpuQueueType Coplt::ToQueueType(const FGpuRecordMode mode) +ResQueue Coplt::ToResQueue(const FGpuRecordMode mode) { switch (mode) { case FGpuRecordMode::Direct: - return FGpuQueueType::Direct; + return ResQueue::Direct; case FGpuRecordMode::Compute: - return FGpuQueueType::Compute; - case FGpuRecordMode::Copy: - return FGpuQueueType::Copy; + return ResQueue::Compute; + default: + break; } - return FGpuQueueType::Direct; + return ResQueue::Common; } NonNull Coplt::GetResource(const FCmdRes& res) @@ -299,7 +299,7 @@ CD3DX12_CPU_DESCRIPTOR_HANDLE Coplt::GetDsv(const FCmdRes& res) COPLT_THROW("Unreachable"); } -NonNull Coplt::GetState(const FCmdRes& res) +NonNull Coplt::GetState(const FCmdRes& res) { switch (res.Type) { diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 06d9b36..cff6d71 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -64,11 +64,11 @@ namespace Coplt void Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); }; - FGpuQueueType ToQueueType(FGpuRecordMode mode); + ResQueue ToResQueue(FGpuRecordMode mode); NonNull GetResource(const FCmdRes& res); NonNull GetBufferData(const FCmdRes& res); NonNull GetImageData(const FCmdRes& res); CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv(const FCmdRes& res); CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv(const FCmdRes& res); - NonNull GetState(const FCmdRes& res); + NonNull GetState(const FCmdRes& res); } diff --git a/Coplt.Graphics.Native/D3d12/Src/ResState.cc b/Coplt.Graphics.Native/D3d12/Src/ResState.cc index 8ebec9b..fb0741c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/ResState.cc +++ b/Coplt.Graphics.Native/D3d12/Src/ResState.cc @@ -168,6 +168,51 @@ D3D12_RESOURCE_STATES Coplt::GetResourceState(const ResAccess access) return state; } +D3D12_RESOURCE_STATES Coplt::GetResourceState(const ResLayout layout) +{ + switch (layout) + { + case ResLayout::Undefined: + case ResLayout::Common: + return D3D12_RESOURCE_STATE_COMMON; + case ResLayout::GenericRead: + return D3D12_RESOURCE_STATE_GENERIC_READ; + case ResLayout::RenderTarget: + return D3D12_RESOURCE_STATE_RENDER_TARGET; + case ResLayout::UnorderedAccess: + return D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + case ResLayout::DepthStencilWrite: + return D3D12_RESOURCE_STATE_DEPTH_WRITE; + case ResLayout::DepthStencilRead: + return D3D12_RESOURCE_STATE_DEPTH_READ; + case ResLayout::ShaderResource: + return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE; + case ResLayout::CopySource: + return D3D12_RESOURCE_STATE_COPY_SOURCE; + case ResLayout::CopyDest: + return D3D12_RESOURCE_STATE_COPY_DEST; + case ResLayout::ResolveSource: + return D3D12_RESOURCE_STATE_RESOLVE_SOURCE; + case ResLayout::ResolveDest: + return D3D12_RESOURCE_STATE_RESOLVE_DEST; + case ResLayout::ShadingRateSource: + return D3D12_RESOURCE_STATE_SHADING_RATE_SOURCE; + case ResLayout::VideoEncodeRead: + return D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ; + case ResLayout::VideoEncodeWrite: + return D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE; + case ResLayout::VideoDecodeRead: + return D3D12_RESOURCE_STATE_VIDEO_DECODE_READ; + case ResLayout::VideoDecodeWrite: + return D3D12_RESOURCE_STATE_VIDEO_DECODE_WRITE; + case ResLayout::VideoProcessRead: + return D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ; + case ResLayout::VideoProcessWrite: + return D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE; + } + return D3D12_RESOURCE_STATE_COMMON; +} + D3D12_BARRIER_ACCESS Coplt::GetBarrierAccess(const ResAccess access) { D3D12_BARRIER_ACCESS ba = D3D12_BARRIER_ACCESS_COMMON; @@ -231,7 +276,7 @@ D3D12_BARRIER_ACCESS Coplt::GetBarrierAccess(const ResAccess access) return ba; } -D3D12_BARRIER_LAYOUT Coplt::GetBarrierLayout(const ResLayout layout, const FGpuQueueType queue, const bool cross_queue) +D3D12_BARRIER_LAYOUT Coplt::GetBarrierLayout(ResLayout layout, ResQueue queue) { switch (layout) { @@ -247,7 +292,7 @@ D3D12_BARRIER_LAYOUT Coplt::GetBarrierLayout(const ResLayout layout, const FGpuQ return D3D12_BARRIER_LAYOUT_RESOLVE_SOURCE; case ResLayout::ResolveDest: return D3D12_BARRIER_LAYOUT_RESOLVE_DEST; - case ResLayout::ShaderRateSource: + case ResLayout::ShadingRateSource: return D3D12_BARRIER_LAYOUT_SHADING_RATE_SOURCE; case ResLayout::VideoEncodeRead: return D3D12_BARRIER_LAYOUT_VIDEO_ENCODE_READ; @@ -262,92 +307,72 @@ D3D12_BARRIER_LAYOUT Coplt::GetBarrierLayout(const ResLayout layout, const FGpuQ case ResLayout::VideoProcessWrite: return D3D12_BARRIER_LAYOUT_VIDEO_PROCESS_WRITE; case ResLayout::GenericRead: - if (!cross_queue) + switch (queue) { - switch (queue) - { - case FGpuQueueType::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ; - case FGpuQueueType::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_GENERIC_READ; - default: - break; - } + case ResQueue::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ; + case ResQueue::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_GENERIC_READ; + default: + break; } return D3D12_BARRIER_LAYOUT_GENERIC_READ; case ResLayout::UnorderedAccess: - if (!cross_queue) + switch (queue) { - switch (queue) - { - case FGpuQueueType::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS; - case FGpuQueueType::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_UNORDERED_ACCESS; - default: - break; - } + case ResQueue::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS; + case ResQueue::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_UNORDERED_ACCESS; + default: + break; } return D3D12_BARRIER_LAYOUT_UNORDERED_ACCESS; case ResLayout::ShaderResource: - if (!cross_queue) + switch (queue) { - switch (queue) - { - case FGpuQueueType::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE; - case FGpuQueueType::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_SHADER_RESOURCE; - default: - break; - } + case ResQueue::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE; + case ResQueue::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_SHADER_RESOURCE; + default: + break; } return D3D12_BARRIER_LAYOUT_SHADER_RESOURCE; case ResLayout::CopySource: - if (!cross_queue) + switch (queue) { - switch (queue) - { - case FGpuQueueType::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE; - case FGpuQueueType::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_SOURCE; - default: - break; - } + case ResQueue::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE; + case ResQueue::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_SOURCE; + default: + break; } return D3D12_BARRIER_LAYOUT_COPY_SOURCE; case ResLayout::CopyDest: - if (!cross_queue) + switch (queue) { - switch (queue) - { - case FGpuQueueType::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_DEST; - case FGpuQueueType::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_DEST; - default: - break; - } + case ResQueue::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_DEST; + case ResQueue::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_DEST; + default: + break; } return D3D12_BARRIER_LAYOUT_COPY_DEST; case ResLayout::Common: default: - if (!cross_queue) + switch (queue) { - switch (queue) - { - case FGpuQueueType::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON; - case FGpuQueueType::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COMMON; - case FGpuQueueType::VideoEncode: - case FGpuQueueType::VideoDecode: - case FGpuQueueType::VideoProcess: - return D3D12_BARRIER_LAYOUT_VIDEO_QUEUE_COMMON; - default: - break; - } + case ResQueue::Direct: + return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON; + case ResQueue::Compute: + return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COMMON; + case ResQueue::Video: + return D3D12_BARRIER_LAYOUT_VIDEO_QUEUE_COMMON; + default: + break; } return D3D12_BARRIER_LAYOUT_COMMON; } diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc index b0a85f7..fc23445 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -19,9 +19,8 @@ D3d12GpuSwapChain::D3d12GpuSwapChain( this->PresentMode = options.PresentMode; this->AlphaMode = AlphaMode; - m_res_state.State = ResState(ResAccess::None, ResUsage::Common, ResLayout::Common); - m_res_state.QueueType = FGpuQueueType::Direct; - m_res_state.CrossQueue = true; + m_layout_state.Layout = ResLayout::Common; + m_layout_state.Queue = ResQueue::Common; if (m_debug_enabled && !options.Name.is_null()) { @@ -221,9 +220,9 @@ FGpuIsolate* D3d12GpuSwapChain::GetIsolate() noexcept return m_isolate.get(); } -NonNull D3d12GpuSwapChain::State() +NonNull D3d12GpuSwapChain::State() { - return &m_res_state; + return &m_layout_state; } NonNull D3d12GpuSwapChain::Data() diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.h b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h index 2fd49eb..95788e0 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.h +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h @@ -36,7 +36,7 @@ namespace Coplt struct D3d12GpuSwapChain final : GpuObject, FGpuSwapChainData { FGpuImageData m_image_data{}; - ResourceState m_res_state{}; + LayoutState m_layout_state{}; private: explicit D3d12GpuSwapChain( @@ -61,7 +61,7 @@ namespace Coplt const FGpuSwapChainData* GpuSwapChainData() noexcept override; FGpuIsolate* GetIsolate() noexcept override; - NonNull State() override; + NonNull State() override; NonNull Data() override; NonNull ImageData() override; NonNull GetResourcePtr() override; From ebbb2e7e762d2ce33c51d0d7d55215dded4fe6a8 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 27 Mar 2025 00:39:17 +0800 Subject: [PATCH 14/46] save --- Coplt.Graphics.Core/Core/GpuIsolate.cs | 9 +- Coplt.Graphics.Core/Core/GpuOutput.cs | 33 ++-- Coplt.Graphics.Core/Core/GpuQueue.cs | 9 +- Coplt.Graphics.Core/Native/Native.cs | 46 ++--- .../Api/FFI/GraphicsFormat.h | 57 +++++++ Coplt.Graphics.Native/Api/FFI/Output.h | 27 ++- .../D3d12/Include/ResState.h | 14 +- Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 160 ++++++++++++++++-- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 43 ++--- Coplt.Graphics.Native/D3d12/Src/Output.cc | 6 +- Coplt.Graphics.Native/D3d12/Src/Record.cc | 17 +- Coplt.Graphics.Native/D3d12/Src/Record.h | 1 - Coplt.Graphics.Native/D3d12/Src/ResState.cc | 63 +------ Coplt.Graphics.Native/D3d12/Src/SwapChain.cc | 30 ++-- Examples/ExampleBase/ExampleBase.cs | 1 + 15 files changed, 302 insertions(+), 214 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 74f4386..a3ccfb5 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -252,18 +252,13 @@ public GpuSwapChain CreateSwapChainForHwnd(IntPtr Hwnd, in GpuSwapChainCreateOpt { Name = new(Name, Name8, p_name, p_name8), PresentMode = (FPresentMode)Options.PresentMode, + Hdr = (FHdrType)Options.Hdr, + Srgb = Options.Srgb, }, Width = Options.Width, Height = Options.Height, - Format = Options.Format.ToFFI(), AlphaMode = (FOutputAlphaMode)Options.AlphaMode, VSync = Options.VSync, - FormatSelector = - { - Specify = Options.FormatSelector.Specify, - Srgb = Options.FormatSelector.Srgb, - Hdr = (FHdrType)Options.FormatSelector.Hdr, - }, }; FGpuSwapChainCreateResult r; Ptr->CreateSwapChainForHwnd(&f_options, (void*)Hwnd, &r).TryThrow(); diff --git a/Coplt.Graphics.Core/Core/GpuOutput.cs b/Coplt.Graphics.Core/Core/GpuOutput.cs index 2f4cbfa..9ae5368 100644 --- a/Coplt.Graphics.Core/Core/GpuOutput.cs +++ b/Coplt.Graphics.Core/Core/GpuOutput.cs @@ -31,34 +31,21 @@ public enum HdrType : byte #region GpuOutputOptions -/// -/// 输出格式选择器,按选择器选择,不符合将回退,保证成功;指定格式不保证 -/// -public record struct GpuOutputFormatSelector +public record struct GpuOutputOptions() { + public required uint Width; + public required uint Height; /// - /// 指定格式,忽略选择器 - /// - public bool Specify; - /// - /// 如果可能,使用 srgb 格式 + /// 是否使用 srgb,实现可以选择忽略 /// public bool Srgb; /// - /// 如果可能,使用 hdr 格式,和 srgb 冲突,并且优先级更高 + /// 是否使用 hdr,实现可以选择忽略 /// public HdrType Hdr; -} - -public record struct GpuOutputOptions() -{ - public required uint Width; - public required uint Height; - public GraphicsFormat Format = GraphicsFormat.R8G8B8A8_UNorm; public PresentMode PresentMode = PresentMode.TripleBuffer; public OutputAlphaMode AlphaMode = OutputAlphaMode.Opaque; public bool VSync = false; - public GpuOutputFormatSelector FormatSelector; } #endregion @@ -241,11 +228,17 @@ public record struct GpuSwapChainCreateOptions() { public required uint Width; public required uint Height; - public GraphicsFormat Format = GraphicsFormat.R8G8B8A8_UNorm; + /// + /// 是否使用 srgb,实现可以选择忽略 + /// + public bool Srgb; + /// + /// 是否使用 hdr,实现可以选择忽略 + /// + public HdrType Hdr; public PresentMode PresentMode = PresentMode.TripleBuffer; public OutputAlphaMode AlphaMode = OutputAlphaMode.Opaque; public bool VSync = false; - public GpuOutputFormatSelector FormatSelector; } public sealed unsafe class GpuSwapChain : GpuOutput2 diff --git a/Coplt.Graphics.Core/Core/GpuQueue.cs b/Coplt.Graphics.Core/Core/GpuQueue.cs index 0d95d92..bfcfcca 100644 --- a/Coplt.Graphics.Core/Core/GpuQueue.cs +++ b/Coplt.Graphics.Core/Core/GpuQueue.cs @@ -159,16 +159,11 @@ public GpuOutput CreateOutputForHwnd( Name = new(Name, Name8, p_name, p_name8), Width = Options.Width, Height = Options.Height, - Format = Options.Format.ToFFI(), + Hdr =(FHdrType) Options.Hdr, + Srgb = Options.Srgb, PresentMode = (FPresentMode)Options.PresentMode, AlphaMode = (FOutputAlphaMode)Options.AlphaMode, VSync = Options.VSync, - FormatSelector = - { - Specify = Options.FormatSelector.Specify, - Srgb = Options.FormatSelector.Srgb, - Hdr = (FHdrType)Options.FormatSelector.Hdr, - }, }; FGpuOutput* ptr; m_ptr->CreateOutputForHwnd(&f_options, (void*)Hwnd, &ptr).TryThrow(); diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 87a3b4a..c908e71 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -3563,18 +3563,6 @@ public enum FHdrType : byte Float16, } - public partial struct FGpuOutputFormatSelector - { - [NativeTypeName("Coplt::b8")] - public B8 Specify; - - [NativeTypeName("Coplt::b8")] - public B8 Srgb; - - [NativeTypeName("Coplt::FHdrType")] - public FHdrType Hdr; - } - public partial struct FGpuOutputFromSwapChainCreateOptions { [NativeTypeName("Coplt::b8")] @@ -3592,8 +3580,11 @@ public partial struct FGpuOutputCreateOptions [NativeTypeName("Coplt::u32")] public uint Height; - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat Format; + [NativeTypeName("Coplt::b8")] + public B8 Srgb; + + [NativeTypeName("Coplt::FHdrType")] + public FHdrType Hdr; [NativeTypeName("Coplt::FPresentMode")] public FPresentMode PresentMode; @@ -3603,9 +3594,6 @@ public partial struct FGpuOutputCreateOptions [NativeTypeName("Coplt::b8")] public B8 VSync; - - [NativeTypeName("Coplt::FGpuOutputFormatSelector")] - public FGpuOutputFormatSelector FormatSelector; } public partial struct FCommandSubmit @@ -3787,6 +3775,12 @@ public partial struct FGpuOutputData [NativeTypeName("Coplt::u32")] public uint Height; + [NativeTypeName("Coplt::b8")] + public B8 Srgb; + + [NativeTypeName("Coplt::FHdrType")] + public FHdrType Hdr; + [NativeTypeName("Coplt::FPresentMode")] public FPresentMode PresentMode; } @@ -3798,6 +3792,12 @@ public partial struct FGpuOutput2CreateOptions [NativeTypeName("Coplt::FPresentMode")] public FPresentMode PresentMode; + + [NativeTypeName("Coplt::b8")] + public B8 Srgb; + + [NativeTypeName("Coplt::FHdrType")] + public FHdrType Hdr; } [Guid("3F82BE7F-2CF5-48A9-8CA4-BB2F9CFE58B2")] @@ -3922,6 +3922,12 @@ public partial struct FGpuSwapChainData [NativeTypeName("Coplt::b8")] public B8 VSync; + + [NativeTypeName("Coplt::b8")] + public B8 Srgb; + + [NativeTypeName("Coplt::FHdrType")] + public FHdrType Hdr; } [NativeTypeName("struct FGpuSwapChainCreateOptions : Coplt::FGpuOutput2CreateOptions")] @@ -3935,12 +3941,6 @@ public partial struct FGpuSwapChainCreateOptions [NativeTypeName("Coplt::u32")] public uint Height; - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat Format; - - [NativeTypeName("Coplt::FGpuOutputFormatSelector")] - public FGpuOutputFormatSelector FormatSelector; - [NativeTypeName("Coplt::FOutputAlphaMode")] public FOutputAlphaMode AlphaMode; diff --git a/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h b/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h index 82262eb..bfb5b9f 100644 --- a/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h +++ b/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h @@ -625,6 +625,63 @@ namespace Coplt } } + inline FGraphicsFormat ToSrgb(const FGraphicsFormat value) + { + switch (value) + { + case FGraphicsFormat::BC1_UNorm: + return FGraphicsFormat::BC1_UNorm_sRGB; + case FGraphicsFormat::BC2_UNorm: + return FGraphicsFormat::BC2_UNorm_sRGB; + case FGraphicsFormat::BC3_UNorm: + return FGraphicsFormat::BC3_UNorm_sRGB; + case FGraphicsFormat::BC7_UNorm: + return FGraphicsFormat::BC7_UNorm_sRGB; + case FGraphicsFormat::B8G8R8A8_UNorm: + return FGraphicsFormat::B8G8R8A8_UNorm_sRGB; + case FGraphicsFormat::B8G8R8X8_UNorm: + return FGraphicsFormat::B8G8R8X8_UNorm_sRGB; + case FGraphicsFormat::R8G8B8A8_UNorm: + return FGraphicsFormat::R8G8B8A8_UNorm_sRGB; + case FGraphicsFormat::Etc2_R8G8B8_UNorm: + return FGraphicsFormat::Etc2_R8G8B8_sRGB; + case FGraphicsFormat::Etc2_R8G8B8A1_UNorm: + return FGraphicsFormat::Etc2_R8G8B8A1_sRGB; + case FGraphicsFormat::Etc2_R8G8B8A8_UNorm: + return FGraphicsFormat::Etc2_R8G8B8A8_sRGB; + case FGraphicsFormat::Astc_4x4_UNorm: + return FGraphicsFormat::Astc_4x4_sRGB; + case FGraphicsFormat::Astc_5x4_UNorm: + return FGraphicsFormat::Astc_5x4_sRGB; + case FGraphicsFormat::Astc_5x5_UNorm: + return FGraphicsFormat::Astc_5x5_sRGB; + case FGraphicsFormat::Astc_6x5_UNorm: + return FGraphicsFormat::Astc_6x5_sRGB; + case FGraphicsFormat::Astc_6x6_UNorm: + return FGraphicsFormat::Astc_6x6_sRGB; + case FGraphicsFormat::Astc_8x5_UNorm: + return FGraphicsFormat::Astc_8x5_sRGB; + case FGraphicsFormat::Astc_8x6_UNorm: + return FGraphicsFormat::Astc_8x6_sRGB; + case FGraphicsFormat::Astc_8x8_UNorm: + return FGraphicsFormat::Astc_8x8_sRGB; + case FGraphicsFormat::Astc_10x5_UNorm: + return FGraphicsFormat::Astc_10x5_sRGB; + case FGraphicsFormat::Astc_10x6_UNorm: + return FGraphicsFormat::Astc_10x6_sRGB; + case FGraphicsFormat::Astc_10x8_UNorm: + return FGraphicsFormat::Astc_10x8_sRGB; + case FGraphicsFormat::Astc_10x10_UNorm: + return FGraphicsFormat::Astc_10x10_sRGB; + case FGraphicsFormat::Astc_12x10_UNorm: + return FGraphicsFormat::Astc_12x10_sRGB; + case FGraphicsFormat::Astc_12x12_UNorm: + return FGraphicsFormat::Astc_12x12_sRGB; + default: + return value; + } + } + inline bool IsDepthStencil(const FGraphicsFormat value) { switch (value) diff --git a/Coplt.Graphics.Native/Api/FFI/Output.h b/Coplt.Graphics.Native/Api/FFI/Output.h index d02c72c..0ca7d43 100644 --- a/Coplt.Graphics.Native/Api/FFI/Output.h +++ b/Coplt.Graphics.Native/Api/FFI/Output.h @@ -29,17 +29,6 @@ namespace Coplt Float16, }; - // 输出格式选择器,按选择器选择,不符合将回退,保证成功;指定格式不保证 - struct FGpuOutputFormatSelector - { - // 指定格式,忽略选择器 - b8 Specify{}; - // 如果可能,使用 srgb 格式 - b8 Srgb{}; - // 如果可能,使用 hdr 格式,和 srgb 冲突,并且优先级更高 - FHdrType Hdr{}; - }; - struct FGpuOutputFromSwapChainCreateOptions { b8 VSync{}; @@ -50,12 +39,14 @@ namespace Coplt FStr8or16 Name{}; u32 Width{}; u32 Height{}; - FGraphicsFormat Format{}; + // 是否使用 srgb,实现可以选择忽略 + b8 Srgb{}; + // 是否使用 hdr,实现可以选择忽略 + FHdrType Hdr{}; // 呈现模式,实现可以选择忽略 FPresentMode PresentMode{}; FOutputAlphaMode AlphaMode{}; b8 VSync{}; - FGpuOutputFormatSelector FormatSelector{}; }; using WhenDoneFn = void COPLT_CDECL(void* obj); @@ -83,6 +74,8 @@ namespace Coplt FGraphicsFormat Format{}; u32 Width{}; u32 Height{}; + b8 Srgb{}; + FHdrType Hdr{}; FPresentMode PresentMode{}; }; @@ -91,6 +84,8 @@ namespace Coplt FStr8or16 Name{}; // 呈现模式,实现可以选择忽略 FPresentMode PresentMode{}; + b8 Srgb{}; + FHdrType Hdr{}; }; COPLT_INTERFACE_DEFINE(FGpuOutput2, "3f82be7f-2cf5-48a9-8ca4-bb2f9cfe58b2", FGpuExecutor) @@ -109,14 +104,16 @@ namespace Coplt { FOutputAlphaMode AlphaMode{}; b8 VSync{}; + // 是否使用 srgb,实现可以选择忽略 + b8 Srgb{}; + // 是否使用 hdr,实现可以选择忽略 + FHdrType Hdr{}; }; struct FGpuSwapChainCreateOptions : FGpuOutput2CreateOptions { u32 Width{}; u32 Height{}; - FGraphicsFormat Format{}; - FGpuOutputFormatSelector FormatSelector{}; FOutputAlphaMode AlphaMode{}; b8 VSync{}; }; diff --git a/Coplt.Graphics.Native/D3d12/Include/ResState.h b/Coplt.Graphics.Native/D3d12/Include/ResState.h index ad28a26..5461932 100644 --- a/Coplt.Graphics.Native/D3d12/Include/ResState.h +++ b/Coplt.Graphics.Native/D3d12/Include/ResState.h @@ -80,20 +80,11 @@ namespace Coplt VideoProcessWrite, }; - enum class ResQueue : u16 - { - Common = 0, - Direct = 1, - Compute = 2, - Video = 3, - }; - struct ResState { ResAccess Access{}; ResUsage Usage{}; ResLayout Layout{}; - ResQueue Queue{}; ResState() = default; explicit ResState(ResAccess Access, ResUsage Usage, ResLayout Layout); @@ -101,12 +92,13 @@ namespace Coplt bool IsCompatible(const ResState& New, bool Enhanced) const; ResState Merge(const ResState& New) const; ResState Split() const; + + bool Same(const ResState& other) const; }; struct LayoutState { ResLayout Layout{}; - ResQueue Queue{}; }; bool IsValid(ResAccess access); @@ -123,7 +115,7 @@ namespace Coplt D3D12_BARRIER_ACCESS GetBarrierAccess(ResAccess access); - D3D12_BARRIER_LAYOUT GetBarrierLayout(ResLayout layout, ResQueue queue); + D3D12_BARRIER_LAYOUT GetBarrierLayout(ResLayout layout); D3D12_BARRIER_SYNC GetBarrierSync(ResAccess access, ResUsage usage); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index 4015baf..ddf5b78 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -21,7 +21,7 @@ namespace Coplt::Enhanced return new EnhancedBarrierCombiner(m_device); } - EnhancedBarrierRecorder::ResInfo::ResInfo(const FCmdResType ResType) : ResType(ResType) + EnhancedBarrierRecorder::ResInfo::ResInfo(const NonNull Res) : Res(Res) { } @@ -39,13 +39,11 @@ namespace Coplt::Enhanced { m_resources.clear(); m_inputs.clear(); - m_groups.clear(); - m_begin_buffer_barriers.clear(); - m_begin_texture_barriers.clear(); - m_end_buffer_barriers.clear(); - m_end_texture_barriers.clear(); - m_current_begin_barrier_group_index = 0; - m_current_end_barrier_group_index = 0; + m_buffer_barriers.clear(); + m_texture_barriers.clear(); + // m_split_buffer_barriers.clear(); + // m_split_texture_barriers.clear(); + m_barrier_points.clear(); } void EnhancedBarrierRecorder::StartRecord(const std::span resources) @@ -55,9 +53,8 @@ namespace Coplt::Enhanced for (usize i = 0; i < resources.size(); ++i) { const auto& res = resources[i]; - m_resources.push_back(ResInfo(res.Type)); + m_resources.push_back(ResInfo(&res)); } - m_groups.push_back({}); } void EnhancedBarrierRecorder::EndRecord() @@ -70,8 +67,19 @@ namespace Coplt::Enhanced { m_inputs.push_back(InputResState{.ResIndex = i, .BeforeUseListIndex = info.CurrentBeforeUseListIndex, .State = info.State}); } + else + { + info.CurrentBeforeUseListIndex = m_storage->CurrentListIndex(); + CreateBarrier(info); + } // todo output + // GetState(*info.Res)->Layout = info.State.Layout; } + // OnCmd(); + std::ranges::sort(m_barrier_points, [](const BarrierPoint& a, const BarrierPoint& b) + { + return a.ListIndex < b.ListIndex && a.IsImage < b.IsImage; + }); } void EnhancedBarrierRecorder::OnUse(const FCmdResRef ResRef, const ResAccess Access, const ResUsage Usage, const ResLayout Layout) @@ -94,11 +102,8 @@ namespace Coplt::Enhanced return; } m_inputs.push_back(InputResState{.ResIndex = ResIndex, .BeforeUseListIndex = info.CurrentBeforeUseListIndex, .State = info.State}); - info.State = new_state; info.InfoState = InfoState::Used; - info.CurrentBeforeUseListIndex = m_storage->CurrentListIndex(); - m_storage->Split(); - // todo 记录屏障 + Split(info, new_state, false); return; } else @@ -108,10 +113,131 @@ namespace Coplt::Enhanced info.State = info.State.Merge(new_state); return; } - // todo + Split(info, new_state); + } + } + + void EnhancedBarrierRecorder::OnCmd() + { + // if (m_split_texture_barriers.size() == 0 && m_split_buffer_barriers.size() == 0) return; + // D3D12_BARRIER_GROUP groups[2]; + // u32 group_count = 0; + // if (m_split_texture_barriers.size() > 0) + // { + // groups[group_count++] = D3D12_BARRIER_GROUP{ + // .Type = D3D12_BARRIER_TYPE_TEXTURE, + // .NumBarriers = m_split_texture_barriers.size(), + // .pTextureBarriers = m_split_texture_barriers.data(), + // }; + // } + // if (m_split_buffer_barriers.size() > 0) + // { + // groups[group_count++] = D3D12_BARRIER_GROUP{ + // .Type = D3D12_BARRIER_TYPE_BUFFER, + // .NumBarriers = m_split_buffer_barriers.size(), + // .pBufferBarriers = m_split_buffer_barriers.data(), + // }; + // } + // m_storage->Lists()[m_storage->CurrentListIndex() - 1]->Barrier(group_count, groups); + // m_split_buffer_barriers.clear(); + // m_split_texture_barriers.clear(); + } + + void EnhancedBarrierRecorder::Split(ResInfo& info, const ResState new_state, bool barrier) + { + info.CurrentBeforeUseListIndex = m_storage->CurrentListIndex(); + m_storage->Split(); + if (barrier) CreateBarrier(info); + info.OldState = info.State; + info.State = new_state; + } + + void EnhancedBarrierRecorder::CreateBarrier(const ResInfo& info) + { + const auto& res = *info.Res; + BarrierPoint point{}; + point.IsImage = res.IsImage(); + const auto LastListIndex = + info.LastBarrierPoint == COPLT_U32_MAX + ? info.CurrentBeforeUseListIndex + : m_barrier_points[info.LastBarrierPoint].ListIndex; + const auto SyncBefore = GetBarrierSync(info.OldState.Access, info.OldState.Usage); + const auto SyncAfter = GetBarrierSync(info.State.Access, info.State.Usage); + const auto AccessBefore = GetBarrierAccess(info.OldState.Access); + const auto AccessAfter = GetBarrierAccess(info.State.Access); + const auto push = [&](auto& barriers, auto& barrier) + { + if (LastListIndex + 1 >= info.CurrentBeforeUseListIndex) + { + point.ListIndex = info.CurrentBeforeUseListIndex; + point.BarrierIndex = barriers.size(); + m_barrier_points.push_back(point); + + barrier.SyncAfter = SyncAfter; + barriers.push_back(barrier); + } + else + { + point.ListIndex = LastListIndex + 1; + point.BarrierIndex = barriers.size(); + m_barrier_points.push_back(point); + + barriers.push_back(barrier); + + point.ListIndex = info.CurrentBeforeUseListIndex; + point.BarrierIndex = barriers.size(); + m_barrier_points.push_back(point); + + barrier.SyncBefore = D3D12_BARRIER_SYNC_SPLIT; + barrier.SyncAfter = SyncAfter; + barriers.push_back(barrier); + } + }; + if (point.IsImage) + { + const auto img_data = GetImageData(res); + D3D12_TEXTURE_BARRIER barrier{ + .SyncBefore = SyncBefore, + .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, + .AccessBefore = AccessBefore, + .AccessAfter = AccessAfter, + .LayoutBefore = GetBarrierLayout(info.OldState.Layout), + .LayoutAfter = GetBarrierLayout(info.State.Layout), + .pResource = GetResource(res), + .Subresources = { + .IndexOrFirstMipLevel = 0, + .NumMipLevels = img_data->m_mip_levels, + .FirstArraySlice = 0, + .NumArraySlices = img_data->m_depth_or_length, + .FirstPlane = 0, + .NumPlanes = img_data->m_planes, + }, + .Flags = D3D12_TEXTURE_BARRIER_FLAG_NONE, + }; + push(m_texture_barriers, barrier); + return; + } + else + { + const auto buffer_data = GetBufferData(res); + D3D12_BUFFER_BARRIER barrier{ + .SyncBefore = SyncBefore, + .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, + .AccessBefore = AccessBefore, + .AccessAfter = AccessAfter, + .pResource = GetResource(res), + .Offset = 0, + .Size = buffer_data->m_size, + }; + push(m_buffer_barriers, barrier); + return; } } + void EnhancedBarrierRecorder::SubmitBarrier() + { + } + EnhancedBarrierCombiner::EnhancedBarrierCombiner(const Rc& device) { m_device = device; @@ -154,8 +280,8 @@ namespace Coplt::Enhanced // .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, // todo 拆分屏障 .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, .AccessAfter = GetBarrierAccess(input.State.Access), - .LayoutBefore = GetBarrierLayout(sr.State->Layout, sr.State->Queue), - .LayoutAfter = GetBarrierLayout(input.State.Layout, ToResQueue(data->Mode)), + .LayoutBefore = GetBarrierLayout(sr.State->Layout), + .LayoutAfter = GetBarrierLayout(input.State.Layout), .pResource = GetResource(res), .Subresources = { .IndexOrFirstMipLevel = 0, diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index dc95023..14cccf9 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -33,6 +33,8 @@ namespace Coplt virtual void EndRecord() = 0; virtual void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) = 0; + // 实际录制命令前需要调用,让暂存的屏障写入命令列表 + virtual void OnCmd() = 0; }; COPLT_INTERFACE_DEFINE(ID3d12BarrierCombiner, "e1e15444-6369-4d8a-90b3-153672abca39", FUnknown) @@ -94,38 +96,34 @@ namespace Coplt Used, }; + struct BarrierPoint + { + u32 ListIndex{}; + u32 BarrierIndex{}; + bool IsImage{}; + }; + struct ResInfo { + NonNull Res; ResState State{}; - // 在使用前的,可以插入屏障的 list 的 index + ResState OldState{}; u32 CurrentBeforeUseListIndex{}; - u32 CurrentBeginBarrierGroupIndex{}; - u32 CurrentEndBarrierGroupIndex{}; - const FCmdResType ResType{}; + u32 LastBarrierPoint{COPLT_U32_MAX}; InfoState InfoState{}; - explicit ResInfo(FCmdResType ResType); - }; - - struct BarrierGroupRange - { - u32 BufferIndex{}; - u32 BufferCount{}; - u32 TextureIndex{}; - u32 TextureCount{}; + explicit ResInfo(NonNull Res); }; Rc m_device{}; Rc m_storage{}; std::vector m_resources{}; std::vector m_inputs{}; - std::vector m_groups{}; - std::vector m_begin_buffer_barriers{}; - std::vector m_begin_texture_barriers{}; - std::vector m_end_buffer_barriers{}; - std::vector m_end_texture_barriers{}; - u32 m_current_begin_barrier_group_index{}; - u32 m_current_end_barrier_group_index{}; + std::vector m_buffer_barriers{}; + std::vector m_texture_barriers{}; + // std::vector m_split_buffer_barriers{}; + // std::vector m_split_texture_barriers{}; + std::vector m_barrier_points{}; explicit EnhancedBarrierRecorder(const Rc& device, const Rc& storage); @@ -135,6 +133,11 @@ namespace Coplt void StartRecord(std::span resources) override; void EndRecord() override; void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) override; + void OnCmd() override; + + void Split(ResInfo& info, ResState new_state, bool barrier = true); + void CreateBarrier(const ResInfo& info); + void SubmitBarrier(); }; struct EnhancedBarrierCombiner final : Object diff --git a/Coplt.Graphics.Native/D3d12/Src/Output.cc b/Coplt.Graphics.Native/D3d12/Src/Output.cc index 7152b43..bccf9ff 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Output.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Output.cc @@ -166,18 +166,16 @@ FGraphicsFormat D3d12GpuSwapChainOutput::SelectFormat( const FGpuOutputCreateOptions& options, bool& is_hdr ) { - if (options.FormatSelector.Specify) return options.Format; - if (options.FormatSelector.Hdr == FHdrType::UNorm10 && options.AlphaMode == FOutputAlphaMode::Opaque) + if (options.Hdr == FHdrType::UNorm10 && options.AlphaMode == FOutputAlphaMode::Opaque) { is_hdr = true; return FGraphicsFormat::R10G10B10A2_UNorm; } - if (options.FormatSelector.Hdr == FHdrType::Float16) + if (options.Hdr == FHdrType::Float16) { is_hdr = true; return FGraphicsFormat::R16G16B16A16_Float; } - if (options.FormatSelector.Srgb) return FGraphicsFormat::R8G8B8A8_UNorm_sRGB; return FGraphicsFormat::R8G8B8A8_UNorm; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 3248843..23f091c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -156,11 +156,13 @@ void D3d12GpuRecord::Interpret_PreparePresent(u32 i, const FCmdPreparePresent& c if (Mode != FGpuRecordMode::Direct) COPLT_THROW("Can only present on the direct mode"); m_barrier_recorder->OnUse(cmd.Output, ResAccess::None, ResUsage::Common, ResLayout::Common); + m_barrier_recorder->OnCmd(); } void D3d12GpuRecord::Interpret_ClearColor(u32 i, const FCmdClearColor& cmd) { m_barrier_recorder->OnUse(cmd.Image, ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); + m_barrier_recorder->OnCmd(); const auto rtv = GetRtv(GetRes(cmd.Image)); CurList()->g0->ClearRenderTargetView( rtv, cmd.Color, cmd.RectCount, @@ -171,6 +173,7 @@ void D3d12GpuRecord::Interpret_ClearColor(u32 i, const FCmdClearColor& cmd) void D3d12GpuRecord::Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd) { m_barrier_recorder->OnUse(cmd.Image, ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); + m_barrier_recorder->OnCmd(); const auto dsv = GetDsv(GetRes(cmd.Image)); D3D12_CLEAR_FLAGS flags{}; if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Depth)) flags |= D3D12_CLEAR_FLAG_DEPTH; @@ -181,20 +184,6 @@ void D3d12GpuRecord::Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthSten ); } -ResQueue Coplt::ToResQueue(const FGpuRecordMode mode) -{ - switch (mode) - { - case FGpuRecordMode::Direct: - return ResQueue::Direct; - case FGpuRecordMode::Compute: - return ResQueue::Compute; - default: - break; - } - return ResQueue::Common; -} - NonNull Coplt::GetResource(const FCmdRes& res) { switch (res.Type) diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index cff6d71..655cb7b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -64,7 +64,6 @@ namespace Coplt void Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); }; - ResQueue ToResQueue(FGpuRecordMode mode); NonNull GetResource(const FCmdRes& res); NonNull GetBufferData(const FCmdRes& res); NonNull GetImageData(const FCmdRes& res); diff --git a/Coplt.Graphics.Native/D3d12/Src/ResState.cc b/Coplt.Graphics.Native/D3d12/Src/ResState.cc index fb0741c..03e7634 100644 --- a/Coplt.Graphics.Native/D3d12/Src/ResState.cc +++ b/Coplt.Graphics.Native/D3d12/Src/ResState.cc @@ -22,6 +22,11 @@ ResState ResState::Split() const return ResState(Access, ResUsage::Common, Layout); } +bool ResState::Same(const ResState& other) const +{ + return Access == other.Access && Layout == other.Layout; +} + bool Coplt::IsValid(const ResAccess access) { switch (access) @@ -276,7 +281,7 @@ D3D12_BARRIER_ACCESS Coplt::GetBarrierAccess(const ResAccess access) return ba; } -D3D12_BARRIER_LAYOUT Coplt::GetBarrierLayout(ResLayout layout, ResQueue queue) +D3D12_BARRIER_LAYOUT Coplt::GetBarrierLayout(ResLayout layout) { switch (layout) { @@ -307,73 +312,17 @@ D3D12_BARRIER_LAYOUT Coplt::GetBarrierLayout(ResLayout layout, ResQueue queue) case ResLayout::VideoProcessWrite: return D3D12_BARRIER_LAYOUT_VIDEO_PROCESS_WRITE; case ResLayout::GenericRead: - switch (queue) - { - case ResQueue::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ; - case ResQueue::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_GENERIC_READ; - default: - break; - } return D3D12_BARRIER_LAYOUT_GENERIC_READ; case ResLayout::UnorderedAccess: - switch (queue) - { - case ResQueue::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS; - case ResQueue::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_UNORDERED_ACCESS; - default: - break; - } return D3D12_BARRIER_LAYOUT_UNORDERED_ACCESS; case ResLayout::ShaderResource: - switch (queue) - { - case ResQueue::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE; - case ResQueue::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_SHADER_RESOURCE; - default: - break; - } return D3D12_BARRIER_LAYOUT_SHADER_RESOURCE; case ResLayout::CopySource: - switch (queue) - { - case ResQueue::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE; - case ResQueue::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_SOURCE; - default: - break; - } return D3D12_BARRIER_LAYOUT_COPY_SOURCE; case ResLayout::CopyDest: - switch (queue) - { - case ResQueue::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_DEST; - case ResQueue::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_DEST; - default: - break; - } return D3D12_BARRIER_LAYOUT_COPY_DEST; case ResLayout::Common: default: - switch (queue) - { - case ResQueue::Direct: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON; - case ResQueue::Compute: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COMMON; - case ResQueue::Video: - return D3D12_BARRIER_LAYOUT_VIDEO_QUEUE_COMMON; - default: - break; - } return D3D12_BARRIER_LAYOUT_COMMON; } } diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc index fc23445..2021744 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -18,9 +18,10 @@ D3d12GpuSwapChain::D3d12GpuSwapChain( this->VSync = VSync; this->PresentMode = options.PresentMode; this->AlphaMode = AlphaMode; + this->Hdr = options.Hdr; + this->Srgb = options.Srgb; m_layout_state.Layout = ResLayout::Common; - m_layout_state.Queue = ResQueue::Common; if (m_debug_enabled && !options.Name.is_null()) { @@ -83,28 +84,18 @@ D3d12GpuSwapChain::D3d12GpuSwapChain(const NonNull isolate, con desc.Format = ToDx(this->Format); desc.SampleDesc.Count = 1; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; switch (options.PresentMode) { case FPresentMode::NoBuffer: - if (is_hdr) - { - m_frame_count = desc.BufferCount = 2; - desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - } - else - { - m_frame_count = desc.BufferCount = 2; - desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - } + m_frame_count = desc.BufferCount = 1; break; case FPresentMode::DoubleBuffer: m_frame_count = desc.BufferCount = 2; - desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; break; case FPresentMode::TripleBuffer: default: m_frame_count = desc.BufferCount = 3; - desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; break; } switch (options.AlphaMode) @@ -143,18 +134,16 @@ D3d12GpuSwapChain::D3d12GpuSwapChain(const NonNull isolate, con FGraphicsFormat D3d12GpuSwapChain::SelectFormat(const FGpuSwapChainCreateOptions& options, bool& is_hdr) { - if (options.FormatSelector.Specify) return options.Format; - if (options.FormatSelector.Hdr == FHdrType::UNorm10 && options.AlphaMode == FOutputAlphaMode::Opaque) + if (options.Hdr == FHdrType::UNorm10 && options.AlphaMode == FOutputAlphaMode::Opaque) { is_hdr = true; return FGraphicsFormat::R10G10B10A2_UNorm; } - if (options.FormatSelector.Hdr == FHdrType::Float16) + if (options.Hdr == FHdrType::Float16) { is_hdr = true; return FGraphicsFormat::R16G16B16A16_Float; } - if (options.FormatSelector.Srgb) return FGraphicsFormat::R8G8B8A8_UNorm_sRGB; return FGraphicsFormat::R8G8B8A8_UNorm; } @@ -170,7 +159,12 @@ void D3d12GpuSwapChain::CreateRts() for (u32 i = 0; i < m_frame_count; ++i) { chr | m_swap_chain->GetBuffer(i, IID_PPV_ARGS(&m_buffers[i])); - m_device->CreateRenderTargetView(m_buffers[i].Get(), nullptr, rtv_handle); + D3D12_RENDER_TARGET_VIEW_DESC desc{}; + desc.Format = ToDx(this->Srgb ? ToSrgb(this->Format) : this->Format); + desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipSlice = 0; + desc.Texture2D.PlaneSlice = 0; + m_device->CreateRenderTargetView(m_buffers[i].Get(), &desc, rtv_handle); rtv_handle.Offset(1, m_rtv_descriptor_size); } } diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index b6f0c78..69d47c8 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -50,6 +50,7 @@ public void DoInitGraphics() Width = Width, Height = Height, // VSync = true, + // Srgb = true, } ); Record = Isolate.RentRecord(); From 7cb9b5cccf4933f7ef8e52b31e0b7023ca040af3 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 27 Mar 2025 15:12:57 +0800 Subject: [PATCH 15/46] barrier --- Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 229 +++++++++++------- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 45 ++-- Coplt.Graphics.Native/D3d12/Src/Record.cc | 1 - .../D3d12/Src/RecordStorage.cc | 20 +- .../D3d12/Src/RecordStorage.h | 10 +- Coplt.Graphics.Native/D3d12/Src/SwapChain.cc | 10 + 6 files changed, 192 insertions(+), 123 deletions(-) diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index ddf5b78..5f4e6d2 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -21,29 +21,47 @@ namespace Coplt::Enhanced return new EnhancedBarrierCombiner(m_device); } + void EnhancedBarrierRecorder::BarrierGroup::Push(D3D12_BUFFER_BARRIER barrier) + { + m_buffer_barriers.push_back(barrier); + } + + void EnhancedBarrierRecorder::BarrierGroup::Push(D3D12_TEXTURE_BARRIER barrier) + { + m_texture_barriers.push_back(barrier); + } + EnhancedBarrierRecorder::ResInfo::ResInfo(const NonNull Res) : Res(Res) { } + void EnhancedBarrierRecorder::ResInfo::SetNewState(const ResState state) + { + OldState = State; + State = state; + } + EnhancedBarrierRecorder::EnhancedBarrierRecorder(const Rc& device, const Rc& storage) : m_device(device), m_storage(storage) { } - std::span EnhancedBarrierRecorder::Inputs() const + std::span EnhancedBarrierRecorder::Inputs() const { return m_inputs; } + std::span EnhancedBarrierRecorder::Outputs() const + { + return m_outputs; + } + void EnhancedBarrierRecorder::Clear() { m_resources.clear(); m_inputs.clear(); - m_buffer_barriers.clear(); - m_texture_barriers.clear(); - // m_split_buffer_barriers.clear(); - // m_split_texture_barriers.clear(); - m_barrier_points.clear(); + m_outputs.clear(); + m_buffer_groups.clear(); } void EnhancedBarrierRecorder::StartRecord(const std::span resources) @@ -55,6 +73,8 @@ namespace Coplt::Enhanced const auto& res = resources[i]; m_resources.push_back(ResInfo(&res)); } + m_buffer_groups.push_back({.ListIndex = 0}); + m_buffer_groups.push_back({.ListIndex = 1}); } void EnhancedBarrierRecorder::EndRecord() @@ -65,21 +85,18 @@ namespace Coplt::Enhanced if (info.InfoState == InfoState::Unused) continue; if (info.InfoState == InfoState::Input) { - m_inputs.push_back(InputResState{.ResIndex = i, .BeforeUseListIndex = info.CurrentBeforeUseListIndex, .State = info.State}); + m_inputs.push_back(IOResState{.ResIndex = i, .CurrentListIndex = info.CurrentListIndex, .State = info.State}); } else { - info.CurrentBeforeUseListIndex = m_storage->CurrentListIndex(); CreateBarrier(info); } - // todo output - // GetState(*info.Res)->Layout = info.State.Layout; + m_outputs.push_back(IOResState{.ResIndex = i, .CurrentListIndex = info.CurrentListIndex, .State = info.State}); } - // OnCmd(); - std::ranges::sort(m_barrier_points, [](const BarrierPoint& a, const BarrierPoint& b) + if (m_last_cmd_count == 0) { - return a.ListIndex < b.ListIndex && a.IsImage < b.IsImage; - }); + m_storage->DropLast(); + } } void EnhancedBarrierRecorder::OnUse(const FCmdResRef ResRef, const ResAccess Access, const ResUsage Usage, const ResLayout Layout) @@ -91,7 +108,8 @@ namespace Coplt::Enhanced { info.InfoState = InfoState::Input; info.State = new_state; - info.CurrentBeforeUseListIndex = m_storage->CurrentListIndex() - 1; + info.LastUseListIndex = 0; + info.CurrentListIndex = m_storage->CurListIndex(); return; } else if (info.InfoState == InfoState::Input) @@ -99,101 +117,68 @@ namespace Coplt::Enhanced if (info.State.IsCompatible(new_state, true)) { info.State = info.State.Merge(new_state); - return; + goto End; } - m_inputs.push_back(InputResState{.ResIndex = ResIndex, .BeforeUseListIndex = info.CurrentBeforeUseListIndex, .State = info.State}); info.InfoState = InfoState::Used; - Split(info, new_state, false); - return; + m_inputs.push_back(IOResState{.ResIndex = ResIndex, .CurrentListIndex = info.CurrentListIndex, .State = info.State}); + if (info.CurrentListIndex == m_storage->CurListIndex()) Split(); + goto EndState; } else { if (info.State.IsCompatible(new_state, true)) { info.State = info.State.Merge(new_state); - return; + goto End; } - Split(info, new_state); } + if (info.CurrentListIndex == m_storage->CurListIndex()) Split(); + CreateBarrier(info); + EndState: + info.SetNewState(new_state); + info.LastUseListIndex = info.CurrentListIndex; + End: + info.CurrentListIndex = m_storage->CurListIndex(); } void EnhancedBarrierRecorder::OnCmd() { - // if (m_split_texture_barriers.size() == 0 && m_split_buffer_barriers.size() == 0) return; - // D3D12_BARRIER_GROUP groups[2]; - // u32 group_count = 0; - // if (m_split_texture_barriers.size() > 0) - // { - // groups[group_count++] = D3D12_BARRIER_GROUP{ - // .Type = D3D12_BARRIER_TYPE_TEXTURE, - // .NumBarriers = m_split_texture_barriers.size(), - // .pTextureBarriers = m_split_texture_barriers.data(), - // }; - // } - // if (m_split_buffer_barriers.size() > 0) - // { - // groups[group_count++] = D3D12_BARRIER_GROUP{ - // .Type = D3D12_BARRIER_TYPE_BUFFER, - // .NumBarriers = m_split_buffer_barriers.size(), - // .pBufferBarriers = m_split_buffer_barriers.data(), - // }; - // } - // m_storage->Lists()[m_storage->CurrentListIndex() - 1]->Barrier(group_count, groups); - // m_split_buffer_barriers.clear(); - // m_split_texture_barriers.clear(); + m_last_cmd_count++; } - void EnhancedBarrierRecorder::Split(ResInfo& info, const ResState new_state, bool barrier) + void EnhancedBarrierRecorder::Split() { - info.CurrentBeforeUseListIndex = m_storage->CurrentListIndex(); m_storage->Split(); - if (barrier) CreateBarrier(info); - info.OldState = info.State; - info.State = new_state; + m_buffer_groups.push_back({.ListIndex = m_buffer_groups.size() - 1}); + m_last_cmd_count = 0; } - void EnhancedBarrierRecorder::CreateBarrier(const ResInfo& info) + void EnhancedBarrierRecorder::CreateBarrier(ResInfo& info) { const auto& res = *info.Res; - BarrierPoint point{}; - point.IsImage = res.IsImage(); - const auto LastListIndex = - info.LastBarrierPoint == COPLT_U32_MAX - ? info.CurrentBeforeUseListIndex - : m_barrier_points[info.LastBarrierPoint].ListIndex; + const auto BeforeListIndex = info.LastUseListIndex; + const auto AfterListIndex = info.CurrentListIndex - 1; const auto SyncBefore = GetBarrierSync(info.OldState.Access, info.OldState.Usage); const auto SyncAfter = GetBarrierSync(info.State.Access, info.State.Usage); const auto AccessBefore = GetBarrierAccess(info.OldState.Access); const auto AccessAfter = GetBarrierAccess(info.State.Access); - const auto push = [&](auto& barriers, auto& barrier) + const auto push = [&](auto& barrier) { - if (LastListIndex + 1 >= info.CurrentBeforeUseListIndex) + if (BeforeListIndex >= AfterListIndex) { - point.ListIndex = info.CurrentBeforeUseListIndex; - point.BarrierIndex = barriers.size(); - m_barrier_points.push_back(point); - barrier.SyncAfter = SyncAfter; - barriers.push_back(barrier); + m_buffer_groups[BeforeListIndex].Push(barrier); } else { - point.ListIndex = LastListIndex + 1; - point.BarrierIndex = barriers.size(); - m_barrier_points.push_back(point); - - barriers.push_back(barrier); - - point.ListIndex = info.CurrentBeforeUseListIndex; - point.BarrierIndex = barriers.size(); - m_barrier_points.push_back(point); + m_buffer_groups[BeforeListIndex].Push(barrier); barrier.SyncBefore = D3D12_BARRIER_SYNC_SPLIT; barrier.SyncAfter = SyncAfter; - barriers.push_back(barrier); + m_buffer_groups[AfterListIndex].Push(barrier); } }; - if (point.IsImage) + if (res.IsImage()) { const auto img_data = GetImageData(res); D3D12_TEXTURE_BARRIER barrier{ @@ -214,8 +199,7 @@ namespace Coplt::Enhanced }, .Flags = D3D12_TEXTURE_BARRIER_FLAG_NONE, }; - push(m_texture_barriers, barrier); - return; + push(barrier); } else { @@ -229,13 +213,39 @@ namespace Coplt::Enhanced .Offset = 0, .Size = buffer_data->m_size, }; - push(m_buffer_barriers, barrier); - return; + push(barrier); } } - void EnhancedBarrierRecorder::SubmitBarrier() + void EnhancedBarrierRecorder::SubmitBarriers() { + for (auto& group : m_buffer_groups) + { + D3D12_BARRIER_GROUP groups[2]; + u32 group_count = 0; + if (group.m_texture_barriers.size() > 0) + { + groups[group_count++] = D3D12_BARRIER_GROUP{ + .Type = D3D12_BARRIER_TYPE_TEXTURE, + .NumBarriers = static_cast(group.m_texture_barriers.size()), + .pTextureBarriers = group.m_texture_barriers.data(), + }; + } + if (group.m_buffer_barriers.size() > 0) + { + groups[group_count++] = D3D12_BARRIER_GROUP{ + .Type = D3D12_BARRIER_TYPE_BUFFER, + .NumBarriers = static_cast(group.m_buffer_barriers.size()), + .pBufferBarriers = group.m_buffer_barriers.data(), + }; + } + if (group_count > 0) + { + m_storage->Lists()[group.ListIndex]->Barrier(group_count, groups); + group.m_texture_barriers.clear(); + group.m_buffer_barriers.clear(); + } + } } EnhancedBarrierCombiner::EnhancedBarrierCombiner(const Rc& device) @@ -257,7 +267,9 @@ namespace Coplt::Enhanced const NonNull data = record->Data(); const auto& barrier_recorder = record->BarrierRecorder(); const auto& storage = record->Storage(); - u32 buffer_barrier_index = m_buffer_barriers.size(), texture_barrier_index = m_texture_barriers.size(); + + #pragma region 生成输入屏障 + for (const auto& input : barrier_recorder->Inputs()) { const auto& res = data->Resources[input.ResIndex]; @@ -297,42 +309,62 @@ namespace Coplt::Enhanced } else { + const auto buffer_data = GetBufferData(res); + D3D12_BUFFER_BARRIER barrier{ + .SyncBefore = D3D12_BARRIER_SYNC_NONE, + .SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage), + // .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, // todo 拆分屏障 + .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, + .AccessAfter = GetBarrierAccess(input.State.Access), + .pResource = GetResource(res), + .Offset = 0, + .Size = buffer_data->m_size, + }; + m_buffer_barriers.push_back(barrier); //todo } } // todo } + #pragma endregion + #pragma region 插入输入屏障 - const u32 buffer_barrier_count = m_buffer_barriers.size() - buffer_barrier_index; - const u32 texture_barrier_count = m_texture_barriers.size() - texture_barrier_index; - if (buffer_barrier_count > 0 || texture_barrier_count > 0) + if (m_buffer_barriers.size() > 0 || m_texture_barriers.size() > 0) { D3D12_BARRIER_GROUP groups[2]; u32 group_count = 0; - if (buffer_barrier_count > 0) + if (m_texture_barriers.size() > 0) { groups[group_count++] = D3D12_BARRIER_GROUP{ - .Type = D3D12_BARRIER_TYPE_BUFFER, - .NumBarriers = buffer_barrier_count, - .pBufferBarriers = m_buffer_barriers.data() + buffer_barrier_index, + .Type = D3D12_BARRIER_TYPE_TEXTURE, + .NumBarriers = m_texture_barriers.size(), + .pTextureBarriers = m_texture_barriers.data(), }; } - if (texture_barrier_count > 0) + if (m_buffer_barriers.size() > 0) { groups[group_count++] = D3D12_BARRIER_GROUP{ - .Type = D3D12_BARRIER_TYPE_TEXTURE, - .NumBarriers = texture_barrier_count, - .pTextureBarriers = m_texture_barriers.data() + texture_barrier_index, + .Type = D3D12_BARRIER_TYPE_BUFFER, + .NumBarriers = m_buffer_barriers.size(), + .pBufferBarriers = m_buffer_barriers.data(), }; } // 第一个列表是保留的用于屏障的 storage->Lists()[0]->Barrier(group_count, groups); + m_buffer_barriers.clear(); + m_texture_barriers.clear(); } #pragma endregion + #pragma region 提交中间屏障 + + barrier_recorder->SubmitBarriers(); + + #pragma endregion + #pragma region 完成录制 记录 list 范围 { @@ -350,6 +382,23 @@ namespace Coplt::Enhanced } #pragma endregion + + #pragma region 记录输出状态 + + for (const auto& output : barrier_recorder->Outputs()) + { + const auto& res = data->Resources[output.ResIndex]; + const auto state = GetState(res); + state->Layout = output.State.Layout; + m_submit_resources.AddOrReplace( + res.GetObjectPtr()->ObjectId(), ResInfo{ + .Res = res, + .State = state, + } + ); + } + + #pragma endregion } } } diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index 14cccf9..05683ac 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -8,10 +8,10 @@ namespace Coplt { - struct InputResState + struct IOResState { u32 ResIndex{}; - u32 BeforeUseListIndex{}; + u32 CurrentListIndex{}; ResState State{}; }; @@ -26,15 +26,17 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12BarrierRecorder, "115741ea-2138-4c92-9f4f-94f91d254587", FUnknown) { - virtual std::span Inputs() const = 0; + virtual std::span Inputs() const = 0; + virtual std::span Outputs() const = 0; virtual void Clear() = 0; virtual void StartRecord(std::span resources) = 0; virtual void EndRecord() = 0; virtual void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) = 0; - // 实际录制命令前需要调用,让暂存的屏障写入命令列表 virtual void OnCmd() = 0; + + virtual void SubmitBarriers() = 0; }; COPLT_INTERFACE_DEFINE(ID3d12BarrierCombiner, "e1e15444-6369-4d8a-90b3-153672abca39", FUnknown) @@ -96,11 +98,15 @@ namespace Coplt Used, }; - struct BarrierPoint + // todo 优化内存分配 + struct BarrierGroup { u32 ListIndex{}; - u32 BarrierIndex{}; - bool IsImage{}; + std::vector m_buffer_barriers{}; + std::vector m_texture_barriers{}; + + void Push(D3D12_BUFFER_BARRIER barrier); + void Push(D3D12_TEXTURE_BARRIER barrier); }; struct ResInfo @@ -108,26 +114,27 @@ namespace Coplt NonNull Res; ResState State{}; ResState OldState{}; - u32 CurrentBeforeUseListIndex{}; - u32 LastBarrierPoint{COPLT_U32_MAX}; + u32 LastUseListIndex{COPLT_U32_MAX}; + u32 CurrentListIndex{COPLT_U32_MAX}; InfoState InfoState{}; explicit ResInfo(NonNull Res); + + void SetNewState(ResState state); }; Rc m_device{}; Rc m_storage{}; std::vector m_resources{}; - std::vector m_inputs{}; - std::vector m_buffer_barriers{}; - std::vector m_texture_barriers{}; - // std::vector m_split_buffer_barriers{}; - // std::vector m_split_texture_barriers{}; - std::vector m_barrier_points{}; + std::vector m_inputs{}; + std::vector m_outputs{}; + std::vector m_buffer_groups{}; + u32 m_last_cmd_count{}; explicit EnhancedBarrierRecorder(const Rc& device, const Rc& storage); - std::span Inputs() const override; + std::span Inputs() const override; + std::span Outputs() const override; void Clear() override; void StartRecord(std::span resources) override; @@ -135,9 +142,9 @@ namespace Coplt void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) override; void OnCmd() override; - void Split(ResInfo& info, ResState new_state, bool barrier = true); - void CreateBarrier(const ResInfo& info); - void SubmitBarrier(); + void Split(); + void CreateBarrier(ResInfo& info); + void SubmitBarriers() override; }; struct EnhancedBarrierCombiner final : Object diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 23f091c..fb9de30 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -156,7 +156,6 @@ void D3d12GpuRecord::Interpret_PreparePresent(u32 i, const FCmdPreparePresent& c if (Mode != FGpuRecordMode::Direct) COPLT_THROW("Can only present on the direct mode"); m_barrier_recorder->OnUse(cmd.Output, ResAccess::None, ResUsage::Common, ResLayout::Common); - m_barrier_recorder->OnCmd(); } void D3d12GpuRecord::Interpret_ClearColor(u32 i, const FCmdClearColor& cmd) diff --git a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc index dca9344..7c1758a 100644 --- a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc +++ b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc @@ -9,22 +9,18 @@ D3d12RecordStorage::D3d12RecordStorage(NonNull isolate, const R void D3d12RecordStorage::Clear() { - m_cur_list = {}; m_result_lists.clear(); } void D3d12RecordStorage::StartRecord(const FGpuRecordMode Mode) { m_list_type = ToListType(Mode); - auto cmd_allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(m_list_type); - m_cur_list = cmd_allocator.RentCommandList(); - m_context->m_recycled_command_allocators.push_back(std::move(cmd_allocator)); + Split(); Split(); } void D3d12RecordStorage::EndRecord() { - m_result_lists.push_back(std::move(m_cur_list)); } void D3d12RecordStorage::BeforeSubmit() @@ -43,14 +39,19 @@ u32 D3d12RecordStorage::Split() { const auto i = m_result_lists.size(); auto cmd_allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(m_list_type); - m_result_lists.push_back(std::exchange(m_cur_list, cmd_allocator.RentCommandList())); + m_result_lists.push_back(cmd_allocator.RentCommandList()); m_context->m_recycled_command_allocators.push_back(std::move(cmd_allocator)); return i; } D3d12RentedCommandList& D3d12RecordStorage::CurList() { - return m_cur_list; + return m_result_lists.back(); +} + +u32 D3d12RecordStorage::CurListIndex() +{ + return m_result_lists.size() - 1; } std::span D3d12RecordStorage::Lists() @@ -58,9 +59,10 @@ std::span D3d12RecordStorage::Lists() return m_result_lists; } -u32 D3d12RecordStorage::CurrentListIndex() +void D3d12RecordStorage::DropLast() { - return m_result_lists.size(); + CurList().Close(); + m_result_lists.pop_back(); } D3D12_COMMAND_LIST_TYPE Coplt::ToListType(const FGpuRecordMode value) diff --git a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h index ecba23d..c63c5b8 100644 --- a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h +++ b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h @@ -22,14 +22,15 @@ namespace Coplt // 永远在前面保留一个空的 list 用于插入屏障 virtual std::span Lists() = 0; - virtual u32 CurrentListIndex() = 0; + virtual u32 CurListIndex() = 0; + + virtual void DropLast() = 0; }; struct D3d12RecordStorage final : Object { Rc m_device{}; Rc m_context{}; - D3d12RentedCommandList m_cur_list{}; std::vector m_result_lists{}; D3D12_COMMAND_LIST_TYPE m_list_type{}; @@ -44,9 +45,10 @@ namespace Coplt u32 Split() override; D3d12RentedCommandList& CurList() override; - + u32 CurListIndex() override; std::span Lists() override; - u32 CurrentListIndex() override; + + void DropLast() override; }; D3D12_COMMAND_LIST_TYPE ToListType(FGpuRecordMode value); diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc index 2021744..fb1e9c3 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -129,6 +129,16 @@ D3d12GpuSwapChain::D3d12GpuSwapChain(const NonNull isolate, con chr | m_swap_chain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020); } + m_image_data.m_format = this->Format; + m_image_data.m_width = this->Width; + m_image_data.m_height = this->Height; + m_image_data.m_depth_or_length = 1; + m_image_data.m_mip_levels = 1; + m_image_data.m_multisample_count = 1; + m_image_data.m_planes = 1; + m_image_data.m_dimension = FImageDimension::Two; + m_image_data.m_layout = FImageLayout::Undefined; + Initialize(); } From bbd846219c06100aa2c15125cb60d80155a37cb7 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 27 Mar 2025 17:36:57 +0800 Subject: [PATCH 16/46] save --- Coplt.Graphics.Core/Core/GpuIsolate.cs | 2 + Coplt.Graphics.Core/Core/GpuRecord.cs | 173 ++++++++++- Coplt.Graphics.Core/Native/FList.cs | 19 +- Coplt.Graphics.Core/Native/Native.cs | 351 ++++++++++++++++++++-- Coplt.Graphics.Native/Api/FFI/Cmd.h | 113 ++++++- Coplt.Graphics.Native/Api/FFI/Command.h | 24 -- Coplt.Graphics.Native/Api/FFI/Record.h | 4 +- Coplt.Graphics.Native/Api/FFI/Structs.h | 24 ++ Coplt.Graphics.Native/D3d12/Src/Record.cc | 79 ++++- Coplt.Graphics.Native/D3d12/Src/Record.h | 20 ++ Examples/HelloTriangle/Example.cs | 1 + 11 files changed, 731 insertions(+), 79 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index a3ccfb5..083714d 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -146,6 +146,7 @@ public void Submit(params ReadOnlySpan records) for (var i = 0; i < records.Length; i++) { if ((p[i] = records[i].Ptr) == null) throw new NullReferenceException(); + records[i].AssertEndOrCanEnd(); } Ptr->Submit((uint)records.Length, p, o).TryThrow(); for (var i = 0; i < records.Length; i++) @@ -164,6 +165,7 @@ public void Submit(params ReadOnlySpan records) for (var i = 0; i < records.Length; i++) { if ((arr[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); + records[i].AssertEndOrCanEnd(); } fixed (IntPtr* p = arr) fixed (FGpuRecordCreateResult* o = @out) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 0ee2a06..ae17416 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -10,6 +10,7 @@ public sealed unsafe class GpuRecord : IsolateChild internal FGpuRecordData* m_data; internal readonly Dictionary m_resources = new(); + internal int m_debug_scope_count; #endregion @@ -17,6 +18,7 @@ public sealed unsafe class GpuRecord : IsolateChild public new FGpuRecord* Ptr => (FGpuRecord*)m_ptr; internal ref FGpuRecordData Data => ref *m_data; + public bool DebugEnabled { get; } #endregion @@ -25,6 +27,7 @@ public sealed unsafe class GpuRecord : IsolateChild internal GpuRecord(FGpuRecord* ptr, FGpuRecordData* data, string? name, GpuIsolate isolate) : base((FGpuObject*)ptr, name, isolate) { m_data = data; + DebugEnabled = Isolate.Device.Instance.DebugEnabled; } #endregion @@ -60,17 +63,30 @@ public void AssertNotEnded() public void End() { AssertNotEnded(); + AssertEndOrCanEnd(); Ptr->End().TryThrow(); } public void EnsureEnded() { if (Data.Ended) return; + AssertEndOrCanEnd(); Ptr->End().TryThrow(); } + internal void AssertEndOrCanEnd() + { + if (Data.Ended) return; + if (m_debug_scope_count != 0) + throw new InvalidOperationException( + "There is still Debug scope not ended, please check whether Dispose is missed." + ); + } + #endregion + #region Payload + #region AddResource internal FCmdResRef AddResource(IGpuResource resource) @@ -97,24 +113,136 @@ internal uint AddRects(ReadOnlySpan Rects) var len = Data.PayloadRect.LongLength; if (len >= uint.MaxValue) throw new IndexOutOfRangeException("Payload >= uint32 max are not supported"); Data.PayloadRect.EnsureCap(len + (uint)Rects.Length); - foreach (var rect in Rects) + Data.PayloadRect.AddRange(MemoryMarshal.Cast(Rects)); + return (uint)len; + } + + #endregion + + #region AddString + + internal uint AddString(string str) + { + var index = Data.Blob.LongLength; + Data.Blob.EnsureCap((nuint)str.Length * 2 + 2); + Data.Blob.AddRange(MemoryMarshal.AsBytes(str.AsSpan())); + Data.Blob.AddRange([0, 0]); + return (uint)index; + } + + internal uint AddString(ReadOnlySpan str) + { + var index = Data.Blob.LongLength; + Data.Blob.EnsureCap((nuint)str.Length + 1); + Data.Blob.AddRange(str); + Data.Blob.Add(0); + return (uint)index; + } + + #endregion + + #endregion + + #region Debug + + #region Label + + public void Label(string Label, Color? Color = null) + { + if (!DebugEnabled) return; + var cmd = new FCmdLabel { - // todo add range - Data.PayloadRect.Add( - new() - { - Left = rect.Left, - Top = rect.Top, - Right = rect.Right, - Bottom = rect.Bottom, - } - ); + Base = { Type = FCmdType.Label }, + StringIndex = AddString(Label), + StringLength = (uint)Label.Length, + StrType = FStrType.Str16, + }; + if (Color is { } color) + { + var c255 = color.To255; + cmd.HasColor = true; + cmd.Color[0] = (byte)c255.R; + cmd.Color[1] = (byte)c255.G; + cmd.Color[2] = (byte)c255.B; } - return (uint)len; + Data.Commands.Add(new() { Label = cmd }); + } + + public void Label(ReadOnlySpan Label, Color? Color = null) + { + if (!DebugEnabled) return; + var cmd = new FCmdLabel + { + Base = { Type = FCmdType.Label }, + StringIndex = AddString(Label), + StringLength = (uint)Label.Length, + StrType = FStrType.Str8, + }; + if (Color is { } color) + { + var c255 = color.To255; + cmd.HasColor = true; + cmd.Color[0] = (byte)c255.R; + cmd.Color[1] = (byte)c255.G; + cmd.Color[2] = (byte)c255.B; + } + Data.Commands.Add(new() { Label = cmd }); + } + + #endregion + + #region Scope + + public DebugScope2 Scope(string Name, Color? Color = null) + { + if (!DebugEnabled) return new(this); + var cmd = new FCmdBeginScope + { + Base = { Type = FCmdType.BeginScope }, + StringIndex = AddString(Name), + StringLength = (uint)Name.Length, + StrType = FStrType.Str16, + }; + if (Color is { } color) + { + var c255 = color.To255; + cmd.HasColor = true; + cmd.Color[0] = (byte)c255.R; + cmd.Color[1] = (byte)c255.G; + cmd.Color[2] = (byte)c255.B; + } + Data.Commands.Add(new() { BeginScope = cmd }); + m_debug_scope_count++; + return new(this); + } + + public DebugScope2 Scope(ReadOnlySpan Name, Color? Color = null) + { + if (!DebugEnabled) return new(this); + var cmd = new FCmdBeginScope + { + Base = { Type = FCmdType.BeginScope }, + StringIndex = AddString(Name), + StringLength = (uint)Name.Length, + StrType = FStrType.Str8, + }; + if (Color is { } color) + { + var c255 = color.To255; + cmd.HasColor = true; + cmd.Color[0] = (byte)c255.R; + cmd.Color[1] = (byte)c255.G; + cmd.Color[2] = (byte)c255.B; + } + Data.Commands.Add(new() { BeginScope = cmd }); + m_debug_scope_count++; + return new(this); } #endregion + #endregion + #region PreparePresent public void PreparePresent(GpuOutput2 Output) @@ -154,3 +282,24 @@ public void ClearColor(IRtv Image, Color Color, ReadOnlySpan Rects = defa #endregion } + +#region DebugScope + +public struct DebugScope2(GpuRecord self) : IDisposable +{ + private bool m_disposed; + public void Dispose() + { + if (m_disposed) throw new ObjectDisposedException(nameof(ComputeScope)); + m_disposed = true; + if (!self.DebugEnabled) return; + var cmd = new FCmdEndScope + { + Base = { Type = FCmdType.EndScope }, + }; + self.Data.Commands.Add(new() { EndScope = cmd }); + self.m_debug_scope_count--; + } +} + +#endregion diff --git a/Coplt.Graphics.Core/Native/FList.cs b/Coplt.Graphics.Core/Native/FList.cs index ccfaf81..e7b4879 100644 --- a/Coplt.Graphics.Core/Native/FList.cs +++ b/Coplt.Graphics.Core/Native/FList.cs @@ -1,4 +1,5 @@ -using System.Runtime.InteropServices; +using System.Numerics; +using System.Runtime.InteropServices; using Coplt.Dropping; using Coplt.Graphics.Utilities; @@ -112,7 +113,8 @@ private void Grow() public void EnsureCap(nuint cap) { - if ((cap & 1) != 0) cap += 1; + cap = BitOperations.RoundUpToPowerOf2(cap); + if (cap < m_cap) return; if (m_ptr == null) { m_cap = cap; @@ -123,7 +125,6 @@ public void EnsureCap(nuint cap) m_cap = cap; m_ptr = (T*)m_allocator->MemoryReAlloc(m_ptr, m_cap * (nuint)sizeof(T), (nuint)Utils.AlignOf()); } - } #endregion @@ -145,6 +146,18 @@ public void Add(T item) #endregion + #region AddRange + + public void AddRange(ReadOnlySpan span) + { + var new_len = m_len + (nuint)span.Length; + if (new_len >= m_cap) EnsureCap(new_len); + span.CopyTo(new Span(m_ptr + m_len, span.Length)); + m_len = new_len; + } + + #endregion + #region RemoveAt public void RemoveAt(int index) diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index c908e71..b1526e1 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -62,6 +62,33 @@ public enum FDepthStencilClearFlags : byte Stencil = 2, } + [NativeTypeName("Coplt::u8")] + public enum FLoadOp : byte + { + Load, + Clear, + Discard, + NoAccess, + } + + [NativeTypeName("Coplt::u8")] + public enum FStoreOp : byte + { + Store, + Discard, + Resolve, + NoAccess, + } + + [NativeTypeName("Coplt::u8")] + public enum FResolveMode : byte + { + Decompress, + Min, + Max, + Average, + } + public unsafe partial struct FObject : FObject.Interface { public void** lpVtbl; @@ -1544,6 +1571,8 @@ public unsafe partial struct FGpuRecordData public FList PayloadViewport; + public FList RenderInfo; + [NativeTypeName("FList")] public FList Blob; @@ -1564,6 +1593,14 @@ public enum FCmdType : uint PreparePresent, ClearColor, ClearDepthStencil, + Render, + Compute, + SetPipeline, + SetBinding, + SetViewportScissor, + SetMeshBuffers, + Draw, + Dispatch, } [NativeTypeName("Coplt::u8")] @@ -1576,7 +1613,7 @@ public enum FCmdResType : byte public unsafe partial struct FCmdRes { - [NativeTypeName("__AnonymousRecord_Cmd_L49_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L66_C9")] public _Anonymous_e__Union Anonymous; [NativeTypeName("Coplt::FCmdResType")] @@ -1635,6 +1672,117 @@ public partial struct FCmdResRef public uint IndexPlusOne; } + public partial struct FResolveInfo2 + { + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Src; + + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Dst; + + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat Format; + + [NativeTypeName("Coplt::FResolveMode")] + public FResolveMode Mode; + } + + public partial struct FRenderInfo2 + { + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Dsv; + + [NativeTypeName("Coplt::u32")] + public uint NumRtv; + + [NativeTypeName("FCmdResRef[8]")] + public _Rtv_e__FixedBuffer Rtv; + + [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; + + [NativeTypeName("Coplt::f32")] + public float Depth; + + [NativeTypeName("Coplt::u8")] + public byte Stencil; + + [NativeTypeName("FLoadOp[2]")] + public _DsvLoadOp_e__FixedBuffer DsvLoadOp; + + [NativeTypeName("FStoreOp[2]")] + public _DsvStoreOp_e__FixedBuffer DsvStoreOp; + + [NativeTypeName("FLoadOp[8]")] + public _RtvLoadOp_e__FixedBuffer RtvLoadOp; + + [NativeTypeName("FStoreOp[8]")] + public _RtvStoreOp_e__FixedBuffer RtvStoreOp; + + [NativeTypeName("Coplt::b8")] + public B8 HasUavWrites; + + [InlineArray(8)] + public partial struct _Rtv_e__FixedBuffer + { + public FCmdResRef e0; + } + + [InlineArray(8)] + 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 + { + public float e0; + } + + [InlineArray(2)] + public partial struct _DsvLoadOp_e__FixedBuffer + { + public FLoadOp e0; + } + + [InlineArray(2)] + public partial struct _DsvStoreOp_e__FixedBuffer + { + public FStoreOp e0; + } + + [InlineArray(8)] + public partial struct _RtvLoadOp_e__FixedBuffer + { + public FLoadOp e0; + } + + [InlineArray(8)] + public partial struct _RtvStoreOp_e__FixedBuffer + { + public FStoreOp e0; + } + } + public partial struct FCmdBase { [NativeTypeName("Coplt::FCmdType")] @@ -1758,9 +1906,105 @@ public partial struct FCmdClearDepthStencil public FDepthStencilClearFlags Clear; } + [NativeTypeName("struct FCmdRender : Coplt::FCmdBase")] + public partial struct FCmdRender + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint InfoIndex; + + [NativeTypeName("Coplt::u32")] + public uint CommandCount; + } + + [NativeTypeName("struct FCmdCompute : Coplt::FCmdBase")] + public partial struct FCmdCompute + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint CommandCount; + } + + [NativeTypeName("struct FCmdSetPipeline : Coplt::FCmdBase")] + public unsafe partial struct FCmdSetPipeline + { + public FCmdBase Base; + + [NativeTypeName("Coplt::FShaderPipeline *")] + public FShaderPipeline* Pipeline; + } + + [NativeTypeName("struct FCmdSetBinding : Coplt::FCmdBase")] + public unsafe partial struct FCmdSetBinding + { + public FCmdBase Base; + + [NativeTypeName("Coplt::FShaderBinding *")] + public FShaderBinding* Binding; + } + + [NativeTypeName("struct FCmdSetViewportScissor : Coplt::FCmdBase")] + public partial struct FCmdSetViewportScissor + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint ViewportCount; + + [NativeTypeName("Coplt::u32")] + public uint ViewportIndex; + + [NativeTypeName("Coplt::u32")] + public uint ScissorRectCount; + + [NativeTypeName("Coplt::u32")] + public uint ScissorRectIndex; + } + + [NativeTypeName("struct FCmdSetMeshBuffers : Coplt::FCmdBase")] + public partial struct FCmdSetMeshBuffers + { + public FCmdBase Base; + + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat IndexFormat; + + [NativeTypeName("Coplt::u32")] + public uint VertexStartSlot; + + [NativeTypeName("Coplt::u32")] + public uint PayloadIndex; + } + + [NativeTypeName("struct FCmdDraw : Coplt::FCmdBase")] + public partial struct FCmdDraw + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint VertexOrIndexCount; + + [NativeTypeName("Coplt::u32")] + public uint InstanceCount; + + [NativeTypeName("Coplt::u32")] + public uint FirstVertexOrIndex; + + [NativeTypeName("Coplt::u32")] + public uint FirstInstance; + + [NativeTypeName("Coplt::u32")] + public uint VertexOffset; + + [NativeTypeName("Coplt::b8")] + public B8 Indexed; + } + public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L176_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L280_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -1833,6 +2077,56 @@ public ref FCmdClearDepthStencil ClearDepthStencil } } + [UnscopedRef] + public ref FCmdSetPipeline SetPipeline + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.SetPipeline; + } + } + + [UnscopedRef] + public ref FCmdSetBinding SetBinding + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.SetBinding; + } + } + + [UnscopedRef] + public ref FCmdSetViewportScissor SetViewportScissor + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.SetViewportScissor; + } + } + + [UnscopedRef] + public ref FCmdSetMeshBuffers SetMeshBuffers + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.SetMeshBuffers; + } + } + + [UnscopedRef] + public ref FCmdDraw Draw + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Draw; + } + } + [UnscopedRef] public Span _pad { @@ -1874,6 +2168,26 @@ public partial struct _Anonymous_e__Union [NativeTypeName("Coplt::FCmdClearDepthStencil")] public FCmdClearDepthStencil ClearDepthStencil; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdSetPipeline")] + public FCmdSetPipeline SetPipeline; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdSetBinding")] + public FCmdSetBinding SetBinding; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdSetViewportScissor")] + public FCmdSetViewportScissor SetViewportScissor; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdSetMeshBuffers")] + public FCmdSetMeshBuffers SetMeshBuffers; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdDraw")] + public FCmdDraw Draw; + [FieldOffset(0)] [NativeTypeName("u8[32]")] public __pad_e__FixedBuffer _pad; @@ -4718,15 +5032,6 @@ public partial struct _ImageExtent_e__FixedBuffer } } - [NativeTypeName("Coplt::u8")] - public enum FResolveMode : byte - { - Decompress, - Min, - Max, - Average, - } - public partial struct FResolveInfo { [NativeTypeName("Coplt::FResourceRef")] @@ -4742,24 +5047,6 @@ public partial struct FResolveInfo public FResolveMode Mode; } - [NativeTypeName("Coplt::u8")] - public enum FLoadOp : byte - { - Load, - Clear, - Discard, - NoAccess, - } - - [NativeTypeName("Coplt::u8")] - public enum FStoreOp : byte - { - Store, - Discard, - Resolve, - NoAccess, - } - public partial struct FRenderInfo { [NativeTypeName("Coplt::FResourceRef")] @@ -5239,7 +5526,7 @@ public partial struct FCommandSyncBinding public partial struct FCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L503_C9")] + [NativeTypeName("__AnonymousRecord_Command_L479_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -5465,7 +5752,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FRenderCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L534_C9")] + [NativeTypeName("__AnonymousRecord_Command_L510_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -5649,7 +5936,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FComputeCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L559_C9")] + [NativeTypeName("__AnonymousRecord_Command_L535_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index b7ae187..321fe10 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -1,7 +1,9 @@ #pragma once #include "Structs.h" -#include "Output.h" +#include "Output.h"" +#include "Binding.h" +#include "Pipeline.h" namespace Coplt { @@ -17,6 +19,21 @@ namespace Coplt ClearColor, ClearDepthStencil, + + Render, + Compute, + + // Render / Compute + SetPipeline, + SetBinding, + + // Render + SetViewportScissor, + SetMeshBuffers, + Draw, + + // Render / Compute + Dispatch, }; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -105,6 +122,35 @@ namespace Coplt #endif }; + struct FResolveInfo2 + { + FCmdResRef Src{}; + FCmdResRef Dst{}; + FGraphicsFormat Format{}; + FResolveMode Mode{}; + }; + + struct FRenderInfo2 + { + // 可选 + FCmdResRef Dsv{}; + u32 NumRtv{}; + FCmdResRef Rtv[8]{}; + // 类型为 FResolveInfo + u32 ResolveInfoIndex[8]{}; + u32 DsvResolveInfoIndex{}; + FGraphicsFormat RtvFormat[8]{}; + FGraphicsFormat DsvFormat{}; + f32 Color[4 * 8]{}; + f32 Depth{}; + u8 Stencil{}; + FLoadOp DsvLoadOp[2]{}; + FStoreOp DsvStoreOp[2]{}; + FLoadOp RtvLoadOp[8]{}; + FStoreOp RtvStoreOp[8]{}; + b8 HasUavWrites{}; + }; + //////////////////////////////////////////////////////////////////////////////////////////////////// struct FCmdBase @@ -169,6 +215,64 @@ namespace Coplt FDepthStencilClearFlags Clear{}; }; + //////////////////////////////////////////////////////////////////////////////////////////////////// + /// + struct FCmdRender : FCmdBase + { + // 类型为 FRenderInfo + u32 InfoIndex{}; + u32 CommandCount{}; + }; + + struct FCmdCompute : FCmdBase + { + u32 CommandCount{}; + }; //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdSetPipeline : FCmdBase + { + FShaderPipeline* Pipeline{}; + }; + + struct FCmdSetBinding : FCmdBase + { + FShaderBinding* Binding{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdSetViewportScissor : FCmdBase + { + // 有多少个 Viewport + u32 ViewportCount{}; + // Payload 内的索引 + u32 ViewportIndex{}; + // 有多少个 Rect + u32 ScissorRectCount{}; + // Payload 内的索引, 类型为 FRect + u32 ScissorRectIndex{}; + }; + + struct FCmdSetMeshBuffers : FCmdBase + { + FGraphicsFormat IndexFormat{}; + // 0 .. 31 + u32 VertexStartSlot{}; + // 类型为 FMeshBuffers + u32 PayloadIndex{}; + }; + + struct FCmdDraw : FCmdBase + { + u32 VertexOrIndexCount{}; + u32 InstanceCount{}; + u32 FirstVertexOrIndex{}; + u32 FirstInstance{}; + // 仅 Indexed 使用 + u32 VertexOffset{}; + b8 Indexed{}; + }; + //////////////////////////////////////////////////////////////////////////////////////////////////// struct FCmdItem @@ -186,6 +290,13 @@ namespace Coplt FCmdClearColor ClearColor; FCmdClearDepthStencil ClearDepthStencil; + FCmdSetPipeline SetPipeline; + FCmdSetBinding SetBinding; + + FCmdSetViewportScissor SetViewportScissor; + FCmdSetMeshBuffers SetMeshBuffers; + FCmdDraw Draw; + u8 _pad[32]; }; }; diff --git a/Coplt.Graphics.Native/Api/FFI/Command.h b/Coplt.Graphics.Native/Api/FFI/Command.h index be51707..99e317e 100644 --- a/Coplt.Graphics.Native/Api/FFI/Command.h +++ b/Coplt.Graphics.Native/Api/FFI/Command.h @@ -216,14 +216,6 @@ namespace Coplt FImagePlane Plane{}; }; - enum class FResolveMode : u8 - { - Decompress, - Min, - Max, - Average, - }; - struct FResolveInfo { FResourceRef Src{}; @@ -232,22 +224,6 @@ namespace Coplt FResolveMode Mode{}; }; - enum class FLoadOp : u8 - { - Load, - Clear, - Discard, - NoAccess, - }; - - enum class FStoreOp : u8 - { - Store, - Discard, - Resolve, - NoAccess, - }; - struct FRenderInfo { // 可选 diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index 36979e3..11c9500 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -32,13 +32,14 @@ namespace Coplt FList Resources; FList PayloadRect; FList PayloadViewport; + FList RenderInfo; FList Blob; b8 Ended{}; FGpuRecordMode Mode{}; #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) - : Commands(allocator), Resources(allocator), PayloadRect(allocator), PayloadViewport(allocator), Blob(allocator) + : Commands(allocator), Resources(allocator), PayloadRect(allocator), PayloadViewport(allocator), RenderInfo(allocator), Blob(allocator) { } @@ -48,6 +49,7 @@ namespace Coplt Resources.Clear(); PayloadRect.Clear(); PayloadViewport.Clear(); + RenderInfo.Clear(); Blob.Clear(); } #endif diff --git a/Coplt.Graphics.Native/Api/FFI/Structs.h b/Coplt.Graphics.Native/Api/FFI/Structs.h index f06fbfe..2ce81c0 100644 --- a/Coplt.Graphics.Native/Api/FFI/Structs.h +++ b/Coplt.Graphics.Native/Api/FFI/Structs.h @@ -34,4 +34,28 @@ namespace Coplt Depth = 1, Stencil = 2, }; + + enum class FLoadOp : u8 + { + Load, + Clear, + Discard, + NoAccess, + }; + + enum class FStoreOp : u8 + { + Store, + Discard, + Resolve, + NoAccess, + }; + + enum class FResolveMode : u8 + { + Decompress, + Min, + Max, + Average, + }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index fb9de30..ec0425e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -1,5 +1,7 @@ #include "Record.h" +#include + #include "Output.h" using namespace Coplt; @@ -128,13 +130,13 @@ void D3d12GpuRecord::Interpret() case FCmdType::None: break; case FCmdType::Label: - // todo + Interpret_Label(i, command.Label); break; case FCmdType::BeginScope: - // todo + Interpret_BeginScope(i, command.BeginScope); break; case FCmdType::EndScope: - // todo + Interpret_EndScope(i, command.EndScope); break; case FCmdType::PreparePresent: Interpret_PreparePresent(i, command.PreparePresent); @@ -145,21 +147,76 @@ void D3d12GpuRecord::Interpret() case FCmdType::ClearDepthStencil: Interpret_ClearDepthStencil(i, command.ClearDepthStencil); break; + case FCmdType::Render: + case FCmdType::Compute: + case FCmdType::SetPipeline: + case FCmdType::SetBinding: + case FCmdType::SetViewportScissor: + case FCmdType::SetMeshBuffers: + case FCmdType::Draw: + case FCmdType::Dispatch: + COPLT_THROW("TODO"); } } m_barrier_recorder->EndRecord(); m_storage->EndRecord(); } -void D3d12GpuRecord::Interpret_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const +void D3d12GpuRecord::Interpret_Label(u32 i, const FCmdLabel& cmd) const +{ + if (!m_device->Debug()) return; + const auto& list = CurList(); + if (!list->g0) return; + auto color = PIX_COLOR_DEFAULT; + if (cmd.HasColor) color = PIX_COLOR(cmd.Color[0], cmd.Color[1], cmd.Color[2]); + if (cmd.StrType == FStrType::Str8) + { + PIXSetMarker(list->g0.Get(), color, "%s", reinterpret_cast(Blob.data() + cmd.StringIndex)); + } + else + { + PIXSetMarker(list->g0.Get(), color, L"%s", reinterpret_cast(Blob.data() + cmd.StringIndex)); + } +} + +void D3d12GpuRecord::Interpret_BeginScope(u32 i, const FCmdBeginScope& cmd) const +{ + if (!m_device->Debug()) return; + const auto& list = CurList(); + if (!list->g0) return; + auto color = PIX_COLOR_DEFAULT; + if (cmd.HasColor) color = PIX_COLOR(cmd.Color[0], cmd.Color[1], cmd.Color[2]); + if (cmd.StrType == FStrType::Str8) + { + PIXBeginEvent(list->g0.Get(), color, "%s", reinterpret_cast(Blob.data() + cmd.StringIndex)); + } + else + { + PIXBeginEvent(list->g0.Get(), color, L"%s", reinterpret_cast(Blob.data() + cmd.StringIndex)); + } +} + +void D3d12GpuRecord::Interpret_EndScope(u32 i, const FCmdEndScope& cmd) const { + if (!m_device->Debug()) return; + const auto& list = CurList(); + if (!list->g0) return; + PIXEndEvent(list->g0.Get()); +} + +void D3d12GpuRecord::Interpret_PreparePresent(const u32 i, const FCmdPreparePresent& cmd) const +{ + if (m_state != InterpretState::Main) + COPLT_THROW("Cannot use PreparePresent in sub scope"); if (Mode != FGpuRecordMode::Direct) COPLT_THROW("Can only present on the direct mode"); m_barrier_recorder->OnUse(cmd.Output, ResAccess::None, ResUsage::Common, ResLayout::Common); } -void D3d12GpuRecord::Interpret_ClearColor(u32 i, const FCmdClearColor& cmd) +void D3d12GpuRecord::Interpret_ClearColor(const u32 i, const FCmdClearColor& cmd) { + if (m_state != InterpretState::Main) + COPLT_THROW("Cannot use ClearColor in sub scope"); m_barrier_recorder->OnUse(cmd.Image, ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); m_barrier_recorder->OnCmd(); const auto rtv = GetRtv(GetRes(cmd.Image)); @@ -169,8 +226,10 @@ void D3d12GpuRecord::Interpret_ClearColor(u32 i, const FCmdClearColor& cmd) ); } -void D3d12GpuRecord::Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd) +void D3d12GpuRecord::Interpret_ClearDepthStencil(const u32 i, const FCmdClearDepthStencil& cmd) { + if (m_state != InterpretState::Main) + COPLT_THROW("Cannot use ClearDepthStencil in sub scope"); m_barrier_recorder->OnUse(cmd.Image, ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); m_barrier_recorder->OnCmd(); const auto dsv = GetDsv(GetRes(cmd.Image)); @@ -183,6 +242,14 @@ void D3d12GpuRecord::Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthSten ); } +void D3d12GpuRecord::Interpret_Render(const u32 i, const FCmdRender& cmd) +{ + if (m_state != InterpretState::Main) + COPLT_THROW("Cannot use Render in sub scope"); + m_state = InterpretState::Render; + m_cur_render = RenderState{.StartIndex = i, .Cmd = cmd}; +} + NonNull Coplt::GetResource(const FCmdRes& res) { switch (res.Type) diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 655cb7b..bcfc4d8 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -26,6 +26,19 @@ namespace Coplt struct D3d12GpuRecord final : GpuObject, FGpuRecordData { + enum class InterpretState : u8 + { + Main, + Render, + Compute, + }; + + struct RenderState + { + u32 StartIndex{}; + FCmdRender Cmd{}; + }; + u64 m_isolate_id{}; u64 m_record_id{}; Rc m_device{}; @@ -34,6 +47,8 @@ namespace Coplt Rc m_barrier_recorder{}; std::vector> m_resources_owner{}; std::vector m_queue_wait_points{}; + RenderState m_cur_render{}; + InterpretState m_state{}; explicit D3d12GpuRecord(NonNull isolate); @@ -59,9 +74,14 @@ namespace Coplt void ReadyResource(); void Interpret(); + void Interpret_Label(u32 i, const FCmdLabel& cmd) const; + void Interpret_BeginScope(u32 i, const FCmdBeginScope& cmd) const; + void Interpret_EndScope(u32 i, const FCmdEndScope& cmd) const; void Interpret_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const; void Interpret_ClearColor(u32 i, const FCmdClearColor& cmd); void Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); + void Interpret_Render(u32 i, const FCmdRender& cmd); + }; NonNull GetResource(const FCmdRes& res); diff --git a/Examples/HelloTriangle/Example.cs b/Examples/HelloTriangle/Example.cs index 5a24f9d..bba8c4b 100644 --- a/Examples/HelloTriangle/Example.cs +++ b/Examples/HelloTriangle/Example.cs @@ -32,6 +32,7 @@ protected override async Task LoadResources(GpuRecord cmd) } protected override void Render(GpuRecord cmd, Time time) { + using var _ = cmd.Scope("Hello Triangle"); cmd.ClearColor(Output, new Color(0.83f, 0.8f, 0.97f)); // using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); // render.Draw(Pipeline, 3); From 3d97be5f465fa37b9b85e0938f3df7740724e0da Mon Sep 17 00:00:00 2001 From: U2A5F Date: Fri, 28 Mar 2025 13:15:02 +0800 Subject: [PATCH 17/46] draw --- Coplt.Graphics.Core/Core/GpuRecord.cs | 552 +++++++++++++++++++++- Coplt.Graphics.Core/Native/Native.cs | 37 +- Coplt.Graphics.Native/Api/FFI/Cmd.h | 6 +- Coplt.Graphics.Native/Api/FFI/Record.h | 9 +- Coplt.Graphics.Native/D3d12/Src/Record.cc | 206 +++++++- Coplt.Graphics.Native/D3d12/Src/Record.h | 22 + Examples/HelloTriangle/Example.cs | 6 +- 7 files changed, 825 insertions(+), 13 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index ae17416..6d943a8 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -4,13 +4,18 @@ namespace Coplt.Graphics.Core; +/// +/// 命令录制对象,非线程安全,需要外部同步 +/// public sealed unsafe class GpuRecord : IsolateChild { #region Fields internal FGpuRecordData* m_data; internal readonly Dictionary m_resources = new(); - internal int m_debug_scope_count; + internal readonly HashSet m_objects = new(); + internal uint m_debug_scope_count; + internal bool m_in_render_or_compute_scope; #endregion @@ -49,6 +54,7 @@ protected override void Dispose(bool disposing) internal void Reset() { m_resources.Clear(); + m_objects.Clear(); } #endregion @@ -81,6 +87,10 @@ internal void AssertEndOrCanEnd() throw new InvalidOperationException( "There is still Debug scope not ended, please check whether Dispose is missed." ); + if (m_in_render_or_compute_scope) + throw new InvalidOperationException( + "There is still Render or Compute scope not ended, please check whether Dispose is missed." + ); } #endregion @@ -106,6 +116,15 @@ internal FCmdResRef AddResource(IGpuResource resource) #endregion + #region AddObject + + /// + /// 返回是否首次 + /// + internal bool AddObject(object obj) => m_objects.Add(obj); + + #endregion + #region AddRects internal uint AddRects(ReadOnlySpan Rects) @@ -119,6 +138,19 @@ internal uint AddRects(ReadOnlySpan Rects) #endregion + #region AddViewports + + internal uint AddViewports(ReadOnlySpan Viewports) + { + var len = Data.PayloadViewport.LongLength; + if (len >= uint.MaxValue) throw new IndexOutOfRangeException("Payload >= uint32 max are not supported"); + Data.PayloadViewport.EnsureCap(len + (uint)Viewports.Length); + Data.PayloadViewport.AddRange(MemoryMarshal.Cast(Viewports)); + return (uint)len; + } + + #endregion + #region AddString internal uint AddString(string str) @@ -281,6 +313,202 @@ public void ClearColor(IRtv Image, Color Color, ReadOnlySpan Rects = defa } #endregion + + #region Render + + public RenderScope2 Render( + ReadOnlySpan Rtvs, RenderInfo.DsvInfo? Dsv = null, + bool AutoViewportScissor = true, + string? Name = null, ReadOnlySpan Name8 = default + ) => Render(new(Rtvs, Dsv), AutoViewportScissor, Name, Name8); + public RenderScope2 Render( + RenderInfo.DsvInfo Dsv, ReadOnlySpan Rtvs = default, + bool AutoViewportScissor = true, + string? Name = null, ReadOnlySpan Name8 = default + ) => Render(new(Rtvs, Dsv), AutoViewportScissor, Name, Name8); + public RenderScope2 Render( + in RenderInfo Info, + bool AutoViewportScissor = true, + string? Name = null, ReadOnlySpan Name8 = default + ) + { + #region Check Nested + + if (m_in_render_or_compute_scope) throw new InvalidOperationException("Cannot nest Render or Compute scopes"); + m_in_render_or_compute_scope = true; + + #endregion + + #region Check Args + + if (Info.Dsv == null && Info.Rtvs.Length == 0) throw new ArgumentException("No any rtv or dsv provided"); + if (Info.Rtvs.Length > 8) throw new ArgumentException("Too many rtvs provided, it can't be more than 8"); + + #endregion + + #region Cmd + + var info_index = (uint)Data.PayloadRenderInfo.LongLength; + var cmd = new FCmdRender + { + Base = { Type = FCmdType.Render }, + InfoIndex = info_index, + }; + + #endregion + + #region Init + + var has_dsv = Info.Dsv.HasValue; + var dsv = Info.Dsv ?? default; + if (has_dsv) dsv.View!.AssertSameIsolate(Isolate); + + #endregion + + #region Info + + FRenderInfo2 info = new() + { + Dsv = has_dsv ? AddResource(dsv.View!.Resource) : default, + NumRtv = (uint)Info.Rtvs.Length, + Depth = has_dsv && dsv.DepthLoad is { IsClear: true, Clear: var cd } ? cd : 1, + Stencil = has_dsv && dsv.StencilLoad is { IsClear: true, Clear: var cs } ? (byte)cs : (byte)0, + }; + + #endregion + + #region DsvLoadOp + + info.DsvLoadOp[0] = has_dsv + ? dsv.DepthLoad.Tag switch + { + LoadOp.Tags.Load => FLoadOp.Load, + LoadOp.Tags.Clear => FLoadOp.Clear, + LoadOp.Tags.Discard => FLoadOp.Discard, + LoadOp.Tags.NoAccess => FLoadOp.NoAccess, + _ => throw new ArgumentOutOfRangeException() + } + : FLoadOp.NoAccess; + info.DsvLoadOp[1] = has_dsv + ? dsv.StencilLoad.Tag switch + { + LoadOp.Tags.Load => FLoadOp.Load, + LoadOp.Tags.Clear => FLoadOp.Clear, + LoadOp.Tags.Discard => FLoadOp.Discard, + LoadOp.Tags.NoAccess => FLoadOp.NoAccess, + _ => throw new ArgumentOutOfRangeException() + } + : FLoadOp.NoAccess; + + #endregion + + #region DsvStoreOp + + info.DsvStoreOp[0] = has_dsv + ? dsv.DepthStore.Tag switch + { + StoreOp.Tags.Store => FStoreOp.Store, + StoreOp.Tags.Discard => FStoreOp.Discard, + StoreOp.Tags.NoAccess => FStoreOp.NoAccess, + _ => throw new ArgumentOutOfRangeException() + } + : FStoreOp.NoAccess; + + info.DsvStoreOp[1] = has_dsv + ? dsv.StencilStore.Tag switch + { + StoreOp.Tags.Store => FStoreOp.Store, + StoreOp.Tags.Discard => FStoreOp.Discard, + StoreOp.Tags.NoAccess => FStoreOp.NoAccess, + _ => throw new ArgumentOutOfRangeException() + } + : FStoreOp.NoAccess; + + #endregion + + #region Rtv + + var rt_size = Info.Dsv?.View.USize2d ?? Info.Rtvs[0].View.USize2d; + for (var i = 0; i < Info.Rtvs.Length; i++) + { + ref readonly var rtv = ref Info.Rtvs[i]; + rtv.View.AssertSameIsolate(Isolate); + if (!rtv.View.USize2d.Equals(rt_size)) + throw new ArgumentException("RenderTargets And DepthStencil must be the same size"); + info.Rtv[i] = AddResource(rtv.View.Resource); + info.ResolveInfoIndex[i] = uint.MaxValue; // todo + if (rtv.Load is { IsClear: true, Clear: var cc }) + Unsafe.As(ref info.Color[i * 4]) = cc; + info.RtvLoadOp[i] = rtv.Load.Tag switch + { + LoadOp.Tags.Load => FLoadOp.Load, + LoadOp.Tags.Clear => FLoadOp.Clear, + LoadOp.Tags.Discard => FLoadOp.Discard, + LoadOp.Tags.NoAccess => FLoadOp.NoAccess, + _ => throw new ArgumentOutOfRangeException() + }; + info.RtvStoreOp[i] = rtv.Store.Tag switch + { + StoreOp.Tags.Store => FStoreOp.Store, + StoreOp.Tags.Discard => FStoreOp.Discard, + StoreOp.Tags.NoAccess => FStoreOp.NoAccess, + _ => throw new ArgumentOutOfRangeException() + }; + } + + #endregion + + #region DebugScope + + var debug_scope = false; + if (Name != null) + { + debug_scope = true; + Scope(Name); + } + else if (Name8.Length > 0) + { + debug_scope = true; + Scope(Name8); + } + + #endregion + + #region EndInfo + + Data.PayloadRenderInfo.Add(info); + + #endregion + + #region EndCmd + + var cmd_index = (uint)Data.Commands.LongLength; + Data.Commands.Add(new() { Render = cmd }); + + #endregion + + #region Scope + + RenderScope2 scope = new(this, info_index, cmd_index, debug_scope, m_debug_scope_count); + + #endregion + + #region AutoViewportScissor + + if (AutoViewportScissor) + { + scope.SetViewportScissor( + [new UViewPort { Width = rt_size.Width, Height = rt_size.Height }], + [new URect { Right = rt_size.Width, Bottom = rt_size.Height }] + ); + } + + #endregion + + return scope; + } + + #endregion } #region DebugScope @@ -303,3 +531,325 @@ public void Dispose() } #endregion + +#region RenderScope + +public unsafe struct RenderScope2( + GpuRecord self, + uint info_index, + uint cmd_index, + bool debug_scope, + uint debug_scope_count +) : IDisposable +{ + #region Fields + + internal bool m_disposed; + internal bool m_has_pixel_shader; + internal bool m_has_vertex_shader; + internal bool m_has_mesh_shader; + internal bool m_has_task_shader; + internal bool m_has_uav_writes; + + #endregion + + #region Props + + internal ref FRenderInfo2 Info => ref self.Data.PayloadRenderInfo[info_index]; + internal ref FCmdRender Cmd => ref self.Data.Commands[cmd_index].Render; + + #endregion + + #region Dispose + + public void Dispose() + { + if (m_disposed) throw new ObjectDisposedException(nameof(ComputeScope)); + m_disposed = true; + if (self.m_debug_scope_count > debug_scope_count) + throw new InvalidOperationException( + "There is still Debug scope not ended, please check whether Dispose is missed." + ); + ref var info = ref Info; + info.HasUavWrites = m_has_uav_writes; + Cmd.CommandCount = (uint)self.m_data->Commands.LongLength - cmd_index; + self.m_in_render_or_compute_scope = false; + self.Data.Commands.Add(new() { Type = FCmdType.End }); + if (debug_scope) new DebugScope2(self).Dispose(); + } + + #endregion + + #region Debug + + #region Label + + public void Label(string Label, Color? Color = null) => self.Label(Label, Color); + + public void Label(ReadOnlySpan Label, Color? Color = null) => self.Label(Label, Color); + + #endregion + + #region Scope + + public DebugScope2 Scope(string Name, Color? Color = null) => self.Scope(Name, Color); + + public DebugScope2 Scope(ReadOnlySpan Name, Color? Color = null) => self.Scope(Name, Color); + + #endregion + + #endregion + + #region SetPipeline + + public void SetPipeline(ShaderPipeline Pipeline) + { + if (!Pipeline.Shader.Stages.HasAnyFlags(ShaderStageFlags.Pixel)) + throw new ArgumentException("Only shaders with a pixel stage can be used for rendering"); + // if (!m_context.SetPipeline(self, Pipeline)) return; + var cmd = new FCmdSetPipeline + { + Base = { Type = FCmdType.SetPipeline }, + Pipeline = Pipeline.m_ptr, + }; + self.Data.Commands.Add(new() { SetPipeline = cmd }); + } + + #endregion + + #region SetViewportScissor + + public void SetViewportScissor( + ReadOnlySpan Viewports, + ReadOnlySpan Scissors + ) + { + var cmd = new FCmdSetViewportScissor + { + Base = { Type = FCmdType.SetViewportScissor }, + ViewportCount = (uint)Viewports.Length, + ScissorRectCount = (uint)Scissors.Length, + }; + if (Viewports.Length > 0) + { + cmd.ViewportIndex = self.AddViewports(Viewports); + } + if (Scissors.Length > 0) + { + cmd.ScissorRectIndex = self.AddRects(Scissors); + } + self.Data.Commands.Add(new() { SetViewportScissor = cmd }); + } + + #endregion + + // #region SetMeshBuffers + // + // public void SetMeshBuffers( + // MeshLayout MeshLayout, + // uint VertexStartSlot, + // ReadOnlySpan VertexBuffers + // ) => SetMeshBuffers(MeshLayout, FGraphicsFormat.Unknown, null, VertexStartSlot, VertexBuffers); + // + // public void SetMeshBuffers( + // MeshLayout MeshLayout, + // ReadOnlySpan VertexBuffers + // ) => SetMeshBuffers(MeshLayout, FGraphicsFormat.Unknown, null, 0, VertexBuffers); + // + // public void SetMeshBuffers( + // MeshLayout MeshLayout, + // FGraphicsFormat IndexFormat, + // BufferRange? IndexBuffer, + // uint VertexStartSlot, + // ReadOnlySpan VertexBuffers + // ) + // { + // self.AddObject(MeshLayout); + // var cmd = new FCommandSetMeshBuffers + // { + // Base = { Type = FCommandType.SetMeshBuffers }, + // IndexFormat = IndexFormat, + // VertexStartSlot = VertexStartSlot, + // PayloadIndex = (uint)self.m_mesh_buffers.Count, + // }; + // var buf = new FMeshBuffers + // { + // MeshLayout = MeshLayout.m_ptr, + // VertexBufferCount = (uint)VertexBuffers.Length, + // }; + // if (IndexBuffer is { } index_buffer) + // { + // buf.IndexBuffer = new() + // { + // Buffer = self.AddResource(index_buffer.Buffer.Resource), + // Offset = index_buffer.Offset, + // Size = index_buffer.Size == uint.MaxValue ? (uint)index_buffer.Buffer.Size : index_buffer.Size, + // }; + // 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) + // { + // var index = self.m_vertex_buffer_ranges.Count; + // buf.VertexBuffersIndex = (uint)index; + // CollectionsMarshal.SetCount( + // self.m_vertex_buffer_ranges, self.m_vertex_buffer_ranges.Count + VertexBuffers.Length + // ); + // var vbs = CollectionsMarshal.AsSpan(self.m_vertex_buffer_ranges).Slice(index, VertexBuffers.Length); + // for (var i = 0; i < VertexBuffers.Length; i++) + // { + // var buffer = VertexBuffers[i]; + // buffer.Buffer.AssertSameQueue(self.Queue); + // ref var dst = ref vbs[i]; + // dst = new() + // { + // Base = + // { + // Buffer = self.AddResource(buffer.Buffer.Resource), + // Offset = buffer.Offset, + // Size = buffer.Size == uint.MaxValue ? (uint)buffer.Buffer.Size : buffer.Size, + // }, + // Index = buffer.Index, + // }; + // 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); + // m_commands.Add(new() { SetMeshBuffers = cmd }); + // } + // + // #endregion + + #region Draw + + public void Draw( + uint VertexCount, uint InstanceCount = 1, + uint FirstVertex = 0, uint FirstInstance = 0, + ShaderBinding? Binding = null + ) => Draw(null, false, VertexCount, InstanceCount, FirstVertex, FirstInstance, 0, Binding); + + public void Draw( + ShaderPipeline? Pipeline, + uint VertexCount, uint InstanceCount = 1, + uint FirstVertex = 0, uint FirstInstance = 0, + ShaderBinding? Binding = null + ) => Draw(Pipeline, false, VertexCount, InstanceCount, FirstVertex, FirstInstance, 0, Binding); + + public void DrawIndexed( + uint IndexCount, uint InstanceCount = 1, + uint FirstIndex = 0, uint FirstInstance = 0, uint VertexOffset = 0, + ShaderBinding? Binding = null + ) => Draw(null, true, IndexCount, InstanceCount, FirstIndex, FirstInstance, VertexOffset, Binding); + + public void DrawIndexed( + ShaderPipeline? Pipeline, + uint IndexCount, uint InstanceCount = 1, + uint FirstIndex = 0, uint FirstInstance = 0, uint VertexOffset = 0, + ShaderBinding? Binding = null + ) => Draw(Pipeline, true, IndexCount, InstanceCount, FirstIndex, FirstInstance, VertexOffset, Binding); + + public void Draw( + ShaderPipeline? Pipeline, bool Indexed, + uint VertexOrIndexCount, uint InstanceCount = 1, + uint FirstVertexOrIndex = 0, uint FirstInstance = 0, uint VertexOffset = 0, + ShaderBinding? Binding = null + ) + { + if (Pipeline != null) + { + if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Vertex)) + throw new ArgumentException("Only Vertex shaders can use Draw"); + SetPipeline(Pipeline); + } + else + { + // if (m_context.CurrentPipeline == null) throw new InvalidOperationException("Pipeline is not set"); + // if (!m_context.CurrentPipeline.Shader.Stages.HasFlags(ShaderStageFlags.Vertex)) + // throw new ArgumentException("Only shaders with a vertex stage can use Draw"); + } + // if (Binding != null) SetBinding(Binding); + var cmd = new FCmdDraw + { + Base = { Type = FCmdType.Draw }, + VertexOrIndexCount = VertexOrIndexCount, + InstanceCount = InstanceCount, + FirstVertexOrIndex = FirstVertexOrIndex, + FirstInstance = FirstInstance, + VertexOffset = VertexOffset, + Indexed = Indexed, + }; + self.Data.Commands.Add(new() { Draw = cmd }); + m_has_pixel_shader = true; + m_has_vertex_shader = true; + } + + #endregion + + // #region DispatchMesh + // + // public void DispatchMesh( + // 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, + // ShaderBinding? Binding = null + // ) + // { + // if (Pipeline != null) + // { + // if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) + // throw new ArgumentException("Only Mesh shaders can use DispatchMesh"); + // SetPipeline(Pipeline); + // } + // else + // { + // // if (m_context.CurrentPipeline == null) throw new InvalidOperationException("Pipeline is not set"); + // // if (!m_context.CurrentPipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) + // // throw new ArgumentException("Only shaders with a mesh stage can use DispatchMesh"); + // } + // // if (Binding != null) SetBinding(Binding); + // // self.SyncBinding(ref m_context, this); + // var cmd = new FCmdDispatch + // { + // Base = { Type = FCmdType.Dispatch }, + // GroupCountX = GroupCountX, + // GroupCountY = GroupCountY, + // GroupCountZ = GroupCountZ, + // Type = FDispatchType.Mesh, + // }; + // m_commands.Add(new() { Dispatch = cmd }); + // m_has_pixel_shader = true; + // m_has_mesh_shader = true; + // m_has_task_shader = m_context.CurrentPipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Task); + // } + // + // #endregion +} + +#endregion diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index b1526e1..62f2c11 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1571,7 +1571,9 @@ public unsafe partial struct FGpuRecordData public FList PayloadViewport; - public FList RenderInfo; + public FList PayloadRenderInfo; + + public FList PayloadResolveInfo; [NativeTypeName("FList")] public FList Blob; @@ -1587,6 +1589,7 @@ public unsafe partial struct FGpuRecordData public enum FCmdType : uint { None = 0, + End = 1, Label, BeginScope, EndScope, @@ -1613,7 +1616,7 @@ public enum FCmdResType : byte public unsafe partial struct FCmdRes { - [NativeTypeName("__AnonymousRecord_Cmd_L66_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L67_C9")] public _Anonymous_e__Union Anonymous; [NativeTypeName("Coplt::FCmdResType")] @@ -2004,7 +2007,7 @@ public partial struct FCmdDraw public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L280_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L281_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -2077,6 +2080,26 @@ public ref FCmdClearDepthStencil ClearDepthStencil } } + [UnscopedRef] + public ref FCmdRender Render + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Render; + } + } + + [UnscopedRef] + public ref FCmdCompute Compute + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Compute; + } + } + [UnscopedRef] public ref FCmdSetPipeline SetPipeline { @@ -2168,6 +2191,14 @@ public partial struct _Anonymous_e__Union [NativeTypeName("Coplt::FCmdClearDepthStencil")] public FCmdClearDepthStencil ClearDepthStencil; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdRender")] + public FCmdRender Render; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdCompute")] + public FCmdCompute Compute; + [FieldOffset(0)] [NativeTypeName("Coplt::FCmdSetPipeline")] public FCmdSetPipeline SetPipeline; diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index 321fe10..6346f91 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -10,6 +10,7 @@ namespace Coplt enum class FCmdType : u32 { None = 0, + End = 1, Label, BeginScope, @@ -108,7 +109,7 @@ namespace Coplt u32 IndexPlusOne{}; #ifdef FFI_SRC - operator bool() const { return IndexPlusOne == 0; } + operator bool() const { return IndexPlusOne != 0; } u32 ResIndex() const { return IndexPlusOne - 1; } @@ -290,6 +291,9 @@ namespace Coplt FCmdClearColor ClearColor; FCmdClearDepthStencil ClearDepthStencil; + FCmdRender Render; + FCmdCompute Compute; + FCmdSetPipeline SetPipeline; FCmdSetBinding SetBinding; diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index 11c9500..e794056 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -32,14 +32,16 @@ namespace Coplt FList Resources; FList PayloadRect; FList PayloadViewport; - FList RenderInfo; + FList PayloadRenderInfo; + FList PayloadResolveInfo; FList Blob; b8 Ended{}; FGpuRecordMode Mode{}; #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) - : Commands(allocator), Resources(allocator), PayloadRect(allocator), PayloadViewport(allocator), RenderInfo(allocator), Blob(allocator) + : Commands(allocator), Resources(allocator), PayloadRect(allocator), PayloadViewport(allocator), + PayloadRenderInfo(allocator), PayloadResolveInfo(allocator), Blob(allocator) { } @@ -49,7 +51,8 @@ namespace Coplt Resources.Clear(); PayloadRect.Clear(); PayloadViewport.Clear(); - RenderInfo.Clear(); + PayloadRenderInfo.Clear(); + PayloadResolveInfo.Clear(); Blob.Clear(); } #endif diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index ec0425e..0fa1a9e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -3,9 +3,47 @@ #include #include "Output.h" +#include "../FFI/Pipeline.h" +#include "../Include/GraphicsFormat.h" +#include "../Include/PipelineState.h" using namespace Coplt; +void D3d12GpuRecord::PipelineContext::Reset() +{ + Pipeline = nullptr; + Layout = nullptr; + GPipeline = nullptr; + // Binding = nullptr; + PipelineChanged = false; + BindingChanged = false; +} + +void D3d12GpuRecord::PipelineContext::SetPipeline(NonNull pipeline, u32 i) +{ + if (pipeline == Pipeline) return; + Pipeline = pipeline->QueryInterface(); + if (!Pipeline) + { + COPLT_THROW_FMT( + "Pipeline({:#x}) comes from different backends at cmd {}", + static_cast(pipeline), i + ); + } + Layout = pipeline->GetLayout()->QueryInterface(); + if (!Layout) + COPLT_THROW("Shader layout from different backends"); + const auto stages = pipeline->GetStages(); + GPipeline = nullptr; + if (HasFlags(stages, FShaderStageFlags::Pixel)) + { + GPipeline = pipeline->QueryInterface(); + if (!GPipeline) + COPLT_THROW("Pipeline from different backends or pipeline not a graphics pipeline"); + } + PipelineChanged = true; +} + D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) : FGpuRecordData(isolate->m_device->m_instance->m_allocator.get()), m_device(isolate->m_device) { @@ -68,6 +106,7 @@ void D3d12GpuRecord::Recycle() m_storage->Clear(); m_context->Recycle(); m_resources_owner.clear(); + m_pipeline_context.Reset(); ClearData(); Ended = false; } @@ -129,6 +168,12 @@ void D3d12GpuRecord::Interpret() { case FCmdType::None: break; + case FCmdType::End: + if (m_state == InterpretState::Render) + Interpret_RenderEnd(i, m_cur_render.Cmd); + else + COPLT_THROW("Cannot use End in main scope"); + break; case FCmdType::Label: Interpret_Label(i, command.Label); break; @@ -148,14 +193,26 @@ void D3d12GpuRecord::Interpret() Interpret_ClearDepthStencil(i, command.ClearDepthStencil); break; case FCmdType::Render: + Interpret_Render(i, command.Render); + break; case FCmdType::Compute: + COPLT_THROW("TODO"); case FCmdType::SetPipeline: + Interpret_SetPipeline(i, command.SetPipeline); + break; case FCmdType::SetBinding: + COPLT_THROW("TODO"); case FCmdType::SetViewportScissor: + Interpret_SetViewportScissor(i, command.SetViewportScissor); + break; case FCmdType::SetMeshBuffers: + COPLT_THROW("TODO"); case FCmdType::Draw: + Interpret_Draw(i, command.Draw); + break; case FCmdType::Dispatch: COPLT_THROW("TODO"); + break; } } m_barrier_recorder->EndRecord(); @@ -184,7 +241,7 @@ void D3d12GpuRecord::Interpret_BeginScope(u32 i, const FCmdBeginScope& cmd) cons if (!m_device->Debug()) return; const auto& list = CurList(); if (!list->g0) return; - auto color = PIX_COLOR_DEFAULT; + u32 color = PIX_COLOR_DEFAULT; if (cmd.HasColor) color = PIX_COLOR(cmd.Color[0], cmd.Color[1], cmd.Color[2]); if (cmd.StrType == FStrType::Str8) { @@ -246,8 +303,155 @@ void D3d12GpuRecord::Interpret_Render(const u32 i, const FCmdRender& cmd) { if (m_state != InterpretState::Main) COPLT_THROW("Cannot use Render in sub scope"); + if (Mode != FGpuRecordMode::Direct) + COPLT_THROW("Render can only be used in Direct mode"); m_state = InterpretState::Render; m_cur_render = RenderState{.StartIndex = i, .Cmd = cmd}; + const auto& list = CurList(); + const auto& info = PayloadRenderInfo[cmd.InfoIndex]; + auto num_rtv = std::min(info.NumRtv, 8u); + if (list->g4) + { + D3D12_RENDER_PASS_RENDER_TARGET_DESC rts[num_rtv]; + D3D12_RENDER_PASS_DEPTH_STENCIL_DESC ds[info.Dsv ? 1 : 0]; + if (info.Dsv) + { + m_barrier_recorder->OnUse(info.Dsv, ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); + const auto& dsv = GetRes(info.Dsv); + const auto& d_load = info.DsvLoadOp[0]; + const auto& d_store = info.DsvStoreOp[0]; + const auto& s_load = info.DsvLoadOp[1]; + const auto& s_store = info.DsvStoreOp[1]; + D3D12_RENDER_PASS_DEPTH_STENCIL_DESC desc{}; + desc.cpuDescriptor = GetDsv(dsv); + desc.DepthBeginningAccess = ToDx(d_load, [&](D3D12_CLEAR_VALUE& cv) + { + cv.Format = ToDx(info.DsvFormat); + cv.DepthStencil.Depth = info.Depth; + }); + desc.DepthBeginningAccess = ToDx(s_load, [&](D3D12_CLEAR_VALUE& cv) + { + cv.Format = ToDx(info.DsvFormat); + cv.DepthStencil.Stencil = info.Stencil; + }); + desc.DepthEndingAccess = ToDx(d_store, [&](D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS& res) + { + const auto& res_info = PayloadResolveInfo[info.DsvResolveInfoIndex]; + res.Format = ToDx(res_info.Format); + res.pSrcResource = GetResource(GetRes(res_info.Src)); + res.pDstResource = GetResource(GetRes(res_info.Dst)); + res.SubresourceCount = 0; + res.ResolveMode = ToDx(res_info.Mode); + }); + desc.StencilEndingAccess = ToDx(s_store, [&](D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS& res) + { + const auto& res_info = PayloadResolveInfo[info.DsvResolveInfoIndex]; + res.Format = ToDx(res_info.Format); + res.pSrcResource = GetResource(GetRes(res_info.Src)); + res.pDstResource = GetResource(GetRes(res_info.Dst)); + res.SubresourceCount = 0; + res.ResolveMode = ToDx(res_info.Mode); + }); + ds[0] = desc; + } + for (u32 n = 0; n < num_rtv; ++n) + { + m_barrier_recorder->OnUse(info.Rtv[n], ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); + const auto& rtv = GetRes(info.Rtv[n]); + const auto& load = info.RtvLoadOp[n]; + const auto& store = info.RtvStoreOp[n]; + D3D12_RENDER_PASS_RENDER_TARGET_DESC desc{}; + desc.cpuDescriptor = GetRtv(rtv); + desc.BeginningAccess = ToDx(load, [&](D3D12_CLEAR_VALUE& cv) + { + cv.Format = ToDx(info.RtvFormat[n]); + cv.Color[0] = info.Color[0]; + cv.Color[1] = info.Color[1]; + cv.Color[2] = info.Color[2]; + cv.Color[3] = info.Color[3]; + }); + desc.EndingAccess = ToDx(store, [&](D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS& res) + { + const auto& res_info = PayloadResolveInfo[info.ResolveInfoIndex[n]]; + res.Format = ToDx(res_info.Format); + res.pSrcResource = GetResource(GetRes(res_info.Src)); + res.pDstResource = GetResource(GetRes(res_info.Dst)); + res.SubresourceCount = 0; + res.ResolveMode = ToDx(res_info.Mode); + }); + rts[n] = desc; + } + D3D12_RENDER_PASS_FLAGS flags = D3D12_RENDER_PASS_FLAG_NONE; + if (info.HasUavWrites) flags |= D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES; + m_barrier_recorder->OnCmd(); + list->g4->BeginRenderPass(info.NumRtv, rts, info.Dsv ? ds : nullptr, flags); + } + else + { + COPLT_THROW("TODO"); + } +} + +void D3d12GpuRecord::Interpret_RenderEnd(u32 i, const FCmdRender& cmd) +{ + if (m_state != InterpretState::Render) + COPLT_THROW("Cannot use End in main scope"); + m_state = InterpretState::Main; + const auto& list = CurList(); + if (list->g4) + { + list->g4->EndRenderPass(); + } +} + +void D3d12GpuRecord::Interpret_SetPipeline(const u32 i, const FCmdSetPipeline& cmd) +{ + if (m_state != InterpretState::Render && m_state != InterpretState::Compute) + COPLT_THROW("Cannot use SetPipeline in main scope"); + SetPipeline(cmd.Pipeline, i); +} + +void D3d12GpuRecord::Interpret_SetViewportScissor(u32 i, const FCmdSetViewportScissor& cmd) const +{ + if (m_state != InterpretState::Render) + COPLT_THROW("Cannot use SetPipeline in main scope or compute scope"); + const auto& list = CurList(); + list->g0->RSSetViewports(cmd.ViewportCount, reinterpret_cast(PayloadViewport.data() + cmd.ViewportIndex)); + list->g0->RSSetScissorRects(cmd.ScissorRectCount, reinterpret_cast(PayloadRect.data() + cmd.ScissorRectIndex)); +} + +void D3d12GpuRecord::Interpret_Draw(u32 i, const FCmdDraw& cmd) const +{ + if (m_state != InterpretState::Render) + COPLT_THROW("Cannot use SetPipeline in main scope or compute scope"); + const auto& list = CurList(); + if (cmd.Indexed) + { + list->g0->DrawIndexedInstanced(cmd.VertexOrIndexCount, cmd.InstanceCount, cmd.FirstVertexOrIndex, cmd.VertexOffset, cmd.FirstInstance); + } + else + { + list->g0->DrawInstanced(cmd.VertexOrIndexCount, cmd.InstanceCount, cmd.FirstVertexOrIndex, cmd.FirstInstance); + } +} + +void D3d12GpuRecord::SetPipeline(NonNull pipeline, u32 i) +{ + if (pipeline == m_pipeline_context.Pipeline) return; + m_pipeline_context.SetPipeline(pipeline, i); + const auto stages = pipeline->GetStages(); + const auto& list = CurList(); + if (HasFlags(stages, FShaderStageFlags::Compute)) + { + list->g0->SetComputeRootSignature(static_cast(m_pipeline_context.Layout->GetRootSignaturePtr())); + } + else if (HasFlags(stages, FShaderStageFlags::Pixel)) + { + const auto& states = m_pipeline_context.GPipeline->GetGraphicsState(); + list->g0->IASetPrimitiveTopology(ToDx(states->Topology)); + list->g0->SetGraphicsRootSignature(static_cast(m_pipeline_context.Layout->GetRootSignaturePtr())); + } + list->g0->SetPipelineState(static_cast(m_pipeline_context.Pipeline->GetPipelineStatePtr())); } NonNull Coplt::GetResource(const FCmdRes& res) diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index bcfc4d8..bb6f0f2 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -39,6 +39,22 @@ namespace Coplt FCmdRender Cmd{}; }; + struct PipelineContext + { + Ptr Pipeline{}; + Ptr Layout{}; + // 如果不是图形管线将不会设置 + Ptr GPipeline{}; + + // Ptr Binding{}; + + bool PipelineChanged{}; + bool BindingChanged{}; + + void Reset(); + void SetPipeline(NonNull pipeline, u32 i); + }; + u64 m_isolate_id{}; u64 m_record_id{}; Rc m_device{}; @@ -48,6 +64,7 @@ namespace Coplt std::vector> m_resources_owner{}; std::vector m_queue_wait_points{}; RenderState m_cur_render{}; + PipelineContext m_pipeline_context{}; InterpretState m_state{}; explicit D3d12GpuRecord(NonNull isolate); @@ -81,7 +98,12 @@ namespace Coplt void Interpret_ClearColor(u32 i, const FCmdClearColor& cmd); void Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); void Interpret_Render(u32 i, const FCmdRender& cmd); + void Interpret_RenderEnd(u32 i, const FCmdRender& cmd); + void Interpret_SetPipeline(u32 i, const FCmdSetPipeline& cmd); + void Interpret_SetViewportScissor(u32 i, const FCmdSetViewportScissor& cmd) const; + void Interpret_Draw(u32 i, const FCmdDraw& cmd) const; + void SetPipeline(NonNull pipeline, u32 i); }; NonNull GetResource(const FCmdRes& res); diff --git a/Examples/HelloTriangle/Example.cs b/Examples/HelloTriangle/Example.cs index bba8c4b..b073656 100644 --- a/Examples/HelloTriangle/Example.cs +++ b/Examples/HelloTriangle/Example.cs @@ -32,9 +32,7 @@ protected override async Task LoadResources(GpuRecord cmd) } protected override void Render(GpuRecord cmd, Time time) { - using var _ = cmd.Scope("Hello Triangle"); - cmd.ClearColor(Output, new Color(0.83f, 0.8f, 0.97f)); - // using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); - // render.Draw(Pipeline, 3); + using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))], Name: "Hello Triangle"); + render.Draw(Pipeline, 3); } } From e7c7311b08f6445bee6dcb4a8aa969ac0c2472d6 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Fri, 28 Mar 2025 15:12:58 +0800 Subject: [PATCH 18/46] upload --- Coplt.Graphics.Core/Core/GpuRecord.cs | 188 ++++++++++++++- .../Core/ImageUploadBufferMemory.cs | 20 ++ Coplt.Graphics.Core/Core/UploadLoc.cs | 1 + Coplt.Graphics.Core/Native/FUploadLoc.cs | 6 + Coplt.Graphics.Core/Native/Native.cs | 214 ++++++++++++------ Coplt.Graphics.Native/Api/FFI/Cmd.h | 43 +++- Coplt.Graphics.Native/Api/FFI/Command.h | 27 --- Coplt.Graphics.Native/Api/FFI/Record.h | 6 +- Coplt.Graphics.Native/Api/FFI/Structs.h | 28 +++ Coplt.Graphics.Native/Api/Include/HashMap.h | 9 +- Coplt.Graphics.Native/Api/Include/Uninit.h | 13 +- Coplt.Graphics.Native/D3d12/Src/Buffer.cc | 5 + Coplt.Graphics.Native/D3d12/Src/Buffer.h | 4 + Coplt.Graphics.Native/D3d12/Src/Image.cc | 5 + Coplt.Graphics.Native/D3d12/Src/Image.h | 4 + Coplt.Graphics.Native/D3d12/Src/Record.cc | 58 ++++- Coplt.Graphics.Native/D3d12/Src/Record.h | 1 + Examples/HelloTriangle/Example.cs | 2 +- Examples/HelloTriangleVertex/Example.cs | 158 ++++++------- 19 files changed, 601 insertions(+), 191 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 6d943a8..ff7ad94 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -1,6 +1,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Coplt.Graphics.Native; +using Coplt.Graphics.Utilities; namespace Coplt.Graphics.Core; @@ -95,15 +96,75 @@ internal void AssertEndOrCanEnd() #endregion + #region Alloc Upload + + /// + /// 返回的 Span 只能写入 + /// + public FSlice AllocUploadMemory(uint Size, out UploadLoc2 loc, uint Align = 4) + { + if (Align > 1) Size += Align - 1; + ref var upload_buffers = ref Data.Context->m_upload_buffer; + for (nuint i = 0; i < upload_buffers.LongLength; i++) + { + ref var block = ref upload_buffers[i]; + if (block.cur_offset + Size < block.size) + { + var offset = block.cur_offset.Aligned(Align); + var r = new FSlice(block.mapped_ptr, (nuint)block.size).Slice((nuint)offset); + loc = new UploadLoc2(Data.Id, Data.Version, i, offset, Size); + block.cur_offset += Size; + return r; + } + } + Data.Context->GrowUploadBuffer(Size).TryThrow(); + upload_buffers = ref Data.Context->m_upload_buffer; + { + var i = upload_buffers.LongLength - 1; + ref var block = ref upload_buffers[i]; + if (block.cur_offset + Size >= block.size) throw new OutOfMemoryException(); + var offset = block.cur_offset.Aligned(Align); + var r = new FSlice(block.mapped_ptr, (nuint)block.size).Slice((nuint)offset); + loc = new UploadLoc2(Data.Id, Data.Version, i, offset, Size); + block.cur_offset += Size; + return r; + } + } + + public UploadLoc2 WriteToUpload(ReadOnlySpan Data, uint Align = 4) + { + Data.CopyTo(AllocUploadMemory((uint)Data.Length, out var loc, Align)); + return loc; + } + + /// + /// 分配用于上传纹理的 256 对齐的内存 + /// + public ImageUploadBufferMemory2 AllocImageUploadMemory2D(uint PixelSize, uint Width, uint Height, uint Length = 1) => + AllocImageUploadMemory2D(PixelSize, Width, Height, Length, out _); + + /// + /// 分配用于上传纹理的 256 对齐的内存 + /// + public ImageUploadBufferMemory2 AllocImageUploadMemory2D(uint PixelSize, uint Width, uint Height, uint Length, out UploadLoc2 loc) + { + if (PixelSize < 1 || Width < 1 || Height < 1 || Length < 1) throw new ArgumentOutOfRangeException(); + var row_stride = (PixelSize * Width).Aligned(256); + var row_count = Height * Length; + var buffer_size = row_stride * row_count + 256u; + var slice = AllocUploadMemory(buffer_size, out loc, 256u); + return new ImageUploadBufferMemory2(slice, row_stride, row_count, Length, Height, loc); + } + + #endregion + #region Payload #region AddResource internal FCmdResRef AddResource(IGpuResource resource) { - if (resource.Isolate != Isolate) - throw new ArgumentException($"Resource {resource} does not belong to isolate {Isolate}"); - ref var slot = ref CollectionsMarshal.GetValueRefOrAddDefault(m_resources, m_resources, out var exists); + ref var slot = ref CollectionsMarshal.GetValueRefOrAddDefault(m_resources, resource, out var exists); if (!exists) { var len = Data.Resources.LongLength; @@ -181,6 +242,7 @@ internal uint AddString(ReadOnlySpan str) public void Label(string Label, Color? Color = null) { + AssertNotEnded(); if (!DebugEnabled) return; var cmd = new FCmdLabel { @@ -202,6 +264,7 @@ public void Label(string Label, Color? Color = null) public void Label(ReadOnlySpan Label, Color? Color = null) { + AssertNotEnded(); if (!DebugEnabled) return; var cmd = new FCmdLabel { @@ -227,6 +290,7 @@ public void Label(ReadOnlySpan Label, Color? Color = null) public DebugScope2 Scope(string Name, Color? Color = null) { + AssertNotEnded(); if (!DebugEnabled) return new(this); var cmd = new FCmdBeginScope { @@ -250,6 +314,7 @@ public DebugScope2 Scope(string Name, Color? Color = null) public DebugScope2 Scope(ReadOnlySpan Name, Color? Color = null) { + AssertNotEnded(); if (!DebugEnabled) return new(this); var cmd = new FCmdBeginScope { @@ -314,6 +379,121 @@ public void ClearColor(IRtv Image, Color Color, ReadOnlySpan Rects = defa #endregion + #region BufferCopy + + public void Copy( + GpuBuffer Dst, + GpuBuffer Src, + ulong DstOffset = 0, + ulong SrcOffset = 0, + ulong Size = ulong.MaxValue + ) + { + AssertNotEnded(); + Dst.AssertSameIsolate(Isolate); + Src.AssertSameIsolate(Isolate); + if (Size != ulong.MaxValue) + { + if (DstOffset + Size > Dst.Size) throw new ArgumentException("The copy range exceeds the buffer range"); + if (SrcOffset + Size > Src.Size) throw new ArgumentException("The copy range exceeds the buffer range"); + } + else if (Dst == Src || Dst.Size != Src.Size) Size = Math.Min(Dst.Size, Src.Size); + var cmd = new FCmdBufferCopy + { + Base = { Type = FCmdType.BufferCopy }, + RangeIndex = (uint)Data.PayloadBufferCopyRange.LongLength, + Dst = { Buffer = AddResource(Dst) }, + DstType = FBufferRefType2.Buffer, + Src = { Buffer = AddResource(Src) }, + SrcType = FBufferRefType2.Buffer, + }; + Data.PayloadBufferCopyRange.Add( + new() + { + Size = Size, + DstOffset = DstOffset, + SrcOffset = SrcOffset, + } + ); + Data.Commands.Add(new() { BufferCopy = cmd }); + } + + #endregion + + #region BufferUpload + + public void Upload( + GpuBuffer Dst, + ReadOnlySpan Data, + ulong DstOffset = 0 + ) where T : unmanaged => Upload(Dst, MemoryMarshal.AsBytes(Data), DstOffset); + + public void Upload( + GpuBuffer Dst, + ReadOnlySpan Data, + ulong DstOffset = 0 + ) + { + AssertNotEnded(); + // Dst.AssertSameIsolate(Isolate); // todo + if (Data.Length == 0) return; + var Size = Math.Min(Dst.Size, (uint)Data.Length); + var src = WriteToUpload(Data); + var cmd = new FCmdBufferCopy + { + Base = { Type = FCmdType.BufferCopy }, + RangeIndex = (uint)this.Data.PayloadBufferCopyRange.LongLength, + Dst = { Buffer = AddResource(Dst) }, + DstType = FBufferRefType2.Buffer, + Src = { Upload = src }, + SrcType = FBufferRefType2.Upload, + }; + this.Data.PayloadBufferCopyRange.Add( + new() + { + Size = Size, + DstOffset = DstOffset, + SrcOffset = src.Offset, + } + ); + this.Data.Commands.Add(new() { BufferCopy = cmd }); + } + + public void Upload( + GpuBuffer Dst, + UploadLoc2 Loc, + ulong DstOffset = 0 + ) + { + AssertNotEnded(); + // Dst.AssertSameIsolate(Isolate); // todo + if (Loc.RecordId != Data.Id) + throw new ArgumentException("Cannot use UploadLoc different GpuRecord"); + if (Loc.RecordVersion != Data.Version) + throw new ArgumentException("An attempt was made to use an expired upload location"); + var Size = Math.Min(Dst.Size, Loc.Size); + var cmd = new FCmdBufferCopy + { + Base = { Type = FCmdType.BufferCopy }, + RangeIndex = (uint)Data.PayloadBufferCopyRange.LongLength, + Dst = { Buffer = AddResource(Dst) }, + DstType = FBufferRefType2.Buffer, + Src = { Upload = Loc }, + SrcType = FBufferRefType2.Upload, + }; + Data.PayloadBufferCopyRange.Add( + new() + { + Size = Size, + DstOffset = DstOffset, + SrcOffset = Loc.Offset, + } + ); + Data.Commands.Add(new() { BufferCopy = cmd }); + } + + #endregion + #region Render public RenderScope2 Render( @@ -332,6 +512,8 @@ public RenderScope2 Render( string? Name = null, ReadOnlySpan Name8 = default ) { + AssertNotEnded(); + #region Check Nested if (m_in_render_or_compute_scope) throw new InvalidOperationException("Cannot nest Render or Compute scopes"); diff --git a/Coplt.Graphics.Core/Core/ImageUploadBufferMemory.cs b/Coplt.Graphics.Core/Core/ImageUploadBufferMemory.cs index 06ddbdf..f704811 100644 --- a/Coplt.Graphics.Core/Core/ImageUploadBufferMemory.cs +++ b/Coplt.Graphics.Core/Core/ImageUploadBufferMemory.cs @@ -21,3 +21,23 @@ public FSlice this[uint index] } } } + +public readonly struct ImageUploadBufferMemory2(FSlice Slice, uint RowStride, uint RowCount, uint ImageCount, uint RowsPerImage, UploadLoc2 Loc) +{ + public readonly FSlice Slice = Slice; + public readonly uint RowStride = RowStride; + public readonly uint RowCount = RowCount; + public readonly uint ImageCount = ImageCount; + public readonly uint RowsPerImage = RowsPerImage; + public readonly UploadLoc2 Loc = Loc; + + public FSlice this[uint index] + { + get + { + if (index >= RowCount) throw new IndexOutOfRangeException(); + var offset = RowStride * index; + return Slice.Slice(offset, RowStride); + } + } +} diff --git a/Coplt.Graphics.Core/Core/UploadLoc.cs b/Coplt.Graphics.Core/Core/UploadLoc.cs index 31aac91..c9e3bfb 100644 --- a/Coplt.Graphics.Core/Core/UploadLoc.cs +++ b/Coplt.Graphics.Core/Core/UploadLoc.cs @@ -1,3 +1,4 @@ namespace Coplt.Graphics.Core; public record struct UploadLoc(nuint Index, ulong Offset, uint Size, SubmitId SubmitId); +public record struct UploadLoc2(ulong RecordId, ulong RecordVersion, nuint Index, ulong Offset, uint Size); diff --git a/Coplt.Graphics.Core/Native/FUploadLoc.cs b/Coplt.Graphics.Core/Native/FUploadLoc.cs index 04c29f9..321deaf 100644 --- a/Coplt.Graphics.Core/Native/FUploadLoc.cs +++ b/Coplt.Graphics.Core/Native/FUploadLoc.cs @@ -8,6 +8,12 @@ public FUploadLoc(in UploadLoc loc) { Index = (uint)loc.Index; } + + public FUploadLoc(in UploadLoc2 loc) + { + Index = (uint)loc.Index; + } public static implicit operator FUploadLoc(in UploadLoc loc) => new(loc); + public static implicit operator FUploadLoc(in UploadLoc2 loc) => new(loc); } diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 62f2c11..58366c6 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -89,6 +89,66 @@ public enum FResolveMode : byte Average, } + public partial struct FBufferCopyRange + { + [NativeTypeName("Coplt::u64")] + public ulong Size; + + [NativeTypeName("Coplt::u64")] + public ulong DstOffset; + + [NativeTypeName("Coplt::u64")] + public ulong SrcOffset; + } + + public partial struct FBufferImageCopyRange + { + [NativeTypeName("Coplt::u64")] + public ulong BufferOffset; + + [NativeTypeName("Coplt::u32")] + public uint BytesPerRow; + + [NativeTypeName("Coplt::u32")] + public uint RowsPerImage; + + [NativeTypeName("u32[3]")] + public _ImageOffset_e__FixedBuffer ImageOffset; + + [NativeTypeName("u32[3]")] + public _ImageExtent_e__FixedBuffer ImageExtent; + + [NativeTypeName("Coplt::u32")] + public uint ImageIndex; + + [NativeTypeName("Coplt::u32")] + public uint ImageCount; + + [NativeTypeName("Coplt::u16")] + public ushort MipLevel; + + [NativeTypeName("Coplt::FImagePlane")] + public FImagePlane Plane; + + [InlineArray(3)] + public partial struct _ImageOffset_e__FixedBuffer + { + public uint e0; + } + + [InlineArray(3)] + public partial struct _ImageExtent_e__FixedBuffer + { + public uint e0; + } + } + + public partial struct FUploadLoc + { + [NativeTypeName("Coplt::u32")] + public uint Index; + } + public unsafe partial struct FObject : FObject.Interface { public void** lpVtbl; @@ -1560,6 +1620,12 @@ public enum FGpuRecordMode : byte public unsafe partial struct FGpuRecordData { + [NativeTypeName("Coplt::u64")] + public ulong Id; + + [NativeTypeName("Coplt::u64")] + public ulong Version; + [NativeTypeName("Coplt::FRecordContext *")] public FRecordContext* Context; @@ -1575,6 +1641,8 @@ public unsafe partial struct FGpuRecordData public FList PayloadResolveInfo; + public FList PayloadBufferCopyRange; + [NativeTypeName("FList")] public FList Blob; @@ -1596,6 +1664,7 @@ public enum FCmdType : uint PreparePresent, ClearColor, ClearDepthStencil, + BufferCopy, Render, Compute, SetPipeline, @@ -1616,7 +1685,7 @@ public enum FCmdResType : byte public unsafe partial struct FCmdRes { - [NativeTypeName("__AnonymousRecord_Cmd_L67_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L69_C9")] public _Anonymous_e__Union Anonymous; [NativeTypeName("Coplt::FCmdResType")] @@ -1786,6 +1855,25 @@ public partial struct _RtvStoreOp_e__FixedBuffer } } + [StructLayout(LayoutKind.Explicit)] + public partial struct FBufferRef2 + { + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Buffer; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FUploadLoc")] + public FUploadLoc Upload; + } + + [NativeTypeName("Coplt::u8")] + public enum FBufferRefType2 : byte + { + Buffer = 0, + Upload, + } + public partial struct FCmdBase { [NativeTypeName("Coplt::FCmdType")] @@ -1909,6 +1997,48 @@ public partial struct FCmdClearDepthStencil public FDepthStencilClearFlags Clear; } + [NativeTypeName("struct FCmdBufferCopy : Coplt::FCmdBase")] + public partial struct FCmdBufferCopy + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint RangeIndex; + + [NativeTypeName("Coplt::FBufferRef2")] + public FBufferRef2 Dst; + + [NativeTypeName("Coplt::FBufferRef2")] + public FBufferRef2 Src; + + [NativeTypeName("Coplt::FBufferRefType2")] + public FBufferRefType2 DstType; + + [NativeTypeName("Coplt::FBufferRefType2")] + public FBufferRefType2 SrcType; + } + + [NativeTypeName("struct FCndBufferImageCopy : Coplt::FCmdBase")] + public partial struct FCndBufferImageCopy + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint RangeIndex; + + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Image; + + [NativeTypeName("Coplt::FBufferRef2")] + public FBufferRef2 Buffer; + + [NativeTypeName("Coplt::FBufferRefType2")] + public FBufferRefType2 BufferType; + + [NativeTypeName("Coplt::b8")] + public B8 ImageToBuffer; + } + [NativeTypeName("struct FCmdRender : Coplt::FCmdBase")] public partial struct FCmdRender { @@ -2007,7 +2137,7 @@ public partial struct FCmdDraw public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L281_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L320_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -2080,6 +2210,16 @@ public ref FCmdClearDepthStencil ClearDepthStencil } } + [UnscopedRef] + public ref FCmdBufferCopy BufferCopy + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.BufferCopy; + } + } + [UnscopedRef] public ref FCmdRender Render { @@ -2191,6 +2331,10 @@ public partial struct _Anonymous_e__Union [NativeTypeName("Coplt::FCmdClearDepthStencil")] public FCmdClearDepthStencil ClearDepthStencil; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdBufferCopy")] + public FCmdBufferCopy BufferCopy; + [FieldOffset(0)] [NativeTypeName("Coplt::FCmdRender")] public FCmdRender Render; @@ -4984,12 +5128,6 @@ public partial struct _Anonymous_e__Union } } - public partial struct FUploadLoc - { - [NativeTypeName("Coplt::u32")] - public uint Index; - } - [StructLayout(LayoutKind.Explicit)] public partial struct FBufferRef { @@ -5009,60 +5147,6 @@ public enum FBufferRefType : byte Upload, } - public partial struct FBufferCopyRange - { - [NativeTypeName("Coplt::u64")] - public ulong Size; - - [NativeTypeName("Coplt::u64")] - public ulong DstOffset; - - [NativeTypeName("Coplt::u64")] - public ulong SrcOffset; - } - - public partial struct FBufferImageCopyRange - { - [NativeTypeName("Coplt::u64")] - public ulong BufferOffset; - - [NativeTypeName("Coplt::u32")] - public uint BytesPerRow; - - [NativeTypeName("Coplt::u32")] - public uint RowsPerImage; - - [NativeTypeName("u32[3]")] - public _ImageOffset_e__FixedBuffer ImageOffset; - - [NativeTypeName("u32[3]")] - public _ImageExtent_e__FixedBuffer ImageExtent; - - [NativeTypeName("Coplt::u32")] - public uint ImageIndex; - - [NativeTypeName("Coplt::u32")] - public uint ImageCount; - - [NativeTypeName("Coplt::u16")] - public ushort MipLevel; - - [NativeTypeName("Coplt::FImagePlane")] - public FImagePlane Plane; - - [InlineArray(3)] - public partial struct _ImageOffset_e__FixedBuffer - { - public uint e0; - } - - [InlineArray(3)] - public partial struct _ImageExtent_e__FixedBuffer - { - public uint e0; - } - } - public partial struct FResolveInfo { [NativeTypeName("Coplt::FResourceRef")] @@ -5557,7 +5641,7 @@ public partial struct FCommandSyncBinding public partial struct FCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L479_C9")] + [NativeTypeName("__AnonymousRecord_Command_L452_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -5783,7 +5867,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FRenderCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L510_C9")] + [NativeTypeName("__AnonymousRecord_Command_L483_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -5967,7 +6051,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FComputeCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L535_C9")] + [NativeTypeName("__AnonymousRecord_Command_L508_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index 6346f91..6324142 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -21,6 +21,8 @@ namespace Coplt ClearColor, ClearDepthStencil, + BufferCopy, + Render, Compute, @@ -152,6 +154,20 @@ namespace Coplt b8 HasUavWrites{}; }; + union FBufferRef2 + { + FCmdResRef Buffer; + FUploadLoc Upload; + }; + + enum class FBufferRefType2 : u8 + { + // GpuBuffer 对象资源引用 + Buffer = 0, + // 当前帧上下文中第几个上传缓冲区 + Upload, + }; + //////////////////////////////////////////////////////////////////////////////////////////////////// struct FCmdBase @@ -217,7 +233,30 @@ namespace Coplt }; //////////////////////////////////////////////////////////////////////////////////////////////////// - /// + + struct FCmdBufferCopy : FCmdBase + { + // 类型为 FBufferCopyRange + u32 RangeIndex{}; + FBufferRef2 Dst{}; + FBufferRef2 Src{}; + FBufferRefType2 DstType{}; + FBufferRefType2 SrcType{}; + }; + + struct FCndBufferImageCopy : FCmdBase + { + // 类型为 FBufferImageCopyRange + u32 RangeIndex{}; + FCmdResRef Image; + FBufferRef2 Buffer{}; + FBufferRefType2 BufferType{}; + // false 为 Buffer To Image + b8 ImageToBuffer{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + struct FCmdRender : FCmdBase { // 类型为 FRenderInfo @@ -291,6 +330,8 @@ namespace Coplt FCmdClearColor ClearColor; FCmdClearDepthStencil ClearDepthStencil; + FCmdBufferCopy BufferCopy; + FCmdRender Render; FCmdCompute Compute; diff --git a/Coplt.Graphics.Native/Api/FFI/Command.h b/Coplt.Graphics.Native/Api/FFI/Command.h index 99e317e..b2c45a8 100644 --- a/Coplt.Graphics.Native/Api/FFI/Command.h +++ b/Coplt.Graphics.Native/Api/FFI/Command.h @@ -175,11 +175,6 @@ namespace Coplt }; }; - struct FUploadLoc - { - u32 Index{}; - }; - union FBufferRef { FResourceRef Buffer; @@ -194,28 +189,6 @@ namespace Coplt Upload, }; - struct FBufferCopyRange - { - // Size 为 u64::max 时复制整个 - u64 Size{}; - u64 DstOffset{}; - u64 SrcOffset{}; - }; - - struct FBufferImageCopyRange - { - u64 BufferOffset{}; - // 必须是 256 的倍数 - u32 BytesPerRow{}; - u32 RowsPerImage{}; - u32 ImageOffset[3]{}; - u32 ImageExtent[3]{}; - u32 ImageIndex{}; - u32 ImageCount{}; - u16 MipLevel{}; - FImagePlane Plane{}; - }; - struct FResolveInfo { FResourceRef Src{}; diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index e794056..fa02fe2 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -26,6 +26,8 @@ namespace Coplt // 里面的 FList 的 T* 生命周期由 c# 部分保证 struct FGpuRecordData { + u64 Id{}; + u64 Version{}; FRecordContext* Context{}; FList Commands; // 需要保证不重复,c# 部分需要使用 HashMap 去重 @@ -34,6 +36,7 @@ namespace Coplt FList PayloadViewport; FList PayloadRenderInfo; FList PayloadResolveInfo; + FList PayloadBufferCopyRange; FList Blob; b8 Ended{}; FGpuRecordMode Mode{}; @@ -41,7 +44,7 @@ namespace Coplt #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) : Commands(allocator), Resources(allocator), PayloadRect(allocator), PayloadViewport(allocator), - PayloadRenderInfo(allocator), PayloadResolveInfo(allocator), Blob(allocator) + PayloadRenderInfo(allocator), PayloadResolveInfo(allocator), PayloadBufferCopyRange(allocator), Blob(allocator) { } @@ -53,6 +56,7 @@ namespace Coplt PayloadViewport.Clear(); PayloadRenderInfo.Clear(); PayloadResolveInfo.Clear(); + PayloadBufferCopyRange.Clear(); Blob.Clear(); } #endif diff --git a/Coplt.Graphics.Native/Api/FFI/Structs.h b/Coplt.Graphics.Native/Api/FFI/Structs.h index 2ce81c0..10d7b56 100644 --- a/Coplt.Graphics.Native/Api/FFI/Structs.h +++ b/Coplt.Graphics.Native/Api/FFI/Structs.h @@ -1,6 +1,7 @@ #pragma once #include "Common.h" +#include "GraphicsFormat.h" namespace Coplt { @@ -58,4 +59,31 @@ namespace Coplt Max, Average, }; + + struct FBufferCopyRange + { + // Size 为 u64::max 时复制整个 + u64 Size{}; + u64 DstOffset{}; + u64 SrcOffset{}; + }; + + struct FBufferImageCopyRange + { + u64 BufferOffset{}; + // 必须是 256 的倍数 + u32 BytesPerRow{}; + u32 RowsPerImage{}; + u32 ImageOffset[3]{}; + u32 ImageExtent[3]{}; + u32 ImageIndex{}; + u32 ImageCount{}; + u16 MipLevel{}; + FImagePlane Plane{}; + }; + + struct FUploadLoc + { + u32 Index{}; + }; } diff --git a/Coplt.Graphics.Native/Api/Include/HashMap.h b/Coplt.Graphics.Native/Api/Include/HashMap.h index 423741f..5c1c2c8 100644 --- a/Coplt.Graphics.Native/Api/Include/HashMap.h +++ b/Coplt.Graphics.Native/Api/Include/HashMap.h @@ -278,10 +278,8 @@ namespace Coplt auto& entry = m_p_entries[index]; slot.hash_code() = hash_code; slot.next = *bucket - 1; - Uninit u_key(entry.first); - Uninit u_value(entry.second); - create_key(u_key); - create_value(u_value); + init_scope(entry.first, create_key); + init_scope(entry.second, create_value); *bucket = index + 1; if (out_entry) *out_entry = std::addressof(entry); @@ -1226,8 +1224,7 @@ namespace Coplt 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); + init_scope(slot_key, create_key); *bucket = index + 1; return true; diff --git a/Coplt.Graphics.Native/Api/Include/Uninit.h b/Coplt.Graphics.Native/Api/Include/Uninit.h index c441827..253d1c4 100644 --- a/Coplt.Graphics.Native/Api/Include/Uninit.h +++ b/Coplt.Graphics.Native/Api/Include/Uninit.h @@ -1,4 +1,5 @@ #pragma once +#include #include namespace Coplt @@ -23,9 +24,9 @@ namespace Coplt Uninit(Uninit&& r) = delete; Uninit(const Uninit& r) = delete; - ~Uninit() + void AssertInitialized() const { - if (!m_initialized) throw std::exception("Uninitialized"); + if (!m_initialized) throw cpptrace::logic_error("Uninitialized"); } T* unsafe_put() @@ -123,4 +124,12 @@ namespace Coplt return operator=(p); } }; + + template&> F> + void init_scope(T& v, F& f) + { + Uninit u(v); + f(u); + u.AssertInitialized(); + } } diff --git a/Coplt.Graphics.Native/D3d12/Src/Buffer.cc b/Coplt.Graphics.Native/D3d12/Src/Buffer.cc index 28f8edf..a180dbd 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Buffer.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Buffer.cc @@ -80,6 +80,11 @@ NonNull D3d12GpuBuffer::Data() return this; } +NonNull D3d12GpuBuffer::State() +{ + return &m_layout_state; +} + void* D3d12GpuBuffer::GetRawResourcePtr() noexcept { return GetResourcePtr(); diff --git a/Coplt.Graphics.Native/D3d12/Src/Buffer.h b/Coplt.Graphics.Native/D3d12/Src/Buffer.h index 0a049f1..4497dd7 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Buffer.h +++ b/Coplt.Graphics.Native/D3d12/Src/Buffer.h @@ -9,6 +9,7 @@ #include "Resource.h" #include "../../Api/Include/GpuObject.h" #include "../../Api/Include/Ptr.h" +#include "../Include/ResState.h" namespace Coplt { @@ -16,10 +17,12 @@ namespace Coplt { virtual NonNull Data() = 0; virtual NonNull GetResourcePtr() = 0; + virtual NonNull State() = 0; }; struct D3d12GpuBuffer final : GpuObject, FGpuBufferData { + LayoutState m_layout_state{}; Rc m_device{}; Rc m_name{}; ComPtr m_allocator{}; @@ -35,6 +38,7 @@ namespace Coplt FGpuResourceData* GpuResourceData() noexcept override; FGpuBufferData* GpuBufferData() noexcept override; NonNull Data() override; + NonNull State() override; void* GetRawResourcePtr() noexcept override; NonNull GetResourcePtr() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Image.cc b/Coplt.Graphics.Native/D3d12/Src/Image.cc index 95bfe92..da27e88 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Image.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Image.cc @@ -128,6 +128,11 @@ NonNull D3d12GpuImage::Data() return this; } +NonNull D3d12GpuImage::State() +{ + return &m_layout_state; +} + void* D3d12GpuImage::GetRawResourcePtr() noexcept { return GetResourcePtr(); diff --git a/Coplt.Graphics.Native/D3d12/Src/Image.h b/Coplt.Graphics.Native/D3d12/Src/Image.h index 50b7fd4..5a037b2 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Image.h +++ b/Coplt.Graphics.Native/D3d12/Src/Image.h @@ -10,6 +10,7 @@ #include "Resource.h" #include "../../Api/Include/GpuObject.h" #include "../../Api/Include/Ptr.h" +#include "../Include/ResState.h" namespace Coplt { @@ -17,10 +18,12 @@ namespace Coplt { virtual NonNull Data() = 0; virtual NonNull GetResourcePtr() = 0; + virtual NonNull State() = 0; }; struct D3d12GpuImage final : GpuObject, FGpuImageData { + LayoutState m_layout_state{}; Rc m_device{}; Rc m_name{}; ComPtr m_allocator{}; @@ -35,6 +38,7 @@ namespace Coplt FGpuResourceData* GpuResourceData() noexcept override; FGpuImageData* GpuImageData() noexcept override; NonNull Data() override; + NonNull State() override; void* GetRawResourcePtr() noexcept override; NonNull GetResourcePtr() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 0fa1a9e..8d47c13 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -47,7 +47,7 @@ void D3d12GpuRecord::PipelineContext::SetPipeline(NonNull pipel D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) : FGpuRecordData(isolate->m_device->m_instance->m_allocator.get()), m_device(isolate->m_device) { - m_isolate_id = isolate->m_object_id; + Id = m_isolate_id = isolate->m_object_id; m_record_id = isolate->m_record_inc++; m_context = new D3d12RecordContext(isolate); m_storage = new D3d12RecordStorage(isolate, m_context); @@ -134,6 +134,7 @@ void D3d12GpuRecord::DoEnd() ReadyResource(); Interpret(); Ended = true; + Version++; } FCmdRes& D3d12GpuRecord::GetRes(const FCmdResRef& ref) @@ -192,6 +193,9 @@ void D3d12GpuRecord::Interpret() case FCmdType::ClearDepthStencil: Interpret_ClearDepthStencil(i, command.ClearDepthStencil); break; + case FCmdType::BufferCopy: + Interpret_BufferCopy(i, command.BufferCopy); + break; case FCmdType::Render: Interpret_Render(i, command.Render); break; @@ -299,6 +303,49 @@ void D3d12GpuRecord::Interpret_ClearDepthStencil(const u32 i, const FCmdClearDep ); } +void D3d12GpuRecord::Interpret_BufferCopy(u32 i, const FCmdBufferCopy& cmd) +{ + if (m_state != InterpretState::Main) + COPLT_THROW("Cannot use BufferCopy in sub scope"); + const auto& range = PayloadBufferCopyRange[cmd.RangeIndex]; + if (cmd.SrcType == FBufferRefType2::Buffer && cmd.DstType == FBufferRefType2::Buffer) + { + m_barrier_recorder->OnUse(cmd.Dst.Buffer, ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); + m_barrier_recorder->OnUse(cmd.Src.Buffer, ResAccess::CopySourceRead, ResUsage::Common, ResLayout::Common); + m_barrier_recorder->OnCmd(); + const auto dst = GetResource(GetRes(cmd.Dst.Buffer)); + const auto src = GetResource(GetRes(cmd.Src.Buffer)); + if (range.Size == std::numeric_limits::max()) + { + CurList()->g0->CopyResource(dst, src); + } + else + { + CurList()->g0->CopyBufferRegion(dst, range.DstOffset, src, range.SrcOffset, range.Size); + } + } + else if (cmd.SrcType == FBufferRefType2::Upload && cmd.DstType == FBufferRefType2::Buffer) + { + m_barrier_recorder->OnUse(cmd.Dst.Buffer, ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); + m_barrier_recorder->OnCmd(); + const auto dst = GetResource(GetRes(cmd.Dst.Buffer)); + if (cmd.Src.Upload.Index >= m_context->m_upload_buffers.size()) + COPLT_THROW_FMT("Index out of bounds at command {}", i); + const auto& src_obj = m_context->m_upload_buffers[cmd.Src.Upload.Index]; + if (range.SrcOffset + range.Size >= src_obj.m_size) + COPLT_THROW_FMT("Size out of range at command {}", i); + const auto src = src_obj.m_resource.m_resource.Get(); + CurList()->g0->CopyBufferRegion(dst, range.DstOffset, src, range.SrcOffset, range.Size); + } + else + { + COPLT_THROW_FMT( + "Unsupported copy combination {{ SrcType = {} DstType = {} }} at command {}", + static_cast(cmd.SrcType), static_cast(cmd.DstType), i + ); + } +} + void D3d12GpuRecord::Interpret_Render(const u32 i, const FCmdRender& cmd) { if (m_state != InterpretState::Main) @@ -307,10 +354,9 @@ void D3d12GpuRecord::Interpret_Render(const u32 i, const FCmdRender& cmd) COPLT_THROW("Render can only be used in Direct mode"); m_state = InterpretState::Render; m_cur_render = RenderState{.StartIndex = i, .Cmd = cmd}; - const auto& list = CurList(); const auto& info = PayloadRenderInfo[cmd.InfoIndex]; auto num_rtv = std::min(info.NumRtv, 8u); - if (list->g4) + if (CurList()->g4) { D3D12_RENDER_PASS_RENDER_TARGET_DESC rts[num_rtv]; D3D12_RENDER_PASS_DEPTH_STENCIL_DESC ds[info.Dsv ? 1 : 0]; @@ -384,7 +430,7 @@ void D3d12GpuRecord::Interpret_Render(const u32 i, const FCmdRender& cmd) D3D12_RENDER_PASS_FLAGS flags = D3D12_RENDER_PASS_FLAG_NONE; if (info.HasUavWrites) flags |= D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES; m_barrier_recorder->OnCmd(); - list->g4->BeginRenderPass(info.NumRtv, rts, info.Dsv ? ds : nullptr, flags); + CurList()->g4->BeginRenderPass(info.NumRtv, rts, info.Dsv ? ds : nullptr, flags); } else { @@ -565,12 +611,12 @@ NonNull Coplt::GetState(const FCmdRes& res) case FCmdResType::Image: { const NonNull obj = res.Image->QueryInterface(); - COPLT_THROW("TODO"); + return obj->State(); } case FCmdResType::Buffer: { const NonNull obj = res.Image->QueryInterface(); - COPLT_THROW("TODO"); + return obj->State(); } case FCmdResType::Output: { diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index bb6f0f2..3491475 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -97,6 +97,7 @@ namespace Coplt void Interpret_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const; void Interpret_ClearColor(u32 i, const FCmdClearColor& cmd); void Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); + void Interpret_BufferCopy(u32 i, const FCmdBufferCopy& cmd); void Interpret_Render(u32 i, const FCmdRender& cmd); void Interpret_RenderEnd(u32 i, const FCmdRender& cmd); void Interpret_SetPipeline(u32 i, const FCmdSetPipeline& cmd); diff --git a/Examples/HelloTriangle/Example.cs b/Examples/HelloTriangle/Example.cs index b073656..ca73c3c 100644 --- a/Examples/HelloTriangle/Example.cs +++ b/Examples/HelloTriangle/Example.cs @@ -32,7 +32,7 @@ protected override async Task LoadResources(GpuRecord cmd) } protected override void Render(GpuRecord cmd, Time time) { - using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))], Name: "Hello Triangle"); + using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))], Name: Name); render.Draw(Pipeline, 3); } } diff --git a/Examples/HelloTriangleVertex/Example.cs b/Examples/HelloTriangleVertex/Example.cs index 7ed5bf6..6c97c2a 100644 --- a/Examples/HelloTriangleVertex/Example.cs +++ b/Examples/HelloTriangleVertex/Example.cs @@ -13,83 +13,83 @@ public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handl private GpuBuffer UvBuffer = null!; public override string Name => "Hello Triangle Vertex"; - // protected override async Task LoadResources(CommandList cmd) - // { - // var SlotId_Position = Graphics.GetSlotId("Position"); - // var SlotId_Color = Graphics.GetSlotId("Color"); - // var SlotId_Uv = Graphics.GetSlotId("Uv"); - // var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); - // Shader = Device.CreateShader( - // modules, null, - // Device.CreateShaderInputLayout( - // [new(SlotId_Position), new(SlotId_Color), new(SlotId_Uv)] - // ) - // ); - // MeshLayout = Device.CreateMeshLayout( - // [ - // new(Stride: sizeof(float) * 7), - // new(Stride: sizeof(float) * 2), - // ], - // [ - // new(SlotId_Position, GraphicsFormat.R32G32B32_Float), - // new(SlotId_Color, GraphicsFormat.R32G32B32A32_Float, Offset: sizeof(float) * 3), - // new(SlotId_Uv, GraphicsFormat.R32G32_Float, BufferIndex: 1), - // ], - // Name: "Mesh" - // ); - // Pipeline = Device.CreateGraphicsShaderPipeline( - // Shader, new() - // { - // DsvFormat = GraphicsFormat.Unknown, - // BlendState = - // { - // Rt0 = - // { - // Src = BlendType.SrcAlpha, - // Dst = BlendType.InvSrcAlpha, - // Op = BlendOp.Add, - // } - // } - // }, MeshLayout, Name: Name - // ); - // PositionColorBuffer = Device.CreateBuffer( - // new() - // { - // Purpose = ResourcePurpose.VertexBuffer, - // Size = sizeof(float) * 4 * 6, - // }, "Position and Color" - // ); - // UvBuffer = Device.CreateBuffer( - // new() - // { - // Purpose = ResourcePurpose.VertexBuffer, - // Size = sizeof(float) * 2 * 3, - // }, "Uv" - // ); - // cmd.Upload( - // PositionColorBuffer, [ - // /* position */ 0.0f, 0.5f * 1.7f, 0f, /* color */ 0.71f, 0.22f, 0.21f, 1f, - // /* position */ 0.5f, -0.5f * 1.7f, 0f, /* color */ 0.34f, 0.64f, 0.31f, 1f, - // /* position */ -0.5f, -0.5f * 1.7f, 0f, /* color */ 0.36f, 0.42f, 0.92f, 1f, - // ] - // ); - // cmd.Upload( - // UvBuffer, [ - // 0.0f, 0.0f, - // -1.0f, 2.0f, - // 1.0f, 2.0f, - // ] - // ); - // } - // protected override void Render(CommandList cmd, Time time) - // { - // using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); - // render.SetMeshBuffers( - // MeshLayout, [ - // new(0, PositionColorBuffer), - // new(1, UvBuffer), - // ] - // ); - // render.Draw(Pipeline, 3); - // } + protected override async Task LoadResources(GpuRecord cmd) + { + var SlotId_Position = Graphics.GetSlotId("Position"); + var SlotId_Color = Graphics.GetSlotId("Color"); + var SlotId_Uv = Graphics.GetSlotId("Uv"); + var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); + Shader = Device.CreateShader( + modules, null, + Device.CreateShaderInputLayout( + [new(SlotId_Position), new(SlotId_Color), new(SlotId_Uv)] + ) + ); + MeshLayout = Device.CreateMeshLayout( + [ + new(Stride: sizeof(float) * 7), + new(Stride: sizeof(float) * 2), + ], + [ + new(SlotId_Position, GraphicsFormat.R32G32B32_Float), + new(SlotId_Color, GraphicsFormat.R32G32B32A32_Float, Offset: sizeof(float) * 3), + new(SlotId_Uv, GraphicsFormat.R32G32_Float, BufferIndex: 1), + ], + Name: "Mesh" + ); + Pipeline = Device.CreateGraphicsShaderPipeline( + Shader, new() + { + DsvFormat = GraphicsFormat.Unknown, + BlendState = + { + Rt0 = + { + Src = BlendType.SrcAlpha, + Dst = BlendType.InvSrcAlpha, + Op = BlendOp.Add, + } + } + }, MeshLayout, Name: Name + ); + PositionColorBuffer = Device.CreateBuffer( + new() + { + Purpose = ResourcePurpose.VertexBuffer, + Size = sizeof(float) * 4 * 6, + }, "Position and Color" + ); + UvBuffer = Device.CreateBuffer( + new() + { + Purpose = ResourcePurpose.VertexBuffer, + Size = sizeof(float) * 2 * 3, + }, "Uv" + ); + cmd.Upload( + PositionColorBuffer, [ + /* position */ 0.0f, 0.5f * 1.7f, 0f, /* color */ 0.71f, 0.22f, 0.21f, 1f, + /* position */ 0.5f, -0.5f * 1.7f, 0f, /* color */ 0.34f, 0.64f, 0.31f, 1f, + /* position */ -0.5f, -0.5f * 1.7f, 0f, /* color */ 0.36f, 0.42f, 0.92f, 1f, + ] + ); + cmd.Upload( + UvBuffer, [ + 0.0f, 0.0f, + -1.0f, 2.0f, + 1.0f, 2.0f, + ] + ); + } + protected override void Render(GpuRecord cmd, Time time) + { + using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))], Name: Name); + // render.SetMeshBuffers( + // MeshLayout, [ + // new(0, PositionColorBuffer), + // new(1, UvBuffer), + // ] + // ); + // render.Draw(Pipeline, 3); + } } From f4b1f99418bfc8453f556c60ba4f676ab17e73d5 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Fri, 28 Mar 2025 16:23:19 +0800 Subject: [PATCH 19/46] save --- Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 25 ++++++++++++++++------ Coplt.Graphics.Native/D3d12/Src/Barrier.h | 3 ++- Coplt.Graphics.Native/D3d12/Src/Record.cc | 7 +++++- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index 5f4e6d2..1477422 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -73,8 +73,8 @@ namespace Coplt::Enhanced const auto& res = resources[i]; m_resources.push_back(ResInfo(&res)); } - m_buffer_groups.push_back({.ListIndex = 0}); - m_buffer_groups.push_back({.ListIndex = 1}); + m_buffer_groups.push_back({}); + m_buffer_groups.push_back({}); } void EnhancedBarrierRecorder::EndRecord() @@ -108,6 +108,7 @@ namespace Coplt::Enhanced { info.InfoState = InfoState::Input; info.State = new_state; + if (m_last_cmd_count > 0) Split(); info.LastUseListIndex = 0; info.CurrentListIndex = m_storage->CurListIndex(); return; @@ -121,7 +122,7 @@ namespace Coplt::Enhanced } info.InfoState = InfoState::Used; m_inputs.push_back(IOResState{.ResIndex = ResIndex, .CurrentListIndex = info.CurrentListIndex, .State = info.State}); - if (info.CurrentListIndex == m_storage->CurListIndex()) Split(); + if (info.CurrentListIndex == m_storage->CurListIndex() || m_last_cmd_count > 0) Split(); goto EndState; } else @@ -132,7 +133,7 @@ namespace Coplt::Enhanced goto End; } } - if (info.CurrentListIndex == m_storage->CurListIndex()) Split(); + if (info.CurrentListIndex == m_storage->CurListIndex() || m_last_cmd_count > 0) Split(); CreateBarrier(info); EndState: info.SetNewState(new_state); @@ -141,6 +142,15 @@ namespace Coplt::Enhanced info.CurrentListIndex = m_storage->CurListIndex(); } + void EnhancedBarrierRecorder::OnUse(FCmdResRef ResRef) + { + const auto ResIndex = ResRef.ResIndex(); + auto& info = m_resources[ResIndex]; + if (info.InfoState == InfoState::Unused) + COPLT_THROW("The resource is not being used and the usage location cannot be updated"); + info.CurrentListIndex = m_storage->CurListIndex(); + } + void EnhancedBarrierRecorder::OnCmd() { m_last_cmd_count++; @@ -149,7 +159,7 @@ namespace Coplt::Enhanced void EnhancedBarrierRecorder::Split() { m_storage->Split(); - m_buffer_groups.push_back({.ListIndex = m_buffer_groups.size() - 1}); + m_buffer_groups.push_back({}); m_last_cmd_count = 0; } @@ -219,8 +229,9 @@ namespace Coplt::Enhanced void EnhancedBarrierRecorder::SubmitBarriers() { - for (auto& group : m_buffer_groups) + for (u32 i = 0; i < m_buffer_groups.size(); ++i) { + auto& group = m_buffer_groups[i]; D3D12_BARRIER_GROUP groups[2]; u32 group_count = 0; if (group.m_texture_barriers.size() > 0) @@ -241,7 +252,7 @@ namespace Coplt::Enhanced } if (group_count > 0) { - m_storage->Lists()[group.ListIndex]->Barrier(group_count, groups); + m_storage->Lists()[i]->Barrier(group_count, groups); group.m_texture_barriers.clear(); group.m_buffer_barriers.clear(); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index 05683ac..a10907f 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -34,6 +34,7 @@ namespace Coplt virtual void EndRecord() = 0; virtual void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) = 0; + virtual void OnUse(FCmdResRef ResRef) = 0; virtual void OnCmd() = 0; virtual void SubmitBarriers() = 0; @@ -101,7 +102,6 @@ namespace Coplt // todo 优化内存分配 struct BarrierGroup { - u32 ListIndex{}; std::vector m_buffer_barriers{}; std::vector m_texture_barriers{}; @@ -140,6 +140,7 @@ namespace Coplt void StartRecord(std::span resources) override; void EndRecord() override; void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) override; + void OnUse(FCmdResRef ResRef) override; void OnCmd() override; void Split(); diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 8d47c13..284a0ed 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -355,7 +355,7 @@ void D3d12GpuRecord::Interpret_Render(const u32 i, const FCmdRender& cmd) m_state = InterpretState::Render; m_cur_render = RenderState{.StartIndex = i, .Cmd = cmd}; const auto& info = PayloadRenderInfo[cmd.InfoIndex]; - auto num_rtv = std::min(info.NumRtv, 8u); + const auto num_rtv = std::min(info.NumRtv, 8u); if (CurList()->g4) { D3D12_RENDER_PASS_RENDER_TARGET_DESC rts[num_rtv]; @@ -444,6 +444,11 @@ void D3d12GpuRecord::Interpret_RenderEnd(u32 i, const FCmdRender& cmd) COPLT_THROW("Cannot use End in main scope"); m_state = InterpretState::Main; const auto& list = CurList(); + const auto& info = PayloadRenderInfo[cmd.InfoIndex]; + const auto num_rtv = std::min(info.NumRtv, 8u); + if (info.Dsv) m_barrier_recorder->OnUse(info.Dsv); + for (u32 n = 0; n < num_rtv; ++n) m_barrier_recorder->OnUse(info.Rtv[n]); + m_barrier_recorder->OnCmd(); if (list->g4) { list->g4->EndRenderPass(); From 56d4b12aa3f5eef5b35163d03959beec56ab489e Mon Sep 17 00:00:00 2001 From: U2A5F Date: Mon, 31 Mar 2025 17:05:37 +0800 Subject: [PATCH 20/46] remove multi list --- Coplt.Graphics.Native/Api/FFI/List.h | 6 + Coplt.Graphics.Native/D3d12/CMakeLists.txt | 2 - Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 305 ++++++++------- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 136 ++++--- Coplt.Graphics.Native/D3d12/Src/Context.h | 1 + Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 4 +- Coplt.Graphics.Native/D3d12/Src/Isolate.h | 4 +- Coplt.Graphics.Native/D3d12/Src/Record.cc | 354 ++++++++++++------ Coplt.Graphics.Native/D3d12/Src/Record.h | 60 +-- .../D3d12/Src/RecordStorage.cc | 80 ---- .../D3d12/Src/RecordStorage.h | 55 --- 11 files changed, 521 insertions(+), 486 deletions(-) delete mode 100644 Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc delete mode 100644 Coplt.Graphics.Native/D3d12/Src/RecordStorage.h diff --git a/Coplt.Graphics.Native/Api/FFI/List.h b/Coplt.Graphics.Native/Api/FFI/List.h index 8e1b4ff..b21ee10 100644 --- a/Coplt.Graphics.Native/Api/FFI/List.h +++ b/Coplt.Graphics.Native/Api/FFI/List.h @@ -75,6 +75,12 @@ namespace Coplt return m_ptr[index]; } + const T& operator[](size_t index) const + { + if (index >= m_len) throw std::out_of_range("FList::operator[]"); + return m_ptr[index]; + } + T* data() const { return m_ptr; diff --git a/Coplt.Graphics.Native/D3d12/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index 62309ce..d8a2905 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -65,8 +65,6 @@ add_library(${target_name} SHARED Src/Barrier.cc Include/ResState.h Src/ResState.cc - Src/RecordStorage.h - Src/RecordStorage.cc ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "Coplt.Graphics.Native.D3d12") diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index 1477422..dfd54e3 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -4,67 +4,93 @@ using namespace Coplt; +void ID3d12EnhancedBarrierAnalyzer::Group::Push(D3D12_BUFFER_BARRIER barrier) +{ + m_buffer_barriers.push_back(barrier); +} + +void ID3d12EnhancedBarrierAnalyzer::Group::Push(D3D12_TEXTURE_BARRIER barrier) +{ + m_texture_barriers.push_back(barrier); +} + +void ID3d12EnhancedBarrierAnalyzer::Group::Clear() +{ + m_buffer_barriers.clear(); + m_texture_barriers.clear(); +} + +ID3d12EnhancedBarrierAnalyzer::ResInfo::ResInfo(const NonNull Res) : Res(Res) +{ +} + +void ID3d12EnhancedBarrierAnalyzer::ResInfo::SetNewState(const ResState state) +{ + OldState = State; + State = state; +} + namespace Coplt::Enhanced { - EnhancedBarrierAnalyzer::EnhancedBarrierAnalyzer(const Rc& device) + EnhancedBarrierMarshal::EnhancedBarrierMarshal(const Rc& device) : m_device(device) { } - Rc EnhancedBarrierAnalyzer::CreateRecorder(const Rc& storage) + Rc EnhancedBarrierMarshal::CreateAnalyzer() { - return new EnhancedBarrierRecorder(m_device, storage); + return new EnhancedBarrierAnalyzer(m_device); } - Rc EnhancedBarrierAnalyzer::CreateCombiner() + Rc EnhancedBarrierMarshal::CreateCombiner() { return new EnhancedBarrierCombiner(m_device); } - void EnhancedBarrierRecorder::BarrierGroup::Push(D3D12_BUFFER_BARRIER barrier) + EnhancedBarrierAnalyzer::EnhancedBarrierAnalyzer(const Rc& device) + : m_device(device) { - m_buffer_barriers.push_back(barrier); } - void EnhancedBarrierRecorder::BarrierGroup::Push(D3D12_TEXTURE_BARRIER barrier) + std::span EnhancedBarrierAnalyzer::Inputs() const { - m_texture_barriers.push_back(barrier); + return m_inputs; } - EnhancedBarrierRecorder::ResInfo::ResInfo(const NonNull Res) : Res(Res) + std::span EnhancedBarrierAnalyzer::Outputs() const { + return m_outputs; } - void EnhancedBarrierRecorder::ResInfo::SetNewState(const ResState state) + std::span EnhancedBarrierAnalyzer::Groups() { - OldState = State; - State = state; + return m_groups; } - EnhancedBarrierRecorder::EnhancedBarrierRecorder(const Rc& device, const Rc& storage) - : m_device(device), m_storage(storage) + ID3d12EnhancedBarrierAnalyzer::Group& EnhancedBarrierAnalyzer::CurGroup() { + return m_groups.back(); } - std::span EnhancedBarrierRecorder::Inputs() const + const ID3d12EnhancedBarrierAnalyzer::Group& EnhancedBarrierAnalyzer::CurGroup() const { - return m_inputs; + return m_groups.back(); } - std::span EnhancedBarrierRecorder::Outputs() const + u32 EnhancedBarrierAnalyzer::CurGroupIndex() const { - return m_outputs; + return m_groups.size() - 1; } - void EnhancedBarrierRecorder::Clear() + void EnhancedBarrierAnalyzer::Clear() { m_resources.clear(); m_inputs.clear(); m_outputs.clear(); - m_buffer_groups.clear(); + m_groups.clear(); } - void EnhancedBarrierRecorder::StartRecord(const std::span resources) + void EnhancedBarrierAnalyzer::StartAnalyze(const std::span resources) { Clear(); m_resources.reserve(resources.size()); @@ -73,11 +99,10 @@ namespace Coplt::Enhanced const auto& res = resources[i]; m_resources.push_back(ResInfo(&res)); } - m_buffer_groups.push_back({}); - m_buffer_groups.push_back({}); + m_groups.push_back({}); } - void EnhancedBarrierRecorder::EndRecord() + void EnhancedBarrierAnalyzer::EndAnalyze() { for (u32 i = 0; i < m_resources.size(); ++i) { @@ -85,21 +110,17 @@ namespace Coplt::Enhanced if (info.InfoState == InfoState::Unused) continue; if (info.InfoState == InfoState::Input) { - m_inputs.push_back(IOResState{.ResIndex = i, .CurrentListIndex = info.CurrentListIndex, .State = info.State}); + m_inputs.push_back(IOResState{.ResIndex = i, .LstGroup = info.LstGroup, .State = info.State}); } else { CreateBarrier(info); } - m_outputs.push_back(IOResState{.ResIndex = i, .CurrentListIndex = info.CurrentListIndex, .State = info.State}); - } - if (m_last_cmd_count == 0) - { - m_storage->DropLast(); + m_outputs.push_back(IOResState{.ResIndex = i, .LstGroup = info.LstGroup, .State = info.State}); } } - void EnhancedBarrierRecorder::OnUse(const FCmdResRef ResRef, const ResAccess Access, const ResUsage Usage, const ResLayout Layout) + void EnhancedBarrierAnalyzer::OnUse(const FCmdResRef ResRef, const ResAccess Access, const ResUsage Usage, const ResLayout Layout) { const auto ResIndex = ResRef.ResIndex(); auto& info = m_resources[ResIndex]; @@ -109,8 +130,8 @@ namespace Coplt::Enhanced info.InfoState = InfoState::Input; info.State = new_state; if (m_last_cmd_count > 0) Split(); - info.LastUseListIndex = 0; - info.CurrentListIndex = m_storage->CurListIndex(); + info.PreGroup = 0; + info.LstGroup = info.CurGroup = CurGroupIndex(); return; } else if (info.InfoState == InfoState::Input) @@ -121,8 +142,8 @@ namespace Coplt::Enhanced goto End; } info.InfoState = InfoState::Used; - m_inputs.push_back(IOResState{.ResIndex = ResIndex, .CurrentListIndex = info.CurrentListIndex, .State = info.State}); - if (info.CurrentListIndex == m_storage->CurListIndex() || m_last_cmd_count > 0) Split(); + m_inputs.push_back(IOResState{.ResIndex = ResIndex, .LstGroup = info.LstGroup, .State = info.State}); + if (info.CurGroup == CurGroupIndex() || m_last_cmd_count > 0) Split(); goto EndState; } else @@ -133,41 +154,49 @@ namespace Coplt::Enhanced goto End; } } - if (info.CurrentListIndex == m_storage->CurListIndex() || m_last_cmd_count > 0) Split(); + if (info.CurGroup == CurGroupIndex() || m_last_cmd_count > 0) Split(); CreateBarrier(info); EndState: info.SetNewState(new_state); - info.LastUseListIndex = info.CurrentListIndex; + info.PreGroup = info.CurGroup; + info.LstGroup = info.CurGroup = CurGroupIndex(); + return; End: - info.CurrentListIndex = m_storage->CurListIndex(); + info.CurGroup = CurGroupIndex(); + return; } - void EnhancedBarrierRecorder::OnUse(FCmdResRef ResRef) + void EnhancedBarrierAnalyzer::OnUse(FCmdResRef ResRef) { const auto ResIndex = ResRef.ResIndex(); auto& info = m_resources[ResIndex]; if (info.InfoState == InfoState::Unused) COPLT_THROW("The resource is not being used and the usage location cannot be updated"); - info.CurrentListIndex = m_storage->CurListIndex(); + info.CurGroup = CurGroupIndex(); } - void EnhancedBarrierRecorder::OnCmd() + void EnhancedBarrierAnalyzer::OnCmd() { m_last_cmd_count++; } - void EnhancedBarrierRecorder::Split() + void EnhancedBarrierAnalyzer::CmdNext() + { + CurGroup().m_cmd_count++; + } + + void EnhancedBarrierAnalyzer::Split() { - m_storage->Split(); - m_buffer_groups.push_back({}); + const auto& cur_group = CurGroup(); + m_groups.push_back({.m_cmd_index = cur_group.m_cmd_index + cur_group.m_cmd_count}); m_last_cmd_count = 0; } - void EnhancedBarrierRecorder::CreateBarrier(ResInfo& info) + void EnhancedBarrierAnalyzer::CreateBarrier(const ResInfo& info) { const auto& res = *info.Res; - const auto BeforeListIndex = info.LastUseListIndex; - const auto AfterListIndex = info.CurrentListIndex - 1; + const auto BeforeListIndex = info.PreGroup + 1; + const auto AfterListIndex = info.LstGroup; const auto SyncBefore = GetBarrierSync(info.OldState.Access, info.OldState.Usage); const auto SyncAfter = GetBarrierSync(info.State.Access, info.State.Usage); const auto AccessBefore = GetBarrierAccess(info.OldState.Access); @@ -177,15 +206,15 @@ namespace Coplt::Enhanced if (BeforeListIndex >= AfterListIndex) { barrier.SyncAfter = SyncAfter; - m_buffer_groups[BeforeListIndex].Push(barrier); + m_groups[AfterListIndex].Push(barrier); } else { - m_buffer_groups[BeforeListIndex].Push(barrier); + m_groups[BeforeListIndex].Push(barrier); barrier.SyncBefore = D3D12_BARRIER_SYNC_SPLIT; barrier.SyncAfter = SyncAfter; - m_buffer_groups[AfterListIndex].Push(barrier); + m_groups[AfterListIndex].Push(barrier); } }; if (res.IsImage()) @@ -227,35 +256,39 @@ namespace Coplt::Enhanced } } - void EnhancedBarrierRecorder::SubmitBarriers() + void EnhancedBarrierAnalyzer::Interpret(const D3d12RentedCommandList& list, ID3d12GpuRecord& record) { - for (u32 i = 0; i < m_buffer_groups.size(); ++i) + for (auto& group : m_groups) { - auto& group = m_buffer_groups[i]; - D3D12_BARRIER_GROUP groups[2]; - u32 group_count = 0; - if (group.m_texture_barriers.size() > 0) - { - groups[group_count++] = D3D12_BARRIER_GROUP{ - .Type = D3D12_BARRIER_TYPE_TEXTURE, - .NumBarriers = static_cast(group.m_texture_barriers.size()), - .pTextureBarriers = group.m_texture_barriers.data(), - }; - } - if (group.m_buffer_barriers.size() > 0) - { - groups[group_count++] = D3D12_BARRIER_GROUP{ - .Type = D3D12_BARRIER_TYPE_BUFFER, - .NumBarriers = static_cast(group.m_buffer_barriers.size()), - .pBufferBarriers = group.m_buffer_barriers.data(), - }; - } - if (group_count > 0) - { - m_storage->Lists()[i]->Barrier(group_count, groups); - group.m_texture_barriers.clear(); - group.m_buffer_barriers.clear(); - } + SubmitBarrier(list, group); + record.Interpret(list, group.m_cmd_index, group.m_cmd_count); + } + } + + void EnhancedBarrierAnalyzer::SubmitBarrier(const D3d12RentedCommandList& list, Group& group) + { + D3D12_BARRIER_GROUP groups[2]; + u32 group_count = 0; + if (group.m_texture_barriers.size() > 0) + { + groups[group_count++] = D3D12_BARRIER_GROUP{ + .Type = D3D12_BARRIER_TYPE_TEXTURE, + .NumBarriers = static_cast(group.m_texture_barriers.size()), + .pTextureBarriers = group.m_texture_barriers.data(), + }; + } + if (group.m_buffer_barriers.size() > 0) + { + groups[group_count++] = D3D12_BARRIER_GROUP{ + .Type = D3D12_BARRIER_TYPE_BUFFER, + .NumBarriers = static_cast(group.m_buffer_barriers.size()), + .pBufferBarriers = group.m_buffer_barriers.data(), + }; + } + if (group_count > 0) + { + list->Barrier(group_count, groups); + group.Clear(); } } @@ -266,8 +299,6 @@ namespace Coplt::Enhanced void EnhancedBarrierCombiner::EndSubmit() { - m_buffer_barriers.clear(); - m_texture_barriers.clear(); Base::EndSubmit(); } @@ -276,12 +307,12 @@ namespace Coplt::Enhanced for (const auto& record : records) { const NonNull data = record->Data(); - const auto& barrier_recorder = record->BarrierRecorder(); - const auto& storage = record->Storage(); + const NonNull barrier_analyzer = record->BarrierAnalyzer()->QueryInterface(); + const auto& context = record->Context(); #pragma region 生成输入屏障 - for (const auto& input : barrier_recorder->Inputs()) + for (const auto& input : barrier_analyzer->Inputs()) { const auto& res = data->Resources[input.ResIndex]; bool exist; @@ -294,13 +325,14 @@ namespace Coplt::Enhanced }); if (!exist) { + const auto AfterIndex = input.LstGroup; if (res.IsImage()) { const auto img_data = GetImageData(res); + const auto SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage); D3D12_TEXTURE_BARRIER barrier{ .SyncBefore = D3D12_BARRIER_SYNC_NONE, - .SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage), - // .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, // todo 拆分屏障 + .SyncAfter = SyncAfter, .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, .AccessAfter = GetBarrierAccess(input.State.Access), .LayoutBefore = GetBarrierLayout(sr.State->Layout), @@ -316,23 +348,35 @@ namespace Coplt::Enhanced }, .Flags = D3D12_TEXTURE_BARRIER_FLAG_NONE, }; - m_texture_barriers.push_back(barrier); + barrier_analyzer->Groups()[0].Push(barrier); } else { const auto buffer_data = GetBufferData(res); + const auto SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage); D3D12_BUFFER_BARRIER barrier{ .SyncBefore = D3D12_BARRIER_SYNC_NONE, - .SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage), - // .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, // todo 拆分屏障 + .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, .AccessAfter = GetBarrierAccess(input.State.Access), .pResource = GetResource(res), .Offset = 0, .Size = buffer_data->m_size, }; - m_buffer_barriers.push_back(barrier); - //todo + barrier.SyncAfter = SyncAfter; + barrier_analyzer->Groups()[0].Push(barrier); + // if (AfterIndex == 0) + // { + // barrier.SyncAfter = SyncAfter; + // barrier_recorder->BarrierGroups()[0].Push(barrier); + // } + // else + // { + // barrier_recorder->BarrierGroups()[0].Push(barrier); + // barrier.SyncBefore = D3D12_BARRIER_SYNC_SPLIT; + // barrier.SyncAfter = SyncAfter; + // barrier_recorder->BarrierGroups()[AfterIndex].Push(barrier); + // } } } // todo @@ -340,63 +384,29 @@ namespace Coplt::Enhanced #pragma endregion - #pragma region 插入输入屏障 + #pragma region 完成录制 记录 list 范围 - if (m_buffer_barriers.size() > 0 || m_texture_barriers.size() > 0) { - D3D12_BARRIER_GROUP groups[2]; - u32 group_count = 0; - if (m_texture_barriers.size() > 0) - { - groups[group_count++] = D3D12_BARRIER_GROUP{ - .Type = D3D12_BARRIER_TYPE_TEXTURE, - .NumBarriers = m_texture_barriers.size(), - .pTextureBarriers = m_texture_barriers.data(), - }; - } - if (m_buffer_barriers.size() > 0) - { - groups[group_count++] = D3D12_BARRIER_GROUP{ - .Type = D3D12_BARRIER_TYPE_BUFFER, - .NumBarriers = m_buffer_barriers.size(), - .pBufferBarriers = m_buffer_barriers.data(), - }; - } - // 第一个列表是保留的用于屏障的 - storage->Lists()[0]->Barrier(group_count, groups); - m_buffer_barriers.clear(); - m_texture_barriers.clear(); - } - - #pragma endregion - - #pragma region 提交中间屏障 + auto allocator = context->m_cmd_alloc_pool->RentCommandAllocator(GetType(data->Mode)); + auto list = allocator.RentCommandList(); - barrier_recorder->SubmitBarriers(); - - #pragma endregion - - #pragma region 完成录制 记录 list 范围 + barrier_analyzer->Interpret(list, *record); - { - ListRange range{}; + ListNode node{}; // todo fence - range.ListIndex = m_submit_lists.size(); - const auto lists = storage->Lists(); - range.ListCount = lists.size(); - range.Queue = FGpuQueueType::Direct; // todo 选择队列 - for (const auto& list : lists) - { - m_submit_lists.push_back(list->ToCommandList()); - } - m_list_ranges.push_back(range); + node.List = list->ToCommandList(); + node.Queue = FGpuQueueType::Direct; // todo 选择队列 + m_list_node.push_back(node); + + list.Close(); + context->m_recycled_command_allocators.push_back(std::move(allocator)); } #pragma endregion #pragma region 记录输出状态 - for (const auto& output : barrier_recorder->Outputs()) + for (const auto& output : barrier_analyzer->Outputs()) { const auto& res = data->Resources[output.ResIndex]; const auto state = GetState(res); @@ -420,8 +430,7 @@ void AD3d12BarrierCombiner::StartSubmit() void AD3d12BarrierCombiner::EndSubmit() { - m_submit_lists.clear(); - m_list_ranges.clear(); + m_list_node.clear(); m_queue_deps.clear(); m_submit_resources.Clear(); m_used_queues = FGpuQueueFlags::None; @@ -431,28 +440,23 @@ bool AD3d12BarrierCombiner::Submit(NonNull isolate, std::spanStorage(); - storage->BeforeSubmit(); - } - const auto has_submit = m_list_ranges.size() > 0; + const auto has_submit = m_list_node.size() > 0; if (has_submit) { const auto& main_queue = isolate->m_main_queue; #pragma region 提交命令列表 - for (const auto& range : m_list_ranges) + for (const auto& node : m_list_node) { - const auto& queue = isolate->GetQueue(range.Queue); - for (u32 i = 0; i < range.DepCount; ++i) + const auto& queue = isolate->GetQueue(node.Queue); + for (u32 i = 0; i < node.DepCount; ++i) { - const auto& dep = m_queue_deps[i + range.DepIndex]; + const auto& dep = m_queue_deps[i + node.DepIndex]; const auto& dep_queue = isolate->GetQueue(dep); queue->Wait(*dep_queue, dep_queue->Signal()); } - queue->m_queue->ExecuteCommandLists(range.ListCount, m_submit_lists.data() + range.ListIndex); + queue->m_queue->ExecuteCommandLists(1, &node.List); } #pragma endregion @@ -484,11 +488,6 @@ bool AD3d12BarrierCombiner::Submit(NonNull isolate, std::spanStorage(); - storage->AfterSubmit(); - } EndSubmit(); return has_submit; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index a10907f..31a23f9 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -1,7 +1,8 @@ #pragma once +#include "Context.h" #include "Device.h" -#include "RecordStorage.h" +#include "Isolate.h" #include "../../Api/Include/Object.h" #include "../../Api/FFI/Cmd.h" #include "../Include/ResState.h" @@ -11,33 +12,33 @@ namespace Coplt struct IOResState { u32 ResIndex{}; - u32 CurrentListIndex{}; + u32 LstGroup{}; ResState State{}; }; - struct ID3d12BarrierRecorder; + struct ID3d12BarrierAnalyzer; struct ID3d12BarrierCombiner; - COPLT_INTERFACE_DEFINE(ID3d12BarrierAnalyzer, "792f273c-376d-4027-af99-0d14d3d71302", FUnknown) + COPLT_INTERFACE_DEFINE(ID3d12BarrierMarshal, "792f273c-376d-4027-af99-0d14d3d71302", FUnknown) { - virtual Rc CreateRecorder(const Rc& storage) = 0; + virtual Rc CreateAnalyzer() = 0; virtual Rc CreateCombiner() = 0; }; - COPLT_INTERFACE_DEFINE(ID3d12BarrierRecorder, "115741ea-2138-4c92-9f4f-94f91d254587", FUnknown) + COPLT_INTERFACE_DEFINE(ID3d12BarrierAnalyzer, "115741ea-2138-4c92-9f4f-94f91d254587", FUnknown) { virtual std::span Inputs() const = 0; virtual std::span Outputs() const = 0; virtual void Clear() = 0; - virtual void StartRecord(std::span resources) = 0; - virtual void EndRecord() = 0; + virtual void StartAnalyze(std::span resources) = 0; + virtual void EndAnalyze() = 0; virtual void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) = 0; virtual void OnUse(FCmdResRef ResRef) = 0; virtual void OnCmd() = 0; - - virtual void SubmitBarriers() = 0; + // 每个命令都需要调用一次 + virtual void CmdNext() = 0; }; COPLT_INTERFACE_DEFINE(ID3d12BarrierCombiner, "e1e15444-6369-4d8a-90b3-153672abca39", FUnknown) @@ -54,18 +55,16 @@ namespace Coplt NonNull State; }; - struct ListRange + struct ListNode { u32 DepIndex{}; u32 DepCount{}; - u32 ListIndex{}; - u32 ListCount{}; + ID3D12CommandList* List; FGpuQueueType Queue{}; }; Rc m_device{}; - std::vector m_submit_lists{}; - std::vector m_list_ranges{}; + std::vector m_list_node{}; std::vector m_queue_deps{}; FGpuQueueFlags m_used_queues{}; HashMap m_submit_resources{}; @@ -78,82 +77,101 @@ namespace Coplt virtual void Process(NonNull isolate, std::span> records) = 0; }; + COPLT_INTERFACE_DEFINE(ID3d12EnhancedBarrierAnalyzer, "09e37529-9ad3-4b69-a9e5-cf57659a48c9", ID3d12BarrierAnalyzer) + { + enum class InfoState : u8 + { + Unused, + Input, + Used, + }; + + // todo 优化内存分配 + struct Group + { + std::vector m_buffer_barriers{}; + std::vector m_texture_barriers{}; + u32 m_cmd_index{}; + u32 m_cmd_count{}; + + void Push(D3D12_BUFFER_BARRIER barrier); + void Push(D3D12_TEXTURE_BARRIER barrier); + + void Clear(); + }; + + struct ResInfo + { + NonNull Res; + ResState State{}; + ResState OldState{}; + u32 PreGroup{COPLT_U32_MAX}; + u32 LstGroup{COPLT_U32_MAX}; + u32 CurGroup{COPLT_U32_MAX}; + InfoState InfoState{}; + + explicit ResInfo(NonNull Res); + + void SetNewState(ResState state); + }; + + virtual std::span Groups() = 0; + + virtual void Interpret(const D3d12RentedCommandList& list, ID3d12GpuRecord& record) = 0; + }; + namespace Enhanced { - struct EnhancedBarrierAnalyzer final : Object + struct EnhancedBarrierMarshal final : Object { Rc m_device; - explicit EnhancedBarrierAnalyzer(const Rc& device); + explicit EnhancedBarrierMarshal(const Rc& device); - Rc CreateRecorder(const Rc& storage) override; + Rc CreateAnalyzer() override; Rc CreateCombiner() override; }; - struct EnhancedBarrierRecorder final : Object + struct EnhancedBarrierAnalyzer final : Object { - enum class InfoState : u8 - { - Unused, - Input, - Used, - }; - - // todo 优化内存分配 - struct BarrierGroup - { - std::vector m_buffer_barriers{}; - std::vector m_texture_barriers{}; - - void Push(D3D12_BUFFER_BARRIER barrier); - void Push(D3D12_TEXTURE_BARRIER barrier); - }; - - struct ResInfo - { - NonNull Res; - ResState State{}; - ResState OldState{}; - u32 LastUseListIndex{COPLT_U32_MAX}; - u32 CurrentListIndex{COPLT_U32_MAX}; - InfoState InfoState{}; - - explicit ResInfo(NonNull Res); - - void SetNewState(ResState state); - }; - Rc m_device{}; - Rc m_storage{}; std::vector m_resources{}; std::vector m_inputs{}; std::vector m_outputs{}; - std::vector m_buffer_groups{}; + std::vector m_groups{}; u32 m_last_cmd_count{}; - explicit EnhancedBarrierRecorder(const Rc& device, const Rc& storage); + explicit EnhancedBarrierAnalyzer(const Rc& device); std::span Inputs() const override; std::span Outputs() const override; + std::span Groups() override; + Group& CurGroup(); + const Group& CurGroup() const; + u32 CurGroupIndex() const; + void Clear() override; - void StartRecord(std::span resources) override; - void EndRecord() override; + void StartAnalyze(std::span resources) override; + void EndAnalyze() override; void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) override; void OnUse(FCmdResRef ResRef) override; void OnCmd() override; + void CmdNext() override; void Split(); - void CreateBarrier(ResInfo& info); - void SubmitBarriers() override; + void CreateBarrier(const ResInfo& info); + + void Interpret(const D3d12RentedCommandList& list, ID3d12GpuRecord& record) override; + static void SubmitBarrier(const D3d12RentedCommandList& list, Group& group); }; struct EnhancedBarrierCombiner final : Object { explicit EnhancedBarrierCombiner(const Rc& device); - std::vector m_buffer_barriers{}; - std::vector m_texture_barriers{}; + // std::vector m_buffer_barriers{}; + // std::vector m_texture_barriers{}; void EndSubmit() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.h b/Coplt.Graphics.Native/D3d12/Src/Context.h index a8b444b..c116939 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.h +++ b/Coplt.Graphics.Native/D3d12/Src/Context.h @@ -177,6 +177,7 @@ namespace Coplt D3d12RentedCommandAllocator(const D3d12RentedCommandAllocator&) = delete; D3d12RentedCommandAllocator& operator=(const D3d12RentedCommandAllocator&) = delete; + // 每个分配器在重置之前只能租用一次 D3d12RentedCommandList RentCommandList() const; operator bool() const noexcept; diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index 54a9656..2939326 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -23,8 +23,8 @@ D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCre #pragma endregion - m_barrier_analyzer = new Enhanced::EnhancedBarrierAnalyzer(m_device); - m_barrier_combiner = m_barrier_analyzer->CreateCombiner(); + m_barrier_marshal = new Enhanced::EnhancedBarrierMarshal(m_device); + m_barrier_combiner = m_barrier_marshal->CreateCombiner(); m_cmd_alloc_pool = new D3d12CommandListPoolCluster(m_device); diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index 1cc2a34..c68ac11 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -21,7 +21,7 @@ namespace Coplt }; struct ID3d12GpuRecord; - struct ID3d12BarrierAnalyzer; + struct ID3d12BarrierMarshal; struct ID3d12BarrierCombiner; struct D3d12GpuIsolate final : GpuObject, FGpuIsolateData @@ -31,7 +31,7 @@ namespace Coplt Rc m_main_queue{}; Rc m_compute_queue{}; Rc m_copy_queue{}; - Rc m_barrier_analyzer{}; + Rc m_barrier_marshal{}; Rc m_barrier_combiner{}; HANDLE m_event{}; Box m_waiting_record{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 284a0ed..0ec8cfb 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -50,9 +50,8 @@ D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) Id = m_isolate_id = isolate->m_object_id; m_record_id = isolate->m_record_inc++; m_context = new D3d12RecordContext(isolate); - m_storage = new D3d12RecordStorage(isolate, m_context); - m_barrier_recorder = isolate->m_barrier_analyzer->CreateRecorder(m_storage); - Context = m_context.get(); + m_barrier_analyzer = isolate->m_barrier_marshal->CreateAnalyzer(); + FGpuRecordData::Context = m_context.get(); } FResult D3d12GpuRecord::SetName(const FStr8or16& name) noexcept @@ -75,14 +74,14 @@ const FGpuRecordData* D3d12GpuRecord::Data() const noexcept return this; } -const Rc& D3d12GpuRecord::Storage() +const Rc& D3d12GpuRecord::Context() const noexcept { - return m_storage; + return m_context; } -const Rc& D3d12GpuRecord::BarrierRecorder() +const Rc& D3d12GpuRecord::BarrierAnalyzer() { - return m_barrier_recorder; + return m_barrier_analyzer; } void D3d12GpuRecord::RegisterWaitPoint(QueueWaitPoint&& wait_point) @@ -102,8 +101,7 @@ void D3d12GpuRecord::WaitAndRecycle(const HANDLE event) void D3d12GpuRecord::Recycle() { m_queue_wait_points.clear(); - m_barrier_recorder->Clear(); - m_storage->Clear(); + m_barrier_analyzer->Clear(); m_context->Recycle(); m_resources_owner.clear(); m_pipeline_context.Reset(); @@ -132,7 +130,7 @@ void D3d12GpuRecord::DoEnd() if (Resources.size() >= std::numeric_limits::max()) COPLT_THROW("Too many resources"); ReadyResource(); - Interpret(); + Analyze(); Ended = true; Version++; } @@ -142,9 +140,11 @@ FCmdRes& D3d12GpuRecord::GetRes(const FCmdResRef& ref) return ref.Get(Resources); } -D3d12RentedCommandList& D3d12GpuRecord::CurList() const +void D3d12GpuRecord::ResetState() { - return m_storage->CurList(); + m_state = RecordState::Main; + m_cur_render = {}; + m_pipeline_context.Reset(); } void D3d12GpuRecord::ReadyResource() @@ -157,76 +157,218 @@ void D3d12GpuRecord::ReadyResource() } } -void D3d12GpuRecord::Interpret() +void D3d12GpuRecord::Analyze() +{ + const auto commands = Commands.AsSpan(); + m_barrier_analyzer->StartAnalyze(Resources.AsSpan()); + for (u32 i = 0; i < commands.size(); ++i, m_barrier_analyzer->CmdNext()) + { + const auto& command = commands[i]; + switch (command.Type) + { + case FCmdType::None: + case FCmdType::Label: + case FCmdType::BeginScope: + case FCmdType::EndScope: + break; + case FCmdType::End: + if (m_state == RecordState::Render) + Analyze_RenderEnd(i, m_cur_render.Cmd); + else + COPLT_THROW("Cannot use End in main scope"); + break; + case FCmdType::PreparePresent: + Analyze_PreparePresent(i, command.PreparePresent); + break; + case FCmdType::ClearColor: + Analyze_ClearColor(i, command.ClearColor); + break; + case FCmdType::ClearDepthStencil: + Analyze_ClearDepthStencil(i, command.ClearDepthStencil); + break; + case FCmdType::BufferCopy: + Analyze_BufferCopy(i, command.BufferCopy); + break; + case FCmdType::Render: + Analyze_Render(i, command.Render); + break; + case FCmdType::Compute: + COPLT_THROW("TODO"); + case FCmdType::SetPipeline: + Analyze_SetPipeline(i, command.SetPipeline); + break; + case FCmdType::SetBinding: + COPLT_THROW("TODO"); + case FCmdType::SetMeshBuffers: + COPLT_THROW("TODO"); + case FCmdType::SetViewportScissor: + if (Mode != FGpuRecordMode::Direct) + COPLT_THROW_FMT("[{}] Can only Draw on the direct mode", i); + break; + case FCmdType::Draw: + if (Mode != FGpuRecordMode::Direct) + COPLT_THROW_FMT("[{}] Can only Draw on the direct mode", i); + case FCmdType::Dispatch: + if (Mode != FGpuRecordMode::Direct && Mode != FGpuRecordMode::Compute) + COPLT_THROW_FMT("[{}] Can only Dispatch on the direct or compute mode", i); + break; + } + } + m_barrier_analyzer->EndAnalyze(); +} + +void D3d12GpuRecord::Analyze_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use PreparePresent in sub scope", i); + if (Mode != FGpuRecordMode::Direct) + COPLT_THROW_FMT("[{}] Can only present on the direct mode", i); + m_barrier_analyzer->OnUse(cmd.Output, ResAccess::None, ResUsage::Common, ResLayout::Common); +} + +void D3d12GpuRecord::Analyze_ClearColor(u32 i, const FCmdClearColor& cmd) const +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use ClearColor in sub scope", i); + m_barrier_analyzer->OnUse(cmd.Image, ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); + m_barrier_analyzer->OnCmd(); +} + +void D3d12GpuRecord::Analyze_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd) const +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use ClearDepthStencil in sub scope", i); + m_barrier_analyzer->OnUse(cmd.Image, ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); + m_barrier_analyzer->OnCmd(); +} + +void D3d12GpuRecord::Analyze_BufferCopy(u32 i, const FCmdBufferCopy& cmd) const +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use BufferCopy in sub scope", i); + if (cmd.SrcType == FBufferRefType2::Buffer && cmd.DstType == FBufferRefType2::Buffer) + { + m_barrier_analyzer->OnUse(cmd.Dst.Buffer, ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); + m_barrier_analyzer->OnUse(cmd.Src.Buffer, ResAccess::CopySourceRead, ResUsage::Common, ResLayout::Common); + m_barrier_analyzer->OnCmd(); + } + else if (cmd.SrcType == FBufferRefType2::Upload && cmd.DstType == FBufferRefType2::Buffer) + { + m_barrier_analyzer->OnUse(cmd.Dst.Buffer, ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); + m_barrier_analyzer->OnCmd(); + } + else + { + COPLT_THROW_FMT( + "[{}] Unsupported copy combination {{ SrcType = {} DstType = {} }}", + i, static_cast(cmd.SrcType), static_cast(cmd.DstType) + ); + } +} + +void D3d12GpuRecord::Analyze_Render(u32 i, const FCmdRender& cmd) +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use Render in sub scope", i); + if (Mode != FGpuRecordMode::Direct) + COPLT_THROW_FMT("[{}] Render can only be used in Direct mode", i); + m_state = RecordState::Render; + m_cur_render = RenderState{.StartIndex = i, .Cmd = cmd}; + const auto& info = PayloadRenderInfo[cmd.InfoIndex]; + const auto num_rtv = std::min(info.NumRtv, 8u); + if (info.Dsv) + { + m_barrier_analyzer->OnUse(info.Dsv, ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); + } + for (u32 n = 0; n < num_rtv; ++n) + { + m_barrier_analyzer->OnUse(info.Rtv[n], ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); + } + m_barrier_analyzer->OnCmd(); +} + +void D3d12GpuRecord::Analyze_RenderEnd(u32 i, const FCmdRender& cmd) +{ + if (m_state != RecordState::Render) + COPLT_THROW_FMT("[{}] Cannot use End in main scope", i); + m_state = RecordState::Main; + const auto& info = PayloadRenderInfo[cmd.InfoIndex]; + const auto num_rtv = std::min(info.NumRtv, 8u); + if (info.Dsv) m_barrier_analyzer->OnUse(info.Dsv); + for (u32 n = 0; n < num_rtv; ++n) m_barrier_analyzer->OnUse(info.Rtv[n]); + m_barrier_analyzer->OnCmd(); +} + +void D3d12GpuRecord::Analyze_SetPipeline(u32 i, const FCmdSetPipeline& cmd) +{ + if (m_state != RecordState::Render && m_state != RecordState::Compute) + COPLT_THROW_FMT("[{}] Cannot use SetPipeline in main scope", i); + SetPipeline(cmd.Pipeline, i); +} + +void D3d12GpuRecord::Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) { - m_storage->StartRecord(Mode); - m_barrier_recorder->StartRecord(Resources.AsSpan()); const auto commands = Commands.AsSpan(); - for (u32 i = 0; i < commands.size(); ++i) + for (u32 c = 0; c < count; ++c) { + const auto i = offset + c; const auto& command = commands[i]; switch (command.Type) { case FCmdType::None: + case FCmdType::PreparePresent: break; case FCmdType::End: - if (m_state == InterpretState::Render) - Interpret_RenderEnd(i, m_cur_render.Cmd); + if (m_state == RecordState::Render) + Interpret_RenderEnd(list, i, m_cur_render.Cmd); else COPLT_THROW("Cannot use End in main scope"); break; case FCmdType::Label: - Interpret_Label(i, command.Label); + Interpret_Label(list, i, command.Label); break; case FCmdType::BeginScope: - Interpret_BeginScope(i, command.BeginScope); + Interpret_BeginScope(list, i, command.BeginScope); break; case FCmdType::EndScope: - Interpret_EndScope(i, command.EndScope); - break; - case FCmdType::PreparePresent: - Interpret_PreparePresent(i, command.PreparePresent); + Interpret_EndScope(list, i, command.EndScope); break; case FCmdType::ClearColor: - Interpret_ClearColor(i, command.ClearColor); + Interpret_ClearColor(list, i, command.ClearColor); break; case FCmdType::ClearDepthStencil: - Interpret_ClearDepthStencil(i, command.ClearDepthStencil); + Interpret_ClearDepthStencil(list, i, command.ClearDepthStencil); break; case FCmdType::BufferCopy: - Interpret_BufferCopy(i, command.BufferCopy); + Interpret_BufferCopy(list, i, command.BufferCopy); break; case FCmdType::Render: - Interpret_Render(i, command.Render); + Interpret_Render(list, i, command.Render); break; case FCmdType::Compute: COPLT_THROW("TODO"); case FCmdType::SetPipeline: - Interpret_SetPipeline(i, command.SetPipeline); + Interpret_SetPipeline(list, i, command.SetPipeline); break; case FCmdType::SetBinding: COPLT_THROW("TODO"); case FCmdType::SetViewportScissor: - Interpret_SetViewportScissor(i, command.SetViewportScissor); + Interpret_SetViewportScissor(list, i, command.SetViewportScissor); break; case FCmdType::SetMeshBuffers: COPLT_THROW("TODO"); case FCmdType::Draw: - Interpret_Draw(i, command.Draw); + Interpret_Draw(list, i, command.Draw); break; case FCmdType::Dispatch: COPLT_THROW("TODO"); - break; } } - m_barrier_recorder->EndRecord(); - m_storage->EndRecord(); } -void D3d12GpuRecord::Interpret_Label(u32 i, const FCmdLabel& cmd) const +void D3d12GpuRecord::Interpret_Label(const CmdList& list, u32 i, const FCmdLabel& cmd) const { if (!m_device->Debug()) return; - const auto& list = CurList(); if (!list->g0) return; auto color = PIX_COLOR_DEFAULT; if (cmd.HasColor) color = PIX_COLOR(cmd.Color[0], cmd.Color[1], cmd.Color[2]); @@ -240,10 +382,9 @@ void D3d12GpuRecord::Interpret_Label(u32 i, const FCmdLabel& cmd) const } } -void D3d12GpuRecord::Interpret_BeginScope(u32 i, const FCmdBeginScope& cmd) const +void D3d12GpuRecord::Interpret_BeginScope(const CmdList& list, u32 i, const FCmdBeginScope& cmd) const { if (!m_device->Debug()) return; - const auto& list = CurList(); if (!list->g0) return; u32 color = PIX_COLOR_DEFAULT; if (cmd.HasColor) color = PIX_COLOR(cmd.Color[0], cmd.Color[1], cmd.Color[2]); @@ -257,112 +398,92 @@ void D3d12GpuRecord::Interpret_BeginScope(u32 i, const FCmdBeginScope& cmd) cons } } -void D3d12GpuRecord::Interpret_EndScope(u32 i, const FCmdEndScope& cmd) const +void D3d12GpuRecord::Interpret_EndScope(const CmdList& list, u32 i, const FCmdEndScope& cmd) const { if (!m_device->Debug()) return; - const auto& list = CurList(); if (!list->g0) return; PIXEndEvent(list->g0.Get()); } -void D3d12GpuRecord::Interpret_PreparePresent(const u32 i, const FCmdPreparePresent& cmd) const +void D3d12GpuRecord::Interpret_ClearColor(const CmdList& list, const u32 i, const FCmdClearColor& cmd) { - if (m_state != InterpretState::Main) - COPLT_THROW("Cannot use PreparePresent in sub scope"); - if (Mode != FGpuRecordMode::Direct) - COPLT_THROW("Can only present on the direct mode"); - m_barrier_recorder->OnUse(cmd.Output, ResAccess::None, ResUsage::Common, ResLayout::Common); -} - -void D3d12GpuRecord::Interpret_ClearColor(const u32 i, const FCmdClearColor& cmd) -{ - if (m_state != InterpretState::Main) - COPLT_THROW("Cannot use ClearColor in sub scope"); - m_barrier_recorder->OnUse(cmd.Image, ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); - m_barrier_recorder->OnCmd(); + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use ClearColor in sub scope", i); const auto rtv = GetRtv(GetRes(cmd.Image)); - CurList()->g0->ClearRenderTargetView( + list->g0->ClearRenderTargetView( rtv, cmd.Color, cmd.RectCount, cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) ); } -void D3d12GpuRecord::Interpret_ClearDepthStencil(const u32 i, const FCmdClearDepthStencil& cmd) +void D3d12GpuRecord::Interpret_ClearDepthStencil(const CmdList& list, const u32 i, const FCmdClearDepthStencil& cmd) { - if (m_state != InterpretState::Main) - COPLT_THROW("Cannot use ClearDepthStencil in sub scope"); - m_barrier_recorder->OnUse(cmd.Image, ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); - m_barrier_recorder->OnCmd(); + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use ClearDepthStencil in sub scope", i); const auto dsv = GetDsv(GetRes(cmd.Image)); D3D12_CLEAR_FLAGS flags{}; if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Depth)) flags |= D3D12_CLEAR_FLAG_DEPTH; if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Stencil)) flags |= D3D12_CLEAR_FLAG_STENCIL; - CurList()->g0->ClearDepthStencilView( + list->g0->ClearDepthStencilView( dsv, flags, cmd.Depth, cmd.Stencil, cmd.RectCount, cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) ); } -void D3d12GpuRecord::Interpret_BufferCopy(u32 i, const FCmdBufferCopy& cmd) +void D3d12GpuRecord::Interpret_BufferCopy(const CmdList& list, u32 i, const FCmdBufferCopy& cmd) { - if (m_state != InterpretState::Main) - COPLT_THROW("Cannot use BufferCopy in sub scope"); + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use BufferCopy in sub scope", i); const auto& range = PayloadBufferCopyRange[cmd.RangeIndex]; if (cmd.SrcType == FBufferRefType2::Buffer && cmd.DstType == FBufferRefType2::Buffer) { - m_barrier_recorder->OnUse(cmd.Dst.Buffer, ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); - m_barrier_recorder->OnUse(cmd.Src.Buffer, ResAccess::CopySourceRead, ResUsage::Common, ResLayout::Common); - m_barrier_recorder->OnCmd(); const auto dst = GetResource(GetRes(cmd.Dst.Buffer)); const auto src = GetResource(GetRes(cmd.Src.Buffer)); if (range.Size == std::numeric_limits::max()) { - CurList()->g0->CopyResource(dst, src); + list->g0->CopyResource(dst, src); } else { - CurList()->g0->CopyBufferRegion(dst, range.DstOffset, src, range.SrcOffset, range.Size); + list->g0->CopyBufferRegion(dst, range.DstOffset, src, range.SrcOffset, range.Size); } } else if (cmd.SrcType == FBufferRefType2::Upload && cmd.DstType == FBufferRefType2::Buffer) { - m_barrier_recorder->OnUse(cmd.Dst.Buffer, ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); - m_barrier_recorder->OnCmd(); const auto dst = GetResource(GetRes(cmd.Dst.Buffer)); if (cmd.Src.Upload.Index >= m_context->m_upload_buffers.size()) - COPLT_THROW_FMT("Index out of bounds at command {}", i); + COPLT_THROW_FMT("[{}] Index out of bounds", i); const auto& src_obj = m_context->m_upload_buffers[cmd.Src.Upload.Index]; if (range.SrcOffset + range.Size >= src_obj.m_size) - COPLT_THROW_FMT("Size out of range at command {}", i); + COPLT_THROW_FMT("[{}] Size out of range", i); const auto src = src_obj.m_resource.m_resource.Get(); - CurList()->g0->CopyBufferRegion(dst, range.DstOffset, src, range.SrcOffset, range.Size); + list->g0->CopyBufferRegion(dst, range.DstOffset, src, range.SrcOffset, range.Size); } else { COPLT_THROW_FMT( - "Unsupported copy combination {{ SrcType = {} DstType = {} }} at command {}", - static_cast(cmd.SrcType), static_cast(cmd.DstType), i + "[{}] Unsupported copy combination {{ SrcType = {} DstType = {} }}", + i, static_cast(cmd.SrcType), static_cast(cmd.DstType) ); } } -void D3d12GpuRecord::Interpret_Render(const u32 i, const FCmdRender& cmd) +void D3d12GpuRecord::Interpret_Render(const CmdList& list, const u32 i, const FCmdRender& cmd) { - if (m_state != InterpretState::Main) - COPLT_THROW("Cannot use Render in sub scope"); + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use Render in sub scope", i); if (Mode != FGpuRecordMode::Direct) - COPLT_THROW("Render can only be used in Direct mode"); - m_state = InterpretState::Render; + COPLT_THROW_FMT("[{}] Render can only be used in Direct mode", i); + m_state = RecordState::Render; m_cur_render = RenderState{.StartIndex = i, .Cmd = cmd}; const auto& info = PayloadRenderInfo[cmd.InfoIndex]; const auto num_rtv = std::min(info.NumRtv, 8u); - if (CurList()->g4) + if (list->g4) { D3D12_RENDER_PASS_RENDER_TARGET_DESC rts[num_rtv]; D3D12_RENDER_PASS_DEPTH_STENCIL_DESC ds[info.Dsv ? 1 : 0]; if (info.Dsv) { - m_barrier_recorder->OnUse(info.Dsv, ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); const auto& dsv = GetRes(info.Dsv); const auto& d_load = info.DsvLoadOp[0]; const auto& d_store = info.DsvStoreOp[0]; @@ -402,7 +523,6 @@ void D3d12GpuRecord::Interpret_Render(const u32 i, const FCmdRender& cmd) } for (u32 n = 0; n < num_rtv; ++n) { - m_barrier_recorder->OnUse(info.Rtv[n], ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); const auto& rtv = GetRes(info.Rtv[n]); const auto& load = info.RtvLoadOp[n]; const auto& store = info.RtvStoreOp[n]; @@ -429,53 +549,48 @@ void D3d12GpuRecord::Interpret_Render(const u32 i, const FCmdRender& cmd) } D3D12_RENDER_PASS_FLAGS flags = D3D12_RENDER_PASS_FLAG_NONE; if (info.HasUavWrites) flags |= D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES; - m_barrier_recorder->OnCmd(); - CurList()->g4->BeginRenderPass(info.NumRtv, rts, info.Dsv ? ds : nullptr, flags); + list->g4->BeginRenderPass(info.NumRtv, rts, info.Dsv ? ds : nullptr, flags); } else { - COPLT_THROW("TODO"); + COPLT_THROW_FMT("[{}] Render pass is not supported, please check the agility sdk version", i); } } -void D3d12GpuRecord::Interpret_RenderEnd(u32 i, const FCmdRender& cmd) +void D3d12GpuRecord::Interpret_RenderEnd(const CmdList& list, u32 i, const FCmdRender& cmd) { - if (m_state != InterpretState::Render) - COPLT_THROW("Cannot use End in main scope"); - m_state = InterpretState::Main; - const auto& list = CurList(); - const auto& info = PayloadRenderInfo[cmd.InfoIndex]; - const auto num_rtv = std::min(info.NumRtv, 8u); - if (info.Dsv) m_barrier_recorder->OnUse(info.Dsv); - for (u32 n = 0; n < num_rtv; ++n) m_barrier_recorder->OnUse(info.Rtv[n]); - m_barrier_recorder->OnCmd(); + if (m_state != RecordState::Render) + COPLT_THROW_FMT("[{}] Cannot use End in main scope", i); + m_state = RecordState::Main; if (list->g4) { list->g4->EndRenderPass(); } + else + { + COPLT_THROW_FMT("[{}] Render pass is not supported, please check the agility sdk version", i); + } } -void D3d12GpuRecord::Interpret_SetPipeline(const u32 i, const FCmdSetPipeline& cmd) +void D3d12GpuRecord::Interpret_SetPipeline(const CmdList& list, const u32 i, const FCmdSetPipeline& cmd) { - if (m_state != InterpretState::Render && m_state != InterpretState::Compute) - COPLT_THROW("Cannot use SetPipeline in main scope"); - SetPipeline(cmd.Pipeline, i); + if (m_state != RecordState::Render && m_state != RecordState::Compute) + COPLT_THROW_FMT("[{}] Cannot use SetPipeline in main scope", i); + SetPipeline(list, cmd.Pipeline, i); } -void D3d12GpuRecord::Interpret_SetViewportScissor(u32 i, const FCmdSetViewportScissor& cmd) const +void D3d12GpuRecord::Interpret_SetViewportScissor(const CmdList& list, u32 i, const FCmdSetViewportScissor& cmd) const { - if (m_state != InterpretState::Render) - COPLT_THROW("Cannot use SetPipeline in main scope or compute scope"); - const auto& list = CurList(); + if (m_state != RecordState::Render) + COPLT_THROW_FMT("[{}] Can only use SetViewportScissor in render scope", i); list->g0->RSSetViewports(cmd.ViewportCount, reinterpret_cast(PayloadViewport.data() + cmd.ViewportIndex)); list->g0->RSSetScissorRects(cmd.ScissorRectCount, reinterpret_cast(PayloadRect.data() + cmd.ScissorRectIndex)); } -void D3d12GpuRecord::Interpret_Draw(u32 i, const FCmdDraw& cmd) const +void D3d12GpuRecord::Interpret_Draw(const CmdList& list, u32 i, const FCmdDraw& cmd) const { - if (m_state != InterpretState::Render) - COPLT_THROW("Cannot use SetPipeline in main scope or compute scope"); - const auto& list = CurList(); + if (m_state != RecordState::Render) + COPLT_THROW_FMT("[{}] Can only use _Draw in render scope", i); if (cmd.Indexed) { list->g0->DrawIndexedInstanced(cmd.VertexOrIndexCount, cmd.InstanceCount, cmd.FirstVertexOrIndex, cmd.VertexOffset, cmd.FirstInstance); @@ -487,11 +602,16 @@ void D3d12GpuRecord::Interpret_Draw(u32 i, const FCmdDraw& cmd) const } void D3d12GpuRecord::SetPipeline(NonNull pipeline, u32 i) +{ + if (pipeline == m_pipeline_context.Pipeline) return; + m_pipeline_context.SetPipeline(pipeline, i); +} + +void D3d12GpuRecord::SetPipeline(const CmdList& list, NonNull pipeline, u32 i) { if (pipeline == m_pipeline_context.Pipeline) return; m_pipeline_context.SetPipeline(pipeline, i); const auto stages = pipeline->GetStages(); - const auto& list = CurList(); if (HasFlags(stages, FShaderStageFlags::Compute)) { list->g0->SetComputeRootSignature(static_cast(m_pipeline_context.Layout->GetRootSignaturePtr())); @@ -505,6 +625,20 @@ void D3d12GpuRecord::SetPipeline(NonNull pipeline, u32 i) list->g0->SetPipelineState(static_cast(m_pipeline_context.Pipeline->GetPipelineStatePtr())); } +D3D12_COMMAND_LIST_TYPE Coplt::GetType(const FGpuRecordMode Mode) +{ + switch (Mode) + { + case FGpuRecordMode::Direct: + return D3D12_COMMAND_LIST_TYPE_DIRECT; + case FGpuRecordMode::Compute: + return D3D12_COMMAND_LIST_TYPE_COMPUTE; + case FGpuRecordMode::Copy: + return D3D12_COMMAND_LIST_TYPE_COPY; + } + return D3D12_COMMAND_LIST_TYPE_DIRECT; +} + NonNull Coplt::GetResource(const FCmdRes& res) { switch (res.Type) diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 3491475..613e82c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -3,7 +3,6 @@ #include "Barrier.h" #include "Context.h" #include "Isolate.h" -#include "RecordStorage.h" #include "../../Api/FFI/Record.h" #include "../../Api/Include/GpuObject.h" @@ -14,19 +13,24 @@ namespace Coplt virtual FGpuRecordData* Data() noexcept = 0; virtual const FGpuRecordData* Data() const noexcept = 0; + virtual const Rc& Context() const noexcept = 0; + virtual void RegisterWaitPoint(QueueWaitPoint&& wait_point) = 0; virtual void WaitAndRecycle(HANDLE event) = 0; virtual void Recycle() = 0; virtual void EnsureEnd() = 0; - virtual const Rc& Storage() = 0; - virtual const Rc& BarrierRecorder() = 0; + virtual const Rc& BarrierAnalyzer() = 0; + + virtual void Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) = 0; }; struct D3d12GpuRecord final : GpuObject, FGpuRecordData { - enum class InterpretState : u8 + using CmdList = D3d12RentedCommandList; + + enum class RecordState : u8 { Main, Render, @@ -59,13 +63,12 @@ namespace Coplt u64 m_record_id{}; Rc m_device{}; Rc m_context{}; - Rc m_storage{}; - Rc m_barrier_recorder{}; + Rc m_barrier_analyzer{}; std::vector> m_resources_owner{}; std::vector m_queue_wait_points{}; RenderState m_cur_render{}; PipelineContext m_pipeline_context{}; - InterpretState m_state{}; + RecordState m_state{}; explicit D3d12GpuRecord(NonNull isolate); @@ -73,9 +76,9 @@ namespace Coplt FGpuRecordData* GpuFGpuRecordData() noexcept override; FGpuRecordData* Data() noexcept override; const FGpuRecordData* Data() const noexcept override; + const Rc& Context() const noexcept override; - const Rc& Storage() override; - const Rc& BarrierRecorder() override; + const Rc& BarrierAnalyzer() override; void RegisterWaitPoint(QueueWaitPoint&& wait_point) override; void WaitAndRecycle(HANDLE event) override; @@ -87,26 +90,37 @@ namespace Coplt FCmdRes& GetRes(const FCmdResRef& ref); - D3d12RentedCommandList& CurList() const; + void ResetState(); void ReadyResource(); - void Interpret(); - void Interpret_Label(u32 i, const FCmdLabel& cmd) const; - void Interpret_BeginScope(u32 i, const FCmdBeginScope& cmd) const; - void Interpret_EndScope(u32 i, const FCmdEndScope& cmd) const; - void Interpret_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const; - void Interpret_ClearColor(u32 i, const FCmdClearColor& cmd); - void Interpret_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd); - void Interpret_BufferCopy(u32 i, const FCmdBufferCopy& cmd); - void Interpret_Render(u32 i, const FCmdRender& cmd); - void Interpret_RenderEnd(u32 i, const FCmdRender& cmd); - void Interpret_SetPipeline(u32 i, const FCmdSetPipeline& cmd); - void Interpret_SetViewportScissor(u32 i, const FCmdSetViewportScissor& cmd) const; - void Interpret_Draw(u32 i, const FCmdDraw& cmd) const; + + void Analyze(); + void Analyze_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const; + void Analyze_ClearColor(u32 i, const FCmdClearColor& cmd) const; + void Analyze_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd) const; + void Analyze_BufferCopy(u32 i, const FCmdBufferCopy& cmd) const; + void Analyze_Render(u32 i, const FCmdRender& cmd); + void Analyze_RenderEnd(u32 i, const FCmdRender& cmd); + void Analyze_SetPipeline(u32 i, const FCmdSetPipeline& cmd); + + void Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) override; + void Interpret_Label(const CmdList& list, u32 i, const FCmdLabel& cmd) const; + void Interpret_BeginScope(const CmdList& list, u32 i, const FCmdBeginScope& cmd) const; + void Interpret_EndScope(const CmdList& list, u32 i, const FCmdEndScope& cmd) const; + void Interpret_ClearColor(const CmdList& list, u32 i, const FCmdClearColor& cmd); + void Interpret_ClearDepthStencil(const CmdList& list, u32 i, const FCmdClearDepthStencil& cmd); + void Interpret_BufferCopy(const CmdList& list, u32 i, const FCmdBufferCopy& cmd); + void Interpret_Render(const CmdList& list, u32 i, const FCmdRender& cmd); + void Interpret_RenderEnd(const CmdList& list, u32 i, const FCmdRender& cmd); + void Interpret_SetPipeline(const CmdList& list, u32 i, const FCmdSetPipeline& cmd); + void Interpret_SetViewportScissor(const CmdList& list, u32 i, const FCmdSetViewportScissor& cmd) const; + void Interpret_Draw(const CmdList& list, u32 i, const FCmdDraw& cmd) const; void SetPipeline(NonNull pipeline, u32 i); + void SetPipeline(const CmdList& list, NonNull pipeline, u32 i); }; + D3D12_COMMAND_LIST_TYPE GetType(FGpuRecordMode Mode); NonNull GetResource(const FCmdRes& res); NonNull GetBufferData(const FCmdRes& res); NonNull GetImageData(const FCmdRes& res); diff --git a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc deleted file mode 100644 index 7c1758a..0000000 --- a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.cc +++ /dev/null @@ -1,80 +0,0 @@ -#include "RecordStorage.h" - -using namespace Coplt; - -D3d12RecordStorage::D3d12RecordStorage(NonNull isolate, const Rc& context) - : m_device(isolate->m_device), m_context(context) -{ -} - -void D3d12RecordStorage::Clear() -{ - m_result_lists.clear(); -} - -void D3d12RecordStorage::StartRecord(const FGpuRecordMode Mode) -{ - m_list_type = ToListType(Mode); - Split(); - Split(); -} - -void D3d12RecordStorage::EndRecord() -{ -} - -void D3d12RecordStorage::BeforeSubmit() -{ - for (auto& list : m_result_lists) - { - list.Close(); - } -} - -void D3d12RecordStorage::AfterSubmit() -{ -} - -u32 D3d12RecordStorage::Split() -{ - const auto i = m_result_lists.size(); - auto cmd_allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(m_list_type); - m_result_lists.push_back(cmd_allocator.RentCommandList()); - m_context->m_recycled_command_allocators.push_back(std::move(cmd_allocator)); - return i; -} - -D3d12RentedCommandList& D3d12RecordStorage::CurList() -{ - return m_result_lists.back(); -} - -u32 D3d12RecordStorage::CurListIndex() -{ - return m_result_lists.size() - 1; -} - -std::span D3d12RecordStorage::Lists() -{ - return m_result_lists; -} - -void D3d12RecordStorage::DropLast() -{ - CurList().Close(); - m_result_lists.pop_back(); -} - -D3D12_COMMAND_LIST_TYPE Coplt::ToListType(const FGpuRecordMode value) -{ - switch (value) - { - case FGpuRecordMode::Direct: - return D3D12_COMMAND_LIST_TYPE_DIRECT; - case FGpuRecordMode::Compute: - return D3D12_COMMAND_LIST_TYPE_COMPUTE; - case FGpuRecordMode::Copy: - return D3D12_COMMAND_LIST_TYPE_COPY; - } - return D3D12_COMMAND_LIST_TYPE_DIRECT; -} diff --git a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h b/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h deleted file mode 100644 index c63c5b8..0000000 --- a/Coplt.Graphics.Native/D3d12/Src/RecordStorage.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include "Context.h" -#include "../../Api/Include/Object.h" -#include "../../Api/FFI/Record.h" -#include "Isolate.h" - -namespace Coplt -{ - COPLT_INTERFACE_DEFINE(ID3d12RecordStorage, "ba14d287-5cea-4715-b655-7ad81184fd84", FUnknown) - { - virtual void Clear() = 0; - - virtual void StartRecord(FGpuRecordMode Mode) = 0; - virtual void EndRecord() = 0; - virtual void BeforeSubmit() = 0; - virtual void AfterSubmit() = 0; - - // 返回当前 List 的 index,是拆分后的新 list - virtual u32 Split() = 0; - virtual D3d12RentedCommandList& CurList() = 0; - - // 永远在前面保留一个空的 list 用于插入屏障 - virtual std::span Lists() = 0; - virtual u32 CurListIndex() = 0; - - virtual void DropLast() = 0; - }; - - struct D3d12RecordStorage final : Object - { - Rc m_device{}; - Rc m_context{}; - std::vector m_result_lists{}; - D3D12_COMMAND_LIST_TYPE m_list_type{}; - - explicit D3d12RecordStorage(NonNull isolate, const Rc& context); - - void Clear() override; - - void StartRecord(FGpuRecordMode Mode) override; - void EndRecord() override; - void BeforeSubmit() override; - void AfterSubmit() override; - - u32 Split() override; - D3d12RentedCommandList& CurList() override; - u32 CurListIndex() override; - std::span Lists() override; - - void DropLast() override; - }; - - D3D12_COMMAND_LIST_TYPE ToListType(FGpuRecordMode value); -} From 4b8060eeffcb8759ce268f11a0c2105996e49faf Mon Sep 17 00:00:00 2001 From: U2A5F Date: Mon, 31 Mar 2025 22:20:41 +0800 Subject: [PATCH 21/46] save --- Coplt.Graphics.Core/Core/GpuIsolate.cs | 8 ++ Coplt.Graphics.Core/Native/Native.cs | 14 +++- Coplt.Graphics.Native/Api/FFI/Cmd.h | 2 +- Coplt.Graphics.Native/Api/FFI/Common.h | 6 ++ Coplt.Graphics.Native/Api/FFI/Isolate.h | 10 +++ Coplt.Graphics.Native/Api/Include/Object.h | 4 + Coplt.Graphics.Native/Api/Include/Ptr.h | 12 +++ Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 92 ++++++++++++++-------- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 19 +++-- Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 4 +- Coplt.Graphics.Native/D3d12/Src/Isolate.h | 1 + Coplt.Graphics.Native/D3d12/Src/Record.cc | 22 +++++- Coplt.Graphics.Native/D3d12/Src/Record.h | 10 +++ 13 files changed, 161 insertions(+), 43 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 083714d..e89c883 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -6,6 +6,13 @@ namespace Coplt.Graphics.Core; +public ref struct GpuIsolateConfig(ref FGpuIsolateConfig @ref) +{ + internal ref FGpuIsolateConfig m_ref = ref @ref; + public ref bool MultiThreadRecord => ref Unsafe.As(ref m_ref.MultiThreadRecord); + public ref bool UseSplitBarrier => ref Unsafe.As(ref m_ref.UseSplitBarrier); +} + [Dropping(Unmanaged = true)] public sealed unsafe partial class GpuIsolate : DeviceChild { @@ -19,6 +26,7 @@ public sealed unsafe partial class GpuIsolate : DeviceChild public new FGpuIsolate* Ptr => (FGpuIsolate*)m_ptr; internal ref readonly FGpuIsolateData Data => ref *m_data; + public GpuIsolateConfig Config => new(ref *Data.Config); public FrameId FrameId => new(Data.FrameId); #endregion diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 58366c6..d609420 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1462,10 +1462,22 @@ public partial struct FGpuIsolateCreateOptions public FStr8or16 Name; } - public partial struct FGpuIsolateData + public partial struct FGpuIsolateConfig + { + [NativeTypeName("Coplt::b8")] + public B8 MultiThreadRecord; + + [NativeTypeName("Coplt::b8")] + public B8 UseSplitBarrier; + } + + public unsafe partial struct FGpuIsolateData { [NativeTypeName("Coplt::u64")] public ulong FrameId; + + [NativeTypeName("Coplt::FGpuIsolateConfig *")] + public FGpuIsolateConfig* Config; } [Guid("777C5774-8EB8-4550-A977-62CCCD7BDDA6")] diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index 6324142..7731fd5 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -1,7 +1,7 @@ #pragma once #include "Structs.h" -#include "Output.h"" +#include "Output.h" #include "Binding.h" #include "Pipeline.h" diff --git a/Coplt.Graphics.Native/Api/FFI/Common.h b/Coplt.Graphics.Native/Api/FFI/Common.h index 57e4b8e..8053507 100644 --- a/Coplt.Graphics.Native/Api/FFI/Common.h +++ b/Coplt.Graphics.Native/Api/FFI/Common.h @@ -72,6 +72,12 @@ #endif #endif +#ifndef COPLT_NULL_CHECK +#ifdef _DEBUG +#define COPLT_NULL_CHECK +#endif +#endif + #if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__) #define COPLT_X64 #elif defined(__aarch64__) || defined(_M_ARM64) diff --git a/Coplt.Graphics.Native/Api/FFI/Isolate.h b/Coplt.Graphics.Native/Api/FFI/Isolate.h index fe8efc0..a2b1593 100644 --- a/Coplt.Graphics.Native/Api/FFI/Isolate.h +++ b/Coplt.Graphics.Native/Api/FFI/Isolate.h @@ -24,9 +24,19 @@ namespace Coplt FStr8or16 Name{}; }; + struct FGpuIsolateConfig + { + // 提示可能会使用多线程命令录制,将在命令录制的 End 中完成转义操作,以分摊提交开销, + // 但是这会导致 gpu 屏障处于非最优状态,可能导致提交批次开始时的 gpu 管线停转,建议只在具有大量命令时使用多线程录制 + b8 MultiThreadRecord{}; + // 仅 d3d12,提示尽可能使用拆分屏障 + b8 UseSplitBarrier{}; + }; + struct FGpuIsolateData { u64 FrameId{}; + FGpuIsolateConfig* Config{}; }; COPLT_INTERFACE_DEFINE(FGpuIsolate, "777c5774-8eb8-4550-a977-62cccd7bdda6", FGpuObject) diff --git a/Coplt.Graphics.Native/Api/Include/Object.h b/Coplt.Graphics.Native/Api/Include/Object.h index 78e340d..37b7a48 100644 --- a/Coplt.Graphics.Native/Api/Include/Object.h +++ b/Coplt.Graphics.Native/Api/Include/Object.h @@ -662,8 +662,10 @@ namespace Coplt T& Rc::operator*() const { const auto ptr = get(); + #ifdef COPLT_NULL_CHECK if (ptr == nullptr) [[unlikely]] COPLT_THROW("Null Pointer"); + #endif return *ptr; } @@ -671,8 +673,10 @@ namespace Coplt T* Rc::operator->() const { const auto ptr = get(); + #ifdef COPLT_NULL_CHECK if (ptr == nullptr) [[unlikely]] COPLT_THROW("Null Pointer"); + #endif return ptr; } } diff --git a/Coplt.Graphics.Native/Api/Include/Ptr.h b/Coplt.Graphics.Native/Api/Include/Ptr.h index 1932659..a93e018 100644 --- a/Coplt.Graphics.Native/Api/Include/Ptr.h +++ b/Coplt.Graphics.Native/Api/Include/Ptr.h @@ -123,15 +123,19 @@ namespace Coplt T* operator->() const { + #ifdef COPLT_NULL_CHECK if (m_ptr == nullptr) [[unlikely]] COPLT_THROW("Null Pointer"); + #endif return m_ptr; } T& operator*() const { + #ifdef COPLT_NULL_CHECK if (m_ptr == nullptr) [[unlikely]] COPLT_THROW("Null Pointer"); + #endif return *m_ptr; } @@ -214,15 +218,19 @@ namespace Coplt NonNull(T* ptr) : m_ptr(ptr) { + #ifdef COPLT_NULL_CHECK if (m_ptr == nullptr) [[unlikely]] COPLT_THROW("Null Pointer"); + #endif } template requires std::convertible_to NonNull(U* ptr) : m_ptr(ptr) { + #ifdef COPLT_NULL_CHECK if (m_ptr == nullptr) [[unlikely]] COPLT_THROW("Null Pointer"); + #endif } NonNull(const Rc& rc) : NonNull(rc.get()) @@ -236,15 +244,19 @@ namespace Coplt NonNull(Ptr ptr) : m_ptr(ptr.m_ptr) { + #ifdef COPLT_NULL_CHECK if (m_ptr == nullptr) [[unlikely]] COPLT_THROW("Null Pointer"); + #endif } template requires std::convertible_to NonNull(Ptr ptr) : m_ptr(ptr.m_ptr) { + #ifdef COPLT_NULL_CHECK if (m_ptr == nullptr) [[unlikely]] COPLT_THROW("Null Pointer"); + #endif } NonNull(NonNull&& other) noexcept : m_ptr(std::exchange(other.m_ptr, nullptr)) diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index dfd54e3..e8b1cdd 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -20,6 +20,11 @@ void ID3d12EnhancedBarrierAnalyzer::Group::Clear() m_texture_barriers.clear(); } +bool ID3d12EnhancedBarrierAnalyzer::Group::IsEmpty() const +{ + return m_buffer_barriers.empty() && m_texture_barriers.empty(); +} + ID3d12EnhancedBarrierAnalyzer::ResInfo::ResInfo(const NonNull Res) : Res(Res) { } @@ -32,14 +37,14 @@ void ID3d12EnhancedBarrierAnalyzer::ResInfo::SetNewState(const ResState state) namespace Coplt::Enhanced { - EnhancedBarrierMarshal::EnhancedBarrierMarshal(const Rc& device) - : m_device(device) + EnhancedBarrierMarshal::EnhancedBarrierMarshal(const D3d12GpuIsolate& isolate) + : m_isolate_config(isolate.m_config), m_device(isolate.m_device) { } Rc EnhancedBarrierMarshal::CreateAnalyzer() { - return new EnhancedBarrierAnalyzer(m_device); + return new EnhancedBarrierAnalyzer(*this); } Rc EnhancedBarrierMarshal::CreateCombiner() @@ -47,8 +52,8 @@ namespace Coplt::Enhanced return new EnhancedBarrierCombiner(m_device); } - EnhancedBarrierAnalyzer::EnhancedBarrierAnalyzer(const Rc& device) - : m_device(device) + EnhancedBarrierAnalyzer::EnhancedBarrierAnalyzer(const EnhancedBarrierMarshal& marshal) + : m_isolate_config(marshal.m_isolate_config), m_device(marshal.m_device) { } @@ -208,7 +213,7 @@ namespace Coplt::Enhanced barrier.SyncAfter = SyncAfter; m_groups[AfterListIndex].Push(barrier); } - else + else if (m_isolate_config->UseSplitBarrier) { m_groups[BeforeListIndex].Push(barrier); @@ -216,6 +221,11 @@ namespace Coplt::Enhanced barrier.SyncAfter = SyncAfter; m_groups[AfterListIndex].Push(barrier); } + else + { + barrier.SyncAfter = SyncAfter; + m_groups[BeforeListIndex].Push(barrier); + } }; if (res.IsImage()) { @@ -300,6 +310,7 @@ namespace Coplt::Enhanced void EnhancedBarrierCombiner::EndSubmit() { Base::EndSubmit(); + m_tmp_group.Clear(); } void EnhancedBarrierCombiner::Process(NonNull isolate, std::span> records) @@ -310,6 +321,8 @@ namespace Coplt::Enhanced const NonNull barrier_analyzer = record->BarrierAnalyzer()->QueryInterface(); const auto& context = record->Context(); + const auto& result_list = record->ResultList(); + #pragma region 生成输入屏障 for (const auto& input : barrier_analyzer->Inputs()) @@ -325,7 +338,7 @@ namespace Coplt::Enhanced }); if (!exist) { - const auto AfterIndex = input.LstGroup; + auto& group = result_list ? m_tmp_group : barrier_analyzer->Groups()[0]; if (res.IsImage()) { const auto img_data = GetImageData(res); @@ -348,7 +361,7 @@ namespace Coplt::Enhanced }, .Flags = D3D12_TEXTURE_BARRIER_FLAG_NONE, }; - barrier_analyzer->Groups()[0].Push(barrier); + group.Push(barrier); } else { @@ -364,19 +377,7 @@ namespace Coplt::Enhanced .Size = buffer_data->m_size, }; barrier.SyncAfter = SyncAfter; - barrier_analyzer->Groups()[0].Push(barrier); - // if (AfterIndex == 0) - // { - // barrier.SyncAfter = SyncAfter; - // barrier_recorder->BarrierGroups()[0].Push(barrier); - // } - // else - // { - // barrier_recorder->BarrierGroups()[0].Push(barrier); - // barrier.SyncBefore = D3D12_BARRIER_SYNC_SPLIT; - // barrier.SyncAfter = SyncAfter; - // barrier_recorder->BarrierGroups()[AfterIndex].Push(barrier); - // } + group.Push(barrier); } } // todo @@ -384,22 +385,43 @@ namespace Coplt::Enhanced #pragma endregion - #pragma region 完成录制 记录 list 范围 + #pragma region 完成录制 记录 list 节点 { - auto allocator = context->m_cmd_alloc_pool->RentCommandAllocator(GetType(data->Mode)); - auto list = allocator.RentCommandList(); - - barrier_analyzer->Interpret(list, *record); - ListNode node{}; // todo fence - node.List = list->ToCommandList(); node.Queue = FGpuQueueType::Direct; // todo 选择队列 - m_list_node.push_back(node); + node.ListIndex = m_lists.size(); + node.ListCount++; + + if (!m_tmp_group.IsEmpty()) + { + auto allocator = context->m_cmd_alloc_pool->RentCommandAllocator(GetType(data->Mode)); + auto list = allocator.RentCommandList(); + EnhancedBarrierAnalyzer::SubmitBarrier(list, m_tmp_group); + list.Close(); + m_lists.push_back(list->ToCommandList()); + node.ListCount++; + m_rented_lists.push_back(std::move(list)); + context->m_recycled_command_allocators.push_back(std::move(allocator)); + } + + if (result_list) + { + m_lists.push_back(result_list->ToCommandList()); + } + else + { + auto allocator = context->m_cmd_alloc_pool->RentCommandAllocator(GetType(data->Mode)); + auto list = allocator.RentCommandList(); + barrier_analyzer->Interpret(list, *record); + list.Close(); + m_lists.push_back(list->ToCommandList()); + m_rented_lists.push_back(std::move(list)); + context->m_recycled_command_allocators.push_back(std::move(allocator)); + } - list.Close(); - context->m_recycled_command_allocators.push_back(std::move(allocator)); + m_list_node.push_back(node); } #pragma endregion @@ -431,6 +453,8 @@ void AD3d12BarrierCombiner::StartSubmit() void AD3d12BarrierCombiner::EndSubmit() { m_list_node.clear(); + m_lists.clear(); + m_rented_lists.clear(); m_queue_deps.clear(); m_submit_resources.Clear(); m_used_queues = FGpuQueueFlags::None; @@ -456,7 +480,7 @@ bool AD3d12BarrierCombiner::Submit(NonNull isolate, std::spanGetQueue(dep); queue->Wait(*dep_queue, dep_queue->Signal()); } - queue->m_queue->ExecuteCommandLists(1, &node.List); + queue->m_queue->ExecuteCommandLists(node.ListCount, m_lists.data() + node.ListIndex); } #pragma endregion @@ -489,5 +513,9 @@ bool AD3d12BarrierCombiner::Submit(NonNull isolate, std::spanAfterSubmit(); + } return has_submit; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index 31a23f9..2688a68 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -39,6 +39,8 @@ namespace Coplt virtual void OnCmd() = 0; // 每个命令都需要调用一次 virtual void CmdNext() = 0; + + virtual void Interpret(const D3d12RentedCommandList& list, ID3d12GpuRecord& record) = 0; }; COPLT_INTERFACE_DEFINE(ID3d12BarrierCombiner, "e1e15444-6369-4d8a-90b3-153672abca39", FUnknown) @@ -59,11 +61,14 @@ namespace Coplt { u32 DepIndex{}; u32 DepCount{}; - ID3D12CommandList* List; + u32 ListIndex{}; + u32 ListCount{}; FGpuQueueType Queue{}; }; Rc m_device{}; + std::vector m_lists{}; + std::vector m_rented_lists{}; std::vector m_list_node{}; std::vector m_queue_deps{}; FGpuQueueFlags m_used_queues{}; @@ -98,6 +103,7 @@ namespace Coplt void Push(D3D12_TEXTURE_BARRIER barrier); void Clear(); + bool IsEmpty() const; }; struct ResInfo @@ -116,17 +122,16 @@ namespace Coplt }; virtual std::span Groups() = 0; - - virtual void Interpret(const D3d12RentedCommandList& list, ID3d12GpuRecord& record) = 0; }; namespace Enhanced { struct EnhancedBarrierMarshal final : Object { + SRc m_isolate_config{}; Rc m_device; - explicit EnhancedBarrierMarshal(const Rc& device); + explicit EnhancedBarrierMarshal(const D3d12GpuIsolate& isolate); Rc CreateAnalyzer() override; Rc CreateCombiner() override; @@ -134,6 +139,7 @@ namespace Coplt struct EnhancedBarrierAnalyzer final : Object { + SRc m_isolate_config{}; Rc m_device{}; std::vector m_resources{}; std::vector m_inputs{}; @@ -141,7 +147,7 @@ namespace Coplt std::vector m_groups{}; u32 m_last_cmd_count{}; - explicit EnhancedBarrierAnalyzer(const Rc& device); + explicit EnhancedBarrierAnalyzer(const EnhancedBarrierMarshal& marshal); std::span Inputs() const override; std::span Outputs() const override; @@ -170,8 +176,7 @@ namespace Coplt { explicit EnhancedBarrierCombiner(const Rc& device); - // std::vector m_buffer_barriers{}; - // std::vector m_texture_barriers{}; + ID3d12EnhancedBarrierAnalyzer::Group m_tmp_group{}; void EndSubmit() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index 2939326..3c83567 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -11,6 +11,8 @@ using namespace Coplt; D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options) : FGpuIsolateData() { + m_config = src(); + this->Config = m_config.get(); m_waiting_record = box(); m_record_pool = box(); m_device = std::move(device); @@ -23,7 +25,7 @@ D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCre #pragma endregion - m_barrier_marshal = new Enhanced::EnhancedBarrierMarshal(m_device); + m_barrier_marshal = new Enhanced::EnhancedBarrierMarshal(*this); m_barrier_combiner = m_barrier_marshal->CreateCombiner(); m_cmd_alloc_pool = new D3d12CommandListPoolCluster(m_device); diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index c68ac11..6dde66c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -28,6 +28,7 @@ namespace Coplt { using RecordQueue = moodycamel::ConcurrentQueue>; + SRc m_config{}; Rc m_main_queue{}; Rc m_compute_queue{}; Rc m_copy_queue{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 0ec8cfb..4d637f7 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -45,7 +45,8 @@ void D3d12GpuRecord::PipelineContext::SetPipeline(NonNull pipel } D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) - : FGpuRecordData(isolate->m_device->m_instance->m_allocator.get()), m_device(isolate->m_device) + : FGpuRecordData(isolate->m_device->m_instance->m_allocator.get()), + m_isolate_config(isolate->m_config), m_device(isolate->m_device) { Id = m_isolate_id = isolate->m_object_id; m_record_id = isolate->m_record_inc++; @@ -79,6 +80,11 @@ const Rc& D3d12GpuRecord::Context() const noexcept return m_context; } +const D3d12RentedCommandList& D3d12GpuRecord::ResultList() const noexcept +{ + return m_result_list; +} + const Rc& D3d12GpuRecord::BarrierAnalyzer() { return m_barrier_analyzer; @@ -131,10 +137,24 @@ void D3d12GpuRecord::DoEnd() COPLT_THROW("Too many resources"); ReadyResource(); Analyze(); + if (m_isolate_config->MultiThreadRecord) + { + auto allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(GetType(Mode)); + auto list = allocator.RentCommandList(); + m_barrier_analyzer->Interpret(list, *this); + list.Close(); + m_result_list = std::move(list); + m_context->m_recycled_command_allocators.push_back(std::move(allocator)); + } Ended = true; Version++; } +void D3d12GpuRecord::AfterSubmit() +{ + m_result_list = {}; +} + FCmdRes& D3d12GpuRecord::GetRes(const FCmdResRef& ref) { return ref.Get(Resources); diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 613e82c..1636f32 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -15,6 +15,9 @@ namespace Coplt virtual const Rc& Context() const noexcept = 0; + // 可空 + virtual const D3d12RentedCommandList& ResultList() const noexcept = 0; + virtual void RegisterWaitPoint(QueueWaitPoint&& wait_point) = 0; virtual void WaitAndRecycle(HANDLE event) = 0; virtual void Recycle() = 0; @@ -24,6 +27,8 @@ namespace Coplt virtual const Rc& BarrierAnalyzer() = 0; virtual void Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) = 0; + + virtual void AfterSubmit() = 0; }; struct D3d12GpuRecord final : GpuObject, FGpuRecordData @@ -61,6 +66,7 @@ namespace Coplt u64 m_isolate_id{}; u64 m_record_id{}; + SRc m_isolate_config{}; Rc m_device{}; Rc m_context{}; Rc m_barrier_analyzer{}; @@ -69,6 +75,7 @@ namespace Coplt RenderState m_cur_render{}; PipelineContext m_pipeline_context{}; RecordState m_state{}; + D3d12RentedCommandList m_result_list{}; explicit D3d12GpuRecord(NonNull isolate); @@ -77,6 +84,7 @@ namespace Coplt FGpuRecordData* Data() noexcept override; const FGpuRecordData* Data() const noexcept override; const Rc& Context() const noexcept override; + const D3d12RentedCommandList& ResultList() const noexcept override; const Rc& BarrierAnalyzer() override; @@ -88,6 +96,8 @@ namespace Coplt void EnsureEnd() override; void DoEnd(); + void AfterSubmit() override; + FCmdRes& GetRes(const FCmdResRef& ref); void ResetState(); From 138509eb7d5ee7841025d735fa2f8fd3a66103f6 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Mon, 31 Mar 2025 23:17:01 +0800 Subject: [PATCH 22/46] save --- Coplt.Graphics.Core/Core/GpuRecord.cs | 172 +++++++++------------ Coplt.Graphics.Core/Native/FList.cs | 9 +- Coplt.Graphics.Core/Native/Native.cs | 42 ++++- Coplt.Graphics.Native/Api/FFI/Cmd.h | 33 +++- Coplt.Graphics.Native/Api/FFI/Record.h | 7 +- Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 10 +- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 1 + Coplt.Graphics.Native/D3d12/Src/Record.cc | 59 ++++++- Coplt.Graphics.Native/D3d12/Src/Record.h | 3 + Examples/HelloTriangleVertex/Example.cs | 14 +- 10 files changed, 231 insertions(+), 119 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index ff7ad94..8aaa5d3 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -513,7 +513,7 @@ public RenderScope2 Render( ) { AssertNotEnded(); - + #region Check Nested if (m_in_render_or_compute_scope) throw new InvalidOperationException("Cannot nest Render or Compute scopes"); @@ -825,105 +825,77 @@ ReadOnlySpan Scissors #endregion - // #region SetMeshBuffers - // - // public void SetMeshBuffers( - // MeshLayout MeshLayout, - // uint VertexStartSlot, - // ReadOnlySpan VertexBuffers - // ) => SetMeshBuffers(MeshLayout, FGraphicsFormat.Unknown, null, VertexStartSlot, VertexBuffers); - // - // public void SetMeshBuffers( - // MeshLayout MeshLayout, - // ReadOnlySpan VertexBuffers - // ) => SetMeshBuffers(MeshLayout, FGraphicsFormat.Unknown, null, 0, VertexBuffers); - // - // public void SetMeshBuffers( - // MeshLayout MeshLayout, - // FGraphicsFormat IndexFormat, - // BufferRange? IndexBuffer, - // uint VertexStartSlot, - // ReadOnlySpan VertexBuffers - // ) - // { - // self.AddObject(MeshLayout); - // var cmd = new FCommandSetMeshBuffers - // { - // Base = { Type = FCommandType.SetMeshBuffers }, - // IndexFormat = IndexFormat, - // VertexStartSlot = VertexStartSlot, - // PayloadIndex = (uint)self.m_mesh_buffers.Count, - // }; - // var buf = new FMeshBuffers - // { - // MeshLayout = MeshLayout.m_ptr, - // VertexBufferCount = (uint)VertexBuffers.Length, - // }; - // if (IndexBuffer is { } index_buffer) - // { - // buf.IndexBuffer = new() - // { - // Buffer = self.AddResource(index_buffer.Buffer.Resource), - // Offset = index_buffer.Offset, - // Size = index_buffer.Size == uint.MaxValue ? (uint)index_buffer.Buffer.Size : index_buffer.Size, - // }; - // 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) - // { - // var index = self.m_vertex_buffer_ranges.Count; - // buf.VertexBuffersIndex = (uint)index; - // CollectionsMarshal.SetCount( - // self.m_vertex_buffer_ranges, self.m_vertex_buffer_ranges.Count + VertexBuffers.Length - // ); - // var vbs = CollectionsMarshal.AsSpan(self.m_vertex_buffer_ranges).Slice(index, VertexBuffers.Length); - // for (var i = 0; i < VertexBuffers.Length; i++) - // { - // var buffer = VertexBuffers[i]; - // buffer.Buffer.AssertSameQueue(self.Queue); - // ref var dst = ref vbs[i]; - // dst = new() - // { - // Base = - // { - // Buffer = self.AddResource(buffer.Buffer.Resource), - // Offset = buffer.Offset, - // Size = buffer.Size == uint.MaxValue ? (uint)buffer.Buffer.Size : buffer.Size, - // }, - // Index = buffer.Index, - // }; - // 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); - // m_commands.Add(new() { SetMeshBuffers = cmd }); - // } - // - // #endregion + #region SetMeshBuffers + + public void SetMeshBuffers( + MeshLayout MeshLayout, + uint VertexStartSlot, + ReadOnlySpan VertexBuffers + ) => SetMeshBuffers(MeshLayout, FGraphicsFormat.Unknown, null, VertexStartSlot, VertexBuffers); + + public void SetMeshBuffers( + MeshLayout MeshLayout, + ReadOnlySpan VertexBuffers + ) => SetMeshBuffers(MeshLayout, FGraphicsFormat.Unknown, null, 0, VertexBuffers); + + public void SetMeshBuffers( + MeshLayout MeshLayout, + FGraphicsFormat IndexFormat, + BufferRange? IndexBuffer, + uint VertexStartSlot, + ReadOnlySpan VertexBuffers + ) + { + self.AddObject(MeshLayout); + var cmd = new FCmdSetMeshBuffers + { + Base = { Type = FCmdType.SetMeshBuffers }, + IndexFormat = IndexFormat, + VertexStartSlot = VertexStartSlot, + PayloadIndex = (uint)self.Data.PayloadMeshBuffers.LongLength, + }; + var buf = new FMeshBuffers2 + { + MeshLayout = MeshLayout.m_ptr, + VertexBufferCount = (uint)VertexBuffers.Length, + }; + if (IndexBuffer is { } index_buffer) + { + // index_buffer.Buffer.AssertSameIsolate(self.Isolate); // todo + buf.IndexBuffer = new() + { + Buffer = self.AddResource(index_buffer.Buffer.Resource), + Offset = index_buffer.Offset, + Size = index_buffer.Size == uint.MaxValue ? (uint)index_buffer.Buffer.Size : index_buffer.Size, + }; + } + if (VertexBuffers.Length > 0) + { + var index = self.Data.PayloadVertexBufferRange.LongLength; + buf.VertexBuffersIndex = (uint)index; + var vbs = self.Data.PayloadVertexBufferRange.UnsafeAddRange(VertexBuffers.Length); + for (var i = 0; i < VertexBuffers.Length; i++) + { + var buffer = VertexBuffers[i]; + // buffer.Buffer.AssertSameIsolate(self.Isolate); // todo + ref var dst = ref vbs[i]; + dst = new() + { + Base = + { + Buffer = self.AddResource(buffer.Buffer.Resource), + Offset = buffer.Offset, + Size = buffer.Size == uint.MaxValue ? (uint)buffer.Buffer.Size : buffer.Size, + }, + Index = buffer.Index, + }; + } + } + self.Data.PayloadMeshBuffers.Add(buf); + self.Data.Commands.Add(new() { SetMeshBuffers = cmd }); + } + + #endregion #region Draw diff --git a/Coplt.Graphics.Core/Native/FList.cs b/Coplt.Graphics.Core/Native/FList.cs index e7b4879..ef8de13 100644 --- a/Coplt.Graphics.Core/Native/FList.cs +++ b/Coplt.Graphics.Core/Native/FList.cs @@ -148,14 +148,17 @@ public void Add(T item) #region AddRange - public void AddRange(ReadOnlySpan span) + public Span UnsafeAddRange(int size) { - var new_len = m_len + (nuint)span.Length; + var new_len = m_len + (nuint)size; if (new_len >= m_cap) EnsureCap(new_len); - span.CopyTo(new Span(m_ptr + m_len, span.Length)); + var span = new Span(m_ptr + m_len, size); m_len = new_len; + return span; } + public void AddRange(ReadOnlySpan span) => span.CopyTo(UnsafeAddRange(span.Length)); + #endregion #region RemoveAt diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index d609420..b34d0bf 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1655,6 +1655,10 @@ public unsafe partial struct FGpuRecordData public FList PayloadBufferCopyRange; + public FList PayloadMeshBuffers; + + public FList PayloadVertexBufferRange; + [NativeTypeName("FList")] public FList Blob; @@ -2108,6 +2112,42 @@ public partial struct FCmdSetViewportScissor public uint ScissorRectIndex; } + public partial struct FBufferRange2 + { + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Buffer; + + [NativeTypeName("Coplt::u32")] + public uint Offset; + + [NativeTypeName("Coplt::u32")] + public uint Size; + } + + [NativeTypeName("struct FVertexBufferRange2 : Coplt::FBufferRange2")] + public partial struct FVertexBufferRange2 + { + public FBufferRange2 Base; + + [NativeTypeName("Coplt::u32")] + public uint Index; + } + + public unsafe partial struct FMeshBuffers2 + { + [NativeTypeName("Coplt::FMeshLayout *")] + public FMeshLayout* MeshLayout; + + [NativeTypeName("Coplt::FBufferRange2")] + public FBufferRange2 IndexBuffer; + + [NativeTypeName("Coplt::u32")] + public uint VertexBufferCount; + + [NativeTypeName("Coplt::u32")] + public uint VertexBuffersIndex; + } + [NativeTypeName("struct FCmdSetMeshBuffers : Coplt::FCmdBase")] public partial struct FCmdSetMeshBuffers { @@ -2149,7 +2189,7 @@ public partial struct FCmdDraw public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L320_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L343_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index 7731fd5..8ef40c8 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -122,6 +122,14 @@ namespace Coplt COPLT_THROW("Index out of range"); return list[index]; } + + const FCmdRes& Get(const FList& list) const + { + const auto index = ResIndex(); + if (index > list.m_len) + COPLT_THROW("Index out of range"); + return list[index]; + } #endif }; @@ -293,12 +301,35 @@ namespace Coplt u32 ScissorRectIndex{}; }; + struct FBufferRange2 + { + FCmdResRef Buffer{}; + u32 Offset{}; + u32 Size{}; + }; + + struct FVertexBufferRange2 : FBufferRange2 + { + u32 Index{}; + }; + + struct FMeshBuffers2 + { + FMeshLayout* MeshLayout{}; + // 可选 + FBufferRange2 IndexBuffer{}; + // 0 .. 31 + u32 VertexBufferCount{}; + // Payload 内的索引,类型为 FVertexBufferRange2 + u32 VertexBuffersIndex{}; + }; + struct FCmdSetMeshBuffers : FCmdBase { FGraphicsFormat IndexFormat{}; // 0 .. 31 u32 VertexStartSlot{}; - // 类型为 FMeshBuffers + // 类型为 FMeshBuffers2 u32 PayloadIndex{}; }; diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index fa02fe2..d6ead62 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -37,6 +37,8 @@ namespace Coplt FList PayloadRenderInfo; FList PayloadResolveInfo; FList PayloadBufferCopyRange; + FList PayloadMeshBuffers; + FList PayloadVertexBufferRange; FList Blob; b8 Ended{}; FGpuRecordMode Mode{}; @@ -44,7 +46,8 @@ namespace Coplt #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) : Commands(allocator), Resources(allocator), PayloadRect(allocator), PayloadViewport(allocator), - PayloadRenderInfo(allocator), PayloadResolveInfo(allocator), PayloadBufferCopyRange(allocator), Blob(allocator) + PayloadRenderInfo(allocator), PayloadResolveInfo(allocator), PayloadBufferCopyRange(allocator), + PayloadMeshBuffers(allocator), PayloadVertexBufferRange(allocator), Blob(allocator) { } @@ -57,6 +60,8 @@ namespace Coplt PayloadRenderInfo.Clear(); PayloadResolveInfo.Clear(); PayloadBufferCopyRange.Clear(); + PayloadMeshBuffers.Clear(); + PayloadVertexBufferRange.Clear(); Blob.Clear(); } #endif diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index e8b1cdd..4da7765 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -97,6 +97,7 @@ namespace Coplt::Enhanced void EnhancedBarrierAnalyzer::StartAnalyze(const std::span resources) { + m_use_split_barrier = m_isolate_config->UseSplitBarrier; Clear(); m_resources.reserve(resources.size()); for (usize i = 0; i < resources.size(); ++i) @@ -130,11 +131,12 @@ namespace Coplt::Enhanced const auto ResIndex = ResRef.ResIndex(); auto& info = m_resources[ResIndex]; const auto new_state = ResState(Access, Usage, Layout); + const auto need_split = m_use_split_barrier && m_last_cmd_count > 0; if (info.InfoState == InfoState::Unused) { info.InfoState = InfoState::Input; info.State = new_state; - if (m_last_cmd_count > 0) Split(); + if (need_split) Split(); info.PreGroup = 0; info.LstGroup = info.CurGroup = CurGroupIndex(); return; @@ -148,7 +150,7 @@ namespace Coplt::Enhanced } info.InfoState = InfoState::Used; m_inputs.push_back(IOResState{.ResIndex = ResIndex, .LstGroup = info.LstGroup, .State = info.State}); - if (info.CurGroup == CurGroupIndex() || m_last_cmd_count > 0) Split(); + if (info.CurGroup == CurGroupIndex() || need_split) Split(); goto EndState; } else @@ -159,7 +161,7 @@ namespace Coplt::Enhanced goto End; } } - if (info.CurGroup == CurGroupIndex() || m_last_cmd_count > 0) Split(); + if (info.CurGroup == CurGroupIndex() || need_split) Split(); CreateBarrier(info); EndState: info.SetNewState(new_state); @@ -213,7 +215,7 @@ namespace Coplt::Enhanced barrier.SyncAfter = SyncAfter; m_groups[AfterListIndex].Push(barrier); } - else if (m_isolate_config->UseSplitBarrier) + else if (m_use_split_barrier) { m_groups[BeforeListIndex].Push(barrier); diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index 2688a68..af50f98 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -146,6 +146,7 @@ namespace Coplt std::vector m_outputs{}; std::vector m_groups{}; u32 m_last_cmd_count{}; + b8 m_use_split_barrier{}; explicit EnhancedBarrierAnalyzer(const EnhancedBarrierMarshal& marshal); diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 4d637f7..d513755 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -160,6 +160,11 @@ FCmdRes& D3d12GpuRecord::GetRes(const FCmdResRef& ref) return ref.Get(Resources); } +const FCmdRes& D3d12GpuRecord::GetRes(const FCmdResRef& ref) const +{ + return ref.Get(Resources); +} + void D3d12GpuRecord::ResetState() { m_state = RecordState::Main; @@ -220,7 +225,8 @@ void D3d12GpuRecord::Analyze() case FCmdType::SetBinding: COPLT_THROW("TODO"); case FCmdType::SetMeshBuffers: - COPLT_THROW("TODO"); + Analyze_SetMeshBuffers(i, command.SetMeshBuffers); + break; case FCmdType::SetViewportScissor: if (Mode != FGpuRecordMode::Direct) COPLT_THROW_FMT("[{}] Can only Draw on the direct mode", i); @@ -326,6 +332,23 @@ void D3d12GpuRecord::Analyze_SetPipeline(u32 i, const FCmdSetPipeline& cmd) SetPipeline(cmd.Pipeline, i); } +void D3d12GpuRecord::Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd) +{ + if (m_state != RecordState::Render) + COPLT_THROW_FMT("[{}] Can only use SetMeshBuffers in render scope", i); + const auto& buf = PayloadMeshBuffers[cmd.PayloadIndex]; + if (buf.IndexBuffer.Buffer) + { + m_barrier_analyzer->OnUse(buf.IndexBuffer.Buffer, ResAccess::IndexBufferRead, ResUsage::VertexOrMesh, ResLayout::Undefined); + } + for (u32 c = 0; c < buf.VertexBufferCount; ++c) + { + const auto& item = PayloadVertexBufferRange[c]; + m_barrier_analyzer->OnUse(item.Buffer, ResAccess::VertexBufferRead, ResUsage::VertexOrMesh, ResLayout::Undefined); + } + m_barrier_analyzer->OnCmd(); +} + void D3d12GpuRecord::Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) { const auto commands = Commands.AsSpan(); @@ -376,7 +399,8 @@ void D3d12GpuRecord::Interpret(const D3d12RentedCommandList& list, u32 offset, u Interpret_SetViewportScissor(list, i, command.SetViewportScissor); break; case FCmdType::SetMeshBuffers: - COPLT_THROW("TODO"); + Interpret_SetMeshBuffers(list, i, command.SetMeshBuffers); + break; case FCmdType::Draw: Interpret_Draw(list, i, command.Draw); break; @@ -607,6 +631,37 @@ void D3d12GpuRecord::Interpret_SetViewportScissor(const CmdList& list, u32 i, co list->g0->RSSetScissorRects(cmd.ScissorRectCount, reinterpret_cast(PayloadRect.data() + cmd.ScissorRectIndex)); } +void D3d12GpuRecord::Interpret_SetMeshBuffers(const CmdList& list, u32 i, const FCmdSetMeshBuffers& cmd) const +{ + if (m_state != RecordState::Render) + COPLT_THROW_FMT("[{}] Can only use SetViewportScissor in render scope", i); + const auto& buffers = PayloadMeshBuffers[cmd.PayloadIndex]; + const auto defs = buffers.MeshLayout->GetBuffers(); + const auto vbs = std::span(PayloadVertexBufferRange.data() + buffers.VertexBuffersIndex, buffers.VertexBufferCount); + if (buffers.IndexBuffer.Buffer) + { + const auto resource = GetResource(GetRes(buffers.IndexBuffer.Buffer)); + D3D12_INDEX_BUFFER_VIEW view{}; + view.BufferLocation = resource->GetGPUVirtualAddress() + buffers.IndexBuffer.Offset; + view.SizeInBytes = buffers.IndexBuffer.Size; + view.Format = ToDx(cmd.IndexFormat); + list->g0->IASetIndexBuffer(&view); + } + D3D12_VERTEX_BUFFER_VIEW views[vbs.size()]; + for (u32 j = 0; j < vbs.size(); j++) + { + const auto& range = vbs[j]; + const auto& def = defs[range.Index]; + const auto resource = GetResource(GetRes(range.Buffer)); + D3D12_VERTEX_BUFFER_VIEW view{}; + view.BufferLocation = resource->GetGPUVirtualAddress() + range.Offset; + view.SizeInBytes = range.Size; + view.StrideInBytes = def.Stride; + views[j] = view; + } + list->g0->IASetVertexBuffers(cmd.VertexStartSlot, buffers.VertexBufferCount, views); +} + void D3d12GpuRecord::Interpret_Draw(const CmdList& list, u32 i, const FCmdDraw& cmd) const { if (m_state != RecordState::Render) diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 1636f32..ad8d1cb 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -99,6 +99,7 @@ namespace Coplt void AfterSubmit() override; FCmdRes& GetRes(const FCmdResRef& ref); + const FCmdRes& GetRes(const FCmdResRef& ref) const; void ResetState(); @@ -112,6 +113,7 @@ namespace Coplt void Analyze_Render(u32 i, const FCmdRender& cmd); void Analyze_RenderEnd(u32 i, const FCmdRender& cmd); void Analyze_SetPipeline(u32 i, const FCmdSetPipeline& cmd); + void Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd); void Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) override; void Interpret_Label(const CmdList& list, u32 i, const FCmdLabel& cmd) const; @@ -124,6 +126,7 @@ namespace Coplt void Interpret_RenderEnd(const CmdList& list, u32 i, const FCmdRender& cmd); void Interpret_SetPipeline(const CmdList& list, u32 i, const FCmdSetPipeline& cmd); void Interpret_SetViewportScissor(const CmdList& list, u32 i, const FCmdSetViewportScissor& cmd) const; + void Interpret_SetMeshBuffers(const CmdList& list, u32 i, const FCmdSetMeshBuffers& cmd) const; void Interpret_Draw(const CmdList& list, u32 i, const FCmdDraw& cmd) const; void SetPipeline(NonNull pipeline, u32 i); diff --git a/Examples/HelloTriangleVertex/Example.cs b/Examples/HelloTriangleVertex/Example.cs index 6c97c2a..21c2656 100644 --- a/Examples/HelloTriangleVertex/Example.cs +++ b/Examples/HelloTriangleVertex/Example.cs @@ -84,12 +84,12 @@ protected override async Task LoadResources(GpuRecord cmd) protected override void Render(GpuRecord cmd, Time time) { using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))], Name: Name); - // render.SetMeshBuffers( - // MeshLayout, [ - // new(0, PositionColorBuffer), - // new(1, UvBuffer), - // ] - // ); - // render.Draw(Pipeline, 3); + render.SetMeshBuffers( + MeshLayout, [ + new(0, PositionColorBuffer), + new(1, UvBuffer), + ] + ); + render.Draw(Pipeline, 3); } } From 71e60f0b0d8cd9adc84bbbdf72ed52e4f445bf51 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Mon, 31 Mar 2025 23:30:10 +0800 Subject: [PATCH 23/46] save --- Coplt.Graphics.Core/Native/Native.cs | 2 +- Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 81 +++++++++++----------- 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index b34d0bf..fed1d65 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -2189,7 +2189,7 @@ public partial struct FCmdDraw public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L343_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L351_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index 4da7765..a0be04e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -340,46 +340,49 @@ namespace Coplt::Enhanced }); if (!exist) { - auto& group = result_list ? m_tmp_group : barrier_analyzer->Groups()[0]; - if (res.IsImage()) + if (sr.State->Layout != input.State.Layout) { - const auto img_data = GetImageData(res); - const auto SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage); - D3D12_TEXTURE_BARRIER barrier{ - .SyncBefore = D3D12_BARRIER_SYNC_NONE, - .SyncAfter = SyncAfter, - .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, - .AccessAfter = GetBarrierAccess(input.State.Access), - .LayoutBefore = GetBarrierLayout(sr.State->Layout), - .LayoutAfter = GetBarrierLayout(input.State.Layout), - .pResource = GetResource(res), - .Subresources = { - .IndexOrFirstMipLevel = 0, - .NumMipLevels = img_data->m_mip_levels, - .FirstArraySlice = 0, - .NumArraySlices = img_data->m_depth_or_length, - .FirstPlane = 0, - .NumPlanes = img_data->m_planes, - }, - .Flags = D3D12_TEXTURE_BARRIER_FLAG_NONE, - }; - group.Push(barrier); - } - else - { - const auto buffer_data = GetBufferData(res); - const auto SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage); - D3D12_BUFFER_BARRIER barrier{ - .SyncBefore = D3D12_BARRIER_SYNC_NONE, - .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, - .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, - .AccessAfter = GetBarrierAccess(input.State.Access), - .pResource = GetResource(res), - .Offset = 0, - .Size = buffer_data->m_size, - }; - barrier.SyncAfter = SyncAfter; - group.Push(barrier); + auto& group = result_list ? m_tmp_group : barrier_analyzer->Groups()[0]; + if (res.IsImage()) + { + const auto img_data = GetImageData(res); + const auto SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage); + D3D12_TEXTURE_BARRIER barrier{ + .SyncBefore = D3D12_BARRIER_SYNC_NONE, + .SyncAfter = SyncAfter, + .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, + .AccessAfter = GetBarrierAccess(input.State.Access), + .LayoutBefore = GetBarrierLayout(sr.State->Layout), + .LayoutAfter = GetBarrierLayout(input.State.Layout), + .pResource = GetResource(res), + .Subresources = { + .IndexOrFirstMipLevel = 0, + .NumMipLevels = img_data->m_mip_levels, + .FirstArraySlice = 0, + .NumArraySlices = img_data->m_depth_or_length, + .FirstPlane = 0, + .NumPlanes = img_data->m_planes, + }, + .Flags = D3D12_TEXTURE_BARRIER_FLAG_NONE, + }; + group.Push(barrier); + } + else + { + const auto buffer_data = GetBufferData(res); + const auto SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage); + D3D12_BUFFER_BARRIER barrier{ + .SyncBefore = D3D12_BARRIER_SYNC_NONE, + .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, + .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, + .AccessAfter = GetBarrierAccess(input.State.Access), + .pResource = GetResource(res), + .Offset = 0, + .Size = buffer_data->m_size, + }; + barrier.SyncAfter = SyncAfter; + group.Push(barrier); + } } } // todo From d97b4c07953ff76022319ef461d22214d9fbce03 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 1 Apr 2025 13:18:23 +0800 Subject: [PATCH 24/46] save --- Coplt.Graphics.Core/Core/GpuRecord.cs | 95 ++++++++++++----------- Coplt.Graphics.Core/Native/Native.cs | 54 ++++++++++--- Coplt.Graphics.Native/Api/FFI/Cmd.h | 12 +++ Coplt.Graphics.Native/Api/FFI/Command.h | 6 -- Coplt.Graphics.Native/Api/FFI/Structs.h | 6 ++ Coplt.Graphics.Native/D3d12/Src/Record.cc | 43 +++++++++- Coplt.Graphics.Native/D3d12/Src/Record.h | 2 + 7 files changed, 151 insertions(+), 67 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 8aaa5d3..7708acd 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -726,6 +726,7 @@ uint debug_scope_count { #region Fields + internal ShaderPipeline? m_current_pipeline; internal bool m_disposed; internal bool m_has_pixel_shader; internal bool m_has_vertex_shader; @@ -786,9 +787,11 @@ public void Dispose() public void SetPipeline(ShaderPipeline Pipeline) { + if (m_current_pipeline == Pipeline) return; if (!Pipeline.Shader.Stages.HasAnyFlags(ShaderStageFlags.Pixel)) throw new ArgumentException("Only shaders with a pixel stage can be used for rendering"); - // if (!m_context.SetPipeline(self, Pipeline)) return; + m_current_pipeline = Pipeline; + self.AddObject(m_current_pipeline); var cmd = new FCmdSetPipeline { Base = { Type = FCmdType.SetPipeline }, @@ -940,9 +943,9 @@ public void Draw( } else { - // if (m_context.CurrentPipeline == null) throw new InvalidOperationException("Pipeline is not set"); - // if (!m_context.CurrentPipeline.Shader.Stages.HasFlags(ShaderStageFlags.Vertex)) - // throw new ArgumentException("Only shaders with a vertex stage can use Draw"); + if (m_current_pipeline == null) throw new InvalidOperationException("Pipeline is not set"); + if (!m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Vertex)) + throw new ArgumentException("Only shaders with a vertex stage can use Draw"); } // if (Binding != null) SetBinding(Binding); var cmd = new FCmdDraw @@ -962,48 +965,48 @@ public void Draw( #endregion - // #region DispatchMesh - // - // public void DispatchMesh( - // 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, - // ShaderBinding? Binding = null - // ) - // { - // if (Pipeline != null) - // { - // if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) - // throw new ArgumentException("Only Mesh shaders can use DispatchMesh"); - // SetPipeline(Pipeline); - // } - // else - // { - // // if (m_context.CurrentPipeline == null) throw new InvalidOperationException("Pipeline is not set"); - // // if (!m_context.CurrentPipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) - // // throw new ArgumentException("Only shaders with a mesh stage can use DispatchMesh"); - // } - // // if (Binding != null) SetBinding(Binding); - // // self.SyncBinding(ref m_context, this); - // var cmd = new FCmdDispatch - // { - // Base = { Type = FCmdType.Dispatch }, - // GroupCountX = GroupCountX, - // GroupCountY = GroupCountY, - // GroupCountZ = GroupCountZ, - // Type = FDispatchType.Mesh, - // }; - // m_commands.Add(new() { Dispatch = cmd }); - // m_has_pixel_shader = true; - // m_has_mesh_shader = true; - // m_has_task_shader = m_context.CurrentPipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Task); - // } - // - // #endregion + #region DispatchMesh + + public void DispatchMesh( + 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, + ShaderBinding? Binding = null + ) + { + if (Pipeline != null) + { + if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) + throw new ArgumentException("Only Mesh shaders can use DispatchMesh"); + SetPipeline(Pipeline); + } + else + { + if (m_current_pipeline == null) throw new InvalidOperationException("Pipeline is not set"); + if (!m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) + throw new ArgumentException("Only shaders with a mesh stage can use DispatchMesh"); + } + // if (Binding != null) SetBinding(Binding); + // self.SyncBinding(ref m_context, this); + var cmd = new FCmdDispatch + { + Base = { Type = FCmdType.Dispatch }, + GroupCountX = GroupCountX, + GroupCountY = GroupCountY, + GroupCountZ = GroupCountZ, + Type = FDispatchType.Mesh, + }; + self.Data.Commands.Add(new() { Dispatch = cmd }); + m_has_pixel_shader = true; + m_has_mesh_shader = true; + m_has_task_shader = m_current_pipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Task); + } + + #endregion } #endregion diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index fed1d65..c6573c1 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -149,6 +149,13 @@ public partial struct FUploadLoc public uint Index; } + [NativeTypeName("Coplt::u8")] + public enum FDispatchType : byte + { + Compute, + Mesh, + } + public unsafe partial struct FObject : FObject.Interface { public void** lpVtbl; @@ -2187,9 +2194,27 @@ public partial struct FCmdDraw public B8 Indexed; } + [NativeTypeName("struct FCmdDispatch : Coplt::FCmdBase")] + public partial struct FCmdDispatch + { + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint GroupCountX; + + [NativeTypeName("Coplt::u32")] + public uint GroupCountY; + + [NativeTypeName("Coplt::u32")] + public uint GroupCountZ; + + [NativeTypeName("Coplt::FDispatchType")] + public FDispatchType Type; + } + public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L351_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L361_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -2342,6 +2367,16 @@ public ref FCmdDraw Draw } } + [UnscopedRef] + public ref FCmdDispatch Dispatch + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Dispatch; + } + } + [UnscopedRef] public Span _pad { @@ -2415,6 +2450,10 @@ public partial struct _Anonymous_e__Union [NativeTypeName("Coplt::FCmdDraw")] public FCmdDraw Draw; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdDispatch")] + public FCmdDispatch Dispatch; + [FieldOffset(0)] [NativeTypeName("u8[32]")] public __pad_e__FixedBuffer _pad; @@ -5350,13 +5389,6 @@ public unsafe partial struct FMeshBuffers public uint VertexBuffersIndex; } - [NativeTypeName("Coplt::u8")] - public enum FDispatchType : byte - { - Compute, - Mesh, - } - public partial struct FCommandBase { [NativeTypeName("Coplt::FCommandType")] @@ -5693,7 +5725,7 @@ public partial struct FCommandSyncBinding public partial struct FCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L452_C9")] + [NativeTypeName("__AnonymousRecord_Command_L446_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -5919,7 +5951,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FRenderCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L483_C9")] + [NativeTypeName("__AnonymousRecord_Command_L477_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -6103,7 +6135,7 @@ public partial struct __pad_e__FixedBuffer public partial struct FComputeCommandItem { - [NativeTypeName("__AnonymousRecord_Command_L508_C9")] + [NativeTypeName("__AnonymousRecord_Command_L502_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index 8ef40c8..39b0712 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -346,6 +346,16 @@ namespace Coplt //////////////////////////////////////////////////////////////////////////////////////////////////// + struct FCmdDispatch : FCmdBase + { + u32 GroupCountX{}; + u32 GroupCountY{}; + u32 GroupCountZ{}; + FDispatchType Type{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + struct FCmdItem { union @@ -373,6 +383,8 @@ namespace Coplt FCmdSetMeshBuffers SetMeshBuffers; FCmdDraw Draw; + FCmdDispatch Dispatch; + u8 _pad[32]; }; }; diff --git a/Coplt.Graphics.Native/Api/FFI/Command.h b/Coplt.Graphics.Native/Api/FFI/Command.h index b2c45a8..e139fd4 100644 --- a/Coplt.Graphics.Native/Api/FFI/Command.h +++ b/Coplt.Graphics.Native/Api/FFI/Command.h @@ -245,12 +245,6 @@ namespace Coplt u32 VertexBuffersIndex{}; }; - enum class FDispatchType : u8 - { - Compute, - Mesh, - }; - //////////////////////////////////////////////////////////////////////////////////////////////////// struct FCommandBase diff --git a/Coplt.Graphics.Native/Api/FFI/Structs.h b/Coplt.Graphics.Native/Api/FFI/Structs.h index 10d7b56..375ea3e 100644 --- a/Coplt.Graphics.Native/Api/FFI/Structs.h +++ b/Coplt.Graphics.Native/Api/FFI/Structs.h @@ -86,4 +86,10 @@ namespace Coplt { u32 Index{}; }; + + enum class FDispatchType : u8 + { + Compute, + Mesh, + }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index d513755..8fc7270 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -234,9 +234,9 @@ void D3d12GpuRecord::Analyze() case FCmdType::Draw: if (Mode != FGpuRecordMode::Direct) COPLT_THROW_FMT("[{}] Can only Draw on the direct mode", i); + break; case FCmdType::Dispatch: - if (Mode != FGpuRecordMode::Direct && Mode != FGpuRecordMode::Compute) - COPLT_THROW_FMT("[{}] Can only Dispatch on the direct or compute mode", i); + Analyze_Dispatch(i, command.Dispatch); break; } } @@ -349,6 +349,21 @@ void D3d12GpuRecord::Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd m_barrier_analyzer->OnCmd(); } +void D3d12GpuRecord::Analyze_Dispatch(u32 i, const FCmdDispatch& cmd) const +{ + switch (cmd.Type) + { + case FDispatchType::Compute: + if (m_state != RecordState::Compute) + COPLT_THROW_FMT("[{}] Can only use Dispatch (Compute) in compute scope", i); + break; + case FDispatchType::Mesh: + if (m_state != RecordState::Render) + COPLT_THROW_FMT("[{}] Can only use Dispatch (Mesh) in render scope", i); + break; + } +} + void D3d12GpuRecord::Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) { const auto commands = Commands.AsSpan(); @@ -405,7 +420,8 @@ void D3d12GpuRecord::Interpret(const D3d12RentedCommandList& list, u32 offset, u Interpret_Draw(list, i, command.Draw); break; case FCmdType::Dispatch: - COPLT_THROW("TODO"); + Interpret_Dispatch(list, i, command.Dispatch); + break; } } } @@ -665,7 +681,7 @@ void D3d12GpuRecord::Interpret_SetMeshBuffers(const CmdList& list, u32 i, const void D3d12GpuRecord::Interpret_Draw(const CmdList& list, u32 i, const FCmdDraw& cmd) const { if (m_state != RecordState::Render) - COPLT_THROW_FMT("[{}] Can only use _Draw in render scope", i); + COPLT_THROW_FMT("[{}] Can only use Draw in render scope", i); if (cmd.Indexed) { list->g0->DrawIndexedInstanced(cmd.VertexOrIndexCount, cmd.InstanceCount, cmd.FirstVertexOrIndex, cmd.VertexOffset, cmd.FirstInstance); @@ -676,6 +692,25 @@ void D3d12GpuRecord::Interpret_Draw(const CmdList& list, u32 i, const FCmdDraw& } } +void D3d12GpuRecord::Interpret_Dispatch(const CmdList& list, u32 i, const FCmdDispatch& cmd) const +{ + switch (cmd.Type) + { + case FDispatchType::Compute: + if (m_state != RecordState::Compute) + COPLT_THROW_FMT("[{}] Can only use Dispatch (Compute) in compute scope", i); + list->g0->Dispatch(cmd.GroupCountX, cmd.GroupCountY, cmd.GroupCountZ); + break; + case FDispatchType::Mesh: + if (m_state != RecordState::Render) + COPLT_THROW_FMT("[{}] Can only use Dispatch (Mesh) in render scope", i); + if (!list->g6) + COPLT_THROW_FMT("[{}] The device does not support mesh shaders", i); + list->g6->DispatchMesh(cmd.GroupCountX, cmd.GroupCountY, cmd.GroupCountZ); + break; + } +} + void D3d12GpuRecord::SetPipeline(NonNull pipeline, u32 i) { if (pipeline == m_pipeline_context.Pipeline) return; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index ad8d1cb..ed29c5d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -114,6 +114,7 @@ namespace Coplt void Analyze_RenderEnd(u32 i, const FCmdRender& cmd); void Analyze_SetPipeline(u32 i, const FCmdSetPipeline& cmd); void Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd); + void Analyze_Dispatch( u32 i, const FCmdDispatch& cmd) const; void Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) override; void Interpret_Label(const CmdList& list, u32 i, const FCmdLabel& cmd) const; @@ -128,6 +129,7 @@ namespace Coplt void Interpret_SetViewportScissor(const CmdList& list, u32 i, const FCmdSetViewportScissor& cmd) const; void Interpret_SetMeshBuffers(const CmdList& list, u32 i, const FCmdSetMeshBuffers& cmd) const; void Interpret_Draw(const CmdList& list, u32 i, const FCmdDraw& cmd) const; + void Interpret_Dispatch(const CmdList& list, u32 i, const FCmdDispatch& cmd) const; void SetPipeline(NonNull pipeline, u32 i); void SetPipeline(const CmdList& list, NonNull pipeline, u32 i); From 430e0db2b2b02a4a05c33754fc9c1bd65cb334a5 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 1 Apr 2025 13:32:26 +0800 Subject: [PATCH 25/46] save --- Coplt.Graphics.Core/Core/GpuRecord.cs | 200 ++++++++++++++++++++-- Coplt.Graphics.Native/D3d12/Src/Record.cc | 42 ++++- Coplt.Graphics.Native/D3d12/Src/Record.h | 11 ++ 3 files changed, 239 insertions(+), 14 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 7708acd..d2fbe85 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -691,6 +691,62 @@ public RenderScope2 Render( } #endregion + + #region Compute + + public ComputeScope2 Compute(string? Name = null, ReadOnlySpan Name8 = default) + { + AssertNotEnded(); + + #region Check Nested + + if (m_in_render_or_compute_scope) throw new InvalidOperationException("Cannot nest Render or Compute scopes"); + m_in_render_or_compute_scope = true; + + #endregion + + #region Cmd + + var cmd = new FCmdCompute + { + Base = { Type = FCmdType.Compute }, + }; + + #endregion + + #region DebugScope + + var debug_scope = false; + if (Name != null) + { + debug_scope = true; + Scope(Name); + } + else if (Name8.Length > 0) + { + debug_scope = true; + Scope(Name8); + } + + #endregion + + #region EndCmd + + var cmd_index = (uint)Data.Commands.LongLength; + Data.Commands.Add(new() { Compute = cmd }); + + #endregion + + #region Scope + + ComputeScope2 scope = new(this, cmd_index, debug_scope, m_debug_scope_count); + + #endregion + + return scope; + } + + #endregion } #region DebugScope @@ -700,7 +756,7 @@ public struct DebugScope2(GpuRecord self) : IDisposable private bool m_disposed; public void Dispose() { - if (m_disposed) throw new ObjectDisposedException(nameof(ComputeScope)); + if (m_disposed) throw new ObjectDisposedException(nameof(DebugScope2)); m_disposed = true; if (!self.DebugEnabled) return; var cmd = new FCmdEndScope @@ -728,10 +784,6 @@ uint debug_scope_count internal ShaderPipeline? m_current_pipeline; internal bool m_disposed; - internal bool m_has_pixel_shader; - internal bool m_has_vertex_shader; - internal bool m_has_mesh_shader; - internal bool m_has_task_shader; internal bool m_has_uav_writes; #endregion @@ -747,7 +799,7 @@ uint debug_scope_count public void Dispose() { - if (m_disposed) throw new ObjectDisposedException(nameof(ComputeScope)); + if (m_disposed) throw new ObjectDisposedException(nameof(RenderScope)); m_disposed = true; if (self.m_debug_scope_count > debug_scope_count) throw new InvalidOperationException( @@ -787,9 +839,10 @@ public void Dispose() public void SetPipeline(ShaderPipeline Pipeline) { + self.AssertNotEnded(); if (m_current_pipeline == Pipeline) return; if (!Pipeline.Shader.Stages.HasAnyFlags(ShaderStageFlags.Pixel)) - throw new ArgumentException("Only shaders with a pixel stage can be used for rendering"); + throw new ArgumentException("Only shaders with a Pixel stage can be used for rendering"); m_current_pipeline = Pipeline; self.AddObject(m_current_pipeline); var cmd = new FCmdSetPipeline @@ -809,6 +862,7 @@ public void SetViewportScissor( ReadOnlySpan Scissors ) { + self.AssertNotEnded(); var cmd = new FCmdSetViewportScissor { Base = { Type = FCmdType.SetViewportScissor }, @@ -849,6 +903,7 @@ public void SetMeshBuffers( ReadOnlySpan VertexBuffers ) { + self.AssertNotEnded(); self.AddObject(MeshLayout); var cmd = new FCmdSetMeshBuffers { @@ -935,6 +990,7 @@ public void Draw( ShaderBinding? Binding = null ) { + self.AssertNotEnded(); if (Pipeline != null) { if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Vertex)) @@ -959,8 +1015,6 @@ public void Draw( Indexed = Indexed, }; self.Data.Commands.Add(new() { Draw = cmd }); - m_has_pixel_shader = true; - m_has_vertex_shader = true; } #endregion @@ -978,6 +1032,7 @@ public void DispatchMesh( ShaderBinding? Binding = null ) { + self.AssertNotEnded(); if (Pipeline != null) { if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) @@ -1001,9 +1056,130 @@ public void DispatchMesh( Type = FDispatchType.Mesh, }; self.Data.Commands.Add(new() { Dispatch = cmd }); - m_has_pixel_shader = true; - m_has_mesh_shader = true; - m_has_task_shader = m_current_pipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Task); + } + + #endregion +} + +#endregion + +#region ComputeScope + +public unsafe struct ComputeScope2( + GpuRecord self, + uint cmd_index, + bool debug_scope, + uint debug_scope_count +) : IDisposable +{ + #region Fields + + internal ShaderPipeline? m_current_pipeline; + internal bool m_disposed; + + #endregion + + #region Props + + internal ref FCmdCompute Cmd => ref self.Data.Commands[cmd_index].Compute; + + #endregion + + #region Dispose + + public void Dispose() + { + if (m_disposed) throw new ObjectDisposedException(nameof(ComputeScope2)); + m_disposed = true; + if (self.m_debug_scope_count > debug_scope_count) + throw new InvalidOperationException( + "There is still Debug scope not ended, please check whether Dispose is missed." + ); + Cmd.CommandCount = (uint)self.m_data->Commands.LongLength - cmd_index; + self.m_in_render_or_compute_scope = false; + self.Data.Commands.Add(new() { Type = FCmdType.End }); + if (debug_scope) new DebugScope2(self).Dispose(); + } + + #endregion + + #region Debug + + #region Label + + public void Label(string Label, Color? Color = null) => self.Label(Label, Color); + + public void Label(ReadOnlySpan Label, Color? Color = null) => self.Label(Label, Color); + + #endregion + + #region Scope + + public DebugScope2 Scope(string Name, Color? Color = null) => self.Scope(Name, Color); + + public DebugScope2 Scope(ReadOnlySpan Name, Color? Color = null) => self.Scope(Name, Color); + + #endregion + + #endregion + + #region SetPipeline + + public void SetPipeline(ShaderPipeline Pipeline) + { + self.AssertNotEnded(); + if (m_current_pipeline == Pipeline) return; + if (!Pipeline.Shader.Stages.HasAnyFlags(ShaderStageFlags.Compute)) + throw new ArgumentException("Only shaders with a Compute stage can be used for computing"); + m_current_pipeline = Pipeline; + self.AddObject(m_current_pipeline); + var cmd = new FCmdSetPipeline + { + Base = { Type = FCmdType.SetPipeline }, + Pipeline = Pipeline.m_ptr, + }; + self.Data.Commands.Add(new() { SetPipeline = cmd }); + } + + #endregion + + #region Dispatch + + public void Dispatch( + uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1, + ShaderBinding? Binding = null + ) => Dispatch(null, GroupCountX, GroupCountY, GroupCountZ, Binding); + + public void Dispatch( + ShaderPipeline? Pipeline, + uint GroupCountX = 1, uint GroupCountY = 1, uint GroupCountZ = 1, + ShaderBinding? Binding = null + ) + { + self.AssertNotEnded(); + if (Pipeline != null) + { + if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Compute)) + throw new ArgumentException("Only Compute shaders can use Dispatch"); + SetPipeline(Pipeline); + } + else + { + if (m_current_pipeline == null) throw new InvalidOperationException("Pipeline is not set"); + if (!m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Compute)) + throw new ArgumentException("Only shaders with a Compute stage can use Dispatch"); + } + // if (Binding != null) SetBinding(Binding); + // self.SyncBinding(ref m_context, this); + var cmd = new FCmdDispatch + { + Base = { Type = FCmdType.Dispatch }, + GroupCountX = GroupCountX, + GroupCountY = GroupCountY, + GroupCountZ = GroupCountZ, + Type = FDispatchType.Compute, + }; + self.Data.Commands.Add(new() { Dispatch = cmd }); } #endregion diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 8fc7270..89ddf7d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -316,13 +316,32 @@ void D3d12GpuRecord::Analyze_Render(u32 i, const FCmdRender& cmd) void D3d12GpuRecord::Analyze_RenderEnd(u32 i, const FCmdRender& cmd) { if (m_state != RecordState::Render) - COPLT_THROW_FMT("[{}] Cannot use End in main scope", i); + COPLT_THROW_FMT("[{}] Cannot use End in main scope or some end is missing", i); m_state = RecordState::Main; const auto& info = PayloadRenderInfo[cmd.InfoIndex]; const auto num_rtv = std::min(info.NumRtv, 8u); if (info.Dsv) m_barrier_analyzer->OnUse(info.Dsv); for (u32 n = 0; n < num_rtv; ++n) m_barrier_analyzer->OnUse(info.Rtv[n]); m_barrier_analyzer->OnCmd(); + m_pipeline_context.Reset(); +} + +void D3d12GpuRecord::Analyze_Compute(u32 i, const FCmdCompute& cmd) +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use Compute in sub scope", i); + if (Mode != FGpuRecordMode::Direct && Mode != FGpuRecordMode::Compute) + COPLT_THROW_FMT("[{}] Compute can only be used in Direct or Compute mode", i); + m_state = RecordState::Compute; + m_cur_compute = ComputeState{.StartIndex = i, .Cmd = cmd}; +} + +void D3d12GpuRecord::Analyze_ComputeEnd(u32 i, const FCmdCompute& cmd) +{ + if (m_state != RecordState::Compute) + COPLT_THROW_FMT("[{}] Cannot use End in main scope or some end is missing", i); + m_state = RecordState::Main; + m_pipeline_context.Reset(); } void D3d12GpuRecord::Analyze_SetPipeline(u32 i, const FCmdSetPipeline& cmd) @@ -620,7 +639,7 @@ void D3d12GpuRecord::Interpret_Render(const CmdList& list, const u32 i, const FC void D3d12GpuRecord::Interpret_RenderEnd(const CmdList& list, u32 i, const FCmdRender& cmd) { if (m_state != RecordState::Render) - COPLT_THROW_FMT("[{}] Cannot use End in main scope", i); + COPLT_THROW_FMT("[{}] Cannot use End in main scope or some end is missing", i); m_state = RecordState::Main; if (list->g4) { @@ -630,6 +649,25 @@ void D3d12GpuRecord::Interpret_RenderEnd(const CmdList& list, u32 i, const FCmdR { COPLT_THROW_FMT("[{}] Render pass is not supported, please check the agility sdk version", i); } + m_pipeline_context.Reset(); +} + +void D3d12GpuRecord::Interpret_Compute(const CmdList& list, u32 i, const FCmdCompute& cmd) +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use Compute in sub scope", i); + if (Mode != FGpuRecordMode::Direct && Mode != FGpuRecordMode::Compute) + COPLT_THROW_FMT("[{}] Compute can only be used in Direct or Compute mode", i); + m_state = RecordState::Compute; + m_cur_compute = ComputeState{.StartIndex = i, .Cmd = cmd}; +} + +void D3d12GpuRecord::Interpret_ComputeEnd(const CmdList& list, u32 i, const FCmdCompute& cmd) +{ + if (m_state != RecordState::Compute) + COPLT_THROW_FMT("[{}] Cannot use End in main scope or some end is missing", i); + m_state = RecordState::Main; + m_pipeline_context.Reset(); } void D3d12GpuRecord::Interpret_SetPipeline(const CmdList& list, const u32 i, const FCmdSetPipeline& cmd) diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index ed29c5d..f618652 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -48,6 +48,12 @@ namespace Coplt FCmdRender Cmd{}; }; + struct ComputeState + { + u32 StartIndex{}; + FCmdCompute Cmd{}; + }; + struct PipelineContext { Ptr Pipeline{}; @@ -73,6 +79,7 @@ namespace Coplt std::vector> m_resources_owner{}; std::vector m_queue_wait_points{}; RenderState m_cur_render{}; + ComputeState m_cur_compute{}; PipelineContext m_pipeline_context{}; RecordState m_state{}; D3d12RentedCommandList m_result_list{}; @@ -112,6 +119,8 @@ namespace Coplt void Analyze_BufferCopy(u32 i, const FCmdBufferCopy& cmd) const; void Analyze_Render(u32 i, const FCmdRender& cmd); void Analyze_RenderEnd(u32 i, const FCmdRender& cmd); + void Analyze_Compute(u32 i, const FCmdCompute& cmd); + void Analyze_ComputeEnd(u32 i, const FCmdCompute& cmd); void Analyze_SetPipeline(u32 i, const FCmdSetPipeline& cmd); void Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd); void Analyze_Dispatch( u32 i, const FCmdDispatch& cmd) const; @@ -125,6 +134,8 @@ namespace Coplt void Interpret_BufferCopy(const CmdList& list, u32 i, const FCmdBufferCopy& cmd); void Interpret_Render(const CmdList& list, u32 i, const FCmdRender& cmd); void Interpret_RenderEnd(const CmdList& list, u32 i, const FCmdRender& cmd); + void Interpret_Compute(const CmdList& list, u32 i, const FCmdCompute& cmd); + void Interpret_ComputeEnd(const CmdList& list, u32 i, const FCmdCompute& cmd); void Interpret_SetPipeline(const CmdList& list, u32 i, const FCmdSetPipeline& cmd); void Interpret_SetViewportScissor(const CmdList& list, u32 i, const FCmdSetViewportScissor& cmd) const; void Interpret_SetMeshBuffers(const CmdList& list, u32 i, const FCmdSetMeshBuffers& cmd) const; From 625fda802f07039ef23a469193c17954bd21a07f Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 1 Apr 2025 15:42:53 +0800 Subject: [PATCH 26/46] remove old code --- Coplt.Graphics.Core/Core/CommandList.cs | 2427 ----------------- Coplt.Graphics.Core/Core/GpuAdapter.cs | 7 +- Coplt.Graphics.Core/Core/GpuBuffer.cs | 13 +- Coplt.Graphics.Core/Core/GpuDevice.cs | 72 +- Coplt.Graphics.Core/Core/GpuExecutor.cs | 130 - Coplt.Graphics.Core/Core/GpuImage.cs | 11 +- Coplt.Graphics.Core/Core/GpuIsolate.cs | 91 + Coplt.Graphics.Core/Core/GpuOutput.cs | 99 - Coplt.Graphics.Core/Core/GpuQueue.cs | 336 +-- Coplt.Graphics.Core/Core/GpuRecord.cs | 107 +- Coplt.Graphics.Core/Core/GpuResource.cs | 14 +- Coplt.Graphics.Core/Core/GpuViewable.cs | 56 +- Coplt.Graphics.Core/Core/GraphicsInstance.cs | 5 +- Coplt.Graphics.Core/Core/IQueueOwned.cs | 17 - Coplt.Graphics.Core/Core/ShaderBinding.cs | 124 +- Coplt.Graphics.Core/Core/Views.cs | 7 +- Coplt.Graphics.Core/Native/FResourceRef.cs | 24 - Coplt.Graphics.Core/Native/Native.cs | 2126 ++------------- Coplt.Graphics.Native/Api/CMakeLists.txt | 1 - Coplt.Graphics.Native/Api/FFI/Command.h | 559 ---- Coplt.Graphics.Native/Api/FFI/Context.h | 7 - Coplt.Graphics.Native/Api/FFI/Device.h | 1 - Coplt.Graphics.Native/Api/FFI/Isolate.h | 1 + Coplt.Graphics.Native/Api/FFI/Output.h | 43 - Coplt.Graphics.Native/Api/FFI/PipelineState.h | 1 + Coplt.Graphics.Native/Api/FFI/Queue.h | 40 - Coplt.Graphics.Native/D3d12/CMakeLists.txt | 5 - Coplt.Graphics.Native/D3d12/FFI/Output.h | 18 - Coplt.Graphics.Native/D3d12/FFI/Queue.h | 5 - .../D3d12/Include/GraphicsFormat.h | 1 - .../D3d12/Include/PipelineState.h | 1 - Coplt.Graphics.Native/D3d12/Src/CmdListPack.h | 49 - Coplt.Graphics.Native/D3d12/Src/Command.cc | 1138 -------- Coplt.Graphics.Native/D3d12/Src/Command.h | 145 - Coplt.Graphics.Native/D3d12/Src/Context.cc | 78 - Coplt.Graphics.Native/D3d12/Src/Context.h | 24 - Coplt.Graphics.Native/D3d12/Src/Device.cc | 8 - Coplt.Graphics.Native/D3d12/Src/Device.h | 1 - Coplt.Graphics.Native/D3d12/Src/Executor.h | 14 - Coplt.Graphics.Native/D3d12/Src/Output.cc | 362 --- Coplt.Graphics.Native/D3d12/Src/Output.h | 76 - Coplt.Graphics.Native/D3d12/Src/Queue.cc | 131 - Coplt.Graphics.Native/D3d12/Src/Queue.h | 43 - Coplt.Graphics.Native/D3d12/Src/Record.cc | 5 +- Coplt.Graphics.Native/D3d12/Src/Record.h | 3 + Examples/HelloTriangleVertex/Example.cs | 4 +- 46 files changed, 457 insertions(+), 7973 deletions(-) delete mode 100644 Coplt.Graphics.Core/Core/CommandList.cs delete mode 100644 Coplt.Graphics.Core/Core/GpuExecutor.cs delete mode 100644 Coplt.Graphics.Core/Core/IQueueOwned.cs delete mode 100644 Coplt.Graphics.Core/Native/FResourceRef.cs delete mode 100644 Coplt.Graphics.Native/Api/FFI/Command.h delete mode 100644 Coplt.Graphics.Native/D3d12/FFI/Output.h delete mode 100644 Coplt.Graphics.Native/D3d12/Src/CmdListPack.h delete mode 100644 Coplt.Graphics.Native/D3d12/Src/Command.cc delete mode 100644 Coplt.Graphics.Native/D3d12/Src/Command.h delete mode 100644 Coplt.Graphics.Native/D3d12/Src/Executor.h diff --git a/Coplt.Graphics.Core/Core/CommandList.cs b/Coplt.Graphics.Core/Core/CommandList.cs deleted file mode 100644 index d3851c8..0000000 --- a/Coplt.Graphics.Core/Core/CommandList.cs +++ /dev/null @@ -1,2427 +0,0 @@ -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Coplt.Graphics.Native; -using Coplt.Graphics.Utilities; -using Coplt.Union; -using static Coplt.Graphics.Core.CommandList; - -namespace Coplt.Graphics.Core; - -public enum DispatchType : byte -{ - Auto, - Compute, - Mesh, -} - -internal interface ISubCommandList -{ - void OnSyncBinding(uint index); -} - -/// -/// 命令列表,不支持多线程访问 -/// -public sealed unsafe class CommandList : IQueueOwned -{ - #region Struct - - internal struct ResourceState(int SlotIndex, IGpuResource Resource) - { - public readonly int SlotIndex = SlotIndex; - public readonly IGpuResource Resource = Resource; - public int CurrentBarrierIndex = -1; - public int CurrentBarrierCmdIndex = -1; - public int LastUsedBarrierCmdIndex = -1; - public bool First = true; - - public void MarkUse(CommandList self) - { - LastUsedBarrierCmdIndex = self.m_current_barrier_cmd_index; - } - - public void ReqState( - CommandList self, - FResLayout Layout, - FResAccess Access, - FShaderStageFlags Stages, - FLegacyState Legacy, - bool? CrossQueue = null, - FImageBarrierFlags ImageFlags = FImageBarrierFlags.None - ) => ReqState( - self, new FResState - { - Layout = Layout, - Access = Access, - Stages = Stages, - Legacy = Legacy, - CrossQueue = CrossQueue ?? Resource.NativeState.CrossQueue, - }, ImageFlags - ); - private void ReqState( - CommandList self, FResState NewState, - FImageBarrierFlags ImageFlags = FImageBarrierFlags.None - ) - { - ref var OldState = ref Resource.NativeState; - if (First) - { - First = false; - OldState.Access = FResAccess.NoAccess; - } - if (OldState.IsCompatible(NewState, self.UseLegacyState, true, out var same)) - { - if (same) goto Ret; - NewState = OldState.Merge(NewState, self.UseLegacyState, true); - if (CurrentBarrierIndex < 0) goto Add; - goto Merge; - } - Add: - { - CurrentBarrierIndex = self.m_barriers.Count; - if (self.m_current_barrier_cmd_index < 0 || LastUsedBarrierCmdIndex >= self.m_current_barrier_cmd_index) - { - CurrentBarrierCmdIndex = self.m_current_barrier_cmd_index = self.m_commands.Count; - var cmd = new FCommandBarrier - { - Base = { Type = FCommandType.Barrier }, - BarrierCount = 1, - BarrierIndex = (uint)CurrentBarrierIndex, - }; - self.m_commands.Add(new() { Barrier = cmd }); - } - else - { - CurrentBarrierCmdIndex = self.m_current_barrier_cmd_index; - ref var cmd = ref self.m_commands.At(CurrentBarrierCmdIndex); - cmd.Barrier.BarrierCount++; - } - self.m_barriers.Add(BuildBarrier(OldState, NewState)); - goto End; - } - Merge: - { - ref var barrier = ref self.m_barriers.At(CurrentBarrierIndex); - UpdateBarrier(ref barrier, NewState); - goto End; - } - End: - OldState = NewState; - Ret: - MarkUse(self); - return; - } - - private FBarrier BuildBarrier( - in FResState OldState, in FResState NewState, - FImageBarrierFlags ImageFlags = FImageBarrierFlags.None - ) - { - var barrier = new FBarrier(); - switch (Resource.Type) - { - case GpuResourceType.Unknown: - barrier.Type = FBarrierType.Global; - barrier.Global = new() - { - AccessBefore = OldState.Access, - AccessAfter = NewState.Access, - StagesBefore = OldState.Stages, - StagesAfter = NewState.Stages, - }; - break; - case GpuResourceType.Buffer: - barrier.Type = FBarrierType.Buffer; - barrier.Buffer = new() - { - LegacyBefore = OldState.Legacy, - LegacyAfter = NewState.Legacy, - AccessBefore = OldState.Access, - AccessAfter = NewState.Access, - StagesBefore = OldState.Stages, - StagesAfter = NewState.Stages, - Buffer = new(SlotIndex + 1), - Offset = 0, - Size = Resource.Size, - }; - break; - case GpuResourceType.Image: - barrier.Type = FBarrierType.Image; - barrier.Image = new() - { - LegacyBefore = OldState.Legacy, - LegacyAfter = NewState.Legacy, - AccessBefore = OldState.Access, - AccessAfter = NewState.Access, - StagesBefore = OldState.Stages, - StagesAfter = NewState.Stages, - LayoutBefore = OldState.Layout, - LayoutAfter = NewState.Layout, - Image = new(SlotIndex + 1), - SubResourceRange = new() - { - IndexOrFirstMipLevel = 0, - NumMipLevels = Resource.MipLevels, - FirstArraySlice = 0, - NumArraySlices = Resource.DepthOrLength, - FirstPlane = 0, - NumPlanes = Resource.Planes, - }, - Flags = ImageFlags, - }; - if (OldState.CrossQueue || NewState.CrossQueue) - { - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - barrier.Image.Flags |= FImageBarrierFlags.CrossQueue; - } - break; - default: - throw new ArgumentOutOfRangeException(); - } - return barrier; - } - - private void UpdateBarrier(ref FBarrier barrier, in FResState NewState) - { - switch (Resource.Type) - { - case GpuResourceType.Unknown: - barrier.Global.AccessAfter = NewState.Access; - barrier.Global.StagesAfter = NewState.Stages; - break; - case GpuResourceType.Buffer: - barrier.Buffer.LegacyAfter = NewState.Legacy; - barrier.Buffer.AccessAfter = NewState.Access; - barrier.Buffer.StagesAfter = NewState.Stages; - break; - case GpuResourceType.Image: - barrier.Image.LegacyAfter = NewState.Legacy; - barrier.Image.AccessAfter = NewState.Access; - barrier.Image.StagesAfter = NewState.Stages; - // 状态兼容布局必须相同,这里不需要设置布局 - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - } - - [Flags] - internal enum ScopedStateUsage - { - Common = 0, - Pixel = 1 << 0, - Vertex = 1 << 1, - Mesh = 1 << 2, - Compute = 1 << 3, - } - - internal record struct ScopedState( - ScopedStateUsage Usage, - ResLayout Layout, - ResAccess Access, - LegacyState Legacy - ) - { - public ScopedStateUsage Usage = Usage; - public ResLayout Layout = Layout; - public ResAccess Access = Access; - public LegacyState Legacy = Legacy; - - public readonly bool IsCompatible(in ScopedState other, bool legacy, out bool same) - { - if (legacy) - { - same = Legacy == other.Legacy; - return Legacy.IsCompatible(other.Legacy); - } - if (!Layout.IsCompatible(other.Layout)) goto no; - if (Access != other.Access) - { - same = false; - var sna = (Access & ResAccess.NoAccess) != 0; - var ona = (other.Access & ResAccess.NoAccess) != 0; - if (sna || ona) return true; - if (!Access.IsReadOnly() || !other.Access.IsReadOnly()) goto no; - } - else - { - same = true; - } - return true; - no: - same = false; - return false; - } - - public void Merge(in ScopedState other, bool legacy, bool same) - { - Usage |= other.Usage; - if (!same) - { - if (legacy) Legacy |= other.Legacy; - else - { - Layout = Layout.Merge(other.Layout, (Access & ResAccess.NoAccess) != 0); - Access |= other.Access; - } - } - } - } - - internal struct PipelineContext - { - public ShaderPipeline? CurrentPipeline; - public ShaderBinding? CurrentBinding; - - public bool PipelineChanged; - public bool BindingChanged; - - public bool SetPipeline(CommandList self, ShaderPipeline Pipeline) - { - if (CurrentPipeline == Pipeline) return false; - self.AddObject(CurrentPipeline = Pipeline); - PipelineChanged = true; - if (CurrentBinding != null) - { - if (Pipeline.Shader.Layout != CurrentBinding.Layout) - CurrentBinding = null; - } - return true; - } - - public bool SetBinding(CommandList self, ShaderBinding Binding) - { - if (CurrentBinding == Binding) return false; - Binding.AssertSameQueue(self.Queue); - if (CurrentPipeline != null) - { - if (CurrentPipeline.Shader.Layout != Binding.Layout) - throw new ArgumentException("This binding is incompatible with the current pipeline"); - } - self.AddObject(CurrentBinding = Binding); - BindingChanged = true; - return true; - } - } - - #endregion - - #region Fields - - internal readonly GraphicsInstance m_instance; - internal readonly GpuQueue m_queue; - internal readonly List m_commands = new(); - internal readonly List m_render_commands = new(); - internal readonly List m_compute_commands = new(); - internal readonly List m_resource_metas = new(); - internal readonly List m_resource_states = new(); - internal readonly List m_render_infos = new(); - internal readonly List m_compute_infos = new(); - internal readonly List m_resolve_infos = new(); - internal readonly List m_rects = new(); - internal readonly List m_viewports = new(); - internal readonly List m_mesh_buffers = new(); - internal readonly List m_vertex_buffer_ranges = new(); - internal readonly List m_buffer_copy_ranges = new(); - internal readonly List m_buffer_image_copy_ranges = new(); - internal readonly List m_bind_items = new(); - internal readonly List m_barriers = new(); - internal readonly List m_string8 = new(); - internal readonly List m_string16 = new(); - internal readonly Dictionary m_resources = new(); - internal readonly Dictionary m_scoped_res_state = new(); - internal readonly HashSet m_objects = new(); - internal readonly HashSet m_bindings = new(); - internal GpuOutput? m_current_output; - internal uint m_sync_binding_count; - internal uint m_growing_resource_binding_capacity; - internal uint m_growing_sampler_binding_capacity; - internal int m_debug_scope_count; - internal int m_render_debug_scope_count; - internal int m_compute_debug_scope_count; - internal int m_current_barrier_cmd_index = -1; - internal bool m_in_render_or_compute_scope; - internal bool m_auto_barrier = true; - internal readonly bool m_use_legacy_state; - - #endregion - - #region Props - - public GpuQueue Queue => m_queue; - public bool DebugEnabled => m_instance.DebugEnabled; - public bool AutoBarrierEnabled => m_auto_barrier; - public bool UseLegacyState => m_use_legacy_state; - - internal ref ResourceState StateAt(FResourceRef r) => ref m_resource_states.At((int)(r.ResourceIndex - 1)); - - #endregion - - #region Ctor - - internal CommandList(GpuQueue queue) - { - m_queue = queue; - m_instance = queue.Device.Instance; - m_use_legacy_state = m_queue.m_device.m_adapter.UseLegacyState; - } - - #endregion - - #region Reset - - internal void Reset() - { - m_commands.Clear(); - m_render_commands.Clear(); - m_compute_commands.Clear(); - m_resource_metas.Clear(); - m_resource_states.Clear(); - m_render_infos.Clear(); - m_compute_infos.Clear(); - m_resolve_infos.Clear(); - m_rects.Clear(); - m_viewports.Clear(); - m_mesh_buffers.Clear(); - m_vertex_buffer_ranges.Clear(); - m_buffer_copy_ranges.Clear(); - m_buffer_image_copy_ranges.Clear(); - m_bind_items.Clear(); - m_barriers.Clear(); - m_string8.Clear(); - m_string16.Clear(); - m_resources.Clear(); - m_objects.Clear(); - m_bindings.Clear(); - m_current_output = null; - m_sync_binding_count = 0; - m_growing_resource_binding_capacity = 0; - m_growing_sampler_binding_capacity = 0; - m_current_barrier_cmd_index = -1; - m_auto_barrier = true; - } - - #endregion - - #region Submit - - internal void BuildSubmitStruct(GpuExecutor Executor, bool NoWait) - { - if (m_debug_scope_count != 0) - throw new InvalidOperationException( - "There is still Debug scope not ended, please check whether Dispose is missed." - ); - if (m_in_render_or_compute_scope) - throw new InvalidOperationException( - "There is still Render or Compute scope not ended, please check whether Dispose is missed." - ); - - fixed (FCommandItem* p_commands = CollectionsMarshal.AsSpan(m_commands)) - fixed (FRenderCommandItem* p_render_commands = CollectionsMarshal.AsSpan(m_render_commands)) - fixed (FComputeCommandItem* p_compute_commands = CollectionsMarshal.AsSpan(m_compute_commands)) - fixed (FResourceMeta* p_resources = CollectionsMarshal.AsSpan(m_resource_metas)) - fixed (FRenderInfo* p_render_infos = CollectionsMarshal.AsSpan(m_render_infos)) - fixed (FComputeInfo* p_compute_infos = CollectionsMarshal.AsSpan(m_compute_infos)) - fixed (FResolveInfo* p_resolve_infos = CollectionsMarshal.AsSpan(m_resolve_infos)) - fixed (FRect* p_rects = CollectionsMarshal.AsSpan(m_rects)) - fixed (FViewport* p_viewports = CollectionsMarshal.AsSpan(m_viewports)) - fixed (FMeshBuffers* p_mesh_buffers = CollectionsMarshal.AsSpan(m_mesh_buffers)) - fixed (FVertexBufferRange* p_vertex_buffer_ranges = CollectionsMarshal.AsSpan(m_vertex_buffer_ranges)) - fixed (FBufferCopyRange* p_buffer_copy_ranges = CollectionsMarshal.AsSpan(m_buffer_copy_ranges)) - fixed (FBufferImageCopyRange* p_buffer_image_copy_ranges = CollectionsMarshal.AsSpan(m_buffer_image_copy_ranges)) - fixed (FBindItem* p_bind_items = CollectionsMarshal.AsSpan(m_bind_items)) - fixed (FBarrier* p_barriers = CollectionsMarshal.AsSpan(m_barriers)) - fixed (byte* p_string8 = CollectionsMarshal.AsSpan(m_string8)) - fixed (char* p_string16 = CollectionsMarshal.AsSpan(m_string16)) - { - FCommandSubmit submit = new() - { - Commands = p_commands, - RenderCommands = p_render_commands, - ComputeCommands = p_compute_commands, - Resources = p_resources, - RenderInfos = p_render_infos, - ComputeInfos = p_compute_infos, - ResolveInfos = p_resolve_infos, - Rects = p_rects, - Viewports = p_viewports, - MeshBuffers = p_mesh_buffers, - VertexBufferRanges = p_vertex_buffer_ranges, - BufferCopyRanges = p_buffer_copy_ranges, - BufferImageCopyRanges = p_buffer_image_copy_ranges, - BindItems = p_bind_items, - Barriers = p_barriers, - Str8 = p_string8, - Str16 = p_string16, - CommandCount = (uint)m_commands.Count, - ResourceCount = (uint)m_resource_metas.Count, - SyncBindingCount = m_sync_binding_count, - GrowingResourceBindingCapacity = m_growing_resource_binding_capacity, - GrowingSamplerBindingCapacity = m_growing_sampler_binding_capacity, - }; - Queue.ActualSubmit(Executor, &submit, NoWait); - } - } - - #endregion - - #region RecordScopedResState - - internal ref ScopedState RecordScopedResState(FResourceRef res, ScopedState state, out bool compatible) - { - ref var slot = ref CollectionsMarshal.GetValueRefOrAddDefault( - m_scoped_res_state, res, out var exists - ); - if (!exists) - { - slot = state; - compatible = true; - return ref slot; - } - if (slot.IsCompatible(state, UseLegacyState, out var same)) - { - slot.Merge(state, UseLegacyState, same); - compatible = true; - return ref slot; - } - else - { - compatible = false; - return ref slot; - } - } - - internal ArgumentException Incompatible( - 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};{Layout}] and [{old_state.Access};{old_state.Layout}] states at the same time" - ); - - #endregion - - #region AddResource - - internal FResourceRef AddResource(IGpuResource resource) - { - if (resource.Queue != m_queue) - throw new ArgumentException($"Resource {resource} does not belong to queue {m_queue}"); - if (resource is GpuOutput output) - { - if (m_current_output != null && output != m_current_output) - throw new ArgumentException($"Multiple outputs cannot be used at the same time"); - m_current_output = output; - } - ref var slot = ref CollectionsMarshal.GetValueRefOrAddDefault(m_resources, resource, out var exists); - if (!exists) - { - slot = m_resource_metas.Count; - m_resource_metas.Add(resource.GetMeta()); - m_resource_states.Add(new(slot, resource)); - } - return new(slot + 1); - } - - #endregion - - #region AddObject - - /// - /// 返回是否首次添加 - /// - public bool AddObject(object obj) => m_objects.Add(obj); - - #endregion - - #region Commands - - #region Debug - - #region AddString - - internal uint AddString(string str) - { - var index = m_string16.Count; - CollectionsMarshal.SetCount(m_string16, index + str.Length + 1); - var dst = CollectionsMarshal.AsSpan(m_string16).Slice(index, str.Length + 1); - str.CopyTo(dst); - dst[str.Length] = '\0'; - return (uint)index; - } - - internal uint AddString(ReadOnlySpan str) - { - var index = m_string8.Count; - CollectionsMarshal.SetCount(m_string8, index + str.Length + 1); - var dst = CollectionsMarshal.AsSpan(m_string8).Slice(index, str.Length + 1); - str.CopyTo(dst); - dst[str.Length] = 0; - return (uint)index; - } - - #endregion - - #region Label - - public void Label(string Label) - { - if (!DebugEnabled) return; - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.Label }, - StringIndex = AddString(Label), - StringLength = (uint)Label.Length, - StrType = FStrType.Str16, - }; - m_commands.Add(new() { Label = cmd }); - } - - public void Label(ReadOnlySpan Label) - { - if (!DebugEnabled) return; - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.Label }, - StringIndex = AddString(Label), - StringLength = (uint)Label.Length, - StrType = FStrType.Str8, - }; - m_commands.Add(new() { Label = cmd }); - } - - #endregion - - #region Scope - - public DebugScope Scope(string Name) - { - if (!DebugEnabled) return new(this); - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.BeginScope }, - StringIndex = AddString(Name), - StringLength = (uint)Name.Length, - StrType = FStrType.Str16, - }; - m_commands.Add(new() { Label = cmd }); - m_debug_scope_count++; - return new(this); - } - - public DebugScope Scope(ReadOnlySpan Name) - { - if (!DebugEnabled) return new(this); - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.BeginScope }, - StringIndex = AddString(Name), - StringLength = (uint)Name.Length, - StrType = FStrType.Str8, - }; - m_commands.Add(new() { Label = cmd }); - m_debug_scope_count++; - return new(this); - } - - #endregion - - #endregion - - #region Present - - internal void Present(GpuOutput Output) - { - var cmd = new FCommandPresent - { - Base = { Type = FCommandType.Present }, - Image = AddResource(Output), - }; - if (AutoBarrierEnabled) - { - ref var state = ref StateAt(cmd.Image); - state.ReqState( - this, - FResLayout.Present, - FResAccess.NoAccess, - FShaderStageFlags.None, - FLegacyState.Present, - true - ); - } - m_commands.Add(new() { Present = cmd }); - } - - #endregion - - #region Barrier - - public void SetAutoBarrier(bool Enable) => m_auto_barrier = Enable; - - public void Barrier(params ReadOnlySpan Barriers) - { - var index = m_barriers.Count; - CollectionsMarshal.SetCount(m_barriers, index + Barriers.Length); - var barriers = CollectionsMarshal.AsSpan(m_barriers).Slice(index, Barriers.Length); - for (var i = 0; i < Barriers.Length; i++) - { - ref readonly var src = ref Barriers[i]; - ref var dst = ref barriers[i]; - FBarrier item = default; - switch (src.Tag) - { - case Core.Barrier.Tags.None: - { - item.Type = FBarrierType.None; - break; - } - case Core.Barrier.Tags.Global: - { - item.Type = FBarrierType.Global; - var global = src.Global; - item.Global = new() - { - AccessBefore = global.AccessBefore.ToFFI(), - AccessAfter = global.AccessAfter.ToFFI(), - StagesBefore = global.StagesBefore.ToFFI(), - StagesAfter = global.StagesAfter.ToFFI(), - }; - break; - } - case Core.Barrier.Tags.Buffer: - { - item.Type = FBarrierType.Buffer; - var buffer = src.Buffer; - item.Buffer = new() - { - LegacyBefore = buffer.LegacyBefore.ToFFI(), - LegacyAfter = buffer.LegacyAfter.ToFFI(), - AccessBefore = buffer.AccessBefore.ToFFI(), - AccessAfter = buffer.AccessAfter.ToFFI(), - StagesBefore = buffer.StagesBefore.ToFFI(), - StagesAfter = buffer.StagesAfter.ToFFI(), - Buffer = AddResource(buffer.Buffer), - Offset = buffer.Offset, - Size = buffer.Size, - }; - break; - } - case Core.Barrier.Tags.Image: - { - item.Type = FBarrierType.Image; - var image = src.Image; - item.Image = new() - { - LegacyBefore = image.LegacyBefore.ToFFI(), - LegacyAfter = image.LegacyAfter.ToFFI(), - AccessBefore = image.AccessBefore.ToFFI(), - AccessAfter = image.AccessAfter.ToFFI(), - StagesBefore = image.StagesBefore.ToFFI(), - StagesAfter = image.StagesAfter.ToFFI(), - LayoutBefore = image.LayoutBefore.ToFFI(), - LayoutAfter = image.LayoutAfter.ToFFI(), - Image = AddResource(image.Image), - SubResourceRange = new() - { - IndexOrFirstMipLevel = image.SubResourceRange.IndexOrFirstMipLevel, - NumMipLevels = image.SubResourceRange.NumMipLevels, - FirstArraySlice = image.SubResourceRange.FirstArraySlice, - NumArraySlices = image.SubResourceRange.NumArraySlices, - FirstPlane = image.SubResourceRange.FirstPlane, - NumPlanes = image.SubResourceRange.NumPlanes, - }, - Flags = (FImageBarrierFlags)image.Flags, - }; - break; - } - default: - throw new ArgumentOutOfRangeException(); - } - dst = item; - } - var cmd = new FCommandBarrier - { - Base = { Type = FCommandType.Barrier }, - BarrierCount = (uint)Barriers.Length, - BarrierIndex = (uint)index, - }; - m_current_barrier_cmd_index = m_commands.Count; - m_commands.Add(new() { Barrier = cmd }); - } - - #endregion - - #region ClearColor - - /// - /// 使用 (0, 0, 0, 1) 清空 Rtv - /// - public void ClearColor(IRtv Image, ReadOnlySpan Rects = default) => - ClearColor(Image, new(0, 0, 0, 1), Rects); - - /// - /// 使用指定的颜色清空 Rtv - /// - public void ClearColor(IRtv Image, Color Color, ReadOnlySpan Rects = default) - { - Image.AssertSameQueue(Queue); - if (!Image.TryRtv()) throw new ArgumentException($"Resource {Image} cannot be used as Rtv"); - - var cmd = new FCommandClearColor - { - Base = { Type = FCommandType.ClearColor }, - RectCount = (uint)Rects.Length, - Image = AddResource(Image.Resource), - Color = Unsafe.BitCast(Color), - }; - if (Rects.Length > 0) - { - cmd.RectIndex = (uint)m_rects.Count; - m_rects.AddRange(MemoryMarshal.Cast(Rects)); - } - if (AutoBarrierEnabled) - { - ref var state = ref StateAt(cmd.Image); - state.ReqState( - this, - FResLayout.RenderTarget, - FResAccess.RenderTarget, - FShaderStageFlags.None, - FLegacyState.RenderTarget - ); - } - m_commands.Add(new() { ClearColor = cmd }); - } - - #endregion - - #region ClearDepthStencil - - /// - /// 使用指定的 1 深度 和 0 模板 清空 Dsv - /// - public void ClearDepthStencil( - IDsv Image, - ReadOnlySpan Rects = default - ) => ClearDepthStencil(Image, 1, 0, DsvClear.All, Rects); - - /// - /// 使用指定的深度清空 Dsv - /// - public void ClearDepthStencil( - IDsv Image, float Depth, - ReadOnlySpan Rects = default - ) => ClearDepthStencil(Image, Depth, 0, DsvClear.Depth, Rects); - - /// - /// 使用指定的模板清空 Dsv - /// - public void ClearDepthStencil( - IDsv Image, byte Stencil, - ReadOnlySpan Rects = default - ) => ClearDepthStencil(Image, 1, Stencil, DsvClear.Stencil, Rects); - - /// - /// 使用指定的深度和模板清空 Dsv - /// - public void ClearDepthStencil( - IDsv Image, float Depth, byte Stencil, DsvClear Clear = DsvClear.All, - ReadOnlySpan Rects = default - ) - { - Image.AssertSameQueue(Queue); - if (!Image.TryDsv()) throw new ArgumentException($"Resource {Image} cannot be used as Dsv"); - - var cmd = new FCommandClearDepthStencil - { - Base = { Type = FCommandType.ClearDepthStencil }, - RectCount = (uint)Rects.Length, - Image = AddResource(Image.Resource), - Depth = Depth, - Stencil = Stencil, - Clear = (FDepthStencilClearFlags)Clear, - }; - if (Rects.Length > 0) - { - cmd.RectIndex = (uint)m_rects.Count; - m_rects.AddRange(MemoryMarshal.Cast(Rects)); - } - if (AutoBarrierEnabled) - { - ref var state = ref StateAt(cmd.Image); - state.ReqState( - this, - FResLayout.DepthStencilWrite, - FResAccess.DepthStencilWrite, - FShaderStageFlags.None, - FLegacyState.DepthWrite - ); - } - m_commands.Add(new() { ClearDepthStencil = cmd }); - } - - #endregion - - #region Bind - - public void Bind( - ShaderBinding Binding, ReadOnlySpan Items - ) - { - Binding.AssertSameQueue(Queue); - if (Items.Length == 0) return; - AddObject(Binding); - var cmd = new FCommandBind - { - Base = { Type = FCommandType.Bind }, - Binding = Binding.m_ptr, - ItemCount = (uint)Items.Length, - ItemsIndex = 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); - Binding.Set(Items, dst); - m_commands.Add(new() { Bind = cmd }); - } - - #endregion - - #region BufferCopy - - public void Copy( - GpuBuffer Dst, - GpuBuffer Src, - ulong DstOffset = 0, - ulong SrcOffset = 0, - ulong Size = ulong.MaxValue - ) - { - Dst.AssertSameQueue(Queue); - Src.AssertSameQueue(Queue); - if (Size != ulong.MaxValue) - { - if (DstOffset + Size > Dst.Size) throw new ArgumentException("The copy range exceeds the buffer range"); - if (SrcOffset + Size > Src.Size) throw new ArgumentException("The copy range exceeds the buffer range"); - } - else if (Dst == Src || Dst.Size != Src.Size) Size = Math.Min(Dst.Size, Src.Size); - var cmd = new FCommandBufferCopy - { - Base = { Type = FCommandType.BufferCopy }, - RangeIndex = (uint)m_buffer_copy_ranges.Count, - Dst = { Buffer = AddResource(Dst) }, - DstType = FBufferRefType.Buffer, - Src = { Buffer = AddResource(Src) }, - SrcType = FBufferRefType.Buffer, - }; - m_buffer_copy_ranges.Add( - new() - { - Size = Size, - DstOffset = DstOffset, - SrcOffset = SrcOffset, - } - ); - if (AutoBarrierEnabled) - { - { - ref var state = ref StateAt(cmd.Src.Buffer); - state.ReqState( - this, - FResLayout.None, - FResAccess.CopySrc, - FShaderStageFlags.None, - FLegacyState.CopySrc - ); - } - { - ref var state = ref StateAt(cmd.Dst.Buffer); - state.ReqState( - this, - FResLayout.None, - FResAccess.CopyDst, - FShaderStageFlags.None, - FLegacyState.CopyDst - ); - } - } - m_commands.Add(new() { BufferCopy = cmd }); - } - - #endregion - - #region BufferUpload - - public void Upload( - GpuBuffer Dst, - ReadOnlySpan Data, - ulong DstOffset = 0 - ) where T : unmanaged => Upload(Dst, MemoryMarshal.AsBytes(Data), DstOffset); - - public void Upload( - GpuBuffer Dst, - ReadOnlySpan Data, - ulong DstOffset = 0 - ) - { - if (Data.Length == 0) return; - var Size = Math.Min(Dst.Size, (uint)Data.Length); - var src = m_queue.WriteToUpload(Data); - var cmd = new FCommandBufferCopy - { - Base = { Type = FCommandType.BufferCopy }, - RangeIndex = (uint)m_buffer_copy_ranges.Count, - Dst = { Buffer = AddResource(Dst) }, - DstType = FBufferRefType.Buffer, - Src = { Upload = src }, - SrcType = FBufferRefType.Upload, - }; - m_buffer_copy_ranges.Add( - new() - { - Size = Size, - DstOffset = DstOffset, - SrcOffset = src.Offset, - } - ); - if (AutoBarrierEnabled) - { - ref var state = ref StateAt(cmd.Dst.Buffer); - state.ReqState( - this, - FResLayout.None, - FResAccess.CopyDst, - FShaderStageFlags.None, - FLegacyState.CopyDst - ); - } - m_commands.Add(new() { BufferCopy = cmd }); - } - - public void Upload( - GpuBuffer Dst, - UploadLoc Loc, - ulong DstOffset = 0 - ) - { - Dst.AssertSameQueue(Queue); - if (Loc.SubmitId != m_queue.SubmitId) - throw new ArgumentException("An attempt was made to use an expired upload location"); - var Size = Math.Min(Dst.Size, Loc.Size); - var cmd = new FCommandBufferCopy - { - Base = { Type = FCommandType.BufferCopy }, - RangeIndex = (uint)m_buffer_copy_ranges.Count, - Dst = { Buffer = AddResource(Dst) }, - DstType = FBufferRefType.Buffer, - Src = { Upload = Loc }, - SrcType = FBufferRefType.Upload, - }; - m_buffer_copy_ranges.Add( - new() - { - Size = Size, - DstOffset = DstOffset, - SrcOffset = Loc.Offset, - } - ); - if (AutoBarrierEnabled) - { - ref var state = ref StateAt(cmd.Dst.Buffer); - state.ReqState( - this, - FResLayout.None, - FResAccess.CopyDst, - FShaderStageFlags.None, - FLegacyState.CopyDst - ); - } - m_commands.Add(new() { BufferCopy = cmd }); - } - - #endregion - - #region ImageUpload - - public void Upload( - GpuImage Dst, - ImageUploadBufferMemory Memory, - uint MipLevel = 0, - uint ImageIndex = 0, - uint ImageCount = 1, - ImagePlane Plane = ImagePlane.All - ) => Upload( - Dst, Memory.Loc, Memory.RowStride, Memory.RowsPerImage, - MipLevel, ImageIndex, ImageCount, Plane - ); - - public void Upload( - GpuImage Dst, - UploadLoc Loc, - uint BytesPerRow, - uint RowsPerImage, - uint MipLevel = 0, - uint ImageIndex = 0, - uint ImageCount = 1, - ImagePlane Plane = ImagePlane.All - ) => Upload( - Dst, Loc, - 0, 0, 0, - Dst.Width, Dst.Height, Dst.DepthOrLength, - BytesPerRow, RowsPerImage, - MipLevel, ImageIndex, ImageCount, Plane - ); - - public void Upload( - GpuImage Dst, - UploadLoc Loc, - uint DstX, - uint DstY, - uint DstZ, - uint DstWidth, - uint DstHeight, - uint DstDepth, - uint BytesPerRow, - uint RowsPerImage, - uint MipLevel = 0, - uint ImageIndex = 0, - uint ImageCount = 1, - ImagePlane Plane = ImagePlane.All - ) - { - Dst.AssertSameQueue(Queue); - if (Loc.SubmitId != m_queue.SubmitId) - throw new ArgumentException("An attempt was made to use an expired upload location"); - var cmd = new FCommandBufferImageCopy - { - Base = { Type = FCommandType.BufferImageCopy }, - RangeIndex = (uint)m_buffer_image_copy_ranges.Count, - Image = AddResource(Dst), - Buffer = { Upload = Loc }, - BufferType = FBufferRefType.Upload, - ImageToBuffer = false, - }; - var range = new FBufferImageCopyRange - { - BufferOffset = Loc.Offset, - BytesPerRow = BytesPerRow, - RowsPerImage = RowsPerImage, - ImageIndex = ImageIndex, - ImageCount = ImageCount, - MipLevel = (ushort)MipLevel, - Plane = Plane.ToFFI(), - }; - range.ImageOffset[0] = DstX; - range.ImageOffset[1] = DstY; - range.ImageOffset[2] = DstZ; - range.ImageExtent[0] = DstWidth; - range.ImageExtent[1] = DstHeight; - range.ImageExtent[2] = DstDepth; - m_buffer_image_copy_ranges.Add(range); - if (AutoBarrierEnabled) - { - ref var state = ref StateAt(cmd.Image); - state.ReqState( - this, - FResLayout.CopyDst, - FResAccess.CopyDst, - FShaderStageFlags.None, - FLegacyState.CopyDst - ); - } - m_commands.Add(new() { BufferImageCopy = cmd }); - } - - #endregion - - #region Render - - public RenderScope Render( - ReadOnlySpan Rtvs, RenderInfo.DsvInfo? Dsv = null, - bool AutoViewportScissor = true, - string? Name = null, ReadOnlySpan Name8 = default - ) => Render(new(Rtvs, Dsv), AutoViewportScissor, Name, Name8); - public RenderScope Render( - RenderInfo.DsvInfo Dsv, ReadOnlySpan Rtvs = default, - bool AutoViewportScissor = true, - string? Name = null, ReadOnlySpan Name8 = default - ) => Render(new(Rtvs, Dsv), AutoViewportScissor, Name, Name8); - public RenderScope Render( - in RenderInfo Info, - bool AutoViewportScissor = true, - string? Name = null, ReadOnlySpan Name8 = default - ) - { - #region Check Nested - - if (m_in_render_or_compute_scope) throw new InvalidOperationException("Cannot nest Render or Compute scopes"); - m_in_render_or_compute_scope = true; - - #endregion - - #region Check Args - - if (Info.Dsv == null && Info.Rtvs.Length == 0) throw new ArgumentException("No any rtv or dsv provided"); - if (Info.Rtvs.Length > 8) throw new ArgumentException("Too many rtvs provided, it can't be more than 8"); - - #endregion - - #region Cmd - - var info_index = m_render_infos.Count; - var cmd = new FCommandRender - { - Base = { Type = FCommandType.Render }, - InfoIndex = (uint)info_index, - CommandStartIndex = (uint)m_render_commands.Count, - }; - - #endregion - - #region Init - - var has_dsv = Info.Dsv.HasValue; - var dsv = Info.Dsv ?? default; - if (has_dsv) dsv.View!.AssertSameQueue(Queue); - - #endregion - - #region Info - - FRenderInfo info = new() - { - Dsv = has_dsv ? AddResource(dsv.View!.Resource) : default, - NumRtv = (uint)Info.Rtvs.Length, - Depth = has_dsv && dsv.DepthLoad is { IsClear: true, Clear: var cd } ? cd : 1, - Stencil = has_dsv && dsv.StencilLoad is { IsClear: true, Clear: var cs } ? (byte)cs : (byte)0, - }; - - #endregion - - #region DsvLoadOp - - info.DsvLoadOp[0] = has_dsv - ? dsv.DepthLoad.Tag switch - { - LoadOp.Tags.Load => FLoadOp.Load, - LoadOp.Tags.Clear => FLoadOp.Clear, - LoadOp.Tags.Discard => FLoadOp.Discard, - LoadOp.Tags.NoAccess => FLoadOp.NoAccess, - _ => throw new ArgumentOutOfRangeException() - } - : FLoadOp.NoAccess; - info.DsvLoadOp[1] = has_dsv - ? dsv.StencilLoad.Tag switch - { - LoadOp.Tags.Load => FLoadOp.Load, - LoadOp.Tags.Clear => FLoadOp.Clear, - LoadOp.Tags.Discard => FLoadOp.Discard, - LoadOp.Tags.NoAccess => FLoadOp.NoAccess, - _ => throw new ArgumentOutOfRangeException() - } - : FLoadOp.NoAccess; - - #endregion - - #region DsvStoreOp - - info.DsvStoreOp[0] = has_dsv - ? dsv.DepthStore.Tag switch - { - StoreOp.Tags.Store => FStoreOp.Store, - StoreOp.Tags.Discard => FStoreOp.Discard, - StoreOp.Tags.NoAccess => FStoreOp.NoAccess, - _ => throw new ArgumentOutOfRangeException() - } - : FStoreOp.NoAccess; - - info.DsvStoreOp[1] = has_dsv - ? dsv.StencilStore.Tag switch - { - StoreOp.Tags.Store => FStoreOp.Store, - StoreOp.Tags.Discard => FStoreOp.Discard, - StoreOp.Tags.NoAccess => FStoreOp.NoAccess, - _ => throw new ArgumentOutOfRangeException() - } - : FStoreOp.NoAccess; - - #endregion - - #region Rtv - - var rt_size = Info.Dsv?.View.USize2d ?? Info.Rtvs[0].View.USize2d; - for (var i = 0; i < Info.Rtvs.Length; i++) - { - ref readonly var rtv = ref Info.Rtvs[i]; - rtv.View.AssertSameQueue(Queue); - if (!rtv.View.USize2d.Equals(rt_size)) - throw new ArgumentException("RenderTargets And DepthStencil must be the same size"); - info.Rtv[i] = AddResource(rtv.View.Resource); - info.ResolveInfoIndex[i] = uint.MaxValue; // todo - if (rtv.Load is { IsClear: true, Clear: var cc }) - Unsafe.As(ref info.Color[i * 4]) = cc; - info.RtvLoadOp[i] = rtv.Load.Tag switch - { - LoadOp.Tags.Load => FLoadOp.Load, - LoadOp.Tags.Clear => FLoadOp.Clear, - LoadOp.Tags.Discard => FLoadOp.Discard, - LoadOp.Tags.NoAccess => FLoadOp.NoAccess, - _ => throw new ArgumentOutOfRangeException() - }; - info.RtvStoreOp[i] = rtv.Store.Tag switch - { - StoreOp.Tags.Store => FStoreOp.Store, - StoreOp.Tags.Discard => FStoreOp.Discard, - StoreOp.Tags.NoAccess => FStoreOp.NoAccess, - _ => throw new ArgumentOutOfRangeException() - }; - } - - #endregion - - #region EndInfo - - m_render_infos.Add(info); - - #endregion - - #region DebugScope - - var debug_scope = false; - if (Name != null) - { - debug_scope = true; - Scope(Name); - } - else if (Name8.Length > 0) - { - debug_scope = true; - Scope(Name8); - } - - #endregion - - #region State - - if (AutoBarrierEnabled) - { - 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 - - #region Scope - - RenderScope scope = new(this, info_index, cmd, m_render_commands, debug_scope); - - #endregion - - #region AutoViewportScissor - - if (AutoViewportScissor) - { - scope.SetViewportScissor( - [new UViewPort { Width = rt_size.Width, Height = rt_size.Height }], - [new URect { Right = rt_size.Width, Bottom = rt_size.Height }] - ); - } - - #endregion - - return scope; - } - - #endregion - - #region Compute - - public ComputeScope Compute(string? Name = null, ReadOnlySpan Name8 = default) - { - #region Check Nested - - if (m_in_render_or_compute_scope) throw new InvalidOperationException("Cannot nest Render or Compute scopes"); - m_in_render_or_compute_scope = true; - - #endregion - - #region Debug - - var debug_scope = false; - if (Name != null) - { - debug_scope = true; - Scope(Name); - } - else if (Name8.Length > 0) - { - debug_scope = true; - Scope(Name8); - } - - #endregion - - #region Cmd and Scope - - var info_index = m_compute_infos.Count; - m_compute_infos.Add(new()); - - var cmd = new FCommandCompute - { - Base = { Type = FCommandType.Compute }, - InfoIndex = (uint)info_index, - CommandStartIndex = (uint)m_compute_commands.Count, - }; - return new(this, info_index, cmd, m_compute_commands, debug_scope); - - #endregion - } - - #endregion - - #endregion - - #region SyncBinding - - /// - /// 必须在 Render 或者 Compute 范围内使用 - /// - internal void SyncBinding(ref PipelineContext context, in L list) where L : ISubCommandList - { - var binding = context.CurrentBinding; - if (binding == null) return; - if (AutoBarrierEnabled) - { - 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 = false; - FResourceRef res; - switch (view.Tag) - { - case View.Tags.Buffer: - res = AddResource(view.Buffer); - is_buffer = true; - break; - case View.Tags.Image: - res = AddResource(view.Image); - break; - default: - 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: - 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: - 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($"{context.CurrentBinding}::[{i}]", old_state, Legacy, Access, Layout); - } - } - if (!(context.PipelineChanged || context.BindingChanged)) return; - context.PipelineChanged = false; - context.BindingChanged = false; - var first = m_bindings.Add(binding); - list.OnSyncBinding(m_sync_binding_count++); - if (first) - { - var layout = binding.Layout; - for (var c = 0u; c < layout.NativeGroupClasses.Length; c++) - { - ref readonly var @class = ref layout.NativeGroupClasses[(int)c]; - for (var g = 0u; g < @class.InfoSpan.Length; g++) - { - SyncBindingItem(binding, layout, c, g, first); - } - } - binding.ApplyChange(); - } - else if (binding.Changed) - { - var layout = binding.Layout; - foreach (var (c, g) in binding.m_changed_groups) - { - SyncBindingItem(binding, layout, c, g, first); - } - binding.ApplyChange(); - } - } - - private void SyncBindingItem(ShaderBinding binding, ShaderLayout layout, uint c, uint g, bool first) - { - ref readonly var @class = ref layout.NativeGroupClasses[(int)c]; - ref readonly var group = ref @class.InfoSpan[(int)g]; - if (@class.Scope != FShaderLayoutGroupScope.Persist) goto Add; - if (!first) goto Add; - var changed = binding.m_changed_groups.Contains((c, g)); - if (changed) goto Add; - return; - Add: - if (@class.Sampler) m_growing_sampler_binding_capacity += group.Size; - else m_growing_resource_binding_capacity += group.Size; - return; - } - - #endregion -} - -#region DebugScope - -public struct DebugScope(CommandList self) : IDisposable -{ - private bool m_disposed; - public void Dispose() - { - if (m_disposed) throw new ObjectDisposedException(nameof(ComputeScope)); - m_disposed = true; - if (!self.DebugEnabled) return; - var cmd = new FCommandEndScope - { - Base = { Type = FCommandType.EndScope }, - }; - self.m_commands.Add(new() { EndScope = cmd }); - self.m_debug_scope_count--; - } -} - -public struct RenderDebugScope(CommandList self) : IDisposable -{ - private bool m_disposed; - public void Dispose() - { - if (m_disposed) throw new ObjectDisposedException(nameof(ComputeScope)); - m_disposed = true; - if (!self.DebugEnabled) return; - var cmd = new FCommandEndScope - { - Base = { Type = FCommandType.EndScope }, - }; - self.m_render_commands.Add(new() { EndScope = cmd }); - self.m_render_debug_scope_count--; - } -} - -public struct ComputeDebugScope(CommandList self) : IDisposable -{ - private bool m_disposed; - public void Dispose() - { - if (m_disposed) throw new ObjectDisposedException(nameof(ComputeScope)); - m_disposed = true; - if (!self.DebugEnabled) return; - var cmd = new FCommandEndScope - { - Base = { Type = FCommandType.EndScope }, - }; - self.m_compute_commands.Add(new() { EndScope = cmd }); - self.m_compute_debug_scope_count--; - } -} - -#endregion - -#region RenderInfo - -[Union] -public partial struct LoadOp -{ - [UnionTemplate] - private interface Template - { - void Load(); - void Discard(); - void NoAccess(); - } - - public static readonly LoadOp Load = MakeLoad(); - public static LoadOp Clear(T Clear) => LoadOp.MakeClear(Clear); - public static readonly LoadOp Discard = MakeDiscard(); - public static readonly LoadOp NoAccess = MakeNoAccess(); -} - -[Union] -public partial struct LoadOp -{ - [UnionTemplate] - private interface Template - { - void Load(); - T Clear(); - void Discard(); - void NoAccess(); - } - - public static readonly LoadOp Load = MakeLoad(); - public static implicit operator LoadOp(T Clear) => MakeClear(Clear); - public static readonly LoadOp Discard = MakeDiscard(); - public static readonly LoadOp NoAccess = MakeNoAccess(); - - public static implicit operator LoadOp(LoadOp op) => op.Tag switch - { - LoadOp.Tags.Load => Load, - LoadOp.Tags.Discard => Discard, - LoadOp.Tags.NoAccess => NoAccess, - _ => throw new ArgumentOutOfRangeException() - }; -} - -[Union] -public partial struct StoreOp -{ - [UnionTemplate] - private interface Template - { - void Store(); - void Discard(); - void NoAccess(); - } - - public static readonly StoreOp Store = MakeStore(); - public static readonly StoreOp Discard = MakeDiscard(); - public static readonly StoreOp NoAccess = MakeNoAccess(); -} - -public ref struct RenderInfo(ReadOnlySpan Rtvs, RenderInfo.DsvInfo? Dsv = null) -{ - public DsvInfo? Dsv = Dsv; - public ReadOnlySpan Rtvs = Rtvs; - - public RenderInfo() : this([]) { } - public RenderInfo(DsvInfo Dsv, ReadOnlySpan Rtvs = default) : this(Rtvs, Dsv) { } - - public struct DsvInfo( - IDsv View, - LoadOp DepthLoad, - LoadOp StencilLoad, - StoreOp DepthStore, - StoreOp StencilStore - ) - { - public IDsv View = View; - public LoadOp DepthLoad = DepthLoad; - public LoadOp StencilLoad = StencilLoad; - public StoreOp DepthStore = DepthStore; - public StoreOp StencilStore = StencilStore; - - public DsvInfo(IDsv View) : this(View, LoadOp.Load, LoadOp.Load, StoreOp.Store, StoreOp.Store) { } - public DsvInfo(IDsv View, LoadOp DepthLoad, LoadOp StencilLoad) - : this(View, DepthLoad, StencilLoad, StoreOp.Store, StoreOp.Store) { } - public DsvInfo(IDsv View, LoadOp DepthLoad) - : this(View, DepthLoad, LoadOp.Load, StoreOp.Store, StoreOp.Store) { } - } - - public struct RtvInfo(IRtv View, LoadOp Load, StoreOp Store) - { - public IRtv View = View; - public LoadOp Load = Load; - public StoreOp Store = Store; - - public RtvInfo(IRtv View) : this(View, LoadOp.Load, StoreOp.Store) { } - - public RtvInfo(IRtv View, LoadOp Load) : this(View, Load, StoreOp.Store) { } - } -} - -#endregion - -#region RenderScope - -public unsafe struct RenderScope( - CommandList self, - int info_index, - FCommandRender render_cmd, - List m_commands, - bool debug_scope -) : IDisposable, ISubCommandList -{ - #region Fields - - internal FCommandRender render_cmd = render_cmd; - internal PipelineContext m_context; - internal bool m_disposed; - internal bool m_has_pixel_shader; - internal bool m_has_vertex_shader; - internal bool m_has_mesh_shader; - internal bool m_has_task_shader; - internal bool m_has_uav_writes; - - #endregion - - #region Props - - internal ref FRenderInfo Info => ref CollectionsMarshal.AsSpan(self.m_render_infos)[info_index]; - - #endregion - - #region Dispose - - public void Dispose() - { - if (m_disposed) throw new ObjectDisposedException(nameof(ComputeScope)); - m_disposed = true; - if (self.m_render_debug_scope_count != 0) - throw new InvalidOperationException( - "There is still Debug scope not ended, please check whether Dispose is missed." - ); - ref var info = ref Info; - info.HasUavWrites = m_has_uav_writes; - if (self.AutoBarrierEnabled) - { - foreach (var (res, scoped_state) in self.m_scoped_res_state) - { - ref var state = ref self.StateAt(res); - var stages = ShaderStageFlags.None; - if (m_has_pixel_shader && (scoped_state.Usage & ScopedStateUsage.Pixel) != 0) - stages |= ShaderStageFlags.Pixel; - if (m_has_vertex_shader && (scoped_state.Usage & ScopedStateUsage.Vertex) != 0) - stages |= ShaderStageFlags.Vertex; - if (m_has_mesh_shader && (scoped_state.Usage & ScopedStateUsage.Mesh) != 0) - stages |= ShaderStageFlags.Mesh; - if (m_has_task_shader && (scoped_state.Usage & ScopedStateUsage.Mesh) != 0) - stages |= ShaderStageFlags.Task; - state.ReqState( - self, - scoped_state.Layout.ToFFI(), - scoped_state.Access.ToFFI(), - stages.ToFFI(), - scoped_state.Legacy.ToFFI() - ); - } - foreach (var res in self.m_scoped_res_state.Keys) - { - ref var state = ref self.StateAt(res); - state.MarkUse(self); - } - } - render_cmd.CommandCount = (uint)m_commands.Count - render_cmd.CommandStartIndex; - self.m_commands.Add(new() { Render = render_cmd }); - self.m_in_render_or_compute_scope = false; - if (debug_scope) new DebugScope(self).Dispose(); - self.m_scoped_res_state.Clear(); - } - - #endregion - - #region Debug - - #region Label - - public void Label(string Label) - { - if (!self.DebugEnabled) return; - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.Label }, - StringIndex = self.AddString(Label), - StringLength = (uint)Label.Length, - StrType = FStrType.Str16, - }; - m_commands.Add(new() { Label = cmd }); - } - - public void Label(ReadOnlySpan Label) - { - if (!self.DebugEnabled) return; - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.EndScope }, - StringIndex = self.AddString(Label), - StringLength = (uint)Label.Length, - StrType = FStrType.Str8, - }; - m_commands.Add(new() { Label = cmd }); - } - - #endregion - - #region Scope - - public RenderDebugScope Scope(string Name) - { - if (!self.DebugEnabled) return new(self); - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.EndScope }, - StringIndex = self.AddString(Name), - StringLength = (uint)Name.Length, - StrType = FStrType.Str16, - }; - m_commands.Add(new() { Label = cmd }); - self.m_render_debug_scope_count++; - return new(self); - } - - public RenderDebugScope Scope(ReadOnlySpan Name) - { - if (!self.DebugEnabled) return new(self); - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.EndScope }, - StringIndex = self.AddString(Name), - StringLength = (uint)Name.Length, - StrType = FStrType.Str8, - }; - m_commands.Add(new() { Label = cmd }); - self.m_render_debug_scope_count++; - return new(self); - } - - #endregion - - #endregion - - #region SetPipeline - - public void SetPipeline(ShaderPipeline Pipeline) - { - if (!Pipeline.Shader.Stages.HasAnyFlags(ShaderStageFlags.Pixel)) - throw new ArgumentException("Only shaders with a pixel stage can be used for rendering"); - if (!m_context.SetPipeline(self, Pipeline)) return; - var cmd = new FCommandSetPipeline - { - Base = { Type = FCommandType.SetPipeline }, - Pipeline = Pipeline.m_ptr, - }; - m_commands.Add(new() { SetPipeline = cmd }); - } - - #endregion - - #region SetBinding - - public void SetBinding(ShaderBinding Binding) - { - if (!m_context.SetBinding(self, Binding)) return; - var cmd = new FCommandSetBinding - { - Base = { Type = FCommandType.SetBinding }, - 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 - - #region SetViewportScissor - - public void SetViewportScissor( - ReadOnlySpan Viewports, - ReadOnlySpan Scissors - ) - { - var cmd = new FCommandSetViewportScissor - { - Base = { Type = FCommandType.SetViewportScissor }, - ViewportCount = (uint)Viewports.Length, - ScissorRectCount = (uint)Scissors.Length, - }; - if (Viewports.Length > 0) - { - cmd.ViewportIndex = (uint)self.m_viewports.Count; - self.m_viewports.AddRange(MemoryMarshal.Cast(Viewports)); - } - if (Scissors.Length > 0) - { - cmd.ScissorRectIndex = (uint)self.m_rects.Count; - self.m_rects.AddRange(MemoryMarshal.Cast(Scissors)); - } - m_commands.Add(new() { SetViewportScissor = cmd }); - } - - #endregion - - #region SetMeshBuffers - - public void SetMeshBuffers( - MeshLayout MeshLayout, - uint VertexStartSlot, - ReadOnlySpan VertexBuffers - ) => SetMeshBuffers(MeshLayout, FGraphicsFormat.Unknown, null, VertexStartSlot, VertexBuffers); - - public void SetMeshBuffers( - MeshLayout MeshLayout, - ReadOnlySpan VertexBuffers - ) => SetMeshBuffers(MeshLayout, FGraphicsFormat.Unknown, null, 0, VertexBuffers); - - public void SetMeshBuffers( - MeshLayout MeshLayout, - FGraphicsFormat IndexFormat, - BufferRange? IndexBuffer, - uint VertexStartSlot, - ReadOnlySpan VertexBuffers - ) - { - self.AddObject(MeshLayout); - var cmd = new FCommandSetMeshBuffers - { - Base = { Type = FCommandType.SetMeshBuffers }, - IndexFormat = IndexFormat, - VertexStartSlot = VertexStartSlot, - PayloadIndex = (uint)self.m_mesh_buffers.Count, - }; - var buf = new FMeshBuffers - { - MeshLayout = MeshLayout.m_ptr, - VertexBufferCount = (uint)VertexBuffers.Length, - }; - if (IndexBuffer is { } index_buffer) - { - buf.IndexBuffer = new() - { - Buffer = self.AddResource(index_buffer.Buffer.Resource), - Offset = index_buffer.Offset, - Size = index_buffer.Size == uint.MaxValue ? (uint)index_buffer.Buffer.Size : index_buffer.Size, - }; - 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) - { - var index = self.m_vertex_buffer_ranges.Count; - buf.VertexBuffersIndex = (uint)index; - CollectionsMarshal.SetCount( - self.m_vertex_buffer_ranges, self.m_vertex_buffer_ranges.Count + VertexBuffers.Length - ); - var vbs = CollectionsMarshal.AsSpan(self.m_vertex_buffer_ranges).Slice(index, VertexBuffers.Length); - for (var i = 0; i < VertexBuffers.Length; i++) - { - var buffer = VertexBuffers[i]; - buffer.Buffer.AssertSameQueue(self.Queue); - ref var dst = ref vbs[i]; - dst = new() - { - Base = - { - Buffer = self.AddResource(buffer.Buffer.Resource), - Offset = buffer.Offset, - Size = buffer.Size == uint.MaxValue ? (uint)buffer.Buffer.Size : buffer.Size, - }, - Index = buffer.Index, - }; - 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); - m_commands.Add(new() { SetMeshBuffers = cmd }); - } - - #endregion - - #region Draw - - public void Draw( - uint VertexCount, uint InstanceCount = 1, - uint FirstVertex = 0, uint FirstInstance = 0, - ShaderBinding? Binding = null - ) => Draw(null, false, VertexCount, InstanceCount, FirstVertex, FirstInstance, 0, Binding); - - public void Draw( - ShaderPipeline? Pipeline, - uint VertexCount, uint InstanceCount = 1, - uint FirstVertex = 0, uint FirstInstance = 0, - ShaderBinding? Binding = null - ) => Draw(Pipeline, false, VertexCount, InstanceCount, FirstVertex, FirstInstance, 0, Binding); - - public void DrawIndexed( - uint IndexCount, uint InstanceCount = 1, - uint FirstIndex = 0, uint FirstInstance = 0, uint VertexOffset = 0, - ShaderBinding? Binding = null - ) => Draw(null, true, IndexCount, InstanceCount, FirstIndex, FirstInstance, VertexOffset, Binding); - - public void DrawIndexed( - ShaderPipeline? Pipeline, - uint IndexCount, uint InstanceCount = 1, - uint FirstIndex = 0, uint FirstInstance = 0, uint VertexOffset = 0, - ShaderBinding? Binding = null - ) => Draw(Pipeline, true, IndexCount, InstanceCount, FirstIndex, FirstInstance, VertexOffset, Binding); - - public void Draw( - ShaderPipeline? Pipeline, bool Indexed, - uint VertexOrIndexCount, uint InstanceCount = 1, - uint FirstVertexOrIndex = 0, uint FirstInstance = 0, uint VertexOffset = 0, - ShaderBinding? Binding = null - ) - { - if (Pipeline != null) - { - if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Vertex)) - throw new ArgumentException("Only Vertex shaders can use Draw"); - SetPipeline(Pipeline); - } - else - { - if (m_context.CurrentPipeline == null) throw new InvalidOperationException("Pipeline is not set"); - if (!m_context.CurrentPipeline.Shader.Stages.HasFlags(ShaderStageFlags.Vertex)) - throw new ArgumentException("Only shaders with a vertex stage can use Draw"); - } - if (Binding != null) SetBinding(Binding); - self.SyncBinding(ref m_context, this); - var cmd = new FCommandDraw - { - Base = { Type = FCommandType.Draw }, - VertexOrIndexCount = VertexOrIndexCount, - InstanceCount = InstanceCount, - FirstVertexOrIndex = FirstVertexOrIndex, - FirstInstance = FirstInstance, - VertexOffset = VertexOffset, - Indexed = Indexed, - }; - m_commands.Add(new() { Draw = cmd }); - m_has_pixel_shader = true; - m_has_vertex_shader = true; - } - - #endregion - - #region DispatchMesh - - public void DispatchMesh( - 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, - ShaderBinding? Binding = null - ) - { - if (Pipeline != null) - { - if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) - throw new ArgumentException("Only Mesh shaders can use DispatchMesh"); - SetPipeline(Pipeline); - } - else - { - if (m_context.CurrentPipeline == null) throw new InvalidOperationException("Pipeline is not set"); - if (!m_context.CurrentPipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) - throw new ArgumentException("Only shaders with a mesh stage can use DispatchMesh"); - } - if (Binding != null) SetBinding(Binding); - self.SyncBinding(ref m_context, this); - var cmd = new FCommandDispatch - { - Base = { Type = FCommandType.Draw }, - GroupCountX = GroupCountX, - GroupCountY = GroupCountY, - GroupCountZ = GroupCountZ, - Type = FDispatchType.Mesh, - }; - m_commands.Add(new() { Dispatch = cmd }); - m_has_pixel_shader = true; - m_has_mesh_shader = true; - m_has_task_shader = m_context.CurrentPipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Task); - } - - #endregion - - #region OnSyncBinding - - void ISubCommandList.OnSyncBinding(uint index) - { - var cmd = new FCommandSyncBinding - { - Base = { Type = FCommandType.SyncBinding }, - Index = index, - }; - m_commands.Add(new() { SyncBinding = cmd }); - } - - #endregion -} - -#endregion - -#region ComputeScope - -public unsafe struct ComputeScope( - CommandList self, - int info_index, - FCommandCompute compute_cmd, - List m_commands, - bool debug_scope -) : IDisposable, ISubCommandList -{ - #region Fields - - internal FCommandCompute compute_cmd = compute_cmd; - internal PipelineContext m_context; - internal bool m_disposed; - internal bool m_has_compute_shader; - internal bool m_has_mesh_shader; - internal bool m_has_task_shader; - - #endregion - - #region Props - - internal ref FComputeInfo Info => ref CollectionsMarshal.AsSpan(self.m_compute_infos)[info_index]; - - #endregion - - #region Dispose - - public void Dispose() - { - if (m_disposed) throw new ObjectDisposedException(nameof(ComputeScope)); - m_disposed = true; - if (self.m_compute_debug_scope_count != 0) - throw new InvalidOperationException( - "There is still Debug scope not ended, please check whether Dispose is missed." - ); - if (self.AutoBarrierEnabled) - { - foreach (var (res, scoped_state) in self.m_scoped_res_state) - { - ref var state = ref self.StateAt(res); - var stages = ShaderStageFlags.None; - if (m_has_compute_shader && (scoped_state.Usage & ScopedStateUsage.Compute) != 0) - stages |= ShaderStageFlags.Compute; - if (m_has_mesh_shader && (scoped_state.Usage & ScopedStateUsage.Mesh) != 0) - stages |= ShaderStageFlags.Mesh; - if (m_has_task_shader && (scoped_state.Usage & ScopedStateUsage.Mesh) != 0) - stages |= ShaderStageFlags.Task; - state.ReqState( - self, - scoped_state.Layout.ToFFI(), - scoped_state.Access.ToFFI(), - stages.ToFFI(), - scoped_state.Legacy.ToFFI() - ); - } - foreach (var res in self.m_scoped_res_state.Keys) - { - ref var state = ref self.StateAt(res); - state.MarkUse(self); - } - } - compute_cmd.CommandCount = (uint)m_commands.Count - compute_cmd.CommandStartIndex; - self.m_commands.Add(new() { Compute = compute_cmd }); - self.m_in_render_or_compute_scope = false; - if (debug_scope) new DebugScope(self).Dispose(); - self.m_scoped_res_state.Clear(); - } - - #endregion - - #region Debug - - #region Label - - public void Label(string Label) - { - if (!self.DebugEnabled) return; - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.Label }, - StringIndex = self.AddString(Label), - StringLength = (uint)Label.Length, - StrType = FStrType.Str16, - }; - m_commands.Add(new() { Label = cmd }); - } - - public void Label(ReadOnlySpan Label) - { - if (!self.DebugEnabled) return; - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.EndScope }, - StringIndex = self.AddString(Label), - StringLength = (uint)Label.Length, - StrType = FStrType.Str8, - }; - m_commands.Add(new() { Label = cmd }); - } - - #endregion - - #region Scope - - public ComputeDebugScope Scope(string Name) - { - if (!self.DebugEnabled) return new(self); - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.EndScope }, - StringIndex = self.AddString(Name), - StringLength = (uint)Name.Length, - StrType = FStrType.Str16, - }; - m_commands.Add(new() { Label = cmd }); - self.m_compute_debug_scope_count++; - return new(self); - } - - public ComputeDebugScope Scope(ReadOnlySpan Name) - { - if (!self.DebugEnabled) return new(self); - var cmd = new FCommandLabel - { - Base = { Type = FCommandType.EndScope }, - StringIndex = self.AddString(Name), - StringLength = (uint)Name.Length, - StrType = FStrType.Str8, - }; - m_commands.Add(new() { Label = cmd }); - self.m_compute_debug_scope_count++; - return new(self); - } - - #endregion - - #endregion - - #region SetPipeline - - public void SetPipeline(ShaderPipeline Pipeline) - { - if (!Pipeline.Shader.Stages.HasAnyFlags(ShaderStageFlags.Compute | ShaderStageFlags.Mesh)) - throw new ArgumentException("Only shaders with a Compute or Mesh stage can be used for computation"); - if (Pipeline.Shader.Stages.HasAnyFlags(ShaderStageFlags.Pixel)) - throw new ArgumentException("Shaders with a pixel stage cannot be used for computation"); - if (!m_context.SetPipeline(self, Pipeline)) return; - var cmd = new FCommandSetPipeline - { - Base = { Type = FCommandType.SetPipeline }, - Pipeline = Pipeline.m_ptr, - }; - m_commands.Add(new() { SetPipeline = cmd }); - } - - #endregion - - #region SetBinding - - public void SetBinding(ShaderBinding Binding) - { - if (!m_context.SetBinding(self, Binding)) return; - var cmd = new FCommandSetBinding - { - Base = { Type = FCommandType.SetBinding }, - Binding = Binding.m_ptr, - }; - m_commands.Add(new() { SetBinding = cmd }); - } - - #endregion - - #region Dispatch - - public void Dispatch( - 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, - 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, - 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, - 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, - ShaderBinding? Binding = null - ) - { - if (Pipeline != null) - { - SetPipeline(Pipeline); - } - else - { - if (m_context.CurrentPipeline == null) throw new InvalidOperationException("Pipeline is not set"); - } - if (Binding != null) SetBinding(Binding); - if (Type == DispatchType.Auto) - { - if (m_context.CurrentPipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Compute)) - { - Type = DispatchType.Compute; - m_has_compute_shader = true; - } - else if (m_context.CurrentPipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) - { - Type = DispatchType.Mesh; - m_has_mesh_shader = true; - if (m_context.CurrentPipeline.Shader.Stages.HasFlags(ShaderStageFlags.Task)) - m_has_task_shader = true; - } - else throw new ArgumentException("Only Mesh and Compute shaders can use in Compute Scope"); - } - else if (Type == DispatchType.Mesh) - { - if (!m_context.CurrentPipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) - throw new ArgumentException("Only Mesh shaders can use DispatchMesh"); - m_has_mesh_shader = true; - if (m_context.CurrentPipeline.Shader.Stages.HasFlags(ShaderStageFlags.Task)) - m_has_task_shader = true; - } - else if (Type == DispatchType.Compute) - { - if (!m_context.CurrentPipeline!.Shader.Stages.HasFlags(ShaderStageFlags.Compute)) - throw new ArgumentException("Only Compute shaders can use Dispatch"); - m_has_compute_shader = true; - } - self.SyncBinding(ref m_context, this); - var cmd = new FCommandDispatch - { - Base = { Type = FCommandType.SetBinding }, - GroupCountX = GroupCountX, - GroupCountY = GroupCountY, - GroupCountZ = GroupCountZ, - Type = Type switch - { - DispatchType.Auto => throw new UnreachableException(), - DispatchType.Compute => FDispatchType.Compute, - DispatchType.Mesh => FDispatchType.Mesh, - _ => throw new ArgumentOutOfRangeException(nameof(Type), Type, null) - }, - }; - m_commands.Add(new() { Dispatch = cmd }); - } - - #endregion - - #region OnSyncBinding - - void ISubCommandList.OnSyncBinding(uint index) - { - var cmd = new FCommandSyncBinding - { - Base = { Type = FCommandType.SyncBinding }, - Index = index, - }; - m_commands.Add(new() { SyncBinding = cmd }); - } - - #endregion -} - -#endregion diff --git a/Coplt.Graphics.Core/Core/GpuAdapter.cs b/Coplt.Graphics.Core/Core/GpuAdapter.cs index 12a6d97..ba4b878 100644 --- a/Coplt.Graphics.Core/Core/GpuAdapter.cs +++ b/Coplt.Graphics.Core/Core/GpuAdapter.cs @@ -70,11 +70,6 @@ public GpuDevice CreateDevice( string? Name = null, ReadOnlySpan Name8 = default ) { - var QueueName = !Instance.DebugEnabled || Name is null ? null : $"{Name} Main Queue"; - var QueueName8 = !Instance.DebugEnabled || Name8.Length == 0 - ? Name8 - : Utils.JoinUtf8String(Name8, " Main Queue"u8); - fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) { @@ -84,7 +79,7 @@ public GpuDevice CreateDevice( }; FGpuDevice* ptr; m_ptr->CreateDevice(&f_options, &ptr).TryThrow(); - return new(ptr, Instance, this, Name, QueueName: QueueName, QueueName8: QueueName8); + return new(ptr, Instance, this, Name); } } diff --git a/Coplt.Graphics.Core/Core/GpuBuffer.cs b/Coplt.Graphics.Core/Core/GpuBuffer.cs index cb604d1..c2d7ae2 100644 --- a/Coplt.Graphics.Core/Core/GpuBuffer.cs +++ b/Coplt.Graphics.Core/Core/GpuBuffer.cs @@ -39,19 +39,14 @@ public sealed unsafe partial class GpuBuffer : GpuResource, IGpuResource, ICbv, public BufferUsage Usage => (BufferUsage)Data->m_usage; GpuResourceType IGpuResource.Type => GpuResourceType.Buffer; IGpuResource IGpuView.Resource => this; - FResourceMeta IGpuResource.GetMeta() => new() - { - Type = FResourceRefType.Buffer, - Buffer = Ptr, - }; #endregion #region Ctor - internal GpuBuffer(FGpuBuffer* ptr, string? name, GpuQueue queue) : this(ptr, ptr->GpuBufferData(), name, queue) { } - private GpuBuffer(FGpuBuffer* ptr, FGpuBufferData* data, string? name, GpuQueue queue) - : base((FGpuResource*)ptr, (FGpuResourceData*)data, name, queue) { } + internal GpuBuffer(FGpuBuffer* ptr, string? name, GpuIsolate isolate) : this(ptr, ptr->GpuBufferData(), name, isolate) { } + private GpuBuffer(FGpuBuffer* ptr, FGpuBufferData* data, string? name, GpuIsolate isolate) + : base((FGpuResource*)ptr, (FGpuResourceData*)data, name, isolate) { } #endregion @@ -115,6 +110,4 @@ public Span EnsureMappedMemory() } #endregion - - public GpuIsolate Isolate => throw new NotImplementedException(); } diff --git a/Coplt.Graphics.Core/Core/GpuDevice.cs b/Coplt.Graphics.Core/Core/GpuDevice.cs index de5ee7d..ed8e530 100644 --- a/Coplt.Graphics.Core/Core/GpuDevice.cs +++ b/Coplt.Graphics.Core/Core/GpuDevice.cs @@ -17,8 +17,6 @@ public sealed unsafe partial class GpuDevice : GpuObject internal readonly GraphicsInstance m_instance; internal readonly GpuAdapter m_adapter; - [Drop] - internal readonly GpuQueue m_main_queue; #endregion @@ -27,22 +25,16 @@ public sealed unsafe partial class GpuDevice : GpuObject public new FGpuDevice* Ptr => (FGpuDevice*)m_ptr; public GraphicsInstance Instance => m_instance; public GpuAdapter Adapter => m_adapter; - public GpuQueue MainQueue => m_main_queue; - public CommandList MainCommandList => MainQueue.CommandList; #endregion #region Ctor - internal GpuDevice( - FGpuDevice* ptr, GraphicsInstance instance, GpuAdapter? adapter, - string? name, string? QueueName = null, ReadOnlySpan QueueName8 = default - ) : base((FGpuObject*)ptr, name) + internal GpuDevice(FGpuDevice* ptr, GraphicsInstance instance, GpuAdapter? adapter, string? name) : base((FGpuObject*)ptr, name) { m_instance = instance; m_name = name; m_adapter = adapter ?? m_instance.m_ptr_to_adapters[(nuint)Ptr->GetAdapter()]; - m_main_queue = CreateMainQueue(Name: QueueName, Name8: QueueName8); } #endregion @@ -72,25 +64,6 @@ public GpuIsolate CreateIsolate(string? Name = null, ReadOnlySpan Name8 = #endregion - #region CreateMainQueue - - public GpuQueue CreateMainQueue(string? Name = null, ReadOnlySpan Name8 = default) - { - fixed (char* p_name = Name) - fixed (byte* p_name8 = Name8) - { - FMainQueueCreateOptions f_options = new() - { - Name = new(Name, Name8, p_name, p_name8), - }; - FGpuQueue* ptr; - Ptr->CreateMainQueue(&f_options, &ptr).TryThrow(); - return new(ptr, Name, this); - } - } - - #endregion - #region CreateShaderModule public ShaderModule CreateShaderModule( @@ -262,15 +235,6 @@ public Shader CreateShader( #endregion - #region CreateShaderBinding - - public ShaderBinding CreateShaderBinding( - ShaderLayout Layout, - string? Name = null, ReadOnlySpan Name8 = default - ) => MainQueue.CreateShaderBinding(Layout, Name, Name8); - - #endregion - #region CreateMeshLayout public MeshLayout CreateMeshLayout( @@ -328,23 +292,23 @@ public GraphicsShaderPipeline CreateGraphicsShaderPipeline( #endregion - #region CreateBuffer - - public GpuBuffer CreateBuffer( - in GpuBufferCreateOptions options, - string? Name = null, ReadOnlySpan Name8 = default - ) => MainQueue.CreateBuffer(in options, Name, Name8); - - #endregion - - #region CreateImage - - public GpuImage CreateImage( - in GpuImageCreateOptions options, - string? Name = null, ReadOnlySpan Name8 = default - ) => MainQueue.CreateImage(in options, Name, Name8); - - #endregion + // #region CreateBuffer + // + // public GpuBuffer CreateBuffer( + // in GpuBufferCreateOptions options, + // string? Name = null, ReadOnlySpan Name8 = default + // ) => MainQueue.CreateBuffer(in options, Name, Name8); + // + // #endregion + // + // #region CreateImage + // + // public GpuImage CreateImage( + // in GpuImageCreateOptions options, + // string? Name = null, ReadOnlySpan Name8 = default + // ) => MainQueue.CreateImage(in options, Name, Name8); + // + // #endregion #region CreateSampler diff --git a/Coplt.Graphics.Core/Core/GpuExecutor.cs b/Coplt.Graphics.Core/Core/GpuExecutor.cs deleted file mode 100644 index 3cb245e..0000000 --- a/Coplt.Graphics.Core/Core/GpuExecutor.cs +++ /dev/null @@ -1,130 +0,0 @@ -using Coplt.Dropping; -using Coplt.Graphics.Native; - -namespace Coplt.Graphics.Core; - -[Dropping(Unmanaged = true)] -public abstract unsafe partial class GpuExecutor -{ - #region Fields - - internal FGpuExecutor* m_ptr; - internal string? m_name; - internal readonly GpuQueue m_queue; - internal CommandList? m_recycle_cmd_list; - internal readonly Lock m_wait_lock = new(); - - #endregion - - #region Props - - public FGpuExecutor* Ptr => m_ptr; - public GpuDevice Device => m_queue.m_device; - public GpuQueue Queue => m_queue; - - public bool NeedWait => m_recycle_cmd_list != null; - - #endregion - - #region Ctor - - internal GpuExecutor(FGpuExecutor* ptr, string? name, GpuQueue queue) - { - m_ptr = ptr; - m_name = name; - m_queue = queue; - } - - #endregion - - #region Drop - - [Drop] - private void Drop() - { - Wait(true); - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); - } - - #endregion - - #region SetName - - public void SetName(string name) - { - m_name = name; - fixed (char* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(GpuExecutor)}(0x{(nuint)m_ptr:X})" - : $"{nameof(GpuExecutor)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion - - #region SetNeedWait - - internal void SetNeedWait(CommandList cmd) - { - if (Interlocked.CompareExchange(ref m_recycle_cmd_list, cmd, null) != null) - throw new InvalidOperationException("The current executor has not been waited and cannot be reused"); - } - - #endregion - - #region Wait - - /// - /// 等待可重用 - /// - public void Wait() => Wait(false); - - /// - /// 等待可重用 - /// - private void Wait(bool discard) - { - re: - var recycle_cmd_list = m_recycle_cmd_list; - if (recycle_cmd_list == null) return; - using (m_wait_lock.EnterScope()) - { - if (recycle_cmd_list == m_recycle_cmd_list) goto re; - try - { - m_ptr->Wait().TryThrow(); - } - finally - { - if (!discard) - { - recycle_cmd_list.Reset(); - Queue.m_cmd_pool.Enqueue(recycle_cmd_list); - } - m_recycle_cmd_list = null; - } - } - } - - #endregion -} diff --git a/Coplt.Graphics.Core/Core/GpuImage.cs b/Coplt.Graphics.Core/Core/GpuImage.cs index 5d3564b..097476c 100644 --- a/Coplt.Graphics.Core/Core/GpuImage.cs +++ b/Coplt.Graphics.Core/Core/GpuImage.cs @@ -106,19 +106,14 @@ public sealed unsafe partial class GpuImage : GpuResource, IGpuResource, ISrv, I uint IGpuView.Stride => 0; GpuResourceType IGpuResource.Type => GpuResourceType.Image; IGpuResource IGpuView.Resource => this; - FResourceMeta IGpuResource.GetMeta() => new() - { - Type = FResourceRefType.Image, - Image = Ptr, - }; #endregion #region Ctor - internal GpuImage(FGpuImage* ptr, string? name, GpuQueue queue) : this(ptr, ptr->GpuImageData(), name, queue) { } - private GpuImage(FGpuImage* ptr, FGpuImageData* data, string? name, GpuQueue queue) - : base((FGpuResource*)ptr, (FGpuResourceData*)data, name, queue) { } + internal GpuImage(FGpuImage* ptr, string? name, GpuIsolate isolate) : this(ptr, ptr->GpuImageData(), name, isolate) { } + private GpuImage(FGpuImage* ptr, FGpuImageData* data, string? name, GpuIsolate isolate) + : base((FGpuResource*)ptr, (FGpuResourceData*)data, name, isolate) { } #endregion diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index e89c883..5ec9a5e 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -277,4 +277,95 @@ public GpuSwapChain CreateSwapChainForHwnd(IntPtr Hwnd, in GpuSwapChainCreateOpt } #endregion + + #region CreateBuffer + + public GpuBuffer CreateBuffer( + in GpuBufferCreateOptions options, + string? Name = null, ReadOnlySpan Name8 = default + ) + { + fixed (char* p_name = Name) + fixed (byte* p_name8 = Name8) + { + FGpuBufferCreateOptions f_options = new() + { + Base = + { + Base = + { + Name = new(Name, Name8, p_name, p_name8), + Purpose = options.Purpose.ToFFI(), + }, + CpuAccess = options.CpuAccess.ToFFI(), + }, + Size = options.Size, + Count = options.Count, + Stride = options.Stride, + Usage = options.Usage.ToFFI(), + }; + FGpuBuffer* ptr; + Device.Ptr->CreateBuffer(&f_options, &ptr).TryThrow(); + return new(ptr, Name, this); + } + } + + #endregion + + #region CreateImage + + public GpuImage CreateImage( + in GpuImageCreateOptions options, + string? Name = null, ReadOnlySpan Name8 = default + ) + { + if (options.Format == GraphicsFormat.Unknown) + throw new ArgumentException("The image format cannot be Unknown"); + if (options.Purpose == ResourcePurpose.None) + throw new ArgumentException("The image purpose cannot be None"); + fixed (char* p_name = Name) + fixed (byte* p_name8 = Name8) + { + FGpuImageCreateOptions f_options = new() + { + Base = + { + Base = + { + Name = new(Name, Name8, p_name, p_name8), + Purpose = options.Purpose.ToFFI(), + }, + CpuAccess = options.CpuAccess.ToFFI(), + }, + Format = options.Format.ToFFI(), + Width = Math.Max(options.Width, 1), + Height = Math.Max(options.Height, 1), + DepthOrLength = Math.Max(options.DepthOrLength, 1), + MipLevels = (ushort)Math.Max(options.MipLevels, 1), + MultisampleCount = (byte)Math.Max(options.MultisampleCount, 1), + Dimension = options.Dimension.ToFFI(), + Layout = options.Layout.ToFFI(), + HasOptimizedClearValue = !options.OptimizedClearColor.IsNone, + }; + if (options.OptimizedClearColor.IsColor) + { + f_options.OptimizedClearValue.Format = options.OptimizedClearColor.Color.Format.ToFFI(); + f_options.OptimizedClearValue.Anonymous.Color = + Unsafe.BitCast( + options.OptimizedClearColor.Color.Color + ); + } + else if (options.OptimizedClearColor.IsDepth) + { + f_options.OptimizedClearValue.Format = options.OptimizedClearColor.Depth.Format.ToFFI(); + f_options.OptimizedClearValue.Depth = options.OptimizedClearColor.Depth.Depth; + f_options.OptimizedClearValue.Stencil = options.OptimizedClearColor.Depth.Stencil; + } + FGpuImage* ptr; + Device.Ptr->CreateImage(&f_options, &ptr).TryThrow(); + return new(ptr, Name, this); + } + } + + #endregion } diff --git a/Coplt.Graphics.Core/Core/GpuOutput.cs b/Coplt.Graphics.Core/Core/GpuOutput.cs index 9ae5368..7dbc002 100644 --- a/Coplt.Graphics.Core/Core/GpuOutput.cs +++ b/Coplt.Graphics.Core/Core/GpuOutput.cs @@ -50,96 +50,6 @@ public record struct GpuOutputOptions() #endregion -[Dropping(Unmanaged = true)] -public sealed unsafe partial class GpuOutput : GpuExecutor, IGpuResource, IRtv, ISrv -{ - #region Fields - - internal new FGpuOutput* m_ptr; - - #endregion - - #region Props - - public new FGpuOutput* Ptr => m_ptr; - public GraphicsFormat Format => m_ptr->m_format.FromFFI(); - public ResState State - { - get => NativeState.FromFFI(); - set => NativeState = value.ToFFI(); - } - public ref FResState NativeState => ref m_ptr->m_state; - public USize2d Size2d => new(m_ptr->m_width, m_ptr->m_height); - public USize3d Size3d => new(m_ptr->m_width, m_ptr->m_height, 1); - ulong IGpuView.Size => m_ptr->m_width; - public uint Width => m_ptr->m_width; - public uint Height => m_ptr->m_height; - public uint DepthOrLength => 1; - public uint MipLevels => 1; - public uint Planes => 1; - uint IGpuView.Count => 0; - uint IGpuView.Stride => 0; - GpuResourceType IGpuResource.Type => GpuResourceType.Image; - IGpuResource IGpuView.Resource => this; - FResourceMeta IGpuResource.GetMeta() => new() - { - Type = FResourceRefType.Output, - Output = m_ptr, - }; - public FCmdRes IntoCmd() => throw new NotImplementedException(); - - #endregion - - #region Ctor - - internal GpuOutput(FGpuOutput* ptr, string? name, GpuQueue queue) : base((FGpuExecutor*)ptr, name, queue) - { - m_ptr = ptr; - } - - #endregion - - #region Drop - - [Drop] - private void Drop() - { - m_ptr = null; - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(GpuOutput)}(0x{(nuint)m_ptr:X})" - : $"{nameof(GpuOutput)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion - - #region Present - - public void Present(bool NoWait = false) => Queue.Submit(this, NoWait); - - #endregion - - #region Views - - public bool TrySrv() => true; - public bool TryRtv() => true; - - #endregion - - #region Resize - - public void Resize(uint width, uint height) => m_ptr->Resize(width, height).TryThrow(); - - #endregion - - public GpuIsolate Isolate => throw new NotImplementedException(); -} - [Dropping(Unmanaged = true)] public abstract unsafe partial class GpuOutput2 : IsolateChild, IGpuResource, IRtv, ISrv { @@ -213,15 +123,6 @@ private void Drop() public void Wait() => Ptr->Wait().TryThrow(); #endregion - - public FResourceMeta GetMeta() => throw new NotSupportedException(); - public ResState State - { - get => throw new NotSupportedException(); - set => throw new NotSupportedException(); - } - public ref FResState NativeState => throw new NotSupportedException(); - public GpuQueue Queue => throw new NotSupportedException(); } public record struct GpuSwapChainCreateOptions() diff --git a/Coplt.Graphics.Core/Core/GpuQueue.cs b/Coplt.Graphics.Core/Core/GpuQueue.cs index bfcfcca..be24a80 100644 --- a/Coplt.Graphics.Core/Core/GpuQueue.cs +++ b/Coplt.Graphics.Core/Core/GpuQueue.cs @@ -12,6 +12,9 @@ public enum GpuQueueType : byte Direct, Compute, Copy, + VideoEncode, + VideoDecode, + VideoProcess, } public static partial class GraphicsExtensions @@ -22,331 +25,12 @@ public static partial class GraphicsExtensions public static ReadOnlySpan ToUtf8String(this GpuQueueType value) => value switch { - GpuQueueType.Direct => "Direct"u8, - GpuQueueType.Compute => "Compute"u8, - GpuQueueType.Copy => "Copy"u8, - _ => throw new ArgumentOutOfRangeException(nameof(value), value, null) + GpuQueueType.Direct => "Direct"u8, + GpuQueueType.Compute => "Compute"u8, + GpuQueueType.Copy => "Copy"u8, + GpuQueueType.VideoEncode => "VideoEncode"u8, + GpuQueueType.VideoDecode => "VideoDecode"u8, + GpuQueueType.VideoProcess => "VideoProcess"u8, + _ => throw new ArgumentOutOfRangeException(nameof(value), value, null) }; } - -[Dropping(Unmanaged = true)] -public sealed unsafe partial class GpuQueue -{ - #region Fields - - internal FGpuQueue* m_ptr; - internal string? m_name; - internal readonly GpuDevice m_device; - internal readonly Lock m_lock = new(); - internal CommandList m_current_cmd_list; - internal readonly ConcurrentQueue m_cmd_pool = new(); - - #endregion - - #region Props - - public FGpuQueue* Ptr => m_ptr; - public GpuDevice Device => m_device; - public GpuQueueType QueueType => m_ptr->m_queue_type.FromFFI(); - public SubmitId SubmitId => new(m_ptr->m_submit_id); - public CommandList CommandList => m_current_cmd_list; - - #endregion - - #region Ctor - - internal GpuQueue(FGpuQueue* ptr, string? name, GpuDevice device) - { - m_name = name; - m_ptr = ptr; - m_device = device; - m_current_cmd_list = new(this); - } - - #endregion - - #region Drop - - [Drop] - private void Drop() - { - using var _ = m_lock.EnterScope(); - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); - } - - #endregion - - #region SetName - - public void SetName(string name) - { - m_name = name; - fixed (char* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"0x{nameof(GpuQueue)}({(nuint)m_ptr:X})" - : $"0x{nameof(GpuQueue)}({(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion - - #region Submit - - public void Submit(GpuExecutor Executor, bool NoWait = false) - { - using var _ = m_lock.EnterScope(); - if (Executor is GpuOutput output) - { - if (m_current_cmd_list.m_current_output != null && m_current_cmd_list.m_current_output != output) - throw new ArgumentException( - $"The command is already used by another output and cannot be presented in this output" - ); - m_current_cmd_list.Present(output); - } - m_current_cmd_list.BuildSubmitStruct(Executor, NoWait); - } - - internal void ActualSubmit(GpuExecutor Executor, FCommandSubmit* submit, bool NoWait) - { - if (NoWait) - { - m_ptr->SubmitNoWait(Executor.m_ptr, submit).TryThrow(); - if (!m_cmd_pool.TryDequeue(out var new_cmd_list)) new_cmd_list = new(this); - Executor.SetNeedWait(m_current_cmd_list); - m_current_cmd_list = new_cmd_list; - } - else - { - m_ptr->Submit(Executor.m_ptr, submit).TryThrow(); - m_current_cmd_list.Reset(); - } - } - - #endregion - - #region CreateOutputForHwnd - - public GpuOutput CreateOutputForHwnd( - in GpuOutputOptions Options, IntPtr Hwnd, - string? Name = null, ReadOnlySpan Name8 = default - ) - { - fixed (char* p_name = Name) - fixed (byte* p_name8 = Name8) - { - FGpuOutputCreateOptions f_options = new() - { - Name = new(Name, Name8, p_name, p_name8), - Width = Options.Width, - Height = Options.Height, - Hdr =(FHdrType) Options.Hdr, - Srgb = Options.Srgb, - PresentMode = (FPresentMode)Options.PresentMode, - AlphaMode = (FOutputAlphaMode)Options.AlphaMode, - VSync = Options.VSync, - }; - FGpuOutput* ptr; - m_ptr->CreateOutputForHwnd(&f_options, (void*)Hwnd, &ptr).TryThrow(); - return new(ptr, Name, this); - } - } - - #endregion - - #region CreateShaderBinding - - public ShaderBinding CreateShaderBinding( - ShaderLayout Layout, - string? Name = null, ReadOnlySpan Name8 = default - ) - { - fixed (char* p_name = Name) - fixed (byte* p_name8 = Name8) - { - FShaderBindingCreateOptions f_options = new() - { - Name = new(Name, Name8, p_name, p_name8), - Layout = Layout.m_ptr, - }; - FShaderBinding* ptr; - m_device.Ptr->CreateShaderBinding(&f_options, &ptr).TryThrow(); - return new(ptr, Name, m_device, this, Layout); - } - } - - #endregion - - #region CreateBuffer - - public GpuBuffer CreateBuffer( - in GpuBufferCreateOptions options, - string? Name = null, ReadOnlySpan Name8 = default - ) - { - fixed (char* p_name = Name) - fixed (byte* p_name8 = Name8) - { - FGpuBufferCreateOptions f_options = new() - { - Base = - { - Base = - { - Name = new(Name, Name8, p_name, p_name8), - Purpose = options.Purpose.ToFFI(), - }, - CpuAccess = options.CpuAccess.ToFFI(), - }, - Size = options.Size, - Count = options.Count, - Stride = options.Stride, - Usage = options.Usage.ToFFI(), - }; - FGpuBuffer* ptr; - m_device.Ptr->CreateBuffer(&f_options, &ptr).TryThrow(); - return new(ptr, Name, this); - } - } - - #endregion - - #region CreateImage - - public GpuImage CreateImage( - in GpuImageCreateOptions options, - string? Name = null, ReadOnlySpan Name8 = default - ) - { - if (options.Format == GraphicsFormat.Unknown) - throw new ArgumentException("The image format cannot be Unknown"); - if (options.Purpose == ResourcePurpose.None) - throw new ArgumentException("The image purpose cannot be None"); - fixed (char* p_name = Name) - fixed (byte* p_name8 = Name8) - { - FGpuImageCreateOptions f_options = new() - { - Base = - { - Base = - { - Name = new(Name, Name8, p_name, p_name8), - Purpose = options.Purpose.ToFFI(), - }, - CpuAccess = options.CpuAccess.ToFFI(), - }, - Format = options.Format.ToFFI(), - Width = Math.Max(options.Width, 1), - Height = Math.Max(options.Height, 1), - DepthOrLength = Math.Max(options.DepthOrLength, 1), - MipLevels = (ushort)Math.Max(options.MipLevels, 1), - MultisampleCount = (byte)Math.Max(options.MultisampleCount, 1), - Dimension = options.Dimension.ToFFI(), - Layout = options.Layout.ToFFI(), - HasOptimizedClearValue = !options.OptimizedClearColor.IsNone, - }; - if (options.OptimizedClearColor.IsColor) - { - f_options.OptimizedClearValue.Format = options.OptimizedClearColor.Color.Format.ToFFI(); - f_options.OptimizedClearValue.Anonymous.Color = - Unsafe.BitCast( - options.OptimizedClearColor.Color.Color - ); - } - else if (options.OptimizedClearColor.IsDepth) - { - f_options.OptimizedClearValue.Format = options.OptimizedClearColor.Depth.Format.ToFFI(); - f_options.OptimizedClearValue.Depth = options.OptimizedClearColor.Depth.Depth; - f_options.OptimizedClearValue.Stencil = options.OptimizedClearColor.Depth.Stencil; - } - FGpuImage* ptr; - m_device.Ptr->CreateImage(&f_options, &ptr).TryThrow(); - return new(ptr, Name, this); - } - } - - #endregion - - #region WriteToUpload - - /// - /// 返回的 Span 只能写入 - /// - public FSlice AllocUploadMemory(uint Size, out UploadLoc loc, uint Align = 4) - { - if (Align > 1) Size += Align - 1; - using var _ = m_lock.EnterScope(); - ref var upload_buffers = ref m_ptr->m_context->m_upload_buffer; - for (nuint i = 0; i < upload_buffers.LongLength; i++) - { - ref var block = ref upload_buffers[i]; - if (block.cur_offset + Size < block.size) - { - var offset = block.cur_offset.Aligned(Align); - var r = new FSlice(block.mapped_ptr, (nuint)block.size).Slice((nuint)offset); - loc = new UploadLoc(i, offset, Size, SubmitId); - block.cur_offset += Size; - return r; - } - } - m_ptr->m_context->GrowUploadBuffer(Size).TryThrow(); - upload_buffers = ref m_ptr->m_context->m_upload_buffer; - { - var i = upload_buffers.LongLength - 1; - ref var block = ref upload_buffers[i]; - if (block.cur_offset + Size >= block.size) throw new OutOfMemoryException(); - var offset = block.cur_offset.Aligned(Align); - var r = new FSlice(block.mapped_ptr, (nuint)block.size).Slice((nuint)offset); - loc = new UploadLoc(i, offset, Size, SubmitId); - block.cur_offset += Size; - return r; - } - } - - public UploadLoc WriteToUpload(ReadOnlySpan Data, uint Align = 4) - { - Data.CopyTo(AllocUploadMemory((uint)Data.Length, out var loc, Align)); - return loc; - } - - /// - /// 分配用于上传纹理的 256 对齐的内存 - /// - public ImageUploadBufferMemory AllocImageUploadMemory2D(uint PixelSize, uint Width, uint Height, uint Length = 1) => - AllocImageUploadMemory2D(PixelSize, Width, Height, Length, out _); - - /// - /// 分配用于上传纹理的 256 对齐的内存 - /// - public ImageUploadBufferMemory AllocImageUploadMemory2D(uint PixelSize, uint Width, uint Height, uint Length, out UploadLoc loc) - { - if (PixelSize < 1 || Width < 1 || Height < 1 || Length < 1) throw new ArgumentOutOfRangeException(); - var row_stride = (PixelSize * Width).Aligned(256); - var row_count = Height * Length; - var buffer_size = row_stride * row_count + 256u; - var slice = AllocUploadMemory(buffer_size, out loc, 256u); - return new ImageUploadBufferMemory(slice, row_stride, row_count, Length, Height, loc); - } - - #endregion -} diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index d2fbe85..a118cf5 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -2,6 +2,7 @@ using System.Runtime.InteropServices; using Coplt.Graphics.Native; using Coplt.Graphics.Utilities; +using Coplt.Union; namespace Coplt.Graphics.Core; @@ -799,7 +800,7 @@ uint debug_scope_count public void Dispose() { - if (m_disposed) throw new ObjectDisposedException(nameof(RenderScope)); + if (m_disposed) throw new ObjectDisposedException(nameof(RenderScope2)); m_disposed = true; if (self.m_debug_scope_count > debug_scope_count) throw new InvalidOperationException( @@ -1186,3 +1187,107 @@ public void Dispatch( } #endregion + +#region RenderInfo + +[Union] +public partial struct LoadOp +{ + [UnionTemplate] + private interface Template + { + void Load(); + void Discard(); + void NoAccess(); + } + + public static readonly LoadOp Load = MakeLoad(); + public static LoadOp Clear(T Clear) => LoadOp.MakeClear(Clear); + public static readonly LoadOp Discard = MakeDiscard(); + public static readonly LoadOp NoAccess = MakeNoAccess(); +} + +[Union] +public partial struct LoadOp +{ + [UnionTemplate] + private interface Template + { + void Load(); + T Clear(); + void Discard(); + void NoAccess(); + } + + public static readonly LoadOp Load = MakeLoad(); + public static implicit operator LoadOp(T Clear) => MakeClear(Clear); + public static readonly LoadOp Discard = MakeDiscard(); + public static readonly LoadOp NoAccess = MakeNoAccess(); + + public static implicit operator LoadOp(LoadOp op) => op.Tag switch + { + LoadOp.Tags.Load => Load, + LoadOp.Tags.Discard => Discard, + LoadOp.Tags.NoAccess => NoAccess, + _ => throw new ArgumentOutOfRangeException() + }; +} + +[Union] +public partial struct StoreOp +{ + [UnionTemplate] + private interface Template + { + void Store(); + void Discard(); + void NoAccess(); + } + + public static readonly StoreOp Store = MakeStore(); + public static readonly StoreOp Discard = MakeDiscard(); + public static readonly StoreOp NoAccess = MakeNoAccess(); +} + +public ref struct RenderInfo(ReadOnlySpan Rtvs, RenderInfo.DsvInfo? Dsv = null) +{ + public DsvInfo? Dsv = Dsv; + public ReadOnlySpan Rtvs = Rtvs; + + public RenderInfo() : this([]) { } + public RenderInfo(DsvInfo Dsv, ReadOnlySpan Rtvs = default) : this(Rtvs, Dsv) { } + + public struct DsvInfo( + IDsv View, + LoadOp DepthLoad, + LoadOp StencilLoad, + StoreOp DepthStore, + StoreOp StencilStore + ) + { + public IDsv View = View; + public LoadOp DepthLoad = DepthLoad; + public LoadOp StencilLoad = StencilLoad; + public StoreOp DepthStore = DepthStore; + public StoreOp StencilStore = StencilStore; + + public DsvInfo(IDsv View) : this(View, LoadOp.Load, LoadOp.Load, StoreOp.Store, StoreOp.Store) { } + public DsvInfo(IDsv View, LoadOp DepthLoad, LoadOp StencilLoad) + : this(View, DepthLoad, StencilLoad, StoreOp.Store, StoreOp.Store) { } + public DsvInfo(IDsv View, LoadOp DepthLoad) + : this(View, DepthLoad, LoadOp.Load, StoreOp.Store, StoreOp.Store) { } + } + + public struct RtvInfo(IRtv View, LoadOp Load, StoreOp Store) + { + public IRtv View = View; + public LoadOp Load = Load; + public StoreOp Store = Store; + + public RtvInfo(IRtv View) : this(View, LoadOp.Load, StoreOp.Store) { } + + public RtvInfo(IRtv View, LoadOp Load) : this(View, Load, StoreOp.Store) { } + } +} + +#endregion diff --git a/Coplt.Graphics.Core/Core/GpuResource.cs b/Coplt.Graphics.Core/Core/GpuResource.cs index 5c39489..ed7b4c1 100644 --- a/Coplt.Graphics.Core/Core/GpuResource.cs +++ b/Coplt.Graphics.Core/Core/GpuResource.cs @@ -10,21 +10,15 @@ public abstract unsafe partial class GpuResource : GpuViewable #region Props public new FGpuResource* Ptr => (FGpuResource*)m_ptr; - public new FGpuResourceData* Data => (FGpuResourceData*)m_data; - public ResState State - { - get => NativeState.FromFFI(); - set => NativeState = value.ToFFI(); - } - public ref FResState NativeState => ref Data->m_state; - public CpuAccess CpuAccess => (CpuAccess)Data->m_cpu_access; + internal new ref readonly FGpuResourceData Data => ref *(FGpuResourceData*)m_data; + public CpuAccess CpuAccess => (CpuAccess)Data.m_cpu_access; #endregion #region Ctor - internal GpuResource(FGpuResource* ptr, FGpuResourceData* data, string? name, GpuQueue queue) - : base((FGpuViewable*)ptr, (FGpuViewableData*)data, name, queue) { } + internal GpuResource(FGpuResource* ptr, FGpuResourceData* data, string? name, GpuIsolate isolate) + : base((FGpuViewable*)ptr, (FGpuViewableData*)data, name, isolate) { } #endregion diff --git a/Coplt.Graphics.Core/Core/GpuViewable.cs b/Coplt.Graphics.Core/Core/GpuViewable.cs index 8f317e7..0b96832 100644 --- a/Coplt.Graphics.Core/Core/GpuViewable.cs +++ b/Coplt.Graphics.Core/Core/GpuViewable.cs @@ -5,35 +5,27 @@ namespace Coplt.Graphics.Core; [Dropping(Unmanaged = true)] -public abstract unsafe partial class GpuViewable : IQueueOwned +public abstract unsafe partial class GpuViewable : IsolateChild { #region Fields - internal FGpuViewable* m_ptr; - internal readonly FGpuViewableData* m_data; - internal string? m_name; - internal readonly GpuQueue m_queue; + internal FGpuViewableData* m_data; #endregion #region Props - public FGpuViewable* Ptr => m_ptr; - public FGpuViewableData* Data => m_data; - public GpuDevice Device => m_queue.m_device; - public GpuQueue Queue => m_queue; - public ResourcePurpose Purpose => (ResourcePurpose)Data->m_purpose; + public new FGpuViewable* Ptr => (FGpuViewable*)m_ptr; + internal ref readonly FGpuViewableData Data => ref *m_data; + public ResourcePurpose Purpose => (ResourcePurpose)Data.m_purpose; #endregion #region Ctor - internal GpuViewable(FGpuViewable* ptr, FGpuViewableData* data, string? name, GpuQueue queue) + internal GpuViewable(FGpuViewable* ptr, FGpuViewableData* data, string? name, GpuIsolate isolate) : base((FGpuObject*)ptr, name, isolate) { - m_ptr = ptr; m_data = data; - m_name = name; - m_queue = queue; } #endregion @@ -43,42 +35,8 @@ internal GpuViewable(FGpuViewable* ptr, FGpuViewableData* data, string? name, Gp [Drop] private void Drop() { - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); + m_data = null; } #endregion - - #region SetName - - public void SetName(string name) - { - m_name = name; - fixed (char* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(GpuViewable)}(0x{(nuint)m_ptr:X})" - : $"{nameof(GpuViewable)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion } diff --git a/Coplt.Graphics.Core/Core/GraphicsInstance.cs b/Coplt.Graphics.Core/Core/GraphicsInstance.cs index 5789ee2..35075bd 100644 --- a/Coplt.Graphics.Core/Core/GraphicsInstance.cs +++ b/Coplt.Graphics.Core/Core/GraphicsInstance.cs @@ -314,9 +314,6 @@ public GpuDevice CreateDevice( string? Name = null, ReadOnlySpan Name8 = default ) { - var QueueName = !DebugEnabled || Name is null ? null : $"{Name} Main Queue"; - var QueueName8 = !DebugEnabled || Name8.Length == 0 ? Name8 : Utils.JoinUtf8String(Name8, " Main Queue"u8); - fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) { @@ -342,7 +339,7 @@ public GpuDevice CreateDevice( }; FGpuDevice* ptr; m_ptr->CreateDevice(&f_options, &ptr).TryThrow(); - return new(ptr, this, null, Name, QueueName: QueueName, QueueName8: QueueName8); + return new(ptr, this, null, Name); } } diff --git a/Coplt.Graphics.Core/Core/IQueueOwned.cs b/Coplt.Graphics.Core/Core/IQueueOwned.cs deleted file mode 100644 index f61c25a..0000000 --- a/Coplt.Graphics.Core/Core/IQueueOwned.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Coplt.Graphics.Core; - -public interface IQueueOwned -{ - public GpuQueue Queue { get; } -} - -public static partial class GraphicsExtensions -{ - public static bool IsSameQueue(this T obj, GpuQueue queue) where T : IQueueOwned => obj.Queue == queue; - - public static void AssertSameQueue(this T obj, GpuQueue queue) where T : IQueueOwned - { - if (obj.Queue != queue) - throw new InvalidOperationException($"{obj} does not belong to {queue}."); - } -} diff --git a/Coplt.Graphics.Core/Core/ShaderBinding.cs b/Coplt.Graphics.Core/Core/ShaderBinding.cs index 10d1e30..26b77de 100644 --- a/Coplt.Graphics.Core/Core/ShaderBinding.cs +++ b/Coplt.Graphics.Core/Core/ShaderBinding.cs @@ -7,127 +7,7 @@ namespace Coplt.Graphics.Core; public record struct ShaderBindingSetItem(uint Index, View View); [Dropping(Unmanaged = true)] -public sealed unsafe partial class ShaderBinding : IQueueOwned +public sealed unsafe partial class ShaderBinding { - #region Fields - - internal FShaderBinding* m_ptr; - internal string? m_name; - internal readonly GpuDevice m_device; - internal readonly GpuQueue m_queue; - internal readonly ShaderLayout m_layout; - internal readonly View[] m_views; - internal readonly HashSet<(uint c, uint g)> m_changed_groups = new(); - - #endregion - - #region Props - - public FShaderBinding* Ptr => m_ptr; - public GpuDevice Device => m_device; - public GpuQueue Queue => m_queue; - public ShaderLayout Layout => m_layout; - public ReadOnlySpan Views => m_views; - internal Span MutViews => m_views; - public ref readonly View this[int index] => ref m_views[index]; - internal bool Changed => m_changed_groups.Count != 0; - - #endregion - - #region Ctor - - internal ShaderBinding(FShaderBinding* ptr, string? name, GpuDevice device, GpuQueue queue, ShaderLayout layout) - { - m_name = name; - m_ptr = ptr; - m_device = device; - m_queue = queue; - m_layout = layout; - - m_views = new View[m_layout.m_native_defines.Length]; - } - - #endregion - - #region Drop - - [Drop] - private void Drop() - { - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); - } - - #endregion - - #region SetName - - public void SetName(string name) - { - m_name = name; - fixed (char* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"0x{nameof(ShaderBinding)}({(nuint)m_ptr:X})" - : $"0x{nameof(ShaderBinding)}({(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion - - #region Set - - internal void Set(ReadOnlySpan Items, Span dst) - { - var defines = Layout.NativeDefines; - var infos = Layout.NativeItemInfos; - var views = MutViews; - for (var i = 0; i < Items.Length; i++) - { - var src = Items[i]; - ref readonly var define = ref defines[(int)src.Index]; - ref readonly var info = ref infos[(int)src.Index]; - define.CheckCompatible(src.View, (int)src.Index); - dst[i] = new() - { - View = src.View.ToFFI(), - Index = src.Index, - }; - ref var view = ref views[(int)src.Index]; - view = src.View; - if (info.Place is FShaderLayoutItemPlace.Grouped) - { - m_changed_groups.Add((info.Class, info.Group)); - } - } - } - - #endregion - - #region ApplyChange - - internal void ApplyChange() - { - m_changed_groups.Clear(); - } - - #endregion + } diff --git a/Coplt.Graphics.Core/Core/Views.cs b/Coplt.Graphics.Core/Core/Views.cs index cabeaa9..2cdcdcb 100644 --- a/Coplt.Graphics.Core/Core/Views.cs +++ b/Coplt.Graphics.Core/Core/Views.cs @@ -2,7 +2,7 @@ namespace Coplt.Graphics.Core; -public interface IGpuView : IQueueOwned, IIsolateChild +public interface IGpuView : IIsolateChild { /// /// 视图所属资源 @@ -64,11 +64,6 @@ public enum GpuResourceType public interface IGpuResource : IGpuView { public GpuResourceType Type { get; } - - public ResState State { get; set; } - public ref FResState NativeState { get; } - - public FResourceMeta GetMeta(); public FCmdRes IntoCmd(); } diff --git a/Coplt.Graphics.Core/Native/FResourceRef.cs b/Coplt.Graphics.Core/Native/FResourceRef.cs deleted file mode 100644 index 0b878c7..0000000 --- a/Coplt.Graphics.Core/Native/FResourceRef.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Coplt.Graphics.Native; - -public partial struct FResourceRef - : IEquatable -{ - public FResourceRef(uint index) - { - ResourceIndex = index; - } - public FResourceRef(int index) - { - ResourceIndex = (uint)index; - } - - #region Equals - - public bool Equals(FResourceRef other) => ResourceIndex == other.ResourceIndex; - public override bool Equals(object? obj) => obj is FResourceRef other && Equals(other); - public override int GetHashCode() => (int)ResourceIndex; - public static bool operator ==(FResourceRef left, FResourceRef right) => left.Equals(right); - public static bool operator !=(FResourceRef left, FResourceRef right) => !left.Equals(right); - - #endregion -} diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index c6573c1..6621884 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -963,20 +963,12 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuDevice*)Unsafe.AsPointer(ref this)); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateMainQueue([NativeTypeName("const FMainQueueCreateOptions &")] FMainQueueCreateOptions* options, FGpuQueue** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] public FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &")] FGpuIsolateCreateOptions* options, [NativeTypeName("Coplt::FMainQueueCreateResult &")] FMainQueueCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -984,7 +976,7 @@ public FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &") public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, FShaderModule** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -992,7 +984,7 @@ public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOpti public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, FShaderLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1000,7 +992,7 @@ public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOpti public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, FShaderLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1008,7 +1000,7 @@ public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayout public FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1016,7 +1008,7 @@ public FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayout public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, FShader** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1024,7 +1016,7 @@ public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FSh public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1032,7 +1024,7 @@ public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOp public FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions &")] FMeshLayoutCreateOptions* options, FMeshLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[16]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1040,7 +1032,7 @@ public FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[17]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[16]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1048,7 +1040,7 @@ public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipe public FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] FGpuBufferCreateOptions* options, FGpuBuffer** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[18]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[17]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1056,7 +1048,7 @@ public FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FGpuImageCreateOptions* options, FGpuImage** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[18]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1064,7 +1056,7 @@ public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FG public FResult CreateSampler([NativeTypeName("const FGpuSamplerCreateOptions &")] FGpuSamplerCreateOptions* options, FGpuSampler** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[20]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } public interface Interface : FGpuObject.Interface @@ -1074,9 +1066,6 @@ public interface Interface : FGpuObject.Interface void* GetRawDevice(); - [return: NativeTypeName("Coplt::FResult")] - FResult CreateMainQueue([NativeTypeName("const FMainQueueCreateOptions &")] FMainQueueCreateOptions* options, FGpuQueue** @out); - [return: NativeTypeName("Coplt::FResult")] FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &")] FGpuIsolateCreateOptions* options, [NativeTypeName("Coplt::FMainQueueCreateResult &")] FMainQueueCreateResult* @out); @@ -2963,72 +2952,6 @@ public unsafe partial struct FUploadBufferBlock public ulong size; } - [Guid("3A22DE68-8377-4E57-A167-3EFDB97C102A")] - [NativeTypeName("struct FFrameContext : Coplt::FGpuObject")] - public unsafe partial struct FFrameContext : FFrameContext.Interface, INativeGuid - { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FFrameContext)); - - public void** lpVtbl; - - public FList m_upload_buffer; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FFrameContext*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FFrameContext*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FFrameContext*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FFrameContext*)Unsafe.AsPointer(ref this), id); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FFrameContext*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FFrameContext*)Unsafe.AsPointer(ref this), &result, name); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult GrowUploadBuffer([NativeTypeName("Coplt::u64")] ulong min_required_size) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FFrameContext*)Unsafe.AsPointer(ref this), &result, min_required_size); - } - - public interface Interface : FGpuObject.Interface - { - [return: NativeTypeName("Coplt::FResult")] - FResult GrowUploadBuffer([NativeTypeName("Coplt::u64")] ulong min_required_size); - } - } - [Guid("FA9C7561-AB0B-4311-BB4C-C6BEF93F86FE")] [NativeTypeName("struct FFrameContext2 : Coplt::FGpuObject")] public unsafe partial struct FFrameContext2 : FFrameContext2.Interface, INativeGuid @@ -3149,12 +3072,6 @@ public interface Interface : FGpuObject.Interface } } - public partial struct FMainQueueCreateOptions - { - [NativeTypeName("Coplt::FStr8or16")] - public FStr8or16 Name; - } - [NativeTypeName("Coplt::u8")] public enum FGpuQueueType : byte { @@ -3178,120 +3095,6 @@ public enum FGpuQueueFlags : byte VideoProcess = 1 << 5, } - [Guid("95E60E28-E387-4055-9B33-2D23AF901F8A")] - [NativeTypeName("struct FGpuQueue : Coplt::FGpuObject")] - public unsafe partial struct FGpuQueue : FGpuQueue.Interface, INativeGuid - { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuQueue)); - - public void** lpVtbl; - - [NativeTypeName("Coplt::FFrameContext *")] - public FFrameContext* m_context; - - [NativeTypeName("Coplt::u64")] - public ulong m_submit_id; - - [NativeTypeName("Coplt::FGpuQueueType")] - public FGpuQueueType m_queue_type; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuQueue*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuQueue*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuQueue*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuQueue*)Unsafe.AsPointer(ref this), id); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuQueue*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuQueue*)Unsafe.AsPointer(ref this), &result, name); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* GetRawQueue() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuQueue*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateOutputFromRawSwapchain([NativeTypeName("const FGpuOutputFromSwapChainCreateOptions &")] FGpuOutputFromSwapChainCreateOptions* options, void* swapchain, FGpuOutput** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuQueue*)Unsafe.AsPointer(ref this), &result, options, swapchain, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateOutputForHwnd([NativeTypeName("const FGpuOutputCreateOptions &")] FGpuOutputCreateOptions* options, void* hwnd, FGpuOutput** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuQueue*)Unsafe.AsPointer(ref this), &result, options, hwnd, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Submit([NativeTypeName("Coplt::FGpuExecutor *")] FGpuExecutor* Executor, [NativeTypeName("const FCommandSubmit *")] FCommandSubmit* submit) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuQueue*)Unsafe.AsPointer(ref this), &result, Executor, submit); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SubmitNoWait([NativeTypeName("Coplt::FGpuExecutor *")] FGpuExecutor* Executor, [NativeTypeName("const FCommandSubmit *")] FCommandSubmit* submit) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuQueue*)Unsafe.AsPointer(ref this), &result, Executor, submit); - } - - public interface Interface : FGpuObject.Interface - { - void* GetRawQueue(); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateOutputFromRawSwapchain([NativeTypeName("const FGpuOutputFromSwapChainCreateOptions &")] FGpuOutputFromSwapChainCreateOptions* options, void* swapchain, FGpuOutput** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateOutputForHwnd([NativeTypeName("const FGpuOutputCreateOptions &")] FGpuOutputCreateOptions* options, void* hwnd, FGpuOutput** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult Submit([NativeTypeName("Coplt::FGpuExecutor *")] FGpuExecutor* Executor, [NativeTypeName("const FCommandSubmit *")] FCommandSubmit* submit); - - [return: NativeTypeName("Coplt::FResult")] - FResult SubmitNoWait([NativeTypeName("Coplt::FGpuExecutor *")] FGpuExecutor* Executor, [NativeTypeName("const FCommandSubmit *")] FCommandSubmit* submit); - } - } - public partial struct FGpuQueueData { [NativeTypeName("Coplt::FGpuQueueType")] @@ -4143,16 +3946,10 @@ public enum FHdrType : byte Float16, } - public partial struct FGpuOutputFromSwapChainCreateOptions - { - [NativeTypeName("Coplt::b8")] - public B8 VSync; - } - - public partial struct FGpuOutputCreateOptions + public partial struct FGpuOutputData { - [NativeTypeName("Coplt::FStr8or16")] - public FStr8or16 Name; + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat Format; [NativeTypeName("Coplt::u32")] public uint Width; @@ -4168,138 +3965,62 @@ public partial struct FGpuOutputCreateOptions [NativeTypeName("Coplt::FPresentMode")] public FPresentMode PresentMode; - - [NativeTypeName("Coplt::FOutputAlphaMode")] - public FOutputAlphaMode AlphaMode; - - [NativeTypeName("Coplt::b8")] - public B8 VSync; - } - - public partial struct FCommandSubmit - { } - public unsafe partial struct FCommandSubmit + public partial struct FGpuOutput2CreateOptions { - [NativeTypeName("Coplt::FCommandItem *")] - public FCommandItem* Commands; - - [NativeTypeName("Coplt::FRenderCommandItem *")] - public FRenderCommandItem* RenderCommands; - - [NativeTypeName("Coplt::FComputeCommandItem *")] - public FComputeCommandItem* ComputeCommands; - - [NativeTypeName("Coplt::FResourceMeta *")] - public FResourceMeta* Resources; - - [NativeTypeName("Coplt::FRenderInfo *")] - public FRenderInfo* RenderInfos; - - [NativeTypeName("Coplt::FComputeInfo *")] - public FComputeInfo* ComputeInfos; - - [NativeTypeName("Coplt::FResolveInfo *")] - public FResolveInfo* ResolveInfos; - - [NativeTypeName("Coplt::FRect *")] - public FRect* Rects; - - [NativeTypeName("Coplt::FViewport *")] - public FViewport* Viewports; - - [NativeTypeName("Coplt::FMeshBuffers *")] - public FMeshBuffers* MeshBuffers; - - [NativeTypeName("Coplt::FVertexBufferRange *")] - public FVertexBufferRange* VertexBufferRanges; - - [NativeTypeName("Coplt::FBufferCopyRange *")] - public FBufferCopyRange* BufferCopyRanges; - - [NativeTypeName("Coplt::FBufferImageCopyRange *")] - public FBufferImageCopyRange* BufferImageCopyRanges; - - [NativeTypeName("Coplt::FBindItem *")] - public FBindItem* BindItems; - - [NativeTypeName("Coplt::FBarrier *")] - public FBarrier* Barriers; - - [NativeTypeName("Coplt::Char8 *")] - public byte* Str8; - - [NativeTypeName("Coplt::Char16 *")] - public char* Str16; - - [NativeTypeName("Coplt::u32")] - public uint CommandCount; - - [NativeTypeName("Coplt::u32")] - public uint ResourceCount; + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; - [NativeTypeName("Coplt::u32")] - public uint SyncBindingCount; + [NativeTypeName("Coplt::FPresentMode")] + public FPresentMode PresentMode; - [NativeTypeName("Coplt::u32")] - public uint GrowingResourceBindingCapacity; + [NativeTypeName("Coplt::b8")] + public B8 Srgb; - [NativeTypeName("Coplt::u32")] - public uint GrowingSamplerBindingCapacity; + [NativeTypeName("Coplt::FHdrType")] + public FHdrType Hdr; } - [Guid("F1C59CB4-7EE6-4EE2-80F4-07CC568920D2")] - [NativeTypeName("struct FGpuOutput : Coplt::FGpuExecutor")] - public unsafe partial struct FGpuOutput : FGpuOutput.Interface, INativeGuid + [Guid("3F82BE7F-2CF5-48A9-8CA4-BB2F9CFE58B2")] + [NativeTypeName("struct FGpuOutput2 : Coplt::FGpuExecutor")] + public unsafe partial struct FGpuOutput2 : FGpuOutput2.Interface, INativeGuid { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuOutput)); + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuOutput2)); public void** lpVtbl; - [NativeTypeName("Coplt::FResState")] - public FResState m_state; - - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat m_format; - - [NativeTypeName("Coplt::u32")] - public uint m_width; - - [NativeTypeName("Coplt::u32")] - public uint m_height; - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuOutput*)Unsafe.AsPointer(ref this)); + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("size_t")] public nuint Release() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuOutput*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("size_t")] public nuint AddRef() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuOutput*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuOutput*)Unsafe.AsPointer(ref this), id); + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuOutput2*)Unsafe.AsPointer(ref this), id); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::u64")] public ulong ObjectId() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuOutput*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -4307,7 +4028,7 @@ public ulong ObjectId() public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuOutput*)Unsafe.AsPointer(ref this), &result, name); + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result, name); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -4315,15 +4036,14 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) public FResult Wait() { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuOutput*)Unsafe.AsPointer(ref this), &result); + return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable) + [return: NativeTypeName("const FGpuOutputData *")] + public FGpuOutputData* GpuOutputData() { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuOutput*)Unsafe.AsPointer(ref this), &result, Enable); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -4331,141 +4051,23 @@ public FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable) public FResult Resize([NativeTypeName("Coplt::u32")] uint Width, [NativeTypeName("Coplt::u32")] uint Height) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuOutput*)Unsafe.AsPointer(ref this), &result, Width, Height); + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result, Width, Height); } - public interface Interface : FGpuExecutor.Interface + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Present() { - [return: NativeTypeName("Coplt::FResult")] - FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); + } - [return: NativeTypeName("Coplt::FResult")] - FResult Resize([NativeTypeName("Coplt::u32")] uint Width, [NativeTypeName("Coplt::u32")] uint Height); - } - } - - public partial struct FGpuOutputData - { - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat Format; - - [NativeTypeName("Coplt::u32")] - public uint Width; - - [NativeTypeName("Coplt::u32")] - public uint Height; - - [NativeTypeName("Coplt::b8")] - public B8 Srgb; - - [NativeTypeName("Coplt::FHdrType")] - public FHdrType Hdr; - - [NativeTypeName("Coplt::FPresentMode")] - public FPresentMode PresentMode; - } - - public partial struct FGpuOutput2CreateOptions - { - [NativeTypeName("Coplt::FStr8or16")] - public FStr8or16 Name; - - [NativeTypeName("Coplt::FPresentMode")] - public FPresentMode PresentMode; - - [NativeTypeName("Coplt::b8")] - public B8 Srgb; - - [NativeTypeName("Coplt::FHdrType")] - public FHdrType Hdr; - } - - [Guid("3F82BE7F-2CF5-48A9-8CA4-BB2F9CFE58B2")] - [NativeTypeName("struct FGpuOutput2 : Coplt::FGpuExecutor")] - public unsafe partial struct FGpuOutput2 : FGpuOutput2.Interface, INativeGuid - { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuOutput2)); - - public void** lpVtbl; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuOutput2*)Unsafe.AsPointer(ref this), id); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result, name); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Wait() - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("const FGpuOutputData *")] - public FGpuOutputData* GpuOutputData() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Resize([NativeTypeName("Coplt::u32")] uint Width, [NativeTypeName("Coplt::u32")] uint Height) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result, Width, Height); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Present() - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult PresentNoWait() - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult PresentNoWait() + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -4791,1488 +4393,164 @@ public enum FGraphicsFormat BC6H_SF16 = 96, BC7_TypeLess = 97, BC7_UNorm = 98, - BC7_UNorm_sRGB = 99, - AYUV = 100, - Y410 = 101, - Y416 = 102, - NV12 = 103, - P010 = 104, - P016 = 105, - Opaque_420 = 106, - YUY2 = 107, - Y210 = 108, - Y216 = 109, - NV11 = 110, - AI44 = 111, - IA44 = 112, - P8 = 113, - A8P8 = 114, - B4G4R4A4_UNorm = 115, - P208 = 130, - V208 = 131, - V408 = 132, - A4B4G4R4_UNorm = 191, - S8_UInt = 127, - Etc2_R8G8B8_UNorm = 147, - Etc2_R8G8B8_sRGB = 148, - Etc2_R8G8B8A1_UNorm = 149, - Etc2_R8G8B8A1_sRGB = 150, - Etc2_R8G8B8A8_UNorm = 151, - Etc2_R8G8B8A8_sRGB = 152, - Eac_R11_UNorm = 153, - Eac_R11_SNorm = 154, - Eac_R11G11_UNorm = 155, - Eac_R11G11_SNorm = 156, - Astc_4x4_UNorm = 157, - Astc_4x4_sRGB = 158, - Astc_5x4_UNorm = 159, - Astc_5x4_sRGB = 160, - Astc_5x5_UNorm = 161, - Astc_5x5_sRGB = 162, - Astc_6x5_UNorm = 163, - Astc_6x5_sRGB = 164, - Astc_6x6_UNorm = 165, - Astc_6x6_sRGB = 166, - Astc_8x5_UNorm = 167, - Astc_8x5_sRGB = 168, - Astc_8x6_UNorm = 169, - Astc_8x6_sRGB = 170, - Astc_8x8_UNorm = 171, - Astc_8x8_sRGB = 172, - Astc_10x5_UNorm = 173, - Astc_10x5_sRGB = 174, - Astc_10x6_UNorm = 175, - Astc_10x6_sRGB = 176, - Astc_10x8_UNorm = 177, - Astc_10x8_sRGB = 178, - Astc_10x10_UNorm = 179, - Astc_10x10_sRGB = 180, - Astc_12x10_UNorm = 181, - Astc_12x10_sRGB = 182, - Astc_12x12_UNorm = 183, - Astc_12x12_sRGB = 184, - } - - [NativeTypeName("Coplt::u32")] - public enum FLegacyState : uint - { - Manual = 0, - Common = 1 << 0, - Present = 1 << 1, - VertexBuffer = 1 << 2, - IndexBuffer = 1 << 3, - ConstantBuffer = 1 << 4, - IndirectBuffer = 1 << 5, - RenderTarget = 1 << 6, - DepthRead = 1 << 7, - DepthWrite = 1 << 8, - ShaderResource = 1 << 9, - UnorderedAccess = 1 << 10, - CopySrc = 1 << 11, - CopyDst = 1 << 12, - ResolveSrc = 1 << 13, - ResolveDst = 1 << 14, - RayTracing = 1 << 15, - ShadingRate = 1 << 16, - StreamOutput = 1 << 17, - GenericRead = VertexBuffer | ConstantBuffer | ShaderResource | IndirectBuffer | CopySrc, - } - - [NativeTypeName("Coplt::u32")] - public enum FResLayout : uint - { - None = 0, - Common, - Present = Common, - GenericRead, - RenderTarget, - UnorderedAccess, - DepthStencilRead, - DepthStencilWrite, - ShaderResource, - CopySrc, - CopyDst, - ResolveSrc, - ResolveDst, - ShadingRate, - VideoDecodeRead, - VideoDecodeWrite, - VideoProcessRead, - VideoProcessWrite, - VideoEncodeRead, - VideoEncodeWrite, - } - - [NativeTypeName("Coplt::u32")] - public enum FResAccess : uint - { - NoAccess = 1U << 31, - Common = 0, - ConstantBuffer = 1 << 0, - VertexBuffer = 1 << 1, - IndexBuffer = 1 << 2, - RenderTarget = 1 << 3, - UnorderedAccess = 1 << 4, - DepthStencilRead = 1 << 5, - DepthStencilWrite = 1 << 6, - ShaderResource = 1 << 7, - StreamOutput = 1 << 8, - IndirectOrPredicationBuffer = 1 << 9, - CopySrc = 1 << 10, - CopyDst = 1 << 11, - ResolveSrc = 1 << 12, - ResolveDst = 1 << 13, - RayTracingAccelerationStructureRead = 1 << 14, - RayTracingAccelerationStructureWrite = 1 << 15, - ShadingRate = 1 << 16, - VideoDecodeRead = 1 << 17, - VideoDecodeWrite = 1 << 18, - VideoProcessRead = 1 << 19, - VideoProcessWrite = 1 << 20, - VideoEncodeRead = 1 << 21, - VideoEncodeWrite = 1 << 22, - } - - public partial struct FResState - { - [NativeTypeName("Coplt::FResLayout")] - public FResLayout Layout; - - [NativeTypeName("Coplt::FResAccess")] - public FResAccess Access; - - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags Stages; - - [NativeTypeName("Coplt::FLegacyState")] - public FLegacyState Legacy; - - [NativeTypeName("Coplt::b8")] - public B8 CrossQueue; - } - - [NativeTypeName("Coplt::u32")] - public enum FCommandType : uint - { - None, - Label, - BeginScope, - EndScope, - Present, - Barrier, - ClearColor, - ClearDepthStencil, - Bind, - BufferCopy, - BufferImageCopy, - Render, - Compute, - SetPipeline, - SetBinding, - SetViewportScissor, - SetMeshBuffers, - Draw, - Dispatch, - SyncBinding, - } - - [NativeTypeName("Coplt::u8")] - public enum FResourceRefType : byte - { - Image, - Buffer, - Output, - } - - public unsafe partial struct FResourceMeta - { - [NativeTypeName("__AnonymousRecord_Command_L65_C9")] - public _Anonymous_e__Union Anonymous; - - [NativeTypeName("Coplt::FResourceRefType")] - public FResourceRefType Type; - - [UnscopedRef] - public ref FGpuOutput* Output - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Output; - } - } - - [UnscopedRef] - public ref FGpuBuffer* Buffer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Buffer; - } - } - - [UnscopedRef] - public ref FGpuImage* Image - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Image; - } - } - - [StructLayout(LayoutKind.Explicit)] - public unsafe partial struct _Anonymous_e__Union - { - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuOutput *")] - public FGpuOutput* Output; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuBuffer *")] - public FGpuBuffer* Buffer; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuImage *")] - public FGpuImage* Image; - } - } - - public partial struct FResourceRef - { - [NativeTypeName("Coplt::u32")] - public uint ResourceIndex; - } - - public partial struct FSubResourceRange - { - [NativeTypeName("Coplt::u32")] - public uint IndexOrFirstMipLevel; - - [NativeTypeName("Coplt::u32")] - public uint NumMipLevels; - - [NativeTypeName("Coplt::u32")] - public uint FirstArraySlice; - - [NativeTypeName("Coplt::u32")] - public uint NumArraySlices; - - [NativeTypeName("Coplt::u32")] - public uint FirstPlane; - - [NativeTypeName("Coplt::u32")] - public uint NumPlanes; - } - - [NativeTypeName("Coplt::u32")] - public enum FImageBarrierFlags : uint - { - None, - Discard = 1 << 0, - CrossQueue = 1 << 1, - } - - public partial struct FImageBarrier - { - [NativeTypeName("Coplt::FLegacyState")] - public FLegacyState LegacyBefore; - - [NativeTypeName("Coplt::FLegacyState")] - public FLegacyState LegacyAfter; - - [NativeTypeName("Coplt::FResAccess")] - public FResAccess AccessBefore; - - [NativeTypeName("Coplt::FResAccess")] - public FResAccess AccessAfter; - - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags StagesBefore; - - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags StagesAfter; - - [NativeTypeName("Coplt::FResLayout")] - public FResLayout LayoutBefore; - - [NativeTypeName("Coplt::FResLayout")] - public FResLayout LayoutAfter; - - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Image; - - [NativeTypeName("Coplt::FSubResourceRange")] - public FSubResourceRange SubResourceRange; - - [NativeTypeName("Coplt::FImageBarrierFlags")] - public FImageBarrierFlags Flags; - } - - public partial struct FBufferBarrier - { - [NativeTypeName("Coplt::FLegacyState")] - public FLegacyState LegacyBefore; - - [NativeTypeName("Coplt::FLegacyState")] - public FLegacyState LegacyAfter; - - [NativeTypeName("Coplt::FResAccess")] - public FResAccess AccessBefore; - - [NativeTypeName("Coplt::FResAccess")] - public FResAccess AccessAfter; - - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags StagesBefore; - - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags StagesAfter; - - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Buffer; - - [NativeTypeName("Coplt::u64")] - public ulong Offset; - - [NativeTypeName("Coplt::u64")] - public ulong Size; - } - - public partial struct FGlobalBarrier - { - [NativeTypeName("Coplt::FResAccess")] - public FResAccess AccessBefore; - - [NativeTypeName("Coplt::FResAccess")] - public FResAccess AccessAfter; - - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags StagesBefore; - - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags StagesAfter; - } - - [NativeTypeName("Coplt::u8")] - public enum FBarrierType : byte - { - None, - Global, - Buffer, - Image, - } - - public partial struct FBarrier - { - [NativeTypeName("Coplt::FBarrierType")] - public FBarrierType Type; - - [NativeTypeName("__AnonymousRecord_Command_L170_C9")] - public _Anonymous_e__Union Anonymous; - - [UnscopedRef] - public ref FGlobalBarrier Global - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Global; - } - } - - [UnscopedRef] - public ref FBufferBarrier Buffer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Buffer; - } - } - - [UnscopedRef] - public ref FImageBarrier Image - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Image; - } - } - - [StructLayout(LayoutKind.Explicit)] - public partial struct _Anonymous_e__Union - { - [FieldOffset(0)] - [NativeTypeName("Coplt::FGlobalBarrier")] - public FGlobalBarrier Global; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FBufferBarrier")] - public FBufferBarrier Buffer; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FImageBarrier")] - public FImageBarrier Image; - } - } - - [StructLayout(LayoutKind.Explicit)] - public partial struct FBufferRef - { - [FieldOffset(0)] - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Buffer; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FUploadLoc")] - public FUploadLoc Upload; - } - - [NativeTypeName("Coplt::u8")] - public enum FBufferRefType : byte - { - Buffer = 0, - Upload, - } - - public partial struct FResolveInfo - { - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Src; - - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Dst; - - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat Format; - - [NativeTypeName("Coplt::FResolveMode")] - public FResolveMode Mode; - } - - public partial struct FRenderInfo - { - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Dsv; - - [NativeTypeName("Coplt::u32")] - public uint NumRtv; - - [NativeTypeName("FResourceRef[8]")] - public _Rtv_e__FixedBuffer Rtv; - - [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; - - [NativeTypeName("Coplt::f32")] - public float Depth; - - [NativeTypeName("Coplt::u8")] - public byte Stencil; - - [NativeTypeName("FLoadOp[2]")] - public _DsvLoadOp_e__FixedBuffer DsvLoadOp; - - [NativeTypeName("FStoreOp[2]")] - public _DsvStoreOp_e__FixedBuffer DsvStoreOp; - - [NativeTypeName("FLoadOp[8]")] - public _RtvLoadOp_e__FixedBuffer RtvLoadOp; - - [NativeTypeName("FStoreOp[8]")] - public _RtvStoreOp_e__FixedBuffer RtvStoreOp; - - [NativeTypeName("Coplt::b8")] - public B8 HasUavWrites; - - [InlineArray(8)] - public partial struct _Rtv_e__FixedBuffer - { - public FResourceRef e0; - } - - [InlineArray(8)] - 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 - { - public float e0; - } - - [InlineArray(2)] - public partial struct _DsvLoadOp_e__FixedBuffer - { - public FLoadOp e0; - } - - [InlineArray(2)] - public partial struct _DsvStoreOp_e__FixedBuffer - { - public FStoreOp e0; - } - - [InlineArray(8)] - public partial struct _RtvLoadOp_e__FixedBuffer - { - public FLoadOp e0; - } - - [InlineArray(8)] - public partial struct _RtvStoreOp_e__FixedBuffer - { - public FStoreOp e0; - } - } - - public partial struct FComputeInfo - { - } - - public partial struct FBufferRange - { - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Buffer; - - [NativeTypeName("Coplt::u32")] - public uint Offset; - - [NativeTypeName("Coplt::u32")] - public uint Size; - } - - [NativeTypeName("struct FVertexBufferRange : Coplt::FBufferRange")] - public partial struct FVertexBufferRange - { - public FBufferRange Base; - - [NativeTypeName("Coplt::u32")] - public uint Index; - } - - public unsafe partial struct FMeshBuffers - { - [NativeTypeName("Coplt::FMeshLayout *")] - public FMeshLayout* MeshLayout; - - [NativeTypeName("Coplt::FBufferRange")] - public FBufferRange IndexBuffer; - - [NativeTypeName("Coplt::u32")] - public uint VertexBufferCount; - - [NativeTypeName("Coplt::u32")] - public uint VertexBuffersIndex; - } - - public partial struct FCommandBase - { - [NativeTypeName("Coplt::FCommandType")] - public FCommandType Type; - } - - [NativeTypeName("struct FCommandLabel : Coplt::FCommandBase")] - public partial struct FCommandLabel - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint StringIndex; - - [NativeTypeName("Coplt::u32")] - public uint StringLength; - - [NativeTypeName("Coplt::FStrType")] - public FStrType StrType; - - [NativeTypeName("u8[3]")] - public _Color_e__FixedBuffer Color; - - [NativeTypeName("Coplt::b8")] - public B8 HasColor; - - [InlineArray(3)] - public partial struct _Color_e__FixedBuffer - { - public byte e0; - } - } - - [NativeTypeName("struct FCommandBeginScope : Coplt::FCommandBase")] - public partial struct FCommandBeginScope - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint StringIndex; - - [NativeTypeName("Coplt::u32")] - public uint StringLength; - - [NativeTypeName("Coplt::FStrType")] - public FStrType StrType; - - [NativeTypeName("u8[3]")] - public _Color_e__FixedBuffer Color; - - [NativeTypeName("Coplt::b8")] - public B8 HasColor; - - [InlineArray(3)] - public partial struct _Color_e__FixedBuffer - { - public byte e0; - } - } - - [NativeTypeName("struct FCommandEndScope : Coplt::FCommandBase")] - public partial struct FCommandEndScope - { - public FCommandBase Base; - } - - [NativeTypeName("struct FCommandPresent : Coplt::FCommandBase")] - public partial struct FCommandPresent - { - public FCommandBase Base; - - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Image; - } - - [NativeTypeName("struct FCommandBarrier : Coplt::FCommandBase")] - public partial struct FCommandBarrier - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint BarrierIndex; - - [NativeTypeName("Coplt::u32")] - public uint BarrierCount; - } - - [NativeTypeName("struct FCommandClearColor : Coplt::FCommandBase")] - public partial struct FCommandClearColor - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint RectCount; - - [NativeTypeName("Coplt::u32")] - public uint RectIndex; - - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Image; - - [NativeTypeName("f32[4]")] - public _Color_e__FixedBuffer Color; - - [InlineArray(4)] - public partial struct _Color_e__FixedBuffer - { - public float e0; - } - } - - [NativeTypeName("struct FCommandClearDepthStencil : Coplt::FCommandBase")] - public partial struct FCommandClearDepthStencil - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint RectCount; - - [NativeTypeName("Coplt::u32")] - public uint RectIndex; - - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Image; - - [NativeTypeName("Coplt::f32")] - public float Depth; - - [NativeTypeName("Coplt::u8")] - public byte Stencil; - - [NativeTypeName("Coplt::FDepthStencilClearFlags")] - public FDepthStencilClearFlags Clear; - } - - [NativeTypeName("struct FCommandBind : Coplt::FCommandBase")] - public unsafe partial struct FCommandBind - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint ItemCount; - - [NativeTypeName("Coplt::u32")] - public uint ItemsIndex; - - [NativeTypeName("Coplt::FShaderBinding *")] - public FShaderBinding* Binding; - } - - [NativeTypeName("struct FCommandBufferCopy : Coplt::FCommandBase")] - public partial struct FCommandBufferCopy - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint RangeIndex; - - [NativeTypeName("Coplt::FBufferRef")] - public FBufferRef Dst; - - [NativeTypeName("Coplt::FBufferRef")] - public FBufferRef Src; - - [NativeTypeName("Coplt::FBufferRefType")] - public FBufferRefType DstType; - - [NativeTypeName("Coplt::FBufferRefType")] - public FBufferRefType SrcType; - } - - [NativeTypeName("struct FCommandBufferImageCopy : Coplt::FCommandBase")] - public partial struct FCommandBufferImageCopy - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint RangeIndex; - - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Image; - - [NativeTypeName("Coplt::FBufferRef")] - public FBufferRef Buffer; - - [NativeTypeName("Coplt::FBufferRefType")] - public FBufferRefType BufferType; - - [NativeTypeName("Coplt::b8")] - public B8 ImageToBuffer; - } - - [NativeTypeName("struct FCommandRender : Coplt::FCommandBase")] - public partial struct FCommandRender - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint InfoIndex; - - [NativeTypeName("Coplt::u32")] - public uint CommandStartIndex; - - [NativeTypeName("Coplt::u32")] - public uint CommandCount; - } - - [NativeTypeName("struct FCommandCompute : Coplt::FCommandBase")] - public partial struct FCommandCompute - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint InfoIndex; - - [NativeTypeName("Coplt::u32")] - public uint CommandStartIndex; - - [NativeTypeName("Coplt::u32")] - public uint CommandCount; - } - - [NativeTypeName("struct FCommandSetPipeline : Coplt::FCommandBase")] - public unsafe partial struct FCommandSetPipeline - { - public FCommandBase Base; - - [NativeTypeName("Coplt::FShaderPipeline *")] - public FShaderPipeline* Pipeline; - } - - [NativeTypeName("struct FCommandSetBinding : Coplt::FCommandBase")] - public unsafe partial struct FCommandSetBinding - { - public FCommandBase Base; - - [NativeTypeName("Coplt::FShaderBinding *")] - public FShaderBinding* Binding; - } - - [NativeTypeName("struct FCommandSetViewportScissor : Coplt::FCommandBase")] - public partial struct FCommandSetViewportScissor - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint ViewportCount; - - [NativeTypeName("Coplt::u32")] - public uint ViewportIndex; - - [NativeTypeName("Coplt::u32")] - public uint ScissorRectCount; - - [NativeTypeName("Coplt::u32")] - public uint ScissorRectIndex; - } - - [NativeTypeName("struct FCommandSetMeshBuffers : Coplt::FCommandBase")] - public partial struct FCommandSetMeshBuffers - { - public FCommandBase Base; - - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat IndexFormat; - - [NativeTypeName("Coplt::u32")] - public uint VertexStartSlot; - - [NativeTypeName("Coplt::u32")] - public uint PayloadIndex; - } - - [NativeTypeName("struct FCommandDraw : Coplt::FCommandBase")] - public partial struct FCommandDraw - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint VertexOrIndexCount; - - [NativeTypeName("Coplt::u32")] - public uint InstanceCount; - - [NativeTypeName("Coplt::u32")] - public uint FirstVertexOrIndex; - - [NativeTypeName("Coplt::u32")] - public uint FirstInstance; - - [NativeTypeName("Coplt::u32")] - public uint VertexOffset; - - [NativeTypeName("Coplt::b8")] - public B8 Indexed; - } - - [NativeTypeName("struct FCommandDispatch : Coplt::FCommandBase")] - public partial struct FCommandDispatch - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint GroupCountX; - - [NativeTypeName("Coplt::u32")] - public uint GroupCountY; - - [NativeTypeName("Coplt::u32")] - public uint GroupCountZ; - - [NativeTypeName("Coplt::FDispatchType")] - public FDispatchType Type; - } - - [NativeTypeName("Coplt::u8")] - public enum FBindingSyncType : byte - { - Transient, - Persistent, - } - - [NativeTypeName("struct FCommandSyncBinding : Coplt::FCommandBase")] - public partial struct FCommandSyncBinding - { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint Index; - - [NativeTypeName("Coplt::FBindingSyncType")] - public FBindingSyncType Type; - } - - public partial struct FCommandItem - { - [NativeTypeName("__AnonymousRecord_Command_L446_C9")] - public _Anonymous_e__Union Anonymous; - - [UnscopedRef] - public ref FCommandType Type - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Type; - } - } - - [UnscopedRef] - public ref FCommandLabel Label - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Label; - } - } - - [UnscopedRef] - public ref FCommandBeginScope BeginScope - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.BeginScope; - } - } - - [UnscopedRef] - public ref FCommandEndScope EndScope - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.EndScope; - } - } - - [UnscopedRef] - public ref FCommandPresent Present - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Present; - } - } - - [UnscopedRef] - public ref FCommandBarrier Barrier - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Barrier; - } - } - - [UnscopedRef] - public ref FCommandClearColor ClearColor - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.ClearColor; - } - } - - [UnscopedRef] - public ref FCommandClearDepthStencil ClearDepthStencil - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.ClearDepthStencil; - } - } - - [UnscopedRef] - public ref FCommandBind Bind - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Bind; - } - } - - [UnscopedRef] - public ref FCommandBufferCopy BufferCopy - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.BufferCopy; - } - } - - [UnscopedRef] - public ref FCommandBufferImageCopy BufferImageCopy - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.BufferImageCopy; - } - } - - [UnscopedRef] - public ref FCommandRender Render - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Render; - } - } - - [UnscopedRef] - public ref FCommandCompute Compute - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Compute; - } - } - - [UnscopedRef] - public ref FCommandSyncBinding SyncBinding - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SyncBinding; - } - } - - [UnscopedRef] - public Span _pad - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return Anonymous._pad; - } - } - - [StructLayout(LayoutKind.Explicit)] - public partial struct _Anonymous_e__Union - { - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandType")] - public FCommandType Type; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandLabel")] - public FCommandLabel Label; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBeginScope")] - public FCommandBeginScope BeginScope; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandEndScope")] - public FCommandEndScope EndScope; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandPresent")] - public FCommandPresent Present; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBarrier")] - public FCommandBarrier Barrier; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandClearColor")] - public FCommandClearColor ClearColor; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandClearDepthStencil")] - public FCommandClearDepthStencil ClearDepthStencil; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBind")] - public FCommandBind Bind; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBufferCopy")] - public FCommandBufferCopy BufferCopy; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBufferImageCopy")] - public FCommandBufferImageCopy BufferImageCopy; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandRender")] - public FCommandRender Render; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandCompute")] - public FCommandCompute Compute; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSyncBinding")] - public FCommandSyncBinding SyncBinding; - - [FieldOffset(0)] - [NativeTypeName("u8[32]")] - public __pad_e__FixedBuffer _pad; - - [InlineArray(32)] - public partial struct __pad_e__FixedBuffer - { - public byte e0; - } - } - } - - public partial struct FRenderCommandItem - { - [NativeTypeName("__AnonymousRecord_Command_L477_C9")] - public _Anonymous_e__Union Anonymous; - - [UnscopedRef] - public ref FCommandType Type - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Type; - } - } - - [UnscopedRef] - public ref FCommandLabel Label - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Label; - } - } - - [UnscopedRef] - public ref FCommandBeginScope BeginScope - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.BeginScope; - } - } - - [UnscopedRef] - public ref FCommandEndScope EndScope - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.EndScope; - } - } - - [UnscopedRef] - public ref FCommandSetPipeline SetPipeline - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetPipeline; - } - } - - [UnscopedRef] - public ref FCommandSetBinding SetBinding - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetBinding; - } - } - - [UnscopedRef] - public ref FCommandSetViewportScissor SetViewportScissor - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetViewportScissor; - } - } - - [UnscopedRef] - public ref FCommandSetMeshBuffers SetMeshBuffers - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetMeshBuffers; - } - } - - [UnscopedRef] - public ref FCommandDraw Draw - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Draw; - } - } - - [UnscopedRef] - public ref FCommandDispatch Dispatch - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Dispatch; - } - } - - [UnscopedRef] - public ref FCommandSyncBinding SyncBinding - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SyncBinding; - } - } - - [UnscopedRef] - public Span _pad - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return Anonymous._pad; - } - } - - [StructLayout(LayoutKind.Explicit)] - public partial struct _Anonymous_e__Union - { - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandType")] - public FCommandType Type; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandLabel")] - public FCommandLabel Label; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBeginScope")] - public FCommandBeginScope BeginScope; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandEndScope")] - public FCommandEndScope EndScope; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetPipeline")] - public FCommandSetPipeline SetPipeline; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetBinding")] - public FCommandSetBinding SetBinding; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetViewportScissor")] - public FCommandSetViewportScissor SetViewportScissor; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetMeshBuffers")] - public FCommandSetMeshBuffers SetMeshBuffers; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandDraw")] - public FCommandDraw Draw; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandDispatch")] - public FCommandDispatch Dispatch; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSyncBinding")] - public FCommandSyncBinding SyncBinding; - - [FieldOffset(0)] - [NativeTypeName("u8[32]")] - public __pad_e__FixedBuffer _pad; - - [InlineArray(32)] - public partial struct __pad_e__FixedBuffer - { - public byte e0; - } - } + BC7_UNorm_sRGB = 99, + AYUV = 100, + Y410 = 101, + Y416 = 102, + NV12 = 103, + P010 = 104, + P016 = 105, + Opaque_420 = 106, + YUY2 = 107, + Y210 = 108, + Y216 = 109, + NV11 = 110, + AI44 = 111, + IA44 = 112, + P8 = 113, + A8P8 = 114, + B4G4R4A4_UNorm = 115, + P208 = 130, + V208 = 131, + V408 = 132, + A4B4G4R4_UNorm = 191, + S8_UInt = 127, + Etc2_R8G8B8_UNorm = 147, + Etc2_R8G8B8_sRGB = 148, + Etc2_R8G8B8A1_UNorm = 149, + Etc2_R8G8B8A1_sRGB = 150, + Etc2_R8G8B8A8_UNorm = 151, + Etc2_R8G8B8A8_sRGB = 152, + Eac_R11_UNorm = 153, + Eac_R11_SNorm = 154, + Eac_R11G11_UNorm = 155, + Eac_R11G11_SNorm = 156, + Astc_4x4_UNorm = 157, + Astc_4x4_sRGB = 158, + Astc_5x4_UNorm = 159, + Astc_5x4_sRGB = 160, + Astc_5x5_UNorm = 161, + Astc_5x5_sRGB = 162, + Astc_6x5_UNorm = 163, + Astc_6x5_sRGB = 164, + Astc_6x6_UNorm = 165, + Astc_6x6_sRGB = 166, + Astc_8x5_UNorm = 167, + Astc_8x5_sRGB = 168, + Astc_8x6_UNorm = 169, + Astc_8x6_sRGB = 170, + Astc_8x8_UNorm = 171, + Astc_8x8_sRGB = 172, + Astc_10x5_UNorm = 173, + Astc_10x5_sRGB = 174, + Astc_10x6_UNorm = 175, + Astc_10x6_sRGB = 176, + Astc_10x8_UNorm = 177, + Astc_10x8_sRGB = 178, + Astc_10x10_UNorm = 179, + Astc_10x10_sRGB = 180, + Astc_12x10_UNorm = 181, + Astc_12x10_sRGB = 182, + Astc_12x12_UNorm = 183, + Astc_12x12_sRGB = 184, } - public partial struct FComputeCommandItem + [NativeTypeName("Coplt::u32")] + public enum FLegacyState : uint { - [NativeTypeName("__AnonymousRecord_Command_L502_C9")] - public _Anonymous_e__Union Anonymous; - - [UnscopedRef] - public ref FCommandType Type - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Type; - } - } - - [UnscopedRef] - public ref FCommandLabel Label - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Label; - } - } - - [UnscopedRef] - public ref FCommandBeginScope BeginScope - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.BeginScope; - } - } - - [UnscopedRef] - public ref FCommandEndScope EndScope - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.EndScope; - } - } - - [UnscopedRef] - public ref FCommandSetPipeline SetPipeline - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetPipeline; - } - } - - [UnscopedRef] - public ref FCommandSetBinding SetBinding - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetBinding; - } - } - - [UnscopedRef] - public ref FCommandDispatch Dispatch - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Dispatch; - } - } - - [UnscopedRef] - public ref FCommandSyncBinding SyncBinding - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SyncBinding; - } - } - - [UnscopedRef] - public Span _pad - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return Anonymous._pad; - } - } - - [StructLayout(LayoutKind.Explicit)] - public partial struct _Anonymous_e__Union - { - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandType")] - public FCommandType Type; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandLabel")] - public FCommandLabel Label; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBeginScope")] - public FCommandBeginScope BeginScope; + Manual = 0, + Common = 1 << 0, + Present = 1 << 1, + VertexBuffer = 1 << 2, + IndexBuffer = 1 << 3, + ConstantBuffer = 1 << 4, + IndirectBuffer = 1 << 5, + RenderTarget = 1 << 6, + DepthRead = 1 << 7, + DepthWrite = 1 << 8, + ShaderResource = 1 << 9, + UnorderedAccess = 1 << 10, + CopySrc = 1 << 11, + CopyDst = 1 << 12, + ResolveSrc = 1 << 13, + ResolveDst = 1 << 14, + RayTracing = 1 << 15, + ShadingRate = 1 << 16, + StreamOutput = 1 << 17, + GenericRead = VertexBuffer | ConstantBuffer | ShaderResource | IndirectBuffer | CopySrc, + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandEndScope")] - public FCommandEndScope EndScope; + [NativeTypeName("Coplt::u32")] + public enum FResLayout : uint + { + None = 0, + Common, + Present = Common, + GenericRead, + RenderTarget, + UnorderedAccess, + DepthStencilRead, + DepthStencilWrite, + ShaderResource, + CopySrc, + CopyDst, + ResolveSrc, + ResolveDst, + ShadingRate, + VideoDecodeRead, + VideoDecodeWrite, + VideoProcessRead, + VideoProcessWrite, + VideoEncodeRead, + VideoEncodeWrite, + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetPipeline")] - public FCommandSetPipeline SetPipeline; + [NativeTypeName("Coplt::u32")] + public enum FResAccess : uint + { + NoAccess = 1U << 31, + Common = 0, + ConstantBuffer = 1 << 0, + VertexBuffer = 1 << 1, + IndexBuffer = 1 << 2, + RenderTarget = 1 << 3, + UnorderedAccess = 1 << 4, + DepthStencilRead = 1 << 5, + DepthStencilWrite = 1 << 6, + ShaderResource = 1 << 7, + StreamOutput = 1 << 8, + IndirectOrPredicationBuffer = 1 << 9, + CopySrc = 1 << 10, + CopyDst = 1 << 11, + ResolveSrc = 1 << 12, + ResolveDst = 1 << 13, + RayTracingAccelerationStructureRead = 1 << 14, + RayTracingAccelerationStructureWrite = 1 << 15, + ShadingRate = 1 << 16, + VideoDecodeRead = 1 << 17, + VideoDecodeWrite = 1 << 18, + VideoProcessRead = 1 << 19, + VideoProcessWrite = 1 << 20, + VideoEncodeRead = 1 << 21, + VideoEncodeWrite = 1 << 22, + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetBinding")] - public FCommandSetBinding SetBinding; + public partial struct FResState + { + [NativeTypeName("Coplt::FResLayout")] + public FResLayout Layout; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandDispatch")] - public FCommandDispatch Dispatch; + [NativeTypeName("Coplt::FResAccess")] + public FResAccess Access; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSyncBinding")] - public FCommandSyncBinding SyncBinding; + [NativeTypeName("Coplt::FShaderStageFlags")] + public FShaderStageFlags Stages; - [FieldOffset(0)] - [NativeTypeName("u8[32]")] - public __pad_e__FixedBuffer _pad; + [NativeTypeName("Coplt::FLegacyState")] + public FLegacyState Legacy; - [InlineArray(32)] - public partial struct __pad_e__FixedBuffer - { - public byte e0; - } - } + [NativeTypeName("Coplt::b8")] + public B8 CrossQueue; } [NativeTypeName("Coplt::u8")] @@ -7350,14 +5628,10 @@ public static partial class Native public static readonly Guid IID_FShaderBinding = new Guid(0xA3CA644A, 0x0E02, 0x4D25, 0x9A, 0x18, 0x88, 0x35, 0xD6, 0x66, 0x00, 0xF7); - public static readonly Guid IID_FFrameContext = new Guid(0x3A22DE68, 0x8377, 0x4E57, 0xA1, 0x67, 0x3E, 0xFD, 0xB9, 0x7C, 0x10, 0x2A); - public static readonly Guid IID_FFrameContext2 = new Guid(0xFA9C7561, 0xAB0B, 0x4311, 0xBB, 0x4C, 0xC6, 0xBE, 0xF9, 0x3F, 0x86, 0xFE); public static readonly Guid IID_FRecordContext = new Guid(0x15B4821D, 0x0648, 0x4B78, 0x9C, 0x21, 0xC6, 0xA5, 0xB6, 0xA5, 0xED, 0x75); - public static readonly Guid IID_FGpuQueue = new Guid(0x95E60E28, 0xE387, 0x4055, 0x9B, 0x33, 0x2D, 0x23, 0xAF, 0x90, 0x1F, 0x8A); - public static readonly Guid IID_FGpuQueue2 = new Guid(0xFC94E4D0, 0x5F01, 0x4D4F, 0x89, 0x4C, 0x6A, 0xEF, 0xAA, 0xD9, 0x04, 0x99); public static readonly Guid IID_FGpuExecutor = new Guid(0xEDAB0989, 0xE0C2, 0x4B1E, 0x82, 0x6F, 0xC7, 0x33, 0x80, 0x08, 0x8F, 0xC6); @@ -7370,8 +5644,6 @@ public static partial class Native public static readonly Guid IID_FGpuImage = new Guid(0x667EFA36, 0x21C7, 0x4561, 0xAB, 0xAD, 0x85, 0x78, 0x0F, 0xA4, 0x92, 0x9E); - public static readonly Guid IID_FGpuOutput = new Guid(0xF1C59CB4, 0x7EE6, 0x4EE2, 0x80, 0xF4, 0x07, 0xCC, 0x56, 0x89, 0x20, 0xD2); - public static readonly Guid IID_FGpuOutput2 = new Guid(0x3F82BE7F, 0x2CF5, 0x48A9, 0x8C, 0xA4, 0xBB, 0x2F, 0x9C, 0xFE, 0x58, 0xB2); public static readonly Guid IID_FGpuSwapChain = new Guid(0x2BC677A1, 0x77FC, 0x4540, 0x89, 0xE2, 0x1F, 0xB7, 0xE3, 0x41, 0x7D, 0xC2); diff --git a/Coplt.Graphics.Native/Api/CMakeLists.txt b/Coplt.Graphics.Native/Api/CMakeLists.txt index e5d83ed..6840bd0 100644 --- a/Coplt.Graphics.Native/Api/CMakeLists.txt +++ b/Coplt.Graphics.Native/Api/CMakeLists.txt @@ -25,7 +25,6 @@ add_library(${target_name} STATIC Src/Allocator.cc Src/Allocator.h FFI/List.h - FFI/Command.h FFI/Resource.h FFI/Shader.h Src/Shader.h diff --git a/Coplt.Graphics.Native/Api/FFI/Command.h b/Coplt.Graphics.Native/Api/FFI/Command.h deleted file mode 100644 index e139fd4..0000000 --- a/Coplt.Graphics.Native/Api/FFI/Command.h +++ /dev/null @@ -1,559 +0,0 @@ -#pragma once - -#include "Structs.h" -#include "Binding.h" -#include "Blob.h" -#include "Output.h" -#include "Pipeline.h" -#include "States.h" - -namespace Coplt -{ - enum class FCommandType : u32 - { - None, - - Label, - BeginScope, - EndScope, - - // 仅内部使用 - Present, - - // 手动屏障 - Barrier, - - ClearColor, - ClearDepthStencil, - - Bind, - - BufferCopy, - BufferImageCopy, - - Render, - Compute, - - // Render / Compute - SetPipeline, - SetBinding, - - // Render - SetViewportScissor, - SetMeshBuffers, - Draw, - - // Render / Compute - Dispatch, - - // Render / Compute - // 仅内部使用 - SyncBinding, - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - enum class FResourceRefType : u8 - { - Image, - Buffer, - Output, - }; - - struct FResourceMeta - { - union - { - FGpuOutput* Output{}; - FGpuBuffer* Buffer; - FGpuImage* Image; - }; - - FResourceRefType Type{}; - - #ifdef FFI_SRC - FUnknown* GetObjectPtr() const - { - switch (Type) - { - case FResourceRefType::Image: - return Image; - case FResourceRefType::Buffer: - return Buffer; - case FResourceRefType::Output: - return Output; - } - return nullptr; - } - #endif - }; - - struct FResourceRef - { - u32 ResourceIndex{}; - - #ifdef FFI_SRC - FResourceMeta& Get(const FCommandSubmit& submit) const; - - bool IsEmpty() const - { - return ResourceIndex == 0; - } - #endif - }; - - struct FSubResourceRange - { - u32 IndexOrFirstMipLevel{}; - u32 NumMipLevels{}; - u32 FirstArraySlice{}; - u32 NumArraySlices{}; - u32 FirstPlane{}; - u32 NumPlanes{}; - }; - - COPLT_ENUM_FLAGS(FImageBarrierFlags, u32) - { - None, - Discard = 1 << 0, - CrossQueue = 1 << 1, - }; - - struct FImageBarrier - { - FLegacyState LegacyBefore{}; - FLegacyState LegacyAfter{}; - FResAccess AccessBefore{}; - FResAccess AccessAfter{}; - FShaderStageFlags StagesBefore{}; - FShaderStageFlags StagesAfter{}; - FResLayout LayoutBefore{}; - FResLayout LayoutAfter{}; - FResourceRef Image{}; - FSubResourceRange SubResourceRange{}; - FImageBarrierFlags Flags{}; - }; - - struct FBufferBarrier - { - FLegacyState LegacyBefore{}; - FLegacyState LegacyAfter{}; - FResAccess AccessBefore{}; - FResAccess AccessAfter{}; - FShaderStageFlags StagesBefore{}; - FShaderStageFlags StagesAfter{}; - FResourceRef Buffer{}; - u64 Offset{}; - u64 Size{}; - }; - - struct FGlobalBarrier - { - FResAccess AccessBefore{}; - FResAccess AccessAfter{}; - FShaderStageFlags StagesBefore{}; - FShaderStageFlags StagesAfter{}; - }; - - enum class FBarrierType : u8 - { - None, - Global, - Buffer, - Image, - }; - - struct FBarrier - { - FBarrierType Type{}; - - union - { - FGlobalBarrier Global; - FBufferBarrier Buffer; - FImageBarrier Image; - }; - }; - - union FBufferRef - { - FResourceRef Buffer; - FUploadLoc Upload; - }; - - enum class FBufferRefType : u8 - { - // GpuBuffer 对象资源引用 - Buffer = 0, - // 当前帧上下文中第几个上传缓冲区 - Upload, - }; - - struct FResolveInfo - { - FResourceRef Src{}; - FResourceRef Dst{}; - FGraphicsFormat Format{}; - FResolveMode Mode{}; - }; - - struct FRenderInfo - { - // 可选 - FResourceRef Dsv{}; - u32 NumRtv{}; - FResourceRef Rtv[8]{}; - // 类型为 FResolveInfo - u32 ResolveInfoIndex[8]{}; - u32 DsvResolveInfoIndex{}; - FGraphicsFormat RtvFormat[8]{}; - FGraphicsFormat DsvFormat{}; - f32 Color[4 * 8]{}; - f32 Depth{}; - u8 Stencil{}; - FLoadOp DsvLoadOp[2]{}; - FStoreOp DsvStoreOp[2]{}; - FLoadOp RtvLoadOp[8]{}; - FStoreOp RtvStoreOp[8]{}; - b8 HasUavWrites{}; - }; - - struct FComputeInfo - { - }; - - struct FBufferRange - { - FResourceRef Buffer{}; - u32 Offset{}; - u32 Size{}; - }; - - struct FVertexBufferRange : FBufferRange - { - u32 Index{}; - }; - - struct FMeshBuffers - { - FMeshLayout* MeshLayout{}; - // 可选 - FBufferRange IndexBuffer{}; - // 0 .. 31 - u32 VertexBufferCount{}; - // Payload 内的索引,类型为 FVertexBufferRange - u32 VertexBuffersIndex{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandBase - { - FCommandType Type{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandLabel : FCommandBase - { - u32 StringIndex{}; - u32 StringLength{}; - FStrType StrType{}; - u8 Color[3]{}; - b8 HasColor{}; - }; - - struct FCommandBeginScope : FCommandBase - { - u32 StringIndex{}; - u32 StringLength{}; - FStrType StrType{}; - u8 Color[3]{}; - b8 HasColor{}; - }; - - struct FCommandEndScope : FCommandBase - { - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandPresent : FCommandBase - { - FResourceRef Image{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandBarrier : FCommandBase - { - // Payload 内的索引,类型为 FBarrier - u32 BarrierIndex{}; - u32 BarrierCount{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandClearColor : FCommandBase - { - // 有多少个 Rect - u32 RectCount{}; - // Payload 内的索引 - u32 RectIndex{}; - FResourceRef Image{}; - f32 Color[4]{}; - }; - - struct FCommandClearDepthStencil : FCommandBase - { - // 有多少个 Rect - u32 RectCount{}; - // Payload 内的索引, 类型为 FRect - u32 RectIndex{}; - FResourceRef Image{}; - f32 Depth{}; - u8 Stencil{}; - FDepthStencilClearFlags Clear{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandBind : FCommandBase - { - // 有多少个绑定修改 - u32 ItemCount{}; - // Payload 内的索引, 类型为 FBindItem - u32 ItemsIndex{}; - // 要修改的绑定集 - FShaderBinding* Binding{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandBufferCopy : FCommandBase - { - // 类型为 FBufferCopyRange - u32 RangeIndex{}; - FBufferRef Dst{}; - FBufferRef Src{}; - FBufferRefType DstType{}; - FBufferRefType SrcType{}; - }; - - struct FCommandBufferImageCopy : FCommandBase - { - // 类型为 FBufferImageCopyRange - u32 RangeIndex{}; - FResourceRef Image; - FBufferRef Buffer{}; - FBufferRefType BufferType{}; - // false 为 Buffer To Image - b8 ImageToBuffer{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandRender : FCommandBase - { - // 类型为 FRenderInfo - u32 InfoIndex{}; - u32 CommandStartIndex{}; - u32 CommandCount{}; - }; - - struct FCommandCompute : FCommandBase - { - // 类型为 FComputeInfo - u32 InfoIndex{}; - u32 CommandStartIndex{}; - u32 CommandCount{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandSetPipeline : FCommandBase - { - FShaderPipeline* Pipeline{}; - }; - - struct FCommandSetBinding : FCommandBase - { - FShaderBinding* Binding{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandSetViewportScissor : FCommandBase - { - // 有多少个 Viewport - u32 ViewportCount{}; - // Payload 内的索引 - u32 ViewportIndex{}; - // 有多少个 Rect - u32 ScissorRectCount{}; - // Payload 内的索引, 类型为 FRect - u32 ScissorRectIndex{}; - }; - - struct FCommandSetMeshBuffers : FCommandBase - { - FGraphicsFormat IndexFormat{}; - // 0 .. 31 - u32 VertexStartSlot{}; - // 类型为 FMeshBuffers - u32 PayloadIndex{}; - }; - - struct FCommandDraw : FCommandBase - { - u32 VertexOrIndexCount{}; - u32 InstanceCount{}; - u32 FirstVertexOrIndex{}; - u32 FirstInstance{}; - // 仅 Indexed 使用 - u32 VertexOffset{}; - b8 Indexed{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandDispatch : FCommandBase - { - u32 GroupCountX{}; - u32 GroupCountY{}; - u32 GroupCountZ{}; - FDispatchType Type{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - enum class FBindingSyncType : u8 - { - Transient, - Persistent, - }; - - struct FCommandSyncBinding : FCommandBase - { - u32 Index{}; - FBindingSyncType Type{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandItem - { - union - { - FCommandType Type{}; - - FCommandLabel Label; - FCommandBeginScope BeginScope; - FCommandEndScope EndScope; - - FCommandPresent Present; - - FCommandBarrier Barrier; - - FCommandClearColor ClearColor; - FCommandClearDepthStencil ClearDepthStencil; - - FCommandBind Bind; - - FCommandBufferCopy BufferCopy; - FCommandBufferImageCopy BufferImageCopy; - - FCommandRender Render; - FCommandCompute Compute; - - FCommandSyncBinding SyncBinding; - - u8 _pad[32]; - }; - }; - - struct FRenderCommandItem - { - union - { - FCommandType Type{}; - - FCommandLabel Label; - FCommandBeginScope BeginScope; - FCommandEndScope EndScope; - - FCommandSetPipeline SetPipeline; - FCommandSetBinding SetBinding; - - FCommandSetViewportScissor SetViewportScissor; - FCommandSetMeshBuffers SetMeshBuffers; - FCommandDraw Draw; - - FCommandDispatch Dispatch; - - FCommandSyncBinding SyncBinding; - - u8 _pad[32]; - }; - }; - - struct FComputeCommandItem - { - union - { - FCommandType Type{}; - - FCommandLabel Label; - FCommandBeginScope BeginScope; - FCommandEndScope EndScope; - - FCommandSetPipeline SetPipeline; - FCommandSetBinding SetBinding; - - FCommandDispatch Dispatch; - - FCommandSyncBinding SyncBinding; - - u8 _pad[32]; - }; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - struct FCommandSubmit - { - FCommandItem* Commands{}; - FRenderCommandItem* RenderCommands{}; - FComputeCommandItem* ComputeCommands{}; - FResourceMeta* Resources{}; - FRenderInfo* RenderInfos{}; - FComputeInfo* ComputeInfos{}; - FResolveInfo* ResolveInfos{}; - FRect* Rects{}; - FViewport* Viewports{}; - FMeshBuffers* MeshBuffers{}; - FVertexBufferRange* VertexBufferRanges{}; - FBufferCopyRange* BufferCopyRanges{}; - FBufferImageCopyRange* BufferImageCopyRanges{}; - FBindItem* BindItems{}; - FBarrier* Barriers{}; - Char8* Str8{}; - Char16* Str16{}; - u32 CommandCount{}; - u32 ResourceCount{}; - u32 SyncBindingCount{}; - u32 GrowingResourceBindingCapacity{}; - u32 GrowingSamplerBindingCapacity{}; - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - #ifdef FFI_SRC - - inline FResourceMeta& FResourceRef::Get(const FCommandSubmit& submit) const - { - return submit.Resources[ResourceIndex - 1]; - } - - #endif -} diff --git a/Coplt.Graphics.Native/Api/FFI/Context.h b/Coplt.Graphics.Native/Api/FFI/Context.h index c070f54..c8f2d8e 100644 --- a/Coplt.Graphics.Native/Api/FFI/Context.h +++ b/Coplt.Graphics.Native/Api/FFI/Context.h @@ -14,13 +14,6 @@ namespace Coplt u64 size{}; }; - COPLT_INTERFACE_DEFINE(FFrameContext, "3a22de68-8377-4e57-a167-3efdb97c102a", FGpuObject) - { - FList m_upload_buffer{}; - - virtual FResult GrowUploadBuffer(u64 min_required_size) noexcept = 0; - }; - COPLT_INTERFACE_DEFINE(FFrameContext2, "fa9c7561-ab0b-4311-bb4c-c6bef93f86fe", FGpuObject) { }; diff --git a/Coplt.Graphics.Native/Api/FFI/Device.h b/Coplt.Graphics.Native/Api/FFI/Device.h index f500517..f485e05 100644 --- a/Coplt.Graphics.Native/Api/FFI/Device.h +++ b/Coplt.Graphics.Native/Api/FFI/Device.h @@ -77,7 +77,6 @@ namespace Coplt // d3d12 返回 ID3D12Device* virtual void* GetRawDevice() noexcept = 0; - virtual FResult CreateMainQueue(const FMainQueueCreateOptions& options, FGpuQueue** out) noexcept = 0; virtual FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FMainQueueCreateResult& out) noexcept = 0; virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModule** out) noexcept = 0; diff --git a/Coplt.Graphics.Native/Api/FFI/Isolate.h b/Coplt.Graphics.Native/Api/FFI/Isolate.h index a2b1593..41f4488 100644 --- a/Coplt.Graphics.Native/Api/FFI/Isolate.h +++ b/Coplt.Graphics.Native/Api/FFI/Isolate.h @@ -1,6 +1,7 @@ #pragma once #include "GpuObject.h" +#include "Output.h" #include "Queue.h" namespace Coplt diff --git a/Coplt.Graphics.Native/Api/FFI/Output.h b/Coplt.Graphics.Native/Api/FFI/Output.h index 0ca7d43..e9e9414 100644 --- a/Coplt.Graphics.Native/Api/FFI/Output.h +++ b/Coplt.Graphics.Native/Api/FFI/Output.h @@ -1,10 +1,7 @@ #pragma once #include "Executor.h" -#include "GpuObject.h" -#include "States.h" #include "GraphicsFormat.h" -#include "Resource.h" namespace Coplt { @@ -29,46 +26,6 @@ namespace Coplt Float16, }; - struct FGpuOutputFromSwapChainCreateOptions - { - b8 VSync{}; - }; - - struct FGpuOutputCreateOptions - { - FStr8or16 Name{}; - u32 Width{}; - u32 Height{}; - // 是否使用 srgb,实现可以选择忽略 - b8 Srgb{}; - // 是否使用 hdr,实现可以选择忽略 - FHdrType Hdr{}; - // 呈现模式,实现可以选择忽略 - FPresentMode PresentMode{}; - FOutputAlphaMode AlphaMode{}; - b8 VSync{}; - }; - - using WhenDoneFn = void COPLT_CDECL(void* obj); - - struct FCommandSubmit; - - COPLT_INTERFACE_DEFINE(FGpuOutput, "f1c59cb4-7ee6-4ee2-80f4-07cc568920d2", FGpuExecutor) - { - FResState m_state{}; - // 外部不允许修改 - FGraphicsFormat m_format{}; - // 外部不允许修改 - u32 m_width{}; - // 外部不允许修改 - u32 m_height{}; - - // 设置垂直同步,实现可以选择忽略 - virtual FResult SetVSync(b8 Enable) noexcept = 0; - - virtual FResult Resize(u32 Width, u32 Height) noexcept = 0; - }; - struct FGpuOutputData { FGraphicsFormat Format{}; diff --git a/Coplt.Graphics.Native/Api/FFI/PipelineState.h b/Coplt.Graphics.Native/Api/FFI/PipelineState.h index cd5dd7a..9917e50 100644 --- a/Coplt.Graphics.Native/Api/FFI/PipelineState.h +++ b/Coplt.Graphics.Native/Api/FFI/PipelineState.h @@ -3,6 +3,7 @@ #include "Common.h" #include "GraphicsFormat.h" #include "String.h" +#include "Structs.h" namespace Coplt { diff --git a/Coplt.Graphics.Native/Api/FFI/Queue.h b/Coplt.Graphics.Native/Api/FFI/Queue.h index 82414d8..72d3427 100644 --- a/Coplt.Graphics.Native/Api/FFI/Queue.h +++ b/Coplt.Graphics.Native/Api/FFI/Queue.h @@ -1,18 +1,10 @@ #pragma once #include "GpuObject.h" -#include "Output.h" -#include "Command.h" #include "Context.h" namespace Coplt { - struct FMainQueueCreateOptions - { - // 可选 - FStr8or16 Name{}; - }; - enum class FGpuQueueType : u8 { Direct, @@ -34,38 +26,6 @@ namespace Coplt VideoProcess = 1 << 5, }; - COPLT_INTERFACE_DEFINE(FGpuQueue, "95e60e28-e387-4055-9b33-2d23af901f8a", FGpuObject) - { - // 不安全的内存暴露,外部不能修改,每帧必须保证当前指向可用的帧上下文 - FFrameContext* m_context{}; - // 不安全的内存暴露,外部不能修改,每次提交都会增加计数 - u64 m_submit_id{}; - // 不安全的内存暴露,外部不能修改 - FGpuQueueType m_queue_type{}; - - // d3d12 返回 ID3D12CommandQueue* - virtual void* GetRawQueue() noexcept = 0; - - // swapchain:d3d12 为 IDXGISwapChain3* - virtual FResult CreateOutputFromRawSwapchain( - const FGpuOutputFromSwapChainCreateOptions& options, - void* swapchain, - FGpuOutput** out - ) noexcept = 0; - - // 在非 windows 平台调用会报错 - virtual FResult CreateOutputForHwnd( - const FGpuOutputCreateOptions& options, - void* hwnd, - FGpuOutput** out - ) noexcept = 0; - - // 提交命令并等待执行器可用 - virtual FResult Submit(FGpuExecutor* Executor, const FCommandSubmit* submit) noexcept = 0; - // 提交命令但是不等待执行器可用,必须先等待才能重新使用此执行器提交 - virtual FResult SubmitNoWait(FGpuExecutor* Executor, const FCommandSubmit* submit) noexcept = 0; - }; - struct FGpuQueueData { FGpuQueueType QueueType{}; diff --git a/Coplt.Graphics.Native/D3d12/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index d8a2905..7d1e6f8 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -14,12 +14,9 @@ add_library(${target_name} SHARED FFI/Queue.h Src/Queue.cc Src/Queue.h - FFI/Output.h Src/Output.cc Src/Output.h Include/GraphicsFormat.h - Src/Command.cc - Src/Command.h FFI/Pipeline.h Src/GraphicsPipeline.h Src/GraphicsPipeline.cc @@ -28,7 +25,6 @@ add_library(${target_name} SHARED Src/Layout.cc Include/ShaderVisibility.h Include/PipelineState.h - Src/CmdListPack.h Src/Buffer.h Src/Buffer.cc FFI/Resource.h @@ -43,7 +39,6 @@ add_library(${target_name} SHARED Src/DescriptorManager.h Src/DescriptorManager.cc Include/View.h - Src/Executor.h FFI/Adapter.h Src/Adapter.h Src/Adapter.cc diff --git a/Coplt.Graphics.Native/D3d12/FFI/Output.h b/Coplt.Graphics.Native/D3d12/FFI/Output.h deleted file mode 100644 index e6dce0f..0000000 --- a/Coplt.Graphics.Native/D3d12/FFI/Output.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "../../Api/FFI/Output.h" - -namespace Coplt -{ - COPLT_INTERFACE_DEFINE(FD3d12GpuOutput, "8d068a07-118c-4d1b-9ab0-384576b61897", FGpuOutput) - { - //out 是 ID3D12Resource** - virtual FResult GetCurrentResourcePtr(void* out) const noexcept = 0; - // out 是 D3D12_CPU_DESCRIPTOR_HANDLE* - virtual FResult GetCurrentRtv(void* out) noexcept = 0; - }; - - COPLT_INTERFACE_DEFINE(FD3d12GpuSwapChainOutput, "5ee90a8d-8c3d-48ad-915e-87f3d28dabe7", FD3d12GpuOutput) - { - }; -} diff --git a/Coplt.Graphics.Native/D3d12/FFI/Queue.h b/Coplt.Graphics.Native/D3d12/FFI/Queue.h index 99252d5..b0b84ec 100644 --- a/Coplt.Graphics.Native/D3d12/FFI/Queue.h +++ b/Coplt.Graphics.Native/D3d12/FFI/Queue.h @@ -4,11 +4,6 @@ namespace Coplt { - COPLT_INTERFACE_DEFINE(FD3d12GpuQueue, "11a59db3-49d8-4158-a276-5d80fd37d85f", FGpuQueue) - { - - }; - COPLT_INTERFACE_DEFINE(FD3d12GpuQueue2, "43fe03f5-0b12-43e3-8550-2c7f82bf5224", FGpuQueue2) { diff --git a/Coplt.Graphics.Native/D3d12/Include/GraphicsFormat.h b/Coplt.Graphics.Native/D3d12/Include/GraphicsFormat.h index cfb6961..afeb6bd 100644 --- a/Coplt.Graphics.Native/D3d12/Include/GraphicsFormat.h +++ b/Coplt.Graphics.Native/D3d12/Include/GraphicsFormat.h @@ -2,7 +2,6 @@ #include -#include "../../Api/FFI/Command.h" #include "../../Api/FFI/GraphicsFormat.h" namespace Coplt diff --git a/Coplt.Graphics.Native/D3d12/Include/PipelineState.h b/Coplt.Graphics.Native/D3d12/Include/PipelineState.h index acc3813..c30c924 100644 --- a/Coplt.Graphics.Native/D3d12/Include/PipelineState.h +++ b/Coplt.Graphics.Native/D3d12/Include/PipelineState.h @@ -3,7 +3,6 @@ #include #include "../../Api/FFI/PipelineState.h" -#include "../../Api/FFI/Command.h" namespace Coplt { diff --git a/Coplt.Graphics.Native/D3d12/Src/CmdListPack.h b/Coplt.Graphics.Native/D3d12/Src/CmdListPack.h deleted file mode 100644 index 6045cb0..0000000 --- a/Coplt.Graphics.Native/D3d12/Src/CmdListPack.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include - -#include "../Include/Utils.h" - -namespace Coplt -{ - struct CmdListPack final - { - ComPtr m_list0{}; - ComPtr m_list1{}; - ComPtr m_list2{}; - ComPtr m_list3{}; - ComPtr m_list4{}; - ComPtr m_list5{}; - ComPtr m_list6{}; - ComPtr m_list7{}; - ComPtr m_list8{}; - ComPtr m_list9{}; - ComPtr m_list10{}; - - CmdListPack() = default; - - explicit CmdListPack(ComPtr&& list) noexcept : m_list0(std::move(list)) - { - m_list0->QueryInterface(&m_list1); - m_list0->QueryInterface(&m_list2); - m_list0->QueryInterface(&m_list3); - m_list0->QueryInterface(&m_list4); - m_list0->QueryInterface(&m_list5); - m_list0->QueryInterface(&m_list6); - m_list0->QueryInterface(&m_list7); - m_list0->QueryInterface(&m_list8); - m_list0->QueryInterface(&m_list9); - m_list0->QueryInterface(&m_list10); - } - - ID3D12GraphicsCommandList* operator->() const noexcept - { - return m_list0.Get(); - } - - ID3D12GraphicsCommandList& operator*() const noexcept - { - return *m_list0.Get(); - } - }; -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Command.cc b/Coplt.Graphics.Native/D3d12/Src/Command.cc deleted file mode 100644 index 5fb7889..0000000 --- a/Coplt.Graphics.Native/D3d12/Src/Command.cc +++ /dev/null @@ -1,1138 +0,0 @@ -#include "Command.h" -#include "../../Api/FFI/Command.h" - -#include - -#include "Binding.h" -#include "Context.h" -#include "DescriptorManager.h" -#include "fmt/format.h" -#include "fmt/xchar.h" - -#include "Queue.h" -#include "../FFI/Layout.h" -#include "../FFI/Output.h" -#include "../FFI/Pipeline.h" -#include "../FFI/Resource.h" -#include "../Include/GraphicsFormat.h" -#include "../Include/PipelineState.h" -#include "../ThirdParty/DirectXTK12/Src/d3dx12.h" - -#include "pix3.h" -#include "../FFI/Binding.h" - -using namespace Coplt; - -void D3d12CommandInterpreter::BarrierContext::Reset() -{ - m_groups_count = 0; - m_global_barriers.clear(); - m_texture_barriers.clear(); - m_buffer_barriers.clear(); -} - -void D3d12CommandInterpreter::BarrierContext::Add(const D3D12_GLOBAL_BARRIER& barrier) -{ - m_global_barriers.push_back(barrier); -} - -void D3d12CommandInterpreter::BarrierContext::Add(const D3D12_TEXTURE_BARRIER& barrier) -{ - m_texture_barriers.push_back(barrier); -} - -void D3d12CommandInterpreter::BarrierContext::Add(const D3D12_BUFFER_BARRIER& barrier) -{ - m_buffer_barriers.push_back(barrier); -} - -namespace -{ - template - constexpr void AddBarrierGroup( - D3D12_BARRIER_GROUP (&barrier_groups)[3], - i32& groups_count, std::vector& barriers - ) - { - const auto index = groups_count; - groups_count++; - D3D12_BARRIER_GROUP group{}; - group.Type = Type; - group.NumBarriers = barriers.size(); - if constexpr (Type == D3D12_BARRIER_TYPE_GLOBAL) - { - group.pGlobalBarriers = barriers.data(); - } - else if constexpr (Type == D3D12_BARRIER_TYPE_TEXTURE) - { - group.pTextureBarriers = barriers.data(); - } - else if constexpr (Type == D3D12_BARRIER_TYPE_BUFFER) - { - group.pBufferBarriers = barriers.data(); - } - else static_assert(false); - // ReSharper disable once CppSomeObjectMembersMightNotBeInitialized - barrier_groups[index] = group; - } -} - -void D3d12CommandInterpreter::BarrierContext::BuildBarriers() -{ - if (!m_global_barriers.empty()) - AddBarrierGroup(m_barrier_groups, m_groups_count, m_global_barriers); - if (!m_texture_barriers.empty()) - AddBarrierGroup(m_barrier_groups, m_groups_count, m_texture_barriers); - if (!m_buffer_barriers.empty()) - AddBarrierGroup(m_barrier_groups, m_groups_count, m_buffer_barriers); -} - -void D3d12CommandInterpreter::Context::Reset() -{ - Pipeline = nullptr; - Layout = nullptr; - GPipeline = nullptr; - Binding = nullptr; - PipelineChanged = false; - BindingChanged = false; -} - -D3d12CommandInterpreter::D3d12CommandInterpreter(const NonNull& queue) : m_queue(queue) -{ -} - -void D3d12CommandInterpreter::Interpret(const FCommandSubmit& submit) -{ - m_descriptors = m_queue->m_frame_context->m_descriptors.get(); - m_descriptors->InitFrame(submit.GrowingResourceBindingCapacity, submit.GrowingSamplerBindingCapacity); - const auto desc_heaps = m_descriptors->GetDescriptorHeaps(); - m_queue->m_cmd->SetDescriptorHeaps(2, desc_heaps.data()); - - Analyze(submit); - Translate(submit); - - Reset(); - m_descriptors = nullptr; -} - -void D3d12CommandInterpreter::Reset() -{ - m_barrier_context.Reset(); - m_context.Reset(); - m_bindings_contexts.clear(); - m_bindings_items.clear(); -} - -void D3d12CommandInterpreter::Analyze(const FCommandSubmit& submit) -{ - m_bindings_contexts.reserve(submit.SyncBindingCount); - const std::span command_items(submit.Commands, submit.CommandCount); - for (u32 i = 0; i < command_items.size(); i++) - { - const auto& item = command_items[i]; - switch (item.Type) - { - case FCommandType::None: - case FCommandType::Present: - case FCommandType::Label: - case FCommandType::BeginScope: - case FCommandType::EndScope: - case FCommandType::Barrier: - case FCommandType::ClearColor: - case FCommandType::ClearDepthStencil: - case FCommandType::BufferCopy: - case FCommandType::BufferImageCopy: - continue; - - case FCommandType::Bind: - Bind(submit, i, item.Bind); - continue; - case FCommandType::Render: - AnalyzeRender(submit, i, item.Render); - continue; - case FCommandType::Compute: - AnalyzeCompute(submit, i, item.Compute); - continue; - - // subcommands - case FCommandType::SetPipeline: - case FCommandType::SetBinding: - case FCommandType::SetViewportScissor: - case FCommandType::SetMeshBuffers: - case FCommandType::Draw: - case FCommandType::Dispatch: - case FCommandType::SyncBinding: - COPLT_THROW("Sub commands cannot be placed in the main command list"); - } - COPLT_THROW_FMT("Unknown command type {}", static_cast(item.Type)); - } - // m_descriptors->SyncTmp(); -} - -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::AnalyzeRender(const FCommandSubmit& submit, u32 i, const FCommandRender& cmd) -{ - const auto commands = std::span(submit.RenderCommands + cmd.CommandStartIndex, cmd.CommandCount); - for (u32 j = 0; j < commands.size(); j++) - { - const auto& item = commands[j]; - switch (item.Type) - { - case FCommandType::None: - case FCommandType::Label: - case FCommandType::BeginScope: - case FCommandType::EndScope: - case FCommandType::SetViewportScissor: - case FCommandType::SetMeshBuffers: - case FCommandType::Draw: - case FCommandType::Dispatch: - continue; - - case FCommandType::SetPipeline: - SetPipelineContext(item.SetPipeline.Pipeline, i); - continue; - case FCommandType::SetBinding: - SetBindingContext(item.SetBinding.Binding, i); - continue; - case FCommandType::SyncBinding: - AnalyzeSyncBinding(submit, i, item.SyncBinding); - continue; - - case FCommandType::Present: - case FCommandType::Barrier: - case FCommandType::ClearColor: - case FCommandType::ClearDepthStencil: - case FCommandType::Bind: - case FCommandType::BufferCopy: - case FCommandType::BufferImageCopy: - 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::AnalyzeCompute(const FCommandSubmit& submit, u32 i, const FCommandCompute& cmd) -{ - 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: - case FCommandType::Label: - case FCommandType::BeginScope: - case FCommandType::EndScope: - case FCommandType::Dispatch: - continue; - - case FCommandType::SetPipeline: - SetPipelineContext(item.SetPipeline.Pipeline, i); - continue; - case FCommandType::SetBinding: - SetBindingContext(item.SetBinding.Binding, i); - continue; - case FCommandType::SyncBinding: - AnalyzeSyncBinding(submit, i, item.SyncBinding); - 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::BufferImageCopy: - 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::AnalyzeSyncBinding(const FCommandSubmit& submit, u32 i, const FCommandSyncBinding& cmd) -{ - const auto index = cmd.Index; - assert(index == m_bindings_contexts.size()); - m_bindings_contexts.push_back(BindingContext{}); - auto& ctx = m_bindings_contexts.back(); - if (!(m_context.PipelineChanged || m_context.BindingChanged)) return; - if (const auto binding = m_context.Binding.get()) - { - ctx.Index = m_bindings_items.size(); - binding->Update(m_queue); - AllocBindings(binding); - binding->ApplyChange(); - ctx.Count = m_bindings_items.size() - ctx.Index; - } - m_context.PipelineChanged = false; - m_context.BindingChanged = false; -} - -void D3d12CommandInterpreter::AllocBindings(NonNull binding) -{ - const NonNull descriptors = m_descriptors; - const auto layout = binding->Layout(); - const auto classes = layout->GetTableGroups(); - const auto heaps = binding->DescHeaps(); - for (u32 c = 0; c < classes.size(); ++c) - { - const auto& groups = classes[c]; - const auto da = groups.Sampler ? descriptors->SamplerHeap() : descriptors->ResourceHeap(); - for (u32 g = 0; g < groups.Metas.size(); ++g) - { - const auto& heap = heaps[c][g]; - if (!heap) continue; - const auto al = AllocBindingGroup(groups, da, heap); - m_bindings_items.push_back(BindingItem{.c = c, .g = g, .al = al}); - } - } -} - -DescriptorAllocation D3d12CommandInterpreter::AllocBindingGroup( - const ID3d12ShaderLayout::TableGroup& groups, - NonNull da, - const Rc& heap -) -{ - if (groups.Scope == FShaderLayoutGroupScope::Persist) - { - PersistDescriptorAllocation al_place{}; - PersistDescriptorAllocation* al = &al_place; - bool old = true; - da->AllocatePersistent(heap.get(), al, old); - if (!old || al->Version != heap->Version()) - { - al->Version = heap->Version(); - da->Upload(*al, heap); - } - return static_cast(*al); - } - else - { - DescriptorAllocation al_place{}; - DescriptorAllocation* al = &al_place; - da->AllocateTransient(heap->Size(), al); - da->Upload(*al, heap); - // da->StoreTmp(*al, heap); - return *al; - } -} - -void D3d12CommandInterpreter::Translate(const FCommandSubmit& submit) -{ - const std::span command_items(submit.Commands, submit.CommandCount); - for (u32 i = 0; i < command_items.size(); i++) - { - const auto& item = command_items[i]; - switch (item.Type) - { - case FCommandType::None: - case FCommandType::Present: - case FCommandType::Bind: - 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::Barrier: - Barrier(submit, i, item.Barrier); - continue; - case FCommandType::ClearColor: - ClearColor(submit, i, item.ClearColor); - continue; - case FCommandType::ClearDepthStencil: - ClearDepthStencil(submit, i, item.ClearDepthStencil); - continue; - case FCommandType::BufferCopy: - BufferCopy(submit, i, item.BufferCopy); - continue; - case FCommandType::BufferImageCopy: - BufferImageCopy(submit, i, item.BufferImageCopy); - continue; - case FCommandType::Render: - Render(submit, i, item.Render); - continue; - case FCommandType::Compute: - Compute(submit, i, item.Compute); - continue; - - // subcommands - case FCommandType::SetPipeline: - case FCommandType::SetBinding: - case FCommandType::SetViewportScissor: - case FCommandType::SetMeshBuffers: - case FCommandType::Draw: - case FCommandType::Dispatch: - case FCommandType::SyncBinding: - COPLT_THROW("Sub commands cannot be placed in the main command list"); - } - COPLT_THROW_FMT("Unknown command type {}", static_cast(item.Type)); - } -} - -void D3d12CommandInterpreter::Label(const FCommandSubmit& submit, const FCommandLabel& cmd) const -{ - if (!m_queue->m_device->Debug()) return; - auto color = PIX_COLOR_DEFAULT; - if (cmd.HasColor) color = PIX_COLOR(cmd.Color[0], cmd.Color[1], cmd.Color[2]); - if (cmd.StrType == FStrType::Str8) - { - PIXSetMarker(m_queue->m_cmd.m_list0.Get(), color, "%s", reinterpret_cast(submit.Str8 + cmd.StringIndex)); - } - else - { - PIXSetMarker(m_queue->m_cmd.m_list0.Get(), color, L"%s", reinterpret_cast(submit.Str16 + cmd.StringIndex)); - } -} - -void D3d12CommandInterpreter::BeginScope(const FCommandSubmit& submit, const FCommandBeginScope& cmd) const -{ - if (!m_queue->m_device->Debug()) return; - auto color = PIX_COLOR_DEFAULT; - if (cmd.HasColor) color = PIX_COLOR(cmd.Color[0], cmd.Color[1], cmd.Color[2]); - if (cmd.StrType == FStrType::Str8) - { - PIXBeginEvent(m_queue->m_cmd.m_list0.Get(), color, "%s", reinterpret_cast(submit.Str8 + cmd.StringIndex)); - } - else - { - PIXBeginEvent(m_queue->m_cmd.m_list0.Get(), color, L"%s", reinterpret_cast(submit.Str16 + cmd.StringIndex)); - } -} - -void D3d12CommandInterpreter::EndScope(const FCommandSubmit& submit, const FCommandEndScope& cmd) const -{ - if (!m_queue->m_device->Debug()) return; - PIXEndEvent(m_queue->m_cmd.m_list0.Get()); -} - -void D3d12CommandInterpreter::Barrier(const FCommandSubmit& submit, u32 i, const FCommandBarrier& cmd) -{ - m_barrier_context.Reset(); - const std::span barriers = std::span(&submit.Barriers[cmd.BarrierIndex], cmd.BarrierCount); - for (const auto& barrier : barriers) - { - switch (barrier.Type) - { - case FBarrierType::None: - continue; - case FBarrierType::Global: - Barrier(submit, barrier.Global); - continue; - case FBarrierType::Buffer: - Barrier(submit, barrier.Buffer); - continue; - case FBarrierType::Image: - Barrier(submit, barrier.Image); - continue; - default: - COPLT_THROW_FMT("Unknown barrier type {} at command {}", static_cast(barrier.Type), i); - } - } - m_barrier_context.BuildBarriers(); - if (m_barrier_context.m_groups_count == 0) return; - m_queue->m_cmd.m_list7->Barrier(m_barrier_context.m_groups_count, m_barrier_context.m_barrier_groups); -} - -void D3d12CommandInterpreter::Barrier(const FCommandSubmit& submit, const FGlobalBarrier& item) -{ - D3D12_GLOBAL_BARRIER barrier{}; - barrier.AccessBefore = ToDx(item.AccessBefore); - barrier.AccessAfter = ToDx(item.AccessAfter); - barrier.SyncBefore = CalcSync(item.StagesBefore, item.AccessBefore, item.AccessAfter); - barrier.SyncAfter = CalcSync(item.StagesAfter, item.AccessAfter, item.AccessBefore); - m_barrier_context.m_global_barriers.push_back(barrier); -} - -void D3d12CommandInterpreter::Barrier(const FCommandSubmit& submit, const FBufferBarrier& item) -{ - D3D12_BUFFER_BARRIER barrier{}; - barrier.pResource = GetResource(item.Buffer.Get(submit)); - barrier.Offset = item.Offset; - barrier.Size = item.Size; - barrier.AccessBefore = ToDx(item.AccessBefore); - barrier.AccessAfter = ToDx(item.AccessAfter); - barrier.SyncBefore = CalcSync(item.StagesBefore, item.AccessBefore, item.AccessAfter); - barrier.SyncAfter = CalcSync(item.StagesAfter, item.AccessAfter, item.AccessBefore); - m_barrier_context.m_buffer_barriers.push_back(barrier); -} - -void D3d12CommandInterpreter::Barrier(const FCommandSubmit& submit, const FImageBarrier& item) -{ - const auto cross_queue = HasFlags(item.Flags, FImageBarrierFlags::CrossQueue); - D3D12_TEXTURE_BARRIER barrier{}; - barrier.pResource = GetResource(item.Image.Get(submit)); - barrier.Subresources.IndexOrFirstMipLevel = item.SubResourceRange.IndexOrFirstMipLevel; - barrier.Subresources.NumMipLevels = item.SubResourceRange.NumMipLevels; - barrier.Subresources.FirstArraySlice = item.SubResourceRange.FirstArraySlice; - barrier.Subresources.NumArraySlices = item.SubResourceRange.NumArraySlices; - barrier.Subresources.FirstPlane = item.SubResourceRange.FirstPlane; - barrier.Subresources.NumPlanes = item.SubResourceRange.NumPlanes; - barrier.LayoutBefore = ToDx(item.LayoutBefore, cross_queue ? std::nullopt : std::optional(m_queue->m_queue_type)); - barrier.LayoutAfter = ToDx(item.LayoutAfter, cross_queue ? std::nullopt : std::optional(m_queue->m_queue_type)); - barrier.AccessBefore = ToDx(item.AccessBefore); - barrier.AccessAfter = ToDx(item.AccessAfter); - barrier.SyncBefore = CalcSync(item.StagesBefore, item.AccessBefore, item.AccessAfter); - barrier.SyncAfter = CalcSync(item.StagesAfter, item.AccessAfter, item.AccessBefore); - if (HasFlags(item.Flags, FImageBarrierFlags::Discard)) barrier.Flags |= D3D12_TEXTURE_BARRIER_FLAG_DISCARD; - m_barrier_context.m_texture_barriers.push_back(barrier); -} - -void D3d12CommandInterpreter::ClearColor(const FCommandSubmit& submit, u32 i, const FCommandClearColor& cmd) const -{ - const auto rtv = GetRtv(cmd.Image.Get(submit)); - m_queue->m_cmd->ClearRenderTargetView( - rtv, cmd.Color, cmd.RectCount, - cmd.RectCount == 0 ? nullptr : reinterpret_cast(&submit.Rects[cmd.RectIndex]) - ); -} - -void D3d12CommandInterpreter::ClearDepthStencil(const FCommandSubmit& submit, u32 i, const FCommandClearDepthStencil& cmd) const -{ - D3D12_CPU_DESCRIPTOR_HANDLE dsv{}; // todo - D3D12_CLEAR_FLAGS flags{}; - if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Depth)) flags |= D3D12_CLEAR_FLAG_DEPTH; - if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Stencil)) flags |= D3D12_CLEAR_FLAG_STENCIL; - m_queue->m_cmd->ClearDepthStencilView( - dsv, flags, cmd.Depth, cmd.Stencil, cmd.RectCount, - cmd.RectCount == 0 ? nullptr : reinterpret_cast(&submit.Rects[cmd.RectIndex]) - ); -} - -void D3d12CommandInterpreter::BufferCopy(const FCommandSubmit& submit, u32 i, const FCommandBufferCopy& cmd) const -{ - const auto& cmd_pack = m_queue->m_cmd; - const auto& range = submit.BufferCopyRanges[cmd.RangeIndex]; - if (cmd.SrcType == FBufferRefType::Buffer && cmd.DstType == FBufferRefType::Buffer) - { - const auto dst = GetResource(cmd.Dst.Buffer.Get(submit)); - const auto src = GetResource(cmd.Src.Buffer.Get(submit)); - if (range.Size == std::numeric_limits::max()) - { - cmd_pack->CopyResource(dst, src); - } - else - { - cmd_pack->CopyBufferRegion(dst, range.DstOffset, src, range.SrcOffset, range.Size); - } - } - else if (cmd.SrcType == FBufferRefType::Upload && cmd.DstType == FBufferRefType::Buffer) - { - const auto dst = GetResource(cmd.Dst.Buffer.Get(submit)); - if (cmd.Src.Upload.Index >= m_queue->m_frame_context->m_upload_buffers.size()) - COPLT_THROW_FMT("Index out of bounds at command {}", i); - const auto& src_obj = m_queue->m_frame_context->m_upload_buffers[cmd.Src.Upload.Index]; - if (range.SrcOffset + range.Size >= src_obj.m_size) - COPLT_THROW_FMT("Size out of range at command {}", i); - const auto src = src_obj.m_resource.m_resource.Get(); - cmd_pack->CopyBufferRegion(dst, range.DstOffset, src, range.SrcOffset, range.Size); - } - else - { - COPLT_THROW_FMT( - "Unsupported copy combination {{ SrcType = {} DstType = {} }} at command {}", - static_cast(cmd.SrcType), static_cast(cmd.DstType), i - ); - } -} - -void D3d12CommandInterpreter::BufferImageCopy(const FCommandSubmit& submit, u32 i, const FCommandBufferImageCopy& cmd) const -{ - const auto& cmd_pack = m_queue->m_cmd; - const auto& range = submit.BufferImageCopyRanges[cmd.RangeIndex]; - const auto image_obj_may = TryGetImage(cmd.Image.Get(submit)); - if (image_obj_may == nullptr) - COPLT_THROW_FMT("Image is null or resource is not image at command {}", i); - const NonNull image_obj = image_obj_may; - const auto image_data = image_obj->Data(); - const auto IsDsOrYCbCr = IsDepthStencil(image_data->m_format) || IsYCbCr(image_data->m_format); - auto bytes_per_row = range.BytesPerRow; - auto rows_per_image = range.RowsPerImage; - if (bytes_per_row == 0) - { - const auto [block_width, _] = GetBlockDimensions(image_data->m_format); - const auto block_size = GetBlockCopySize(image_data->m_format, IsDsOrYCbCr ? Some(range.Plane) : nullptr); - bytes_per_row = (range.ImageExtent[0] / block_width) * block_size; - bytes_per_row = Aligned256(bytes_per_row); - } - else - { - if (!IsAligned256(bytes_per_row)) - COPLT_THROW_FMT("BytesPerRow must must be a multiple of 256 at command {}", i); - } - if (rows_per_image == 0) - { - if (image_data->m_dimension == FImageDimension::Three) - { - rows_per_image = range.ImageExtent[1] * range.ImageExtent[2]; - } - else - { - rows_per_image = range.ImageExtent[1]; - } - } - if (image_data->m_dimension == FImageDimension::Three) - { - if (range.ImageIndex != 0 || range.ImageCount != 1) - COPLT_THROW_FMT("Image index or count out of range at command {}", i); - } - else - { - if (range.ImageCount < 1 || range.ImageIndex + range.ImageCount > image_data->m_depth_or_length) - COPLT_THROW_FMT("Image index or count out of range at command {}", i); - } - if (IsDepthStencil(image_data->m_format) || IsYCbCr(image_data->m_format)) - { - if (static_cast(range.Plane) >= 2) - COPLT_THROW_FMT("Plane index or count out of range at command {}", i); - } - else - { - if (range.Plane != FImagePlane::All) - COPLT_THROW_FMT("Plane index or count out of range at command {}", i); - } - const auto image = image_obj->GetResourcePtr(); - auto buffer = NonNull::Unchecked(nullptr); - if (cmd.BufferType == FBufferRefType::Buffer) - { - buffer = GetResource(cmd.Buffer.Buffer.Get(submit)); - } - else if (cmd.BufferType == FBufferRefType::Upload) - { - const auto& obj = m_queue->m_frame_context->m_upload_buffers[cmd.Buffer.Upload.Index]; - buffer = obj.m_resource.m_resource.Get(); - } - else - { - COPLT_THROW_FMT("Unknown Buffer Type {} at command {}", static_cast(cmd.BufferType), i); - } - D3D12_TEXTURE_COPY_LOCATION buffer_loc{}; - buffer_loc.pResource = buffer; - buffer_loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; - buffer_loc.PlacedFootprint.Footprint.Format = GetBufferImageCopyFormat(image_data->m_format, range.Plane, IsDsOrYCbCr); - buffer_loc.PlacedFootprint.Footprint.Width = range.ImageExtent[0]; - buffer_loc.PlacedFootprint.Footprint.Height = range.ImageExtent[1]; - buffer_loc.PlacedFootprint.Footprint.Depth = range.ImageExtent[2]; - buffer_loc.PlacedFootprint.Footprint.RowPitch = bytes_per_row; - D3D12_TEXTURE_COPY_LOCATION image_loc{}; - image_loc.pResource = image; - image_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; - const auto image_stride = bytes_per_row * rows_per_image; - for (auto ai = 0u; ai < range.ImageCount; ++ai) - { - buffer_loc.PlacedFootprint.Offset = range.BufferOffset + ai * image_stride; - image_loc.SubresourceIndex = D3D12CalcSubresource( - range.MipLevel, range.ImageIndex + ai, static_cast(range.Plane), - image_data->m_mip_levels, image_data->m_depth_or_length - ); - if (cmd.ImageToBuffer) - { - D3D12_BOX box{}; - box.left = range.ImageOffset[0]; - box.top = range.ImageOffset[1]; - box.front = range.ImageOffset[2]; - box.right = range.ImageOffset[0] + range.ImageExtent[0]; - box.bottom = range.ImageOffset[1] + range.ImageExtent[1]; - box.back = range.ImageOffset[2] + range.ImageExtent[2]; - cmd_pack->CopyTextureRegion( - &buffer_loc, - 0, - 0, - 0, - &image_loc, - &box - ); - } - else - { - cmd_pack->CopyTextureRegion( - &image_loc, - range.ImageOffset[0], - range.ImageOffset[1], - range.ImageOffset[2], - &buffer_loc, - nullptr - ); - } - } -} - -void D3d12CommandInterpreter::Render(const FCommandSubmit& submit, u32 i, const FCommandRender& cmd) -{ - m_context.Reset(); - const auto& info = submit.RenderInfos[cmd.InfoIndex]; - { - auto num_rtv = std::min(info.NumRtv, 8u); - D3D12_RENDER_PASS_RENDER_TARGET_DESC rts[num_rtv]; - D3D12_RENDER_PASS_DEPTH_STENCIL_DESC ds[info.Dsv.IsEmpty() ? 0 : 1]; - if (!info.Dsv.IsEmpty()) - { - const auto& d_load = info.DsvLoadOp[0]; - const auto& d_store = info.DsvStoreOp[0]; - const auto& s_load = info.DsvLoadOp[1]; - const auto& s_store = info.DsvStoreOp[1]; - D3D12_RENDER_PASS_DEPTH_STENCIL_DESC desc{}; - desc.cpuDescriptor = GetDsv(info.Dsv.Get(submit)); - desc.DepthBeginningAccess = ToDx(d_load, [&](D3D12_CLEAR_VALUE& cv) - { - cv.Format = ToDx(info.DsvFormat); - cv.DepthStencil.Depth = info.Depth; - }); - desc.DepthBeginningAccess = ToDx(s_load, [&](D3D12_CLEAR_VALUE& cv) - { - cv.Format = ToDx(info.DsvFormat); - cv.DepthStencil.Stencil = info.Stencil; - }); - desc.DepthEndingAccess = ToDx(d_store, [&](D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS& res) - { - const auto& res_info = submit.ResolveInfos[info.DsvResolveInfoIndex]; - res.Format = ToDx(res_info.Format); - res.pSrcResource = GetResource(res_info.Src.Get(submit)); - res.pDstResource = GetResource(res_info.Dst.Get(submit)); - res.SubresourceCount = 0; - res.ResolveMode = ToDx(res_info.Mode); - }); - desc.StencilEndingAccess = ToDx(s_store, [&](D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS& res) - { - const auto& res_info = submit.ResolveInfos[info.DsvResolveInfoIndex]; - res.Format = ToDx(res_info.Format); - res.pSrcResource = GetResource(res_info.Src.Get(submit)); - res.pDstResource = GetResource(res_info.Dst.Get(submit)); - res.SubresourceCount = 0; - res.ResolveMode = ToDx(res_info.Mode); - }); - ds[0] = desc; - } - for (u32 n = 0; n < num_rtv; ++n) - { - const auto& rtv = info.Rtv[n]; - const auto& load = info.RtvLoadOp[n]; - const auto& store = info.RtvStoreOp[n]; - D3D12_RENDER_PASS_RENDER_TARGET_DESC desc{}; - desc.cpuDescriptor = GetRtv(rtv.Get(submit)); - desc.BeginningAccess = ToDx(load, [&](D3D12_CLEAR_VALUE& cv) - { - cv.Format = ToDx(info.RtvFormat[n]); - cv.Color[0] = info.Color[0]; - cv.Color[1] = info.Color[1]; - cv.Color[2] = info.Color[2]; - cv.Color[3] = info.Color[3]; - }); - desc.EndingAccess = ToDx(store, [&](D3D12_RENDER_PASS_ENDING_ACCESS_RESOLVE_PARAMETERS& res) - { - const auto& res_info = submit.ResolveInfos[info.ResolveInfoIndex[n]]; - res.Format = ToDx(res_info.Format); - res.pSrcResource = GetResource(res_info.Src.Get(submit)); - res.pDstResource = GetResource(res_info.Dst.Get(submit)); - res.SubresourceCount = 0; - res.ResolveMode = ToDx(res_info.Mode); - }); - rts[n] = desc; - } - D3D12_RENDER_PASS_FLAGS flags = D3D12_RENDER_PASS_FLAG_NONE; - if (info.HasUavWrites) flags |= D3D12_RENDER_PASS_FLAG_ALLOW_UAV_WRITES; - m_queue->m_cmd.m_list4->BeginRenderPass(info.NumRtv, rts, info.Dsv.IsEmpty() ? nullptr : ds, flags); - } - const auto commands = std::span(submit.RenderCommands + 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: - SetBindingContext(item.SetBinding.Binding, j); - continue; - case FCommandType::SetViewportScissor: - RenderSetViewportScissor(submit, j, item.SetViewportScissor); - continue; - case FCommandType::SetMeshBuffers: - RenderSetMeshBuffers(submit, j, item.SetMeshBuffers); - continue; - case FCommandType::Draw: - RenderDraw(submit, j, item.Draw); - continue; - case FCommandType::Dispatch: - RenderDispatch(submit, j, item.Dispatch); - continue; - case FCommandType::SyncBinding: - SyncBinding(submit, j, item.SyncBinding); - continue; - - case FCommandType::Present: - case FCommandType::Barrier: - case FCommandType::ClearColor: - case FCommandType::ClearDepthStencil: - case FCommandType::Bind: - case FCommandType::BufferCopy: - case FCommandType::BufferImageCopy: - 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)); - } - { - m_queue->m_cmd.m_list4->EndRenderPass(); - } -} - -void D3d12CommandInterpreter::RenderDraw(const FCommandSubmit& submit, u32 i, const FCommandDraw& cmd) const -{ - if (cmd.Indexed) - { - m_queue->m_cmd->DrawIndexedInstanced(cmd.VertexOrIndexCount, cmd.InstanceCount, cmd.FirstVertexOrIndex, cmd.VertexOffset, cmd.FirstInstance); - } - else - { - m_queue->m_cmd->DrawInstanced(cmd.VertexOrIndexCount, cmd.InstanceCount, cmd.FirstVertexOrIndex, cmd.FirstInstance); - } -} - -void D3d12CommandInterpreter::RenderDispatch(const FCommandSubmit& submit, u32 i, const FCommandDispatch& cmd) const -{ - if (cmd.Type != FDispatchType::Mesh) - COPLT_THROW_FMT("Render only supports DispatchMesh and does not support Dispatch for Compute at command {}", i); - m_queue->m_cmd.m_list6->DispatchMesh(cmd.GroupCountX, cmd.GroupCountY, cmd.GroupCountZ); -} - -void D3d12CommandInterpreter::RenderSetViewportScissor(const FCommandSubmit& submit, u32 i, const FCommandSetViewportScissor& cmd) const -{ - m_queue->m_cmd->RSSetViewports(cmd.ViewportCount, reinterpret_cast(submit.Viewports + cmd.ViewportIndex)); - m_queue->m_cmd->RSSetScissorRects(cmd.ScissorRectCount, reinterpret_cast(submit.Rects + cmd.ScissorRectIndex)); -} - -void D3d12CommandInterpreter::RenderSetMeshBuffers(const FCommandSubmit& submit, u32 i, const FCommandSetMeshBuffers& cmd) const -{ - const auto& cmd_pack = m_queue->m_cmd; - const auto& buffers = submit.MeshBuffers[cmd.PayloadIndex]; - const auto defs = buffers.MeshLayout->GetBuffers(); - const auto vbs = std::span(submit.VertexBufferRanges + buffers.VertexBuffersIndex, buffers.VertexBufferCount); - if (!buffers.IndexBuffer.Buffer.IsEmpty()) - { - const auto resource = GetResource(buffers.IndexBuffer.Buffer.Get(submit)); - D3D12_INDEX_BUFFER_VIEW view{}; - view.BufferLocation = resource->GetGPUVirtualAddress() + buffers.IndexBuffer.Offset; - view.SizeInBytes = buffers.IndexBuffer.Size; - view.Format = ToDx(cmd.IndexFormat); - cmd_pack->IASetIndexBuffer(&view); - } - D3D12_VERTEX_BUFFER_VIEW views[vbs.size()]; - for (u32 j = 0; j < vbs.size(); j++) - { - const auto& range = vbs[j]; - const auto& def = defs[range.Index]; - const auto resource = GetResource(range.Buffer.Get(submit)); - D3D12_VERTEX_BUFFER_VIEW view{}; - view.BufferLocation = resource->GetGPUVirtualAddress() + range.Offset; - view.SizeInBytes = range.Size; - view.StrideInBytes = def.Stride; - views[j] = view; - } - 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: - SetBindingContext(item.SetBinding.Binding, j); - continue; - case FCommandType::Dispatch: - ComputeDispatch(submit, j, item.Dispatch); - continue; - case FCommandType::SyncBinding: - SyncBinding(submit, j, item.SyncBinding); - 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::BufferImageCopy: - 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) const -{ - 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(NonNull pipeline, const u32 i) -{ - if (pipeline == m_context.Pipeline) return; - m_context.Pipeline = pipeline->QueryInterface(); - if (!m_context.Pipeline) - { - COPLT_THROW_FMT( - "Pipeline({:#x}) comes from different backends at cmd {}", - static_cast(pipeline), i - ); - } - m_context.Layout = pipeline->GetLayout()->QueryInterface(); - if (!m_context.Layout) - COPLT_THROW("Shader layout from different backends"); - const auto stages = pipeline->GetStages(); - m_context.GPipeline = nullptr; - if (HasFlags(stages, FShaderStageFlags::Pixel)) - { - m_context.GPipeline = pipeline->QueryInterface(); - if (!m_context.GPipeline) - COPLT_THROW("Pipeline from different backends or pipeline not a graphics pipeline"); - } - m_context.PipelineChanged = true; -} - -void D3d12CommandInterpreter::SetPipeline( - const CmdListPack& cmd_pack, NonNull pipeline, const u32 i -) -{ - if (pipeline == m_context.Pipeline) return; - SetPipelineContext(pipeline, i); - const auto stages = pipeline->GetStages(); - if (HasFlags(stages, FShaderStageFlags::Compute)) - { - cmd_pack->SetComputeRootSignature(static_cast(m_context.Layout->GetRootSignaturePtr())); - } - else if (HasFlags(stages, FShaderStageFlags::Pixel)) - { - const auto& states = m_context.GPipeline->GetGraphicsState(); - cmd_pack->IASetPrimitiveTopology(ToDx(states->Topology)); - cmd_pack->SetGraphicsRootSignature(static_cast(m_context.Layout->GetRootSignaturePtr())); - } - cmd_pack->SetPipelineState(static_cast(m_context.Pipeline->GetPipelineStatePtr())); -} - -void D3d12CommandInterpreter::SetBindingContext(NonNull 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(const FCommandSubmit& submit, u32 i, const FCommandSyncBinding& cmd) -{ - if (!(m_context.PipelineChanged || m_context.BindingChanged)) return; - if (const auto binding = m_context.Binding.get()) - { - const auto& ctx = m_bindings_contexts[cmd.Index]; - std::span items{}; - if (ctx) items = std::span(m_bindings_items.data() + ctx.Index, ctx.Count); - UseBinding(binding, items); - } - m_context.PipelineChanged = false; - m_context.BindingChanged = false; -} - -void D3d12CommandInterpreter::UseBinding(NonNull binding, const std::span items) -{ - const auto has_pixel = HasFlags(m_context.Pipeline->GetStages(), FShaderStageFlags::Pixel); - const auto& cmd_pack = m_queue->m_cmd; - const auto layout = binding->Layout(); - const auto classes = layout->GetTableGroups(); - - for (const auto& item : items) - { - const auto& groups = classes[item.c]; - const auto& meta = groups.Metas[item.g]; - const auto& da = groups.Sampler ? m_descriptors->SamplerHeap() : m_descriptors->ResourceHeap(); - const auto handle = da->GetRemoteHandle(item.al.Offset); - if (has_pixel) cmd_pack->SetGraphicsRootDescriptorTable(meta.RootIndex, handle); - else cmd_pack->SetComputeRootDescriptorTable(meta.RootIndex, handle); - } - - // todo 其他 Root 项 -} - -Ptr D3d12CommandInterpreter::TryGetImage(const FResourceMeta& meta) -{ - return TryGetImage(meta.Output, meta.Type); -} - -Ptr D3d12CommandInterpreter::TryGetImage(NonNull object, FResourceRefType type) -{ - switch (type) - { - case FResourceRefType::Image: - { - const auto image = object->QueryInterface(); - if (!image) - COPLT_THROW("Resources from different backends"); - return image; - } - case FResourceRefType::Buffer: - return nullptr; - case FResourceRefType::Output: - return nullptr; - default: - COPLT_THROW_FMT("Unknown resource ref type {}", static_cast(type)); - } -} - -Ptr D3d12CommandInterpreter::TryGetBuffer(const FResourceMeta& meta) -{ - return TryGetBuffer(meta.Output, meta.Type); -} - -Ptr D3d12CommandInterpreter::TryGetBuffer(NonNull object, FResourceRefType type) -{ - switch (type) - { - case FResourceRefType::Image: - return nullptr; - case FResourceRefType::Buffer: - { - const auto buffer = object->QueryInterface(); - if (!buffer) - COPLT_THROW("Resources from different backends"); - return buffer; - } - case FResourceRefType::Output: - return nullptr; - default: - COPLT_THROW_FMT("Unknown resource ref type {}", static_cast(type)); - } -} - -NonNull D3d12CommandInterpreter::GetResource(const FResourceMeta& meta) -{ - return GetResource(meta.Output, meta.Type); -} - -NonNull D3d12CommandInterpreter::GetResource(NonNull object, FResourceRefType type) -{ - switch (type) - { - case FResourceRefType::Image: - { - const auto image = object->QueryInterface(); - if (!image) - COPLT_THROW("Resources from different backends"); - return image->GetResourcePtr(); - } - case FResourceRefType::Buffer: - { - const auto buffer = object->QueryInterface(); - if (!buffer) - COPLT_THROW("Resources from different backends"); - return buffer->GetResourcePtr(); - } - case FResourceRefType::Output: - { - const auto output = object->QueryInterface(); - if (!output) - COPLT_THROW("Resources from different backends"); - ID3D12Resource* ptr{}; - output->GetCurrentResourcePtr(&ptr).TryThrow(); - return NonNull::Unchecked(ptr); - } - default: - COPLT_THROW_FMT("Unknown resource ref type {}", static_cast(type)); - } -} - -D3D12_CPU_DESCRIPTOR_HANDLE D3d12CommandInterpreter::GetRtv(const FResourceMeta& meta) -{ - switch (meta.Type) - { - case FResourceRefType::Image: - case FResourceRefType::Buffer: - COPLT_THROW("TODO"); - case FResourceRefType::Output: - { - const auto output = meta.Output->QueryInterface(); - if (!output) - COPLT_THROW("The memory may be corrupted"); - D3D12_CPU_DESCRIPTOR_HANDLE rtv{}; - output->GetCurrentRtv(&rtv).TryThrow(); - return rtv; - } - default: - COPLT_THROW_FMT("Unknown resource ref type {}", static_cast(meta.Type)); - } -} - -D3D12_CPU_DESCRIPTOR_HANDLE D3d12CommandInterpreter::GetDsv(const FResourceMeta& meta) -{ - switch (meta.Type) - { - case FResourceRefType::Image: - case FResourceRefType::Buffer: - COPLT_THROW("TODO"); - case FResourceRefType::Output: - COPLT_THROW("Output does not support Dsv usage"); - default: - COPLT_THROW_FMT("Unknown resource ref type {}", static_cast(meta.Type)); - } -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Command.h b/Coplt.Graphics.Native/D3d12/Src/Command.h deleted file mode 100644 index 98ea00d..0000000 --- a/Coplt.Graphics.Native/D3d12/Src/Command.h +++ /dev/null @@ -1,145 +0,0 @@ -#pragma once - -#include - -#include "Binding.h" -#include "../../Api/FFI/States.h" -#include "../../Api/FFI/Command.h" - -#include "../Include/Utils.h" -#include "../Include/States.h" - -#include "CmdListPack.h" -#include "DescriptorManager.h" -#include "Image.h" -#include "../../Api/Include/ChunkedVector.h" -#include "../../Api/Include/ObjectKey.h" -#include "../../Api/Include/Ptr.h" - -namespace Coplt -{ - struct FD3d12GraphicsShaderPipeline; - struct FD3d12ShaderLayout; - struct FD3d12PipelineState; - struct D3d12GpuQueue; - struct DescriptorContext; - struct DescriptorAllocator; - - struct D3d12CommandInterpreter final - { - NonNull m_queue; - - private: - struct BarrierContext - { - D3D12_BARRIER_GROUP m_barrier_groups[3]{}; - i32 m_groups_count = 0; - std::vector m_global_barriers{}; - std::vector m_texture_barriers{}; - std::vector m_buffer_barriers{}; - - void Reset(); - - void Add(const D3D12_GLOBAL_BARRIER& barrier); - void Add(const D3D12_TEXTURE_BARRIER& barrier); - void Add(const D3D12_BUFFER_BARRIER& barrier); - - void BuildBarriers(); - }; - - struct Context - { - Ptr Pipeline{}; - Ptr Layout{}; - // 如果不是图形管线将不会设置 - Ptr GPipeline{}; - - Ptr Binding{}; - - bool PipelineChanged{}; - bool BindingChanged{}; - - void Reset(); - }; - - struct BindingContext - { - u32 Index{COPLT_U32_MAX}; - u32 Count{}; - - operator bool() const { return Index != COPLT_U32_MAX; } - }; - - struct BindingItem - { - u32 c{}; - u32 g{}; - DescriptorAllocation al{}; - }; - - BarrierContext m_barrier_context{}; - Context m_context{}; - Ptr m_descriptors; - std::vector m_bindings_contexts{}; - std::vector m_bindings_items{}; - - public: - explicit D3d12CommandInterpreter(const NonNull& queue); - - void Interpret(const FCommandSubmit& submit); - - private: - void Reset(); - - void Analyze(const FCommandSubmit& submit); - - void Bind(const FCommandSubmit& submit, u32 i, const FCommandBind& cmd) const; - void AnalyzeRender(const FCommandSubmit& submit, u32 i, const FCommandRender& cmd); - void AnalyzeCompute(const FCommandSubmit& submit, u32 i, const FCommandCompute& cmd); - void AnalyzeSyncBinding(const FCommandSubmit& submit, u32 i, const FCommandSyncBinding& cmd); - void AllocBindings(NonNull binding); - DescriptorAllocation AllocBindingGroup( - const ID3d12ShaderLayout::TableGroup& groups, - NonNull da, - const Rc& heap - ); - - void Translate(const FCommandSubmit& submit); - - void Label(const FCommandSubmit& submit, const FCommandLabel& cmd) const; - void BeginScope(const FCommandSubmit& submit, const FCommandBeginScope& cmd) const; - void EndScope(const FCommandSubmit& submit, const FCommandEndScope& cmd) const; - void Barrier(const FCommandSubmit& submit, u32 i, const FCommandBarrier& cmd); - void Barrier(const FCommandSubmit& submit, const FGlobalBarrier& item); - void Barrier(const FCommandSubmit& submit, const FBufferBarrier& item); - void Barrier(const FCommandSubmit& submit, const FImageBarrier& item); - 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 BufferImageCopy(const FCommandSubmit& submit, u32 i, const FCommandBufferImageCopy& 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 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) const; - - void SetPipelineContext(NonNull pipeline, u32 i); - void SetPipeline(const CmdListPack& cmd_pack, NonNull pipeline, u32 i); - - void SetBindingContext(NonNull binding, u32 i); - - void SyncBinding(const FCommandSubmit& submit, u32 i, const FCommandSyncBinding& cmd); - void UseBinding(NonNull binding, std::span items); - - static Ptr TryGetImage(const FResourceMeta& meta); - static Ptr TryGetImage(NonNull object, FResourceRefType type); - static Ptr TryGetBuffer(const FResourceMeta& meta); - static Ptr TryGetBuffer(NonNull object, FResourceRefType type); - static NonNull GetResource(const FResourceMeta& meta); - static NonNull GetResource(NonNull object, FResourceRefType type); - static D3D12_CPU_DESCRIPTOR_HANDLE GetRtv(const FResourceMeta& meta); - static D3D12_CPU_DESCRIPTOR_HANDLE GetDsv(const FResourceMeta& meta); - }; -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.cc b/Coplt.Graphics.Native/D3d12/Src/Context.cc index b20d361..8029ca8 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Context.cc @@ -2,84 +2,6 @@ using namespace Coplt; -D3d12FrameContext::D3d12FrameContext(Rc&& queue) : m_queue(std::move(queue)) -{ - m_device = m_queue->m_device; - m_dx_device = m_queue->m_dx_device; - - m_descriptors = new DescriptorContext(m_dx_device); - - m_upload_buffer = FList(m_device->m_instance->m_allocator.get()); - - chr | m_dx_device->CreateCommandAllocator( - ToDx(m_queue->m_queue_type), IID_PPV_ARGS(&m_command_allocator) - ); - if (m_device->Debug()) - { - chr | m_command_allocator >> SetNameEx(FStr8or16(fmt::format(L"Frame Context ({}) Command Allocator", m_object_id))); - } -} - -FResult D3d12FrameContext::SetName(const FStr8or16& name) noexcept -{ - return feb([&] - { - }); -} - -FResult D3d12FrameContext::GrowUploadBuffer(const u64 min_required_size) noexcept -{ - return feb([&] - { - const auto size = - std::max( - InitUploadBufferSize, - std::max(m_cur_upload_buffer_size * 2, std::bit_ceil(min_required_size)) - ); - m_cur_upload_buffer_index = m_upload_buffers.size(); - m_cur_upload_buffer_size = size; - m_upload_buffers.push_back( - BufferPack(m_device.get(), m_device->m_gpu_allocator.Get(), FCpuAccess::Write, m_cur_upload_buffer_size) - ); - const auto& upload_buffer = m_upload_buffers.back(); - void* mapped_ptr{}; - if (m_device->Debug()) - { - const auto name = fmt::format( - L"Frame Context ({}) Upload Buffer ({})", m_object_id, upload_buffer.m_size - ); - chr | upload_buffer.m_resource.m_resource >> SetNameEx(FStr8or16(name)); - } - constexpr D3D12_RANGE read_range{.Begin = 0, .End = 0}; - chr | upload_buffer.m_resource.m_resource->Map(0, &read_range, &mapped_ptr); - m_upload_buffer.Add(FUploadBufferBlock{ - .mapped_ptr = static_cast(mapped_ptr), - .cur_offset = 0, - .size = upload_buffer.m_size, - }); - }); -} - -void D3d12FrameContext::Recycle() -{ - chr | m_command_allocator->Reset(); - if (!m_upload_buffers.empty()) - { - { - BufferPack last = std::move(m_upload_buffers.back()); - m_upload_buffers.clear(); - m_upload_buffers.push_back(std::move(last)); - m_cur_upload_buffer_index = 0; - } - { - auto last = m_upload_buffer[m_upload_buffer.size() - 1]; - last.cur_offset = 0; - m_upload_buffer.Clear(); - m_upload_buffer.Add(last); - } - } -} - D3d12RecordContext::D3d12RecordContext(NonNull isolate) { m_device = isolate->m_device; diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.h b/Coplt.Graphics.Native/D3d12/Src/Context.h index c116939..5657bd6 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.h +++ b/Coplt.Graphics.Native/D3d12/Src/Context.h @@ -4,7 +4,6 @@ #include "../../Api/FFI/Context.h" #include "../../Api/Include/Object.h" -#include "CmdListPack.h" #include "Device.h" #include "Isolate.h" #include "Queue.h" @@ -12,29 +11,6 @@ namespace Coplt { - struct D3d12FrameContext final : GpuObject - { - constexpr static u64 InitUploadBufferSize = 1024 * 1024; - - Rc m_device{}; - ComPtr m_dx_device{}; - Rc m_queue{}; - ComPtr m_command_allocator{}; - Rc m_descriptors{}; - std::vector m_upload_buffers{}; - usize m_cur_upload_buffer_index{}; - usize m_cur_upload_buffer_size{}; - - explicit D3d12FrameContext(Rc&& queue); - - FResult SetName(const FStr8or16& name) noexcept override; - - FResult GrowUploadBuffer(u64 min_required_size) noexcept override; - - // 回收帧使用的资源,重复使用,需要在队列中等待帧完成后调用 - void Recycle(); - }; - struct D3d12CommandList; struct D3d12RentedCommandList; struct D3d12RentedCommandAllocator; diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 0be659b..53d7f04 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -146,14 +146,6 @@ const Rc& D3d12GpuDevice::GetEmptyMeshLayout() return m_empty_mesh_layout; } -FResult D3d12GpuDevice::CreateMainQueue(const FMainQueueCreateOptions& options, FGpuQueue** out) noexcept -{ - return feb([&] - { - *out = new D3d12GpuQueue(this->CloneThis(), options); - }); -} - FResult D3d12GpuDevice::CreateIsolate(const FGpuIsolateCreateOptions& options, FMainQueueCreateResult& out) noexcept { return feb([&] diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index b2e4043..5f66816 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -46,7 +46,6 @@ namespace Coplt const Rc& GetEmptyLayout(FShaderLayoutFlags flags); const Rc& GetEmptyMeshLayout(); - FResult CreateMainQueue(const FMainQueueCreateOptions& options, FGpuQueue** out) noexcept override; FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FMainQueueCreateResult& out) noexcept override; FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModule** out) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Executor.h b/Coplt.Graphics.Native/D3d12/Src/Executor.h deleted file mode 100644 index dce292c..0000000 --- a/Coplt.Graphics.Native/D3d12/Src/Executor.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "../../Api/FFI/Executor.h" - -namespace Coplt -{ - struct D3d12GpuQueue; - - COPLT_INTERFACE_DEFINE(ID3d12GpuExecutor, "f9b5793d-b6e9-4b7e-8953-5fa07b815010", FGpuExecutor) - { - virtual void Submit(D3d12GpuQueue* Queue, const FCommandSubmit* submit) = 0; - virtual void SubmitNoWait(D3d12GpuQueue* Queue, const FCommandSubmit* submit) = 0; - }; -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Output.cc b/Coplt.Graphics.Native/D3d12/Src/Output.cc index bccf9ff..7d37d56 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Output.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Output.cc @@ -1,367 +1,5 @@ #include "Output.h" -#include "../../Api/Include/AllocObjectId.h" -#include "directx/d3dx12.h" - #include "../Include/GraphicsFormat.h" -#include "../../Api/Include/Error.h" using namespace Coplt; - -D3d12GpuSwapChainOutput::D3d12GpuSwapChainOutput(Rc&& queue) : m_queue(std::move(queue)) -{ - if (m_queue->m_queue_type != FGpuQueueType::Direct) - COPLT_THROW("Cannot create output on a non direct queue."); - - m_device = m_queue->m_device; - m_dx_device = m_queue->m_dx_device; - m_dx_queue = m_queue->m_queue; - - m_state = { - .Access = FResAccess::NoAccess, - .Layout = FResLayout::Present, - .Stages = FShaderStageFlags::None, - .Legacy = FLegacyState::Present, - .CrossQueue = true, - }; -} - -D3d12GpuSwapChainOutput::D3d12GpuSwapChainOutput(Rc&& queue, const FGpuOutputCreateOptions& options) - : D3d12GpuSwapChainOutput(std::move(queue)) -{ - m_v_sync = options.VSync; -} - -void D3d12GpuSwapChainOutput::Init() -{ - m_frame_index = m_swap_chain->GetCurrentBackBufferIndex(); - - D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc{}; - rtv_heap_desc.NumDescriptors = m_frame_count; - rtv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - chr | m_dx_device->CreateDescriptorHeap(&rtv_heap_desc, IID_PPV_ARGS(&m_rtv_heap)); - m_rtv_descriptor_size = m_dx_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - - D3D12_DESCRIPTOR_HEAP_DESC srv_heap_desc{}; - srv_heap_desc.NumDescriptors = m_frame_count; - srv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - srv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - chr | m_dx_device->CreateDescriptorHeap(&srv_heap_desc, IID_PPV_ARGS(&m_srv_heap)); - m_srv_descriptor_size = m_dx_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - - CreateRts(); - - for (u32 i = 0; i < m_frame_count; ++i) - { - m_frame_contexts[i] = new D3d12FrameContext(m_queue->CloneThis()); - } - - chr | m_dx_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)); - m_fence_value = 1; - - m_fence_event = CreateEvent(nullptr, false, false, nullptr); - if (m_fence_event == nullptr) chr | HRESULT_FROM_WIN32(GetLastError()); -} - -D3d12GpuSwapChainOutput::D3d12GpuSwapChainOutput( - Rc&& queue, - const FGpuOutputFromSwapChainCreateOptions& options, - IDXGISwapChain3* swap_chain -) : D3d12GpuSwapChainOutput(std::move(queue)) -{ - m_swap_chain = swap_chain; - m_v_sync = options.VSync; - - DXGI_SWAP_CHAIN_DESC1 desc{}; - chr | m_swap_chain->GetDesc1(&desc); - - m_format = FromDx(desc.Format); - m_width = desc.Width; - m_height = desc.Height; - m_frame_count = desc.BufferCount; - - Init(); -} - -D3d12GpuSwapChainOutput::D3d12GpuSwapChainOutput( - Rc&& queue, - const FGpuOutputCreateOptions& options, const HWND hwnd -) : D3d12GpuSwapChainOutput(std::move(queue), options) -{ - bool is_hdr = false; - m_format = SelectFormat(options, is_hdr); - - DXGI_SWAP_CHAIN_DESC1 desc{}; - desc.Width = m_width = options.Width; - desc.Height = m_height = options.Height; - desc.Format = ToDx(m_format); - desc.SampleDesc.Count = 1; - desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; - switch (options.PresentMode) - { - case FPresentMode::NoBuffer: - if (is_hdr) - { - m_frame_count = desc.BufferCount = 2; - desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - } - else - { - m_frame_count = desc.BufferCount = 2; - desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - } - break; - case FPresentMode::DoubleBuffer: - m_frame_count = desc.BufferCount = 2; - desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - break; - case FPresentMode::TripleBuffer: - default: - m_frame_count = desc.BufferCount = 3; - desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - break; - } - switch (options.AlphaMode) - { - case FOutputAlphaMode::PrePremultiplied: - desc.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; - break; - case FOutputAlphaMode::PostPremultiplied: - desc.AlphaMode = DXGI_ALPHA_MODE_STRAIGHT; - break; - case FOutputAlphaMode::Opaque: - default: - desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; - break; - } - - ComPtr swap_chain; - chr | m_device->m_instance->m_factory->CreateSwapChainForHwnd( - m_dx_queue.Get(), - hwnd, - &desc, - nullptr, - nullptr, - &swap_chain - ); - - chr | swap_chain.As(&m_swap_chain); - - if (m_format == FGraphicsFormat::R10G10B10A2_UNorm) - { - chr | m_swap_chain->SetColorSpace1(DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020); - } - - Init(); -} - -D3d12GpuSwapChainOutput::~D3d12GpuSwapChainOutput() -{ - WaitAll(); - CloseHandle(m_fence_event); -} - -FGraphicsFormat D3d12GpuSwapChainOutput::SelectFormat( - const FGpuOutputCreateOptions& options, bool& is_hdr -) -{ - if (options.Hdr == FHdrType::UNorm10 && options.AlphaMode == FOutputAlphaMode::Opaque) - { - is_hdr = true; - return FGraphicsFormat::R10G10B10A2_UNorm; - } - if (options.Hdr == FHdrType::Float16) - { - is_hdr = true; - return FGraphicsFormat::R16G16B16A16_Float; - } - return FGraphicsFormat::R8G8B8A8_UNorm; -} - -FResult D3d12GpuSwapChainOutput::SetName(const FStr8or16& name) noexcept -{ - return feb([&] - { - // 交换链不能设置名字 - }); -} - -FResult D3d12GpuSwapChainOutput::SetVSync(const b8 Enable) noexcept -{ - return feb([&] - { - m_v_sync = static_cast(Enable); - }); -} - -FResult D3d12GpuSwapChainOutput::Resize(const u32 Width, const u32 Height) noexcept -{ - return feb([&] - { - if (m_waiting || m_need_resize) - { - m_new_width = Width; - m_new_height = Height; - m_need_resize = true; - - std::lock_guard lock(m_queue->m_mutex); - if (m_need_resize) - { - Resize_NoLock(m_new_width, m_new_height); - } - } - else - { - std::lock_guard lock(m_queue->m_mutex); - Resize_NoLock(Width, Height); - } - }); -} - -FResult D3d12GpuSwapChainOutput::Wait() noexcept -{ - return feb([&] - { - std::lock_guard lock(m_queue->m_mutex); - WaitNextFrame_NoLock(); - }); -} - -void D3d12GpuSwapChainOutput::Submit(D3d12GpuQueue* Queue, const FCommandSubmit* submit) -{ - if (Queue != m_queue) - COPLT_THROW("The executor does not belong to this queue"); - std::lock_guard lock(m_queue->m_mutex); - Submit_NoLock(submit); - Present_NoLock(); - WaitNextFrame_NoLock(); -} - -void D3d12GpuSwapChainOutput::SubmitNoWait(D3d12GpuQueue* Queue, const FCommandSubmit* submit) -{ - if (Queue != m_queue) - COPLT_THROW("The executor does not belong to this queue"); - std::lock_guard lock(m_queue->m_mutex); - Submit_NoLock(submit); - Present_NoLock(); -} - -void D3d12GpuSwapChainOutput::Submit_NoLock(const FCommandSubmit* submit) -{ - m_queue->SubmitNoLock(m_frame_contexts[m_frame_index], submit); -} - -void D3d12GpuSwapChainOutput::Present_NoLock() -{ - chr | m_swap_chain->Present(m_v_sync ? 1 : 0, 0); - Signal_NoLock(); -} - -void D3d12GpuSwapChainOutput::WaitNextFrame_NoLock() -{ - if (m_need_resize) - { - Resize_NoLock(m_new_width, m_new_height); - m_need_resize = false; - } - if (m_fence_value_queue.size() >= m_frame_count) - { - const auto fence_value = m_fence_value_queue.front(); - m_fence_value_queue.pop(); - WaitFenceValue_NoLock(fence_value); - } - m_frame_index = m_swap_chain->GetCurrentBackBufferIndex(); - { - const auto fence_value = m_frame_m_fence_values[m_frame_index]; - WaitFenceValue_NoLock(fence_value); - } - m_frame_contexts[m_frame_index]->Recycle(); -} - -void D3d12GpuSwapChainOutput::Resize_NoLock(const u32 width, const u32 height) -{ - if (width == m_width && height == m_height) return; - WaitAll_NoLock(); - for (u32 i = 0; i < m_frame_count; i++) - { - m_buffers[i] = nullptr; - } - chr | m_swap_chain->ResizeBuffers(m_frame_count, width, height, ToDx(m_format), 0); - CreateRts(); - m_frame_index = m_swap_chain->GetCurrentBackBufferIndex(); - m_width = width; - m_height = height; -} - -void D3d12GpuSwapChainOutput::Signal_NoLock() -{ - const auto fence_value = m_fence_value; - chr | m_dx_queue->Signal(m_fence.Get(), fence_value); - m_fence_value_queue.push(fence_value); - m_frame_m_fence_values[m_frame_index] = fence_value; - m_fence_value++; -} - -void D3d12GpuSwapChainOutput::WaitAll() -{ - std::lock_guard lock(m_queue->m_mutex); - WaitAll_NoLock(); -} - -void D3d12GpuSwapChainOutput::WaitAll_NoLock() -{ - Signal_NoLock(); - const auto fence_value = m_fence_value_queue.back(); - m_fence_value_queue = {}; - WaitFenceValue_NoLock(fence_value); -} - -void D3d12GpuSwapChainOutput::WaitFenceValue_NoLock(const u32 fence_value) -{ - if (m_fence->GetCompletedValue() < fence_value) - { - m_waiting = true; - chr | m_fence->SetEventOnCompletion(fence_value, m_fence_event); - WaitForSingleObject(m_fence_event, INFINITE); - m_waiting = false; - } -} - -void D3d12GpuSwapChainOutput::CreateRts() -{ - CD3DX12_CPU_DESCRIPTOR_HANDLE rtv_handle(m_rtv_heap->GetCPUDescriptorHandleForHeapStart()); - CD3DX12_CPU_DESCRIPTOR_HANDLE srv_handle(m_srv_heap->GetCPUDescriptorHandleForHeapStart()); - for (u32 i = 0; i < m_frame_count; ++i) - { - chr | m_swap_chain->GetBuffer(i, IID_PPV_ARGS(&m_buffers[i])); - m_dx_device->CreateRenderTargetView(m_buffers[i].Get(), nullptr, rtv_handle); - rtv_handle.Offset(1, m_rtv_descriptor_size); - m_dx_device->CreateShaderResourceView(m_buffers[i].Get(), nullptr, srv_handle); - srv_handle.Offset(1, m_rtv_descriptor_size); - - if (m_device->Debug()) - { - chr | m_buffers[i]->SetName( - fmt::format(L"Swap Chain Buffer {} ({}, {})", i, m_width, m_height).c_str()); - } - } -} - -FResult D3d12GpuSwapChainOutput::GetCurrentResourcePtr(void* out) const noexcept -{ - return feb([&] - { - *static_cast(out) = m_buffers[m_frame_index].Get(); - }); -} - -FResult D3d12GpuSwapChainOutput::GetCurrentRtv(void* out) noexcept -{ - return feb([&] - { - CD3DX12_CPU_DESCRIPTOR_HANDLE rtv_handle(m_rtv_heap->GetCPUDescriptorHandleForHeapStart()); - rtv_handle.Offset(static_cast(m_frame_index), m_rtv_descriptor_size); - *static_cast(out) = rtv_handle; - }); -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Output.h b/Coplt.Graphics.Native/D3d12/Src/Output.h index 9b4b757..fe135bf 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Output.h +++ b/Coplt.Graphics.Native/D3d12/Src/Output.h @@ -5,88 +5,12 @@ #include #include "Context.h" -#include "Executor.h" -#include "Queue.h" -#include "../FFI/Output.h" -#include "../../Api/Include/Object.h" #include "../Include/ResState.h" namespace Coplt { struct D3d12GpuDevice; - struct D3d12GpuSwapChainOutput final : GpuObject - { - constexpr static UINT MaxBufferCount = 3; - - Rc m_queue{}; - Rc m_device{}; - ComPtr m_dx_device{}; - ComPtr m_dx_queue{}; - ComPtr m_swap_chain{}; - Rc m_frame_contexts[MaxBufferCount]{}; - ComPtr m_rtv_heap{}; - ComPtr m_srv_heap{}; - ComPtr m_buffers[MaxBufferCount]; - ComPtr m_fence{}; - HANDLE m_fence_event{}; - UINT64 m_fence_value{}; - std::queue m_fence_value_queue{}; - UINT m_frame_count{}; - UINT m_frame_index{}; - UINT m_frame_m_fence_values[MaxBufferCount]{}; - UINT m_rtv_descriptor_size{}; - UINT m_srv_descriptor_size{}; - mutable u32 m_new_width{}; - mutable u32 m_new_height{}; - std::atomic_bool m_v_sync{}; - std::atomic_bool m_waiting{}; - std::atomic_bool m_need_resize{}; - - private: - explicit D3d12GpuSwapChainOutput(Rc&& queue); - explicit D3d12GpuSwapChainOutput(Rc&& queue, const FGpuOutputCreateOptions& options); - void Init(); - - public: - explicit D3d12GpuSwapChainOutput( - Rc&& queue, const FGpuOutputFromSwapChainCreateOptions& options, IDXGISwapChain3* swap_chain - ); - explicit D3d12GpuSwapChainOutput(Rc&& queue, const FGpuOutputCreateOptions& options, HWND hwnd); - - ~D3d12GpuSwapChainOutput() override; - - static FGraphicsFormat SelectFormat(const FGpuOutputCreateOptions& options, bool& is_hdr); - - FResult SetName(const FStr8or16& name) noexcept override; - - FResult SetVSync(b8 Enable) noexcept override; - - FResult Resize(u32 Width, u32 Height) noexcept override; - - FResult Wait() noexcept override; - - void Submit(D3d12GpuQueue* Queue, const FCommandSubmit* submit) override; - void SubmitNoWait(D3d12GpuQueue* Queue, const FCommandSubmit* submit) override; - - void Submit_NoLock(/* 可选 */ const FCommandSubmit* submit); - void Present_NoLock(); - void WaitNextFrame_NoLock(); - void Resize_NoLock(u32 width, u32 height); - - void Signal_NoLock(); - - void WaitAll(); - void WaitAll_NoLock(); - - void WaitFenceValue_NoLock(u32 fence_value); - - void CreateRts(); - - FResult GetCurrentResourcePtr(void* out) const noexcept override; - FResult GetCurrentRtv(void* out) noexcept override; - }; - COPLT_INTERFACE_DEFINE(ID3d12GpuOutput2, "59aa68d8-91bd-4032-ba51-6a05795945b6", FGpuOutput2) { virtual NonNull State() = 0; diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.cc b/Coplt.Graphics.Native/D3d12/Src/Queue.cc index 0dff6ba..a061683 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.cc @@ -7,137 +7,6 @@ using namespace Coplt; -D3d12GpuQueue::D3d12GpuQueue( - Rc&& device, - const FMainQueueCreateOptions& options -) : m_device(std::move(device)), m_command_interpreter(this) -{ - m_queue_type = FGpuQueueType::Direct; - - m_dx_device = m_device->m_device; - - constexpr UINT node_mask = 0; - - D3D12_COMMAND_QUEUE_DESC desc{}; - desc.NodeMask = node_mask; - desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; - desc.Type = ToDx(m_queue_type); - desc.Priority = 0; - - chr | m_dx_device->CreateCommandQueue(&desc, IID_PPV_ARGS(&m_queue)); - - m_frame_context = new D3d12FrameContext(CloneThis()); - m_context = m_frame_context.get(); - - ComPtr command_list{}; - chr | m_dx_device->CreateCommandList( - node_mask, desc.Type, m_frame_context->m_command_allocator.Get(), - nullptr, IID_PPV_ARGS(&command_list) - ); - m_cmd = CmdListPack(std::move(command_list)); - - if (m_device->Debug()) - { - chr | m_queue >> SetNameEx(options.Name); - } -} - -FResult D3d12GpuQueue::SetName(const FStr8or16& name) noexcept -{ - return feb([&] - { - if (!m_device->Debug()) return; - chr | m_queue >> SetNameEx(name); - }); -} - -void* D3d12GpuQueue::GetRawQueue() noexcept -{ - return m_queue.Get(); -} - -FResult D3d12GpuQueue::CreateOutputFromRawSwapchain( - const FGpuOutputFromSwapChainCreateOptions& options, - void* swapchain, - FGpuOutput** out -) noexcept -{ - return feb([&] - { - *out = new D3d12GpuSwapChainOutput(this->CloneThis(), options, static_cast(swapchain)); - }); -} - -FResult D3d12GpuQueue::CreateOutputForHwnd( - const FGpuOutputCreateOptions& options, - void* hwnd, - FGpuOutput** out -) noexcept -{ - return feb([&] - { - *out = new D3d12GpuSwapChainOutput(this->CloneThis(), options, static_cast(hwnd)); - }); -} - -D3d12GpuQueue::~D3d12GpuQueue() noexcept -{ - // ReSharper disable once CppFunctionResultShouldBeUsed - m_cmd->Close(); -} - -void D3d12GpuQueue::Submit( - Rc& frame_context, /* 可选 */ const FCommandSubmit* submit -) -{ - std::lock_guard lock(m_mutex); - SubmitNoLock(frame_context, submit); -} - -void D3d12GpuQueue::SubmitNoLock( - Rc& frame_context, /* 可选 */ const FCommandSubmit* submit -) -{ - if (submit == nullptr) - { - chr | m_cmd->Close(); - } - else - { - m_command_interpreter.Interpret(*submit); - chr | m_cmd->Close(); - ID3D12CommandList* command_lists[1] = {m_cmd.m_list0.Get()}; - m_queue->ExecuteCommandLists(1, command_lists); - } - - std::swap(m_frame_context, frame_context); - chr | m_cmd->Reset(m_frame_context->m_command_allocator.Get(), nullptr); - m_context = m_frame_context.get(); - m_submit_id++; -} - -FResult D3d12GpuQueue::Submit(FGpuExecutor* Executor, const FCommandSubmit* submit) noexcept -{ - return feb([&] - { - const auto executor = Executor->QueryInterface(); - if (executor == nullptr) - COPLT_THROW("Executors from different backends"); - executor->Submit(this, submit); - }); -} - -FResult D3d12GpuQueue::SubmitNoWait(FGpuExecutor* Executor, const FCommandSubmit* submit) noexcept -{ - return feb([&] - { - const auto executor = Executor->QueryInterface(); - if (executor == nullptr) - COPLT_THROW("Executors from different backends"); - executor->SubmitNoWait(this, submit); - }); -} - QueueWaitPoint::QueueWaitPoint(Rc&& queue, const u64 fence_value) : m_queue(std::move(queue)), m_fence_value(fence_value) { } diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.h b/Coplt.Graphics.Native/D3d12/Src/Queue.h index 955b15d..5b3686d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -5,60 +5,17 @@ #include "concurrentqueue.h" -#include "CmdListPack.h" #include "Device.h" #include "../Include/Utils.h" #include "../../Api/Include/Object.h" #include "../FFI/Queue.h" -#include "Command.h" #include "DescriptorManager.h" -#include "Executor.h" namespace Coplt { struct D3d12GpuIsolate; struct D3d12FrameContext; - struct D3d12GpuQueue final : GpuObject - { - Rc m_device{}; - ComPtr m_dx_device{}; - ComPtr m_queue{}; - Rc m_frame_context{}; - CmdListPack m_cmd{}; - std::mutex m_mutex{}; - - D3d12CommandInterpreter m_command_interpreter; - - explicit D3d12GpuQueue(Rc&& device, const FMainQueueCreateOptions& options); - - FResult SetName(const FStr8or16& name) noexcept override; - - void* GetRawQueue() noexcept override; - - FResult CreateOutputFromRawSwapchain( - const FGpuOutputFromSwapChainCreateOptions& options, - void* swapchain, - FGpuOutput** out - ) noexcept override; - - FResult CreateOutputForHwnd( - const FGpuOutputCreateOptions& options, - void* hwnd, - FGpuOutput** out - ) noexcept override; - - ~D3d12GpuQueue() noexcept override; - - // 提交命令,并互换帧上下文,参数提供的帧上下文必须可用 - void Submit(Rc& frame_context, /* 可选 */ const FCommandSubmit* submit); - // 提交命令,并互换帧上下文,但是无锁,需要外部手动锁,参数提供的帧上下文必须可用 - void SubmitNoLock(Rc& frame_context, /* 可选 */ const FCommandSubmit* submit); - - FResult Submit(FGpuExecutor* Executor, const FCommandSubmit* submit) noexcept override; - FResult SubmitNoWait(FGpuExecutor* Executor, const FCommandSubmit* submit) noexcept override; - }; - inline D3D12_COMMAND_LIST_TYPE ToDx(const FGpuQueueType value) { switch (value) diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 89ddf7d..c81ba53 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -2,10 +2,13 @@ #include -#include "Output.h" #include "../FFI/Pipeline.h" #include "../Include/GraphicsFormat.h" #include "../Include/PipelineState.h" +#include "../Include/States.h" +#include "Output.h" +#include "Image.h" +#include "Buffer.h" using namespace Coplt; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index f618652..4a20e78 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -5,9 +5,12 @@ #include "Isolate.h" #include "../../Api/FFI/Record.h" #include "../../Api/Include/GpuObject.h" +#include "../FFI/Pipeline.h" +#include "../FFI/Layout.h" namespace Coplt { + struct FD3d12PipelineState; COPLT_INTERFACE_DEFINE(ID3d12GpuRecord, "57a9c7f9-1ec0-4d78-89b9-e547667c50b3", FGpuRecord) { virtual FGpuRecordData* Data() noexcept = 0; diff --git a/Examples/HelloTriangleVertex/Example.cs b/Examples/HelloTriangleVertex/Example.cs index 21c2656..abc8d5a 100644 --- a/Examples/HelloTriangleVertex/Example.cs +++ b/Examples/HelloTriangleVertex/Example.cs @@ -52,14 +52,14 @@ protected override async Task LoadResources(GpuRecord cmd) } }, MeshLayout, Name: Name ); - PositionColorBuffer = Device.CreateBuffer( + PositionColorBuffer = Isolate.CreateBuffer( new() { Purpose = ResourcePurpose.VertexBuffer, Size = sizeof(float) * 4 * 6, }, "Position and Color" ); - UvBuffer = Device.CreateBuffer( + UvBuffer = Isolate.CreateBuffer( new() { Purpose = ResourcePurpose.VertexBuffer, From 4cbb0606712ace688e2ede97fc98b6e12aca2b78 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 1 Apr 2025 16:54:32 +0800 Subject: [PATCH 27/46] save --- Coplt.Graphics.Core/Core/GpuAdapter.cs | 6 +- Coplt.Graphics.Core/Core/GpuDevice.cs | 94 +-- Coplt.Graphics.Core/Core/GpuImage.cs | 2 - Coplt.Graphics.Core/Core/GpuIsolate.cs | 4 +- Coplt.Graphics.Core/Core/GpuRecord.cs | 14 +- Coplt.Graphics.Core/Core/GraphicsInstance.cs | 6 +- .../Core/GraphicsShaderPipeline.cs | 28 +- Coplt.Graphics.Core/Core/MeshLayout.cs | 62 +- Coplt.Graphics.Core/Core/Shader.cs | 53 +- Coplt.Graphics.Core/Core/ShaderInputLayout.cs | 61 +- Coplt.Graphics.Core/Core/ShaderLayout.cs | 64 +- Coplt.Graphics.Core/Core/ShaderModule.cs | 53 +- Coplt.Graphics.Core/Core/ShaderPipeline.cs | 58 +- Coplt.Graphics.Core/Native/Native.cs | 568 +++++++++--------- Coplt.Graphics.Native/Api/FFI/Adapter.h | 2 +- Coplt.Graphics.Native/Api/FFI/Context.h | 4 - Coplt.Graphics.Native/Api/FFI/Device.h | 14 +- Coplt.Graphics.Native/Api/FFI/Features.h | 2 + Coplt.Graphics.Native/Api/FFI/Instance.h | 4 +- Coplt.Graphics.Native/Api/FFI/Isolate.h | 11 +- Coplt.Graphics.Native/Api/FFI/Shader.h | 48 +- Coplt.Graphics.Native/Api/Src/Shader.cc | 44 +- Coplt.Graphics.Native/Api/Src/Shader.h | 8 +- Coplt.Graphics.Native/D3d12/Src/Adapter.cc | 5 +- Coplt.Graphics.Native/D3d12/Src/Adapter.h | 2 +- Coplt.Graphics.Native/D3d12/Src/Device.cc | 37 +- Coplt.Graphics.Native/D3d12/Src/Device.h | 9 +- .../D3d12/Src/GraphicsPipeline.cc | 26 +- Coplt.Graphics.Native/D3d12/Src/Instance.cc | 4 +- Coplt.Graphics.Native/D3d12/Src/Instance.h | 2 +- Examples/ExampleBase/ExampleBase.cs | 2 +- Examples/HelloTriangleVertex/Example.cs | 4 +- 32 files changed, 561 insertions(+), 740 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuAdapter.cs b/Coplt.Graphics.Core/Core/GpuAdapter.cs index ba4b878..37c3f33 100644 --- a/Coplt.Graphics.Core/Core/GpuAdapter.cs +++ b/Coplt.Graphics.Core/Core/GpuAdapter.cs @@ -77,9 +77,9 @@ public GpuDevice CreateDevice( { Name = new(Name, Name8, p_name, p_name8), }; - FGpuDevice* ptr; - m_ptr->CreateDevice(&f_options, &ptr).TryThrow(); - return new(ptr, Instance, this, Name); + FGpuDeviceCreateResult result; + m_ptr->CreateDevice(&f_options, &result).TryThrow(); + return new(result, Instance, this, Name); } } diff --git a/Coplt.Graphics.Core/Core/GpuDevice.cs b/Coplt.Graphics.Core/Core/GpuDevice.cs index ed8e530..8400eaa 100644 --- a/Coplt.Graphics.Core/Core/GpuDevice.cs +++ b/Coplt.Graphics.Core/Core/GpuDevice.cs @@ -17,6 +17,10 @@ public sealed unsafe partial class GpuDevice : GpuObject internal readonly GraphicsInstance m_instance; internal readonly GpuAdapter m_adapter; + [Drop] + internal readonly GpuIsolate? m_main_isolate; + [Drop] + internal readonly GpuIsolate? m_copy_isolate; #endregion @@ -25,16 +29,23 @@ public sealed unsafe partial class GpuDevice : GpuObject public new FGpuDevice* Ptr => (FGpuDevice*)m_ptr; public GraphicsInstance Instance => m_instance; public GpuAdapter Adapter => m_adapter; + public GpuIsolate MainIsolate => m_main_isolate!; + public GpuIsolate? CopyIsolate => m_copy_isolate; #endregion #region Ctor - internal GpuDevice(FGpuDevice* ptr, GraphicsInstance instance, GpuAdapter? adapter, string? name) : base((FGpuObject*)ptr, name) + internal GpuDevice(FGpuDeviceCreateResult result, GraphicsInstance instance, GpuAdapter? adapter, string? name) : base((FGpuObject*)result.Device, name) { m_instance = instance; m_name = name; m_adapter = adapter ?? m_instance.m_ptr_to_adapters[(nuint)Ptr->GetAdapter()]; + m_main_isolate = new GpuIsolate(result.MainIsolate.Isolate, result.MainIsolate.Data, null, this); + if (result.CopyIsolate.Isolate != null) + { + m_copy_isolate = new GpuIsolate(result.CopyIsolate.Isolate, result.CopyIsolate.Data, null, this); + } } #endregion @@ -56,10 +67,17 @@ internal GpuDevice(FGpuDevice* ptr, GraphicsInstance instance, GpuAdapter? adapt public GpuIsolate CreateIsolate(string? Name = null, ReadOnlySpan Name8 = default) { - FGpuIsolateCreateOptions f_options = new(); - FMainQueueCreateResult f_result; - Ptr->CreateIsolate(&f_options, &f_result).TryThrow(); - return new GpuIsolate(f_result.Isolate, null, this, f_result.Data); + fixed (char* p_name = Name) + fixed (byte* p_name8 = Name8) + { + FGpuIsolateCreateOptions f_options = new() + { + Name = new(Name, Name8, p_name, p_name8), + }; + FGpuIsolateCreateResult f_result; + Ptr->CreateIsolate(&f_options, &f_result).TryThrow(); + return new GpuIsolate(f_result.Isolate, f_result.Data, null, this); + } } #endregion @@ -84,9 +102,9 @@ public ShaderModule CreateShaderModule( Size = (nuint)Blob.Length, Stage = Stage.ToFFI(), }; - FShaderModule* ptr; - Ptr->CreateShaderModule(&f_options, &ptr).TryThrow(); - return new(ptr, Name, EntryPoint); + FShaderModuleCreateResult result; + Ptr->CreateShaderModule(&f_options, &result).TryThrow(); + return new(result, EntryPoint, Name, this); } } @@ -115,7 +133,7 @@ public ShaderLayout CreateShaderLayout( }; FShaderLayout* ptr; Ptr->CreateShaderLayout(&f_options, &ptr).TryThrow(); - return new(ptr, Name); + return new(ptr, Name, this); } } } @@ -132,7 +150,7 @@ public ShaderLayout GetEmptyShaderLayout(ShaderLayoutFlags Flags = ShaderLayoutF }; FShaderLayout* ptr; self.Ptr->GetEmptyShaderLayout(&f_options, &ptr).TryThrow(); - return new(ptr, $"Empty Shader Layout ({flags})"); + return new(ptr, $"Empty Shader Layout ({flags})", self); }, this ); @@ -186,7 +204,7 @@ public ShaderInputLayout CreateShaderInputLayout( }; FShaderInputLayout* ptr; Ptr->CreateShaderInputLayout(&f_options, &ptr).TryThrow(); - return new(ptr, meta, Name); + return new(ptr, meta, Name, this); } } @@ -214,7 +232,7 @@ public Shader CreateShader( { var module = Modules[i]; arr[i] = module; - p_modules[i] = module.m_ptr; + p_modules[i] = module.Ptr; } fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) @@ -222,14 +240,14 @@ public Shader CreateShader( FShaderCreateOptions f_options = new() { Name = new(Name, Name8, p_name, p_name8), - Layout = Layout == null ? null : Layout.m_ptr, - InputLayout = InputLayout == null ? null : InputLayout.m_ptr, + Layout = Layout == null ? null : Layout.Ptr, + InputLayout = InputLayout == null ? null : InputLayout.Ptr, Modules = p_modules, Count = (byte)Modules.Length, }; - FShader* ptr; - Ptr->CreateShader(&f_options, &ptr).TryThrow(); - return new(ptr, arr, Layout, InputLayout, Name); + FShaderCreateResult result; + Ptr->CreateShader(&f_options, &result).TryThrow(); + return new(result, arr, Layout, InputLayout, Name, this); } } @@ -258,7 +276,7 @@ public MeshLayout CreateMeshLayout( }; FMeshLayout* ptr; Ptr->CreateMeshLayout(&f_options, &ptr).TryThrow(); - return new(ptr, Name); + return new(ptr, Name, this); } } @@ -279,36 +297,36 @@ public GraphicsShaderPipeline CreateGraphicsShaderPipeline( Base = new() { Name = new(Name, Name8, p_name, p_name8), - Shader = Shader.m_ptr, + Shader = Shader.Ptr, }, - MeshLayout = MeshLayout == null ? null : MeshLayout.m_ptr, + MeshLayout = MeshLayout == null ? null : MeshLayout.Ptr, GraphicsState = PipelineState.ToFFI(), }; FGraphicsShaderPipeline* ptr; Ptr->CreateGraphicsPipeline(&f_options, &ptr).TryThrow(); return new(ptr, Name, Shader, PipelineState, MeshLayout); } - } + } + + #endregion + + #region CreateBuffer + + public GpuBuffer CreateBuffer( + in GpuBufferCreateOptions options, + string? Name = null, ReadOnlySpan Name8 = default + ) => MainIsolate.CreateBuffer(in options, Name, Name8); #endregion - // #region CreateBuffer - // - // public GpuBuffer CreateBuffer( - // in GpuBufferCreateOptions options, - // string? Name = null, ReadOnlySpan Name8 = default - // ) => MainQueue.CreateBuffer(in options, Name, Name8); - // - // #endregion - // - // #region CreateImage - // - // public GpuImage CreateImage( - // in GpuImageCreateOptions options, - // string? Name = null, ReadOnlySpan Name8 = default - // ) => MainQueue.CreateImage(in options, Name, Name8); - // - // #endregion + #region CreateImage + + public GpuImage CreateImage( + in GpuImageCreateOptions options, + string? Name = null, ReadOnlySpan Name8 = default + ) => MainIsolate.CreateImage(in options, Name, Name8); + + #endregion #region CreateSampler diff --git a/Coplt.Graphics.Core/Core/GpuImage.cs b/Coplt.Graphics.Core/Core/GpuImage.cs index 097476c..fd2406e 100644 --- a/Coplt.Graphics.Core/Core/GpuImage.cs +++ b/Coplt.Graphics.Core/Core/GpuImage.cs @@ -144,6 +144,4 @@ m_name is null public bool TrySrv() => Purpose.HasFlags(ResourcePurpose.ShaderResource); #endregion - - public GpuIsolate Isolate => throw new NotImplementedException(); } diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 5ec9a5e..029e84c 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -25,7 +25,7 @@ public sealed unsafe partial class GpuIsolate : DeviceChild #region Props public new FGpuIsolate* Ptr => (FGpuIsolate*)m_ptr; - internal ref readonly FGpuIsolateData Data => ref *m_data; + public ref readonly FGpuIsolateData Data => ref *m_data; public GpuIsolateConfig Config => new(ref *Data.Config); public FrameId FrameId => new(Data.FrameId); @@ -33,7 +33,7 @@ public sealed unsafe partial class GpuIsolate : DeviceChild #region Ctor - internal GpuIsolate(FGpuIsolate* ptr, string? name, GpuDevice device, FGpuIsolateData* data) + internal GpuIsolate(FGpuIsolate* ptr, FGpuIsolateData* data, string? name, GpuDevice device) : base((FGpuObject*)ptr, name, device) { m_data = data; diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index a118cf5..2d3ef41 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -436,7 +436,7 @@ public void Upload( ) { AssertNotEnded(); - // Dst.AssertSameIsolate(Isolate); // todo + Dst.AssertSameIsolate(Isolate); if (Data.Length == 0) return; var Size = Math.Min(Dst.Size, (uint)Data.Length); var src = WriteToUpload(Data); @@ -467,7 +467,7 @@ public void Upload( ) { AssertNotEnded(); - // Dst.AssertSameIsolate(Isolate); // todo + Dst.AssertSameIsolate(Isolate); if (Loc.RecordId != Data.Id) throw new ArgumentException("Cannot use UploadLoc different GpuRecord"); if (Loc.RecordVersion != Data.Version) @@ -849,7 +849,7 @@ public void SetPipeline(ShaderPipeline Pipeline) var cmd = new FCmdSetPipeline { Base = { Type = FCmdType.SetPipeline }, - Pipeline = Pipeline.m_ptr, + Pipeline = Pipeline.Ptr, }; self.Data.Commands.Add(new() { SetPipeline = cmd }); } @@ -915,12 +915,12 @@ ReadOnlySpan VertexBuffers }; var buf = new FMeshBuffers2 { - MeshLayout = MeshLayout.m_ptr, + MeshLayout = MeshLayout.Ptr, VertexBufferCount = (uint)VertexBuffers.Length, }; if (IndexBuffer is { } index_buffer) { - // index_buffer.Buffer.AssertSameIsolate(self.Isolate); // todo + index_buffer.Buffer.AssertSameIsolate(self.Isolate); buf.IndexBuffer = new() { Buffer = self.AddResource(index_buffer.Buffer.Resource), @@ -936,7 +936,7 @@ ReadOnlySpan VertexBuffers for (var i = 0; i < VertexBuffers.Length; i++) { var buffer = VertexBuffers[i]; - // buffer.Buffer.AssertSameIsolate(self.Isolate); // todo + buffer.Buffer.AssertSameIsolate(self.Isolate); ref var dst = ref vbs[i]; dst = new() { @@ -1137,7 +1137,7 @@ public void SetPipeline(ShaderPipeline Pipeline) var cmd = new FCmdSetPipeline { Base = { Type = FCmdType.SetPipeline }, - Pipeline = Pipeline.m_ptr, + Pipeline = Pipeline.Ptr, }; self.Data.Commands.Add(new() { SetPipeline = cmd }); } diff --git a/Coplt.Graphics.Core/Core/GraphicsInstance.cs b/Coplt.Graphics.Core/Core/GraphicsInstance.cs index 35075bd..c02b28a 100644 --- a/Coplt.Graphics.Core/Core/GraphicsInstance.cs +++ b/Coplt.Graphics.Core/Core/GraphicsInstance.cs @@ -337,9 +337,9 @@ public GpuDevice CreateDevice( }, }, }; - FGpuDevice* ptr; - m_ptr->CreateDevice(&f_options, &ptr).TryThrow(); - return new(ptr, this, null, Name); + FGpuDeviceCreateResult result; + m_ptr->CreateDevice(&f_options, &result).TryThrow(); + return new(result, this, null, Name); } } diff --git a/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs b/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs index c7a8759..bab5486 100644 --- a/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs +++ b/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs @@ -1,15 +1,12 @@ -using Coplt.Dropping; -using Coplt.Graphics.Native; +using Coplt.Graphics.Native; using Coplt.Graphics.States; namespace Coplt.Graphics.Core; -[Dropping(Unmanaged = true)] -public sealed unsafe partial class GraphicsShaderPipeline : ShaderPipeline +public sealed unsafe class GraphicsShaderPipeline : ShaderPipeline { #region Fields - internal new FGraphicsShaderPipeline* m_ptr; internal readonly MeshLayout? m_mesh_layout; internal readonly GraphicsPipelineState m_pipeline_state; @@ -17,7 +14,7 @@ public sealed unsafe partial class GraphicsShaderPipeline : ShaderPipeline #region Props - public new FGraphicsShaderPipeline* Ptr => m_ptr; + public new FGraphicsShaderPipeline* Ptr => (FGraphicsShaderPipeline*)m_ptr; public MeshLayout? MeshLayout => m_mesh_layout; public ref readonly GraphicsPipelineState PipelineState => ref m_pipeline_state; @@ -28,28 +25,11 @@ public sealed unsafe partial class GraphicsShaderPipeline : ShaderPipeline internal GraphicsShaderPipeline( FGraphicsShaderPipeline* ptr, string? name, Shader shader, GraphicsPipelineState pipeline_state, MeshLayout? mesh_layout - ) : base(ptr == null ? null : (FShaderPipeline*)ptr, name, shader) + ) : base((FShaderPipeline*)ptr, name, shader) { - m_ptr = ptr; m_mesh_layout = mesh_layout; m_pipeline_state = pipeline_state; } #endregion - - #region Drop - - [Drop] - private void Drop() => m_ptr = null; - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(GraphicsShaderPipeline)}(0x{(nuint)m_ptr:X})" - : $"{nameof(GraphicsShaderPipeline)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion } diff --git a/Coplt.Graphics.Core/Core/MeshLayout.cs b/Coplt.Graphics.Core/Core/MeshLayout.cs index 82702e4..3d20862 100644 --- a/Coplt.Graphics.Core/Core/MeshLayout.cs +++ b/Coplt.Graphics.Core/Core/MeshLayout.cs @@ -1,5 +1,4 @@ -using Coplt.Dropping; -using Coplt.Graphics.Native; +using Coplt.Graphics.Native; namespace Coplt.Graphics.Core; @@ -59,13 +58,10 @@ public enum MeshBufferElementRate : byte Instance, } -[Dropping(Unmanaged = true)] -public sealed unsafe partial class MeshLayout +public sealed unsafe class MeshLayout : DeviceChild { #region Fields - internal FMeshLayout* m_ptr; - internal string? m_name; internal readonly FMeshBufferDefine* m_native_buffers; internal readonly FMeshBufferElement* m_native_elements; internal readonly uint m_native_buffers_count; @@ -75,7 +71,7 @@ public sealed unsafe partial class MeshLayout #region Props - public FMeshLayout* Ptr => m_ptr; + public new FMeshLayout* Ptr => (FMeshLayout*)m_ptr; public ReadOnlySpan Buffers => new(m_native_buffers, (int)m_native_buffers_count); public ReadOnlySpan Elements => new(m_native_elements, (int)m_native_elements_count); @@ -83,68 +79,22 @@ public sealed unsafe partial class MeshLayout #region Ctor - internal MeshLayout(FMeshLayout* ptr, string? name) + internal MeshLayout(FMeshLayout* ptr, string? name, GpuDevice device) : base((FGpuObject*)ptr, name, device) { - m_ptr = ptr; - m_name = name; if (m_ptr != null) { { uint count; - m_native_buffers = m_ptr->GetBuffers(&count); + m_native_buffers = ptr->GetBuffers(&count); m_native_buffers_count = count; } { uint count; - m_native_elements = m_ptr->GetElements(&count); + m_native_elements = ptr->GetElements(&count); m_native_elements_count = count; } } } #endregion - - #region Drop - - [Drop] - private void Drop() - { - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); - } - - #endregion - - #region SetName - - public void SetName(string name) - { - m_name = name; - fixed (char* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(MeshLayout)}(0x{(nuint)m_ptr:X})" - : $"{nameof(MeshLayout)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion } diff --git a/Coplt.Graphics.Core/Core/Shader.cs b/Coplt.Graphics.Core/Core/Shader.cs index 7980f1f..f347f92 100644 --- a/Coplt.Graphics.Core/Core/Shader.cs +++ b/Coplt.Graphics.Core/Core/Shader.cs @@ -5,12 +5,11 @@ namespace Coplt.Graphics.Core; [Dropping(Unmanaged = true)] -public sealed unsafe partial class Shader +public sealed unsafe partial class Shader : DeviceChild { #region Fields - internal FShader* m_ptr; - internal string? m_name; + internal FShaderData* m_data; internal readonly ShaderLayout? m_layout; internal readonly ShaderInputLayout? m_input_layout; internal ShaderModuleArray m_modules; @@ -25,11 +24,12 @@ internal struct ShaderModuleArray #region Props - public FShader* Ptr => m_ptr; + public new FShader* Ptr => (FShader*)m_ptr; + public ref readonly FShaderData Data => ref *m_data; public ShaderLayout? Layout => m_layout; public ShaderInputLayout? InputLayout => m_input_layout; public ReadOnlySpan Modules => m_modules; - public ShaderStageFlags Stages => m_ptr->Stages.FromFFI(); + public ShaderStageFlags Stages => Data.Stages.FromFFI(); public ShaderModule? Compute => (Stages & ShaderStageFlags.Compute) != 0 ? m_modules[0] : null; public ShaderModule? Pixel => (Stages & ShaderStageFlags.Pixel) != 0 ? m_modules[0] : null; @@ -42,14 +42,13 @@ internal struct ShaderModuleArray #region Ctor internal Shader( - FShader* ptr, ShaderModuleArray modules, ShaderLayout? layout, ShaderInputLayout? input_layout, string? name - ) + FShaderCreateResult result, ShaderModuleArray modules, ShaderLayout? layout, ShaderInputLayout? input_layout, string? name, GpuDevice device + ) : base((FGpuObject*)result.Shader, name, device) { - m_ptr = ptr; + m_data = result.Data; m_modules = modules; m_layout = layout; m_input_layout = input_layout; - m_name = name; } #endregion @@ -59,42 +58,8 @@ internal Shader( [Drop] private void Drop() { - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); + m_data = null; } #endregion - - #region SetName - - public void SetName(string name) - { - m_name = name; - fixed (char* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(Shader)}(0x{(nuint)m_ptr:X})" - : $"{nameof(Shader)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion } diff --git a/Coplt.Graphics.Core/Core/ShaderInputLayout.cs b/Coplt.Graphics.Core/Core/ShaderInputLayout.cs index de6491b..b1091da 100644 --- a/Coplt.Graphics.Core/Core/ShaderInputLayout.cs +++ b/Coplt.Graphics.Core/Core/ShaderInputLayout.cs @@ -1,5 +1,4 @@ -using Coplt.Dropping; -using Coplt.Graphics.Native; +using Coplt.Graphics.Native; using Coplt.Graphics.Utilities; namespace Coplt.Graphics.Core; @@ -79,13 +78,10 @@ public record struct ShaderInputLayoutElementMeta public uint Location; } -[Dropping(Unmanaged = true)] -public sealed unsafe partial class ShaderInputLayout +public sealed unsafe class ShaderInputLayout : DeviceChild { #region Fields - internal FShaderInputLayout* m_ptr; - internal string? m_name; internal readonly ShaderInputLayoutElementMeta[] m_elements; internal readonly FShaderInputLayoutElement* m_native_elements; internal readonly uint m_native_elements_count; @@ -94,7 +90,7 @@ public sealed unsafe partial class ShaderInputLayout #region Props - public FShaderInputLayout* Ptr => m_ptr; + public new FShaderInputLayout* Ptr => (FShaderInputLayout*)m_ptr; public ReadOnlySpan Elements => m_elements; public ReadOnlySpan NativeElements => new(m_native_elements, (int)m_native_elements_count); @@ -103,62 +99,17 @@ public sealed unsafe partial class ShaderInputLayout #region Ctor - internal ShaderInputLayout(FShaderInputLayout* ptr, ShaderInputLayoutElementMeta[] elements, string? name) + internal ShaderInputLayout(FShaderInputLayout* ptr, ShaderInputLayoutElementMeta[] elements, string? name, GpuDevice device) + : base((FGpuObject*)ptr, name, device) { - m_ptr = ptr; - m_name = name; m_elements = elements; if (m_ptr != null) { uint count; - m_native_elements = m_ptr->GetElements(&count); + m_native_elements = ptr->GetElements(&count); m_native_elements_count = count; } } #endregion - - #region Drop - - [Drop] - private void Drop() - { - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); - } - - #endregion - - #region SetName - - public void SetName(string name) - { - m_name = name; - fixed (char* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(ShaderInputLayout)}(0x{(nuint)m_ptr:X})" - : $"{nameof(ShaderInputLayout)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion } diff --git a/Coplt.Graphics.Core/Core/ShaderLayout.cs b/Coplt.Graphics.Core/Core/ShaderLayout.cs index 8d7d9f3..876d3d8 100644 --- a/Coplt.Graphics.Core/Core/ShaderLayout.cs +++ b/Coplt.Graphics.Core/Core/ShaderLayout.cs @@ -1,5 +1,4 @@ using System.Diagnostics; -using Coplt.Dropping; using Coplt.Graphics.Native; namespace Coplt.Graphics.Core; @@ -105,13 +104,10 @@ public enum ShaderLayoutFlags : byte StreamOutput = 1 << 2, } -[Dropping(Unmanaged = true)] -public sealed unsafe partial class ShaderLayout +public sealed unsafe class ShaderLayout : DeviceChild { #region Fields - 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; @@ -120,7 +116,7 @@ public sealed unsafe partial class ShaderLayout #region Props - public FShaderLayout* Ptr => m_ptr; + public new FShaderLayout* Ptr => (FShaderLayout*)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; @@ -129,73 +125,27 @@ public sealed unsafe partial class ShaderLayout #region Ctor - internal ShaderLayout(FShaderLayout* ptr, string? name) + internal ShaderLayout(FShaderLayout* ptr, string? name, GpuDevice device) : base((FGpuObject*)ptr, name, device) { - m_ptr = ptr; - m_name = name; - if (m_ptr != null) + if (ptr != null) { { uint count = 0; - var defines = m_ptr->GetItemDefines(&count); + var defines = ptr->GetItemDefines(&count); m_native_defines = new(defines, count); } { uint count = 0; - var defines = m_ptr->GetItemInfos(&count); + var defines = ptr->GetItemInfos(&count); m_native_item_infos = new(defines, count); } { uint count = 0; - var defines = m_ptr->GetGroupClasses(&count); + var defines = ptr->GetGroupClasses(&count); m_native_group_classes = new(defines, count); } } } #endregion - - #region Drop - - [Drop] - private void Drop() - { - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); - } - - #endregion - - #region SetName - - public void SetName(string name) - { - m_name = name; - fixed (char* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(ShaderLayout)}(0x{(nuint)m_ptr:X})" - : $"{nameof(ShaderLayout)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion } diff --git a/Coplt.Graphics.Core/Core/ShaderModule.cs b/Coplt.Graphics.Core/Core/ShaderModule.cs index 0d931e4..b3bda17 100644 --- a/Coplt.Graphics.Core/Core/ShaderModule.cs +++ b/Coplt.Graphics.Core/Core/ShaderModule.cs @@ -5,30 +5,31 @@ namespace Coplt.Graphics.Core; [Dropping(Unmanaged = true)] -public sealed unsafe partial class ShaderModule +public sealed unsafe partial class ShaderModule : DeviceChild { #region Fields - internal FShaderModule* m_ptr; - internal string? m_name; + internal FShaderModuleData* m_data; internal readonly String8? m_entry_point; #endregion #region Props - public FShaderModule* Ptr => m_ptr; - public ShaderStage Stage => m_ptr->Stage.FromFFI(); + public new FShaderModule* Ptr => (FShaderModule*)m_ptr; + public ref readonly FShaderModuleData Data => ref *m_data; + public ShaderStage Stage => Data.Stage.FromFFI(); public String8? EntryPoint => m_entry_point; + public FSlice Blob => new(Data.Data, Data.Size); #endregion #region Ctor - internal ShaderModule(FShaderModule* ptr, string? name, String8? entry_point) + internal ShaderModule(FShaderModuleCreateResult result, String8? entry_point, string? name, GpuDevice device) + : base((FGpuObject*)result.ShaderModule, name, device) { - m_ptr = ptr; - m_name = name; + m_data = result.Data; m_entry_point = entry_point; } @@ -39,42 +40,8 @@ internal ShaderModule(FShaderModule* ptr, string? name, String8? entry_point) [Drop] private void Drop() { - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); + m_data = null; } #endregion - - #region SetName - - public void SetName(string name) - { - m_name = name; - fixed (char* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(ShaderModule)}(0x{(nuint)m_ptr:X}) {{ Stage = {Stage} }}" - : $"{nameof(ShaderModule)}(0x{(nuint)m_ptr:X} \"{m_name}\") {{ Stage = {Stage} }}"; - - #endregion } diff --git a/Coplt.Graphics.Core/Core/ShaderPipeline.cs b/Coplt.Graphics.Core/Core/ShaderPipeline.cs index 31d0055..744fb1c 100644 --- a/Coplt.Graphics.Core/Core/ShaderPipeline.cs +++ b/Coplt.Graphics.Core/Core/ShaderPipeline.cs @@ -1,78 +1,28 @@ -using Coplt.Dropping; -using Coplt.Graphics.Native; +using Coplt.Graphics.Native; namespace Coplt.Graphics.Core; -[Dropping(Unmanaged = true)] -public abstract unsafe partial class ShaderPipeline +public abstract unsafe class ShaderPipeline : DeviceChild { #region Fields - internal FShaderPipeline* m_ptr; - internal string? m_name; internal readonly Shader m_shader; #endregion #region Props - public FShaderPipeline* Ptr => m_ptr; + public new FShaderPipeline* Ptr => (FShaderPipeline*)m_ptr; public Shader Shader => m_shader; #endregion #region Ctor - internal ShaderPipeline(FShaderPipeline* ptr, string? name, Shader shader) + internal ShaderPipeline(FShaderPipeline* ptr, string? name, Shader shader) : base((FGpuObject*)ptr, name, shader.Device) { - m_ptr = ptr; - m_name = name; m_shader = shader; } #endregion - - #region Drop - - [Drop] - private void Drop() - { - if (ExchangeUtils.ExchangePtr(ref m_ptr, null, out var ptr) is null) return; - ptr->Release(); - } - - #endregion - - #region SetName - - public void SetName(string name) - { - m_name = name; - fixed (char* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - public void SetName(ReadOnlySpan name) - { - m_name = null; - fixed (byte* ptr = name) - { - FStr8or16 str = new(ptr, name.Length); - m_ptr->SetName(&str).TryThrow(); - } - } - - #endregion - - #region ToString - - public override string ToString() => - m_name is null - ? $"{nameof(ShaderPipeline)}(0x{(nuint)m_ptr:X})" - : $"{nameof(ShaderPipeline)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; - - #endregion } diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 6621884..45690fe 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -864,10 +864,10 @@ public B8 IsSupport([NativeTypeName("const FDeviceRequires &")] FDeviceRequires* [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateDevice([NativeTypeName("const FGpuDeviceCreateOptions &")] FGpuDeviceCreateOptions* options, FGpuDevice** @out) + public FResult CreateDevice([NativeTypeName("const FGpuDeviceCreateOptions &")] FGpuDeviceCreateOptions* options, [NativeTypeName("Coplt::FGpuDeviceCreateResult *")] FGpuDeviceCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuAdapter*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuAdapter*)Unsafe.AsPointer(ref this), &result, options, @out); } public interface Interface : FUnknown.Interface @@ -876,7 +876,7 @@ public interface Interface : FUnknown.Interface B8 IsSupport([NativeTypeName("const FDeviceRequires &")] FDeviceRequires* Requires); [return: NativeTypeName("Coplt::FResult")] - FResult CreateDevice([NativeTypeName("const FGpuDeviceCreateOptions &")] FGpuDeviceCreateOptions* options, FGpuDevice** @out); + FResult CreateDevice([NativeTypeName("const FGpuDeviceCreateOptions &")] FGpuDeviceCreateOptions* options, [NativeTypeName("Coplt::FGpuDeviceCreateResult *")] FGpuDeviceCreateResult* @out); } } @@ -897,211 +897,20 @@ public partial struct FGpuAutoSelectDeviceCreateOptions public FDeviceRequires Requires; } - public partial struct FGpuDevice + public partial struct FGpuDeviceCreateResult { } - [Guid("557F032D-ED50-403A-ADC5-214FDDBE6C6B")] - [NativeTypeName("struct FGpuDevice : Coplt::FGpuObject")] - public unsafe partial struct FGpuDevice : FGpuDevice.Interface, INativeGuid + public unsafe partial struct FGpuDeviceCreateResult { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuDevice)); - - public void** lpVtbl; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuDevice*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuDevice*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuDevice*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuDevice*)Unsafe.AsPointer(ref this), id); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuDevice*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, name); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuAdapter *")] - public FGpuAdapter* GetAdapter() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuDevice*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* GetRawDevice() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuDevice*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &")] FGpuIsolateCreateOptions* options, [NativeTypeName("Coplt::FMainQueueCreateResult &")] FMainQueueCreateResult* @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, FShaderModule** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, FShaderLayout** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, FShaderLayout** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, FShader** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions &")] FMeshLayoutCreateOptions* options, FMeshLayout** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[16]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } + [NativeTypeName("Coplt::FGpuDevice *")] + public FGpuDevice* Device; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] FGpuBufferCreateOptions* options, FGpuBuffer** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[17]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } + [NativeTypeName("Coplt::FGpuIsolateCreateResult")] + public FGpuIsolateCreateResult MainIsolate; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FGpuImageCreateOptions* options, FGpuImage** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[18]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateSampler([NativeTypeName("const FGpuSamplerCreateOptions &")] FGpuSamplerCreateOptions* options, FGpuSampler** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - public interface Interface : FGpuObject.Interface - { - [return: NativeTypeName("Coplt::FGpuAdapter *")] - FGpuAdapter* GetAdapter(); - - void* GetRawDevice(); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &")] FGpuIsolateCreateOptions* options, [NativeTypeName("Coplt::FMainQueueCreateResult &")] FMainQueueCreateResult* @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, FShaderModule** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, FShaderLayout** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, FShaderLayout** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, FShader** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions &")] FMeshLayoutCreateOptions* options, FMeshLayout** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] FGpuBufferCreateOptions* options, FGpuBuffer** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FGpuImageCreateOptions* options, FGpuImage** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateSampler([NativeTypeName("const FGpuSamplerCreateOptions &")] FGpuSamplerCreateOptions* options, FGpuSampler** @out); - } + [NativeTypeName("Coplt::FGpuIsolateCreateResult")] + public FGpuIsolateCreateResult CopyIsolate; } public partial struct FInstanceCreateOptions @@ -1197,10 +1006,10 @@ public FResult CreateBlob([NativeTypeName("Coplt::usize")] nuint size, FBlob** @ [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateDevice([NativeTypeName("const FGpuAutoSelectDeviceCreateOptions &")] FGpuAutoSelectDeviceCreateOptions* options, FGpuDevice** @out) + public FResult CreateDevice([NativeTypeName("const FGpuAutoSelectDeviceCreateOptions &")] FGpuAutoSelectDeviceCreateOptions* options, [NativeTypeName("Coplt::FGpuDeviceCreateResult *")] FGpuDeviceCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FInstance*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FInstance*)Unsafe.AsPointer(ref this), &result, options, @out); } public interface Interface : FUnknown.Interface @@ -1221,7 +1030,7 @@ public interface Interface : FUnknown.Interface FGpuAdapter** GetAdapters([NativeTypeName("Coplt::u32 *")] uint* out_count); [return: NativeTypeName("Coplt::FResult")] - FResult CreateDevice([NativeTypeName("const FGpuAutoSelectDeviceCreateOptions &")] FGpuAutoSelectDeviceCreateOptions* options, FGpuDevice** @out); + FResult CreateDevice([NativeTypeName("const FGpuAutoSelectDeviceCreateOptions &")] FGpuAutoSelectDeviceCreateOptions* options, [NativeTypeName("Coplt::FGpuDeviceCreateResult *")] FGpuDeviceCreateResult* @out); } } @@ -1294,6 +1103,9 @@ public partial struct FDeviceFeatures [NativeTypeName("Coplt::b8")] public B8 DynBindlessOnly; + + [NativeTypeName("Coplt::b8")] + public B8 ExtraIsolate; } [NativeTypeName("Coplt::i32")] @@ -1355,6 +1167,209 @@ public partial struct FGpuDeviceCreateOptions public FStr8or16 Name; } + [Guid("557F032D-ED50-403A-ADC5-214FDDBE6C6B")] + [NativeTypeName("struct FGpuDevice : Coplt::FGpuObject")] + public unsafe partial struct FGpuDevice : FGpuDevice.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuDevice)); + + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuDevice*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuDevice*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuDevice*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuDevice*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuDevice*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, name); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuAdapter *")] + public FGpuAdapter* GetAdapter() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuDevice*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* GetRawDevice() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuDevice*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &")] FGpuIsolateCreateOptions* options, [NativeTypeName("Coplt::FGpuIsolateCreateResult &")] FGpuIsolateCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, [NativeTypeName("Coplt::FShaderModuleCreateResult *")] FShaderModuleCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, FShaderLayout** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, FShaderLayout** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, [NativeTypeName("Coplt::FShaderCreateResult *")] FShaderCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions &")] FMeshLayoutCreateOptions* options, FMeshLayout** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[16]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] FGpuBufferCreateOptions* options, FGpuBuffer** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[17]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FGpuImageCreateOptions* options, FGpuImage** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[18]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateSampler([NativeTypeName("const FGpuSamplerCreateOptions &")] FGpuSamplerCreateOptions* options, FGpuSampler** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FGpuAdapter *")] + FGpuAdapter* GetAdapter(); + + void* GetRawDevice(); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &")] FGpuIsolateCreateOptions* options, [NativeTypeName("Coplt::FGpuIsolateCreateResult &")] FGpuIsolateCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, [NativeTypeName("Coplt::FShaderModuleCreateResult *")] FShaderModuleCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, FShaderLayout** @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, FShaderLayout** @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, [NativeTypeName("Coplt::FShaderCreateResult *")] FShaderCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions &")] FMeshLayoutCreateOptions* options, FMeshLayout** @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] FGpuBufferCreateOptions* options, FGpuBuffer** @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FGpuImageCreateOptions* options, FGpuImage** @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateSampler([NativeTypeName("const FGpuSamplerCreateOptions &")] FGpuSamplerCreateOptions* options, FGpuSampler** @out); + } + } + public partial struct FGpuRecord { } @@ -1449,13 +1464,16 @@ public unsafe partial struct FGpuRecordCreateResult public enum FGpuIsolateType { Main, - BackgroundCopy, + Copy, } public partial struct FGpuIsolateCreateOptions { [NativeTypeName("Coplt::FStr8or16")] public FStr8or16 Name; + + [NativeTypeName("Coplt::FGpuIsolateType")] + public FGpuIsolateType Type; } public partial struct FGpuIsolateConfig @@ -1609,7 +1627,7 @@ public partial struct FGpuIsolate { } - public unsafe partial struct FMainQueueCreateResult + public unsafe partial struct FGpuIsolateCreateResult { [NativeTypeName("Coplt::FGpuIsolate *")] public FGpuIsolate* Isolate; @@ -2493,14 +2511,8 @@ public unsafe partial struct FShaderModuleCreateOptions public FShaderStage Stage; } - [Guid("5C0E1FDB-2ACD-4FCE-B985-09E12A7A1AAD")] - [NativeTypeName("struct FShaderModule : Coplt::FGpuObject")] - public unsafe partial struct FShaderModule : FShaderModule.Interface, INativeGuid + public unsafe partial struct FShaderModuleData { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShaderModule)); - - public void** lpVtbl; - [NativeTypeName("Coplt::u8 *")] public byte* Data; @@ -2509,6 +2521,15 @@ public unsafe partial struct FShaderModule : FShaderModule.Interface, INativeGui [NativeTypeName("Coplt::FShaderStage")] public FShaderStage Stage; + } + + [Guid("5C0E1FDB-2ACD-4FCE-B985-09E12A7A1AAD")] + [NativeTypeName("struct FShaderModule : Coplt::FGpuObject")] + public unsafe partial struct FShaderModule : FShaderModule.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShaderModule)); + + public void** lpVtbl; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() @@ -2551,20 +2572,39 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderModule*)Unsafe.AsPointer(ref this), &result, name); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderModuleData *")] + public FShaderModuleData* ShaderModuleData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderModule*)Unsafe.AsPointer(ref this)); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FString8 *")] public FString8* GetEntryPoint() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderModule*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FShaderModule*)Unsafe.AsPointer(ref this)); } public interface Interface : FGpuObject.Interface { + [return: NativeTypeName("Coplt::FShaderModuleData *")] + FShaderModuleData* ShaderModuleData(); + [return: NativeTypeName("Coplt::FString8 *")] FString8* GetEntryPoint(); } } + public unsafe partial struct FShaderModuleCreateResult + { + [NativeTypeName("Coplt::FShaderModule *")] + public FShaderModule* ShaderModule; + + [NativeTypeName("Coplt::FShaderModuleData *")] + public FShaderModuleData* Data; + } + public partial struct FShaderLayout { } @@ -2739,6 +2779,12 @@ public unsafe partial struct FShaderCreateOptions public byte Count; } + public partial struct FShaderData + { + [NativeTypeName("Coplt::FShaderStageFlags")] + public FShaderStageFlags Stages; + } + [Guid("DE1352D5-023D-42B0-BEAC-122B3B296C9C")] [NativeTypeName("struct FShader : Coplt::FGpuObject")] public unsafe partial struct FShader : FShader.Interface, INativeGuid @@ -2747,9 +2793,6 @@ public unsafe partial struct FShader : FShader.Interface, INativeGuid public void** lpVtbl; - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags Stages; - [NativeTypeName("const u32")] public const uint MaxShaderModuleCount = 3; @@ -2794,57 +2837,67 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShader*)Unsafe.AsPointer(ref this), &result, name); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderData *")] + public FShaderData* ShaderData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShader*)Unsafe.AsPointer(ref this)); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FShaderLayout *")] public FShaderLayout* Layout() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShader*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FShader*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FShaderInputLayout *")] public FShaderInputLayout* InputLayout() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FShader*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FShader*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FShaderModule *")] public FShaderModule* Compute() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FShader*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FShader*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FShaderModule *")] public FShaderModule* Pixel() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FShader*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FShader*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FShaderModule *")] public FShaderModule* Vertex() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FShader*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FShader*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FShaderModule *")] public FShaderModule* Mesh() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FShader*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FShader*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FShaderModule *")] public FShaderModule* Task() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FShader*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FShader*)Unsafe.AsPointer(ref this)); } public interface Interface : FGpuObject.Interface { + [return: NativeTypeName("Coplt::FShaderData *")] + FShaderData* ShaderData(); + [return: NativeTypeName("Coplt::FShaderLayout *")] FShaderLayout* Layout(); @@ -2868,6 +2921,15 @@ public interface Interface : FGpuObject.Interface } } + public unsafe partial struct FShaderCreateResult + { + [NativeTypeName("Coplt::FShader *")] + public FShader* Shader; + + [NativeTypeName("Coplt::FShaderData *")] + public FShaderData* Data; + } + public unsafe partial struct FShaderBindingCreateOptions { [NativeTypeName("Coplt::FStr8or16")] @@ -2952,60 +3014,6 @@ public unsafe partial struct FUploadBufferBlock public ulong size; } - [Guid("FA9C7561-AB0B-4311-BB4C-C6BEF93F86FE")] - [NativeTypeName("struct FFrameContext2 : Coplt::FGpuObject")] - public unsafe partial struct FFrameContext2 : FFrameContext2.Interface, INativeGuid - { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FFrameContext2)); - - public void** lpVtbl; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FFrameContext2*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FFrameContext2*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FFrameContext2*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FFrameContext2*)Unsafe.AsPointer(ref this), id); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FFrameContext2*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FFrameContext2*)Unsafe.AsPointer(ref this), &result, name); - } - - public interface Interface : FGpuObject.Interface - { - } - } - [Guid("15B4821D-0648-4B78-9C21-C6A5B6A5ED75")] [NativeTypeName("struct FRecordContext : Coplt::FGpuObject")] public unsafe partial struct FRecordContext : FRecordContext.Interface, INativeGuid @@ -5628,8 +5636,6 @@ public static partial class Native public static readonly Guid IID_FShaderBinding = new Guid(0xA3CA644A, 0x0E02, 0x4D25, 0x9A, 0x18, 0x88, 0x35, 0xD6, 0x66, 0x00, 0xF7); - public static readonly Guid IID_FFrameContext2 = new Guid(0xFA9C7561, 0xAB0B, 0x4311, 0xBB, 0x4C, 0xC6, 0xBE, 0xF9, 0x3F, 0x86, 0xFE); - public static readonly Guid IID_FRecordContext = new Guid(0x15B4821D, 0x0648, 0x4B78, 0x9C, 0x21, 0xC6, 0xA5, 0xB6, 0xA5, 0xED, 0x75); public static readonly Guid IID_FGpuQueue2 = new Guid(0xFC94E4D0, 0x5F01, 0x4D4F, 0x89, 0x4C, 0x6A, 0xEF, 0xAA, 0xD9, 0x04, 0x99); diff --git a/Coplt.Graphics.Native/Api/FFI/Adapter.h b/Coplt.Graphics.Native/Api/FFI/Adapter.h index 85aab46..ade5af5 100644 --- a/Coplt.Graphics.Native/Api/FFI/Adapter.h +++ b/Coplt.Graphics.Native/Api/FFI/Adapter.h @@ -23,6 +23,6 @@ namespace Coplt virtual b8 IsSupport(const FDeviceRequires& Requires) noexcept = 0; - virtual FResult CreateDevice(const FGpuDeviceCreateOptions& options, FGpuDevice** out) noexcept = 0; + virtual FResult CreateDevice(const FGpuDeviceCreateOptions& options, FGpuDeviceCreateResult* out) noexcept = 0; }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Context.h b/Coplt.Graphics.Native/Api/FFI/Context.h index c8f2d8e..30ea0e9 100644 --- a/Coplt.Graphics.Native/Api/FFI/Context.h +++ b/Coplt.Graphics.Native/Api/FFI/Context.h @@ -14,10 +14,6 @@ namespace Coplt u64 size{}; }; - COPLT_INTERFACE_DEFINE(FFrameContext2, "fa9c7561-ab0b-4311-bb4c-c6bef93f86fe", FGpuObject) - { - }; - COPLT_INTERFACE_DEFINE(FRecordContext, "15b4821d-0648-4b78-9c21-c6a5b6a5ed75", FGpuObject) { FList m_upload_buffer{}; diff --git a/Coplt.Graphics.Native/Api/FFI/Device.h b/Coplt.Graphics.Native/Api/FFI/Device.h index f485e05..dce1699 100644 --- a/Coplt.Graphics.Native/Api/FFI/Device.h +++ b/Coplt.Graphics.Native/Api/FFI/Device.h @@ -77,13 +77,13 @@ namespace Coplt // d3d12 返回 ID3D12Device* virtual void* GetRawDevice() noexcept = 0; - virtual FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FMainQueueCreateResult& out) noexcept = 0; + virtual FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FGpuIsolateCreateResult& out) noexcept = 0; - virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModule** out) noexcept = 0; + virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept = 0; virtual FResult CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayout** out) noexcept = 0; virtual FResult GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayout** out) noexcept = 0; virtual FResult CreateShaderInputLayout(const FShaderInputLayoutCreateOptions& options, FShaderInputLayout** out) noexcept = 0; - virtual FResult CreateShader(const FShaderCreateOptions& options, FShader** out) noexcept = 0; + virtual FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept = 0; virtual FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept = 0; virtual FResult CreateMeshLayout(const FMeshLayoutCreateOptions& options, FMeshLayout** out) noexcept = 0; @@ -94,4 +94,12 @@ namespace Coplt virtual FResult CreateImage(const FGpuImageCreateOptions& options, FGpuImage** out) noexcept = 0; virtual FResult CreateSampler(const FGpuSamplerCreateOptions& options, FGpuSampler** out) noexcept = 0; }; + + struct FGpuDeviceCreateResult + { + FGpuDevice* Device{}; + FGpuIsolateCreateResult MainIsolate{}; + // 可空 + FGpuIsolateCreateResult CopyIsolate{}; + }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Features.h b/Coplt.Graphics.Native/Api/FFI/Features.h index 836743d..286500e 100644 --- a/Coplt.Graphics.Native/Api/FFI/Features.h +++ b/Coplt.Graphics.Native/Api/FFI/Features.h @@ -58,5 +58,7 @@ namespace Coplt b8 DynBindless{}; // 仅动态无绑定模式,将无法使用着色器绑定,着色器布局中只能具有根常量/常量推送,此模式具有设备全局描述符堆 b8 DynBindlessOnly{}; + // 可以任意创建隔离,dx12 永远为 true,vk 永远为 false + b8 ExtraIsolate{}; }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Instance.h b/Coplt.Graphics.Native/Api/FFI/Instance.h index b3dac0b..167c3b2 100644 --- a/Coplt.Graphics.Native/Api/FFI/Instance.h +++ b/Coplt.Graphics.Native/Api/FFI/Instance.h @@ -25,7 +25,7 @@ namespace Coplt struct FGpuAdapter; struct FGpuAutoSelectDeviceCreateOptions; - struct FGpuDevice; + struct FGpuDeviceCreateResult; struct FInstanceCreateOptions { @@ -48,6 +48,6 @@ namespace Coplt virtual FResult CreateBlob(usize size, FBlob** out) noexcept = 0; virtual FGpuAdapter* const* GetAdapters(u32* out_count) noexcept = 0; - virtual FResult CreateDevice(const FGpuAutoSelectDeviceCreateOptions& options, FGpuDevice** out) noexcept = 0; + virtual FResult CreateDevice(const FGpuAutoSelectDeviceCreateOptions& options, FGpuDeviceCreateResult* out) noexcept = 0; }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Isolate.h b/Coplt.Graphics.Native/Api/FFI/Isolate.h index 41f4488..77963aa 100644 --- a/Coplt.Graphics.Native/Api/FFI/Isolate.h +++ b/Coplt.Graphics.Native/Api/FFI/Isolate.h @@ -11,11 +11,11 @@ namespace Coplt enum class FGpuIsolateType { - // 包含 direct compute copy 队列,最多同时具有这3个队列 - // 可以提交异步任务自动调度到队列上,同时如果不支持多队列将回退到主 direct 队列 + // 包含 Direct Compute Copy 队列,最多同时具有这3个队列 + // 可以提交异步任务自动调度到队列上,同时如果不支持多队列将回退到主 Direct 队列 Main, - // 仅包含 copy 队列,不一定有 - BackgroundCopy, + // 仅包含 Copy 队列,不一定有 + Copy, // todo video }; @@ -23,6 +23,7 @@ namespace Coplt { // 可选 FStr8or16 Name{}; + FGpuIsolateType Type{}; }; struct FGpuIsolateConfig @@ -58,7 +59,7 @@ namespace Coplt virtual FResult CreateSwapChainForHwnd(const FGpuSwapChainCreateOptions& options, void* hwnd, FGpuSwapChainCreateResult& out) noexcept = 0; }; - struct FMainQueueCreateResult + struct FGpuIsolateCreateResult { FGpuIsolate* Isolate{}; FGpuIsolateData* Data{}; diff --git a/Coplt.Graphics.Native/Api/FFI/Shader.h b/Coplt.Graphics.Native/Api/FFI/Shader.h index ce254e0..27c89c9 100644 --- a/Coplt.Graphics.Native/Api/FFI/Shader.h +++ b/Coplt.Graphics.Native/Api/FFI/Shader.h @@ -35,7 +35,7 @@ namespace Coplt FShaderStage Stage{}; }; - COPLT_INTERFACE_DEFINE(FShaderModule, "5c0e1fdb-2acd-4fce-b985-09e12a7a1aad", FGpuObject) + struct FShaderModuleData { // 外部只读 u8* Data{}; @@ -43,9 +43,28 @@ namespace Coplt usize Size{}; // 外部只读 FShaderStage Stage{}; + }; + COPLT_INTERFACE_DEFINE(FShaderModule, "5c0e1fdb-2acd-4fce-b985-09e12a7a1aad", FGpuObject) + { + virtual FShaderModuleData* ShaderModuleData() noexcept = 0; // 可空 virtual FString8* GetEntryPoint() noexcept = 0; + + #ifdef FFI_SRC + + FShaderModuleData& Data() noexcept + { + return *ShaderModuleData(); + } + + #endif + }; + + struct FShaderModuleCreateResult + { + FShaderModule* ShaderModule{}; + FShaderModuleData* Data{}; }; struct FShaderLayout; @@ -63,11 +82,16 @@ namespace Coplt u8 Count{}; }; + struct FShaderData + { + FShaderStageFlags Stages{}; + }; + COPLT_INTERFACE_DEFINE(FShader, "de1352d5-023d-42b0-beac-122b3b296c9c", FGpuObject) { constexpr static u32 MaxShaderModuleCount = 3; - FShaderStageFlags Stages{}; + virtual FShaderData* ShaderData() noexcept = 0; virtual FShaderLayout* Layout() noexcept = 0; @@ -83,5 +107,25 @@ namespace Coplt virtual FShaderModule* Mesh() noexcept = 0; // 没有返回 null virtual FShaderModule* Task() noexcept = 0; + + #ifdef FFI_SRC + + FShaderData& Data() noexcept + { + return *ShaderData(); + } + + FShaderStageFlags& Stages() noexcept + { + return Data().Stages; + } + + #endif + }; + + struct FShaderCreateResult + { + FShader* Shader{}; + FShaderData* Data{}; }; } diff --git a/Coplt.Graphics.Native/Api/Src/Shader.cc b/Coplt.Graphics.Native/Api/Src/Shader.cc index 46c4587..93b81f3 100644 --- a/Coplt.Graphics.Native/Api/Src/Shader.cc +++ b/Coplt.Graphics.Native/Api/Src/Shader.cc @@ -9,7 +9,7 @@ using namespace Coplt; ShaderModule::ShaderModule(u8* const data, const size_t size, const FShaderStage stage, Rc&& entry_point) : m_entry_point(std::move(entry_point)) { - Data = data; + FShaderModuleData::Data = data; Size = size; Stage = stage; } @@ -34,6 +34,11 @@ FResult ShaderModule::SetName(const FStr8or16& name) noexcept return FResult::None(); } +FShaderModuleData* ShaderModule::ShaderModuleData() noexcept +{ + return this; +} + FString8* ShaderModule::GetEntryPoint() noexcept { return m_entry_point.get(); @@ -60,46 +65,46 @@ Shader::Shader(Rc&& device, const FShaderCreateOptions& options) : m const auto module = options.Modules[i]; if (module == nullptr) COPLT_THROW_FMT("options.Modules[{}] is null", i); - switch (module->Stage) + switch (module->Data().Stage) { case FShaderStage::Compute: if (options.Count != 1) COPLT_THROW("The compute stage cannot be combined with other stage"); - Stages = FShaderStageFlags::Compute; + FShaderData::Stages = FShaderStageFlags::Compute; m_modules[0] = Rc::UnsafeClone(module); return; case FShaderStage::Pixel: if (options.Count == 1) COPLT_THROW("The pixel stage cannot exist alone"); - Stages |= FShaderStageFlags::Pixel; + FShaderData::Stages |= FShaderStageFlags::Pixel; m_modules[0] = Rc::UnsafeClone(module); break; case FShaderStage::Vertex: - if (HasAnyFlags(Stages, FShaderStageFlags::Mesh | FShaderStageFlags::Task)) + if (HasAnyFlags(FShaderData::Stages, FShaderStageFlags::Mesh | FShaderStageFlags::Task)) COPLT_THROW("The vertex stage and the mesh/task stage are mutually exclusive"); - Stages |= FShaderStageFlags::Vertex; + FShaderData::Stages |= FShaderStageFlags::Vertex; m_modules[1] = Rc::UnsafeClone(module); break; case FShaderStage::Mesh: - if (HasFlags(Stages, FShaderStageFlags::Vertex)) + if (HasFlags(FShaderData::Stages, FShaderStageFlags::Vertex)) COPLT_THROW("The vertex stage and the mesh/task stage are mutually exclusive"); - Stages |= FShaderStageFlags::Mesh; + FShaderData::Stages |= FShaderStageFlags::Mesh; m_modules[1] = Rc::UnsafeClone(module); break; case FShaderStage::Task: - if (HasFlags(Stages, FShaderStageFlags::Vertex)) + if (HasFlags(FShaderData::Stages, FShaderStageFlags::Vertex)) COPLT_THROW("The vertex stage and the mesh/task stage are mutually exclusive"); - Stages |= FShaderStageFlags::Task; + FShaderData::Stages |= FShaderStageFlags::Task; m_modules[2] = Rc::UnsafeClone(module); break; default: COPLT_THROW_FMT( - "Unknown shader stage {}", static_cast(module->Stage) + "Unknown shader stage {}", static_cast(module->Data().Stage) ); } } - if (HasFlags(Stages, FShaderStageFlags::Task) && !HasFlags(Stages, FShaderStageFlags::Mesh)) + if (HasFlags(FShaderData::Stages, FShaderStageFlags::Task) && !HasFlags(FShaderData::Stages, FShaderStageFlags::Mesh)) COPLT_THROW("Having a task stage must also have a mesh stage"); } @@ -108,6 +113,11 @@ FResult Shader::SetName(const FStr8or16& name) noexcept return FResult::None(); } +FShaderData* Shader::ShaderData() noexcept +{ + return this; +} + FShaderLayout* Shader::Layout() noexcept { return m_layout.get(); @@ -120,25 +130,25 @@ FShaderInputLayout* Shader::InputLayout() noexcept FShaderModule* Shader::Compute() noexcept { - return HasFlags(Stages, FShaderStageFlags::Compute) ? m_modules[0].get() : nullptr; + return HasFlags(FShaderData::Stages, FShaderStageFlags::Compute) ? m_modules[0].get() : nullptr; } FShaderModule* Shader::Pixel() noexcept { - return HasFlags(Stages, FShaderStageFlags::Pixel) ? m_modules[0].get() : nullptr; + return HasFlags(FShaderData::Stages, FShaderStageFlags::Pixel) ? m_modules[0].get() : nullptr; } FShaderModule* Shader::Vertex() noexcept { - return HasFlags(Stages, FShaderStageFlags::Vertex) ? m_modules[1].get() : nullptr; + return HasFlags(FShaderData::Stages, FShaderStageFlags::Vertex) ? m_modules[1].get() : nullptr; } FShaderModule* Shader::Mesh() noexcept { - return HasFlags(Stages, FShaderStageFlags::Mesh) ? m_modules[1].get() : nullptr; + return HasFlags(FShaderData::Stages, FShaderStageFlags::Mesh) ? m_modules[1].get() : nullptr; } FShaderModule* Shader::Task() noexcept { - return HasFlags(Stages, FShaderStageFlags::Task) ? m_modules[2].get() : nullptr; + return HasFlags(FShaderData::Stages, FShaderStageFlags::Task) ? m_modules[2].get() : nullptr; } diff --git a/Coplt.Graphics.Native/Api/Src/Shader.h b/Coplt.Graphics.Native/Api/Src/Shader.h index 4e0f596..2caa868 100644 --- a/Coplt.Graphics.Native/Api/Src/Shader.h +++ b/Coplt.Graphics.Native/Api/Src/Shader.h @@ -8,7 +8,7 @@ namespace Coplt { - struct ShaderModule final : GpuObject + struct ShaderModule final : GpuObject, FShaderModuleData { private: using Self = ShaderModule; @@ -25,11 +25,13 @@ namespace Coplt FResult SetName(const FStr8or16& name) noexcept override; + FShaderModuleData* ShaderModuleData() noexcept override; + // 可空 FString8* GetEntryPoint() noexcept override; }; - struct Shader final : GpuObject + struct Shader final : GpuObject, FShaderData { Rc m_device{}; // 可空 @@ -43,6 +45,8 @@ namespace Coplt FResult SetName(const FStr8or16& name) noexcept override; + FShaderData* ShaderData() noexcept override; + FShaderLayout* Layout() noexcept override; FShaderInputLayout* InputLayout() noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Adapter.cc b/Coplt.Graphics.Native/D3d12/Src/Adapter.cc index 0be8f25..e209a4e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Adapter.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Adapter.cc @@ -47,6 +47,7 @@ D3d12GpuAdapter::D3d12GpuAdapter( m_features.DescriptorHeap = true; m_features.ArrBindless = true; + m_features.ExtraIsolate = true; 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) @@ -59,11 +60,11 @@ D3d12GpuAdapter::D3d12GpuAdapter( if (m_feature_support.EnhancedBarriersSupported()) m_features.EnhancedBarriers = true; } -FResult D3d12GpuAdapter::CreateDevice(const FGpuDeviceCreateOptions& options, FGpuDevice** out) noexcept +FResult D3d12GpuAdapter::CreateDevice(const FGpuDeviceCreateOptions& options, FGpuDeviceCreateResult* out) noexcept { return feb([&] { - *out = new D3d12GpuDevice(this->CloneThis(), options); + out->Device = new D3d12GpuDevice(this->CloneThis(), options, *out); }); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Adapter.h b/Coplt.Graphics.Native/D3d12/Src/Adapter.h index acce76a..4be56c6 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Adapter.h +++ b/Coplt.Graphics.Native/D3d12/Src/Adapter.h @@ -19,7 +19,7 @@ namespace Coplt explicit D3d12GpuAdapter(Rc&& instance, ComPtr&& adapter); - FResult CreateDevice(const FGpuDeviceCreateOptions& options, FGpuDevice** out) noexcept override; + FResult CreateDevice(const FGpuDeviceCreateOptions& options, FGpuDeviceCreateResult* out) noexcept override; b8 IsSupport(const FDeviceRequires& Requires) noexcept override; }; diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 53d7f04..658c681 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -46,7 +46,7 @@ namespace } } -D3d12GpuDevice::D3d12GpuDevice(Rc&& adapter, const FGpuDeviceCreateOptions& options): +D3d12GpuDevice::D3d12GpuDevice(Rc&& adapter, const FGpuDeviceCreateOptions& options, FGpuDeviceCreateResult& out): m_adapter(std::move(adapter)) { m_instance = m_adapter->m_instance; @@ -80,6 +80,14 @@ D3d12GpuDevice::D3d12GpuDevice(Rc&& adapter, const FGpuDeviceCr } chr | m_device->QueryInterface(IID_PPV_ARGS(&m_device0)); + + FGpuIsolateCreateOptions isolate_options{}; + isolate_options.Type = FGpuIsolateType::Main; + out.MainIsolate = CreateIsolate(isolate_options); + Rc main_isolate = out.MainIsolate.Isolate; + isolate_options.Type = FGpuIsolateType::Copy; + out.CopyIsolate = CreateIsolate(isolate_options); + main_isolate.leak(); } D3d12GpuDevice::~D3d12GpuDevice() @@ -146,21 +154,30 @@ const Rc& D3d12GpuDevice::GetEmptyMeshLayout() return m_empty_mesh_layout; } -FResult D3d12GpuDevice::CreateIsolate(const FGpuIsolateCreateOptions& options, FMainQueueCreateResult& out) noexcept +FResult D3d12GpuDevice::CreateIsolate(const FGpuIsolateCreateOptions& options, FGpuIsolateCreateResult& out) noexcept { return feb([&] { - const auto ptr = new D3d12GpuIsolate(this->CloneThis(), options); - out.Isolate = ptr; - out.Data = ptr; + out = CreateIsolate(options); }); } -FResult D3d12GpuDevice::CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModule** out) noexcept +FGpuIsolateCreateResult D3d12GpuDevice::CreateIsolate(const FGpuIsolateCreateOptions& options) +{ + FGpuIsolateCreateResult out; + const auto ptr = new D3d12GpuIsolate(this->CloneThis(), options); + out.Isolate = ptr; + out.Data = ptr; + return out; +} + +FResult D3d12GpuDevice::CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept { return feb([&] { - *out = ShaderModule::Create(options); + const auto ptr = ShaderModule::Create(options); + out->ShaderModule = ptr; + out->Data = ptr; }); } @@ -190,11 +207,13 @@ FResult D3d12GpuDevice::CreateShaderInputLayout(const FShaderInputLayoutCreateOp }); } -FResult D3d12GpuDevice::CreateShader(const FShaderCreateOptions& options, FShader** out) noexcept +FResult D3d12GpuDevice::CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept { return feb([&] { - *out = new Shader(this->CloneThis(), options); + const auto ptr = new Shader(this->CloneThis(), options); + out->Shader = ptr; + out->Data = ptr; }); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index 5f66816..c761c4c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -29,7 +29,7 @@ namespace Coplt Rc m_empty_mesh_layout{}; DWORD m_callback_cookie{}; - explicit D3d12GpuDevice(Rc&& adapter, const FGpuDeviceCreateOptions& options); + explicit D3d12GpuDevice(Rc&& adapter, const FGpuDeviceCreateOptions& options, FGpuDeviceCreateResult& out); ~D3d12GpuDevice() override; @@ -46,9 +46,10 @@ namespace Coplt const Rc& GetEmptyLayout(FShaderLayoutFlags flags); const Rc& GetEmptyMeshLayout(); - FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FMainQueueCreateResult& out) noexcept override; + FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FGpuIsolateCreateResult& out) noexcept override; + FGpuIsolateCreateResult CreateIsolate(const FGpuIsolateCreateOptions& options); - FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModule** out) noexcept override; + FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept override; FResult CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayout** out) noexcept override; FResult GetEmptyShaderLayout( const FGetEmptyShaderLayoutOptions& options, FShaderLayout** out @@ -56,7 +57,7 @@ namespace Coplt FResult CreateShaderInputLayout( const FShaderInputLayoutCreateOptions& options, FShaderInputLayout** out ) noexcept override; - FResult CreateShader(const FShaderCreateOptions& options, FShader** out) noexcept override; + FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept override; FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; FResult CreateMeshLayout(const FMeshLayoutCreateOptions& options, FMeshLayout** out) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc index fba52e0..3053860 100644 --- a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc +++ b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc @@ -135,7 +135,7 @@ D3d12GraphicsShaderPipeline::D3d12GraphicsShaderPipeline( if (options.Shader == nullptr) COPLT_THROW("Shader is null"); m_shader = Rc::UnsafeClone(options.Shader); - if (!HasFlags(m_shader->Stages, FShaderStageFlags::Pixel)) + if (!HasFlags(m_shader->Stages(), FShaderStageFlags::Pixel)) COPLT_THROW("The shader is not graphics"); if (auto layout = m_shader->Layout()) @@ -162,14 +162,14 @@ D3d12GraphicsShaderPipeline::D3d12GraphicsShaderPipeline( std::vector input_slots{}; CD3DX12_PIPELINE_STATE_STREAM2 stream{}; - if (HasFlags(m_shader->Stages, FShaderStageFlags::Vertex)) + if (HasFlags(m_shader->Stages(), FShaderStageFlags::Vertex)) { D3D12_GRAPHICS_PIPELINE_STATE_DESC desc{}; desc.pRootSignature = root_signature; - auto ps = m_shader->Pixel(); - auto vs = m_shader->Vertex(); - desc.PS = D3D12_SHADER_BYTECODE{ps->Data, ps->Size}; - desc.VS = D3D12_SHADER_BYTECODE{vs->Data, vs->Size}; + NonNull ps = m_shader->Pixel(); + NonNull vs = m_shader->Vertex(); + desc.PS = D3D12_SHADER_BYTECODE{ps->Data().Data, ps->Data().Size}; + desc.VS = D3D12_SHADER_BYTECODE{vs->Data().Data, vs->Data().Size}; SetGraphicsState(desc, options); desc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF; desc.Flags = D3D12_PIPELINE_STATE_FLAG_DYNAMIC_DEPTH_BIAS | @@ -195,17 +195,17 @@ D3d12GraphicsShaderPipeline::D3d12GraphicsShaderPipeline( } stream = CD3DX12_PIPELINE_STATE_STREAM2(desc); } - else if (HasFlags(m_shader->Stages, FShaderStageFlags::Mesh)) + else if (HasFlags(m_shader->Stages(), FShaderStageFlags::Mesh)) { D3DX12_MESH_SHADER_PIPELINE_STATE_DESC desc{}; desc.pRootSignature = root_signature; - auto ps = m_shader->Pixel(); - auto ms = m_shader->Mesh(); + NonNull ps = m_shader->Pixel(); + NonNull ms = m_shader->Mesh(); auto ts = m_shader->Task(); - desc.PS = D3D12_SHADER_BYTECODE{ps->Data, ps->Size}; - desc.MS = D3D12_SHADER_BYTECODE{ms->Data, ms->Size}; + desc.PS = D3D12_SHADER_BYTECODE{ps->Data().Data, ps->Data().Size}; + desc.MS = D3D12_SHADER_BYTECODE{ms->Data().Data, ms->Data().Size}; if (ts != nullptr) - desc.AS = D3D12_SHADER_BYTECODE{ts->Data, ts->Size}; + desc.AS = D3D12_SHADER_BYTECODE{ts->Data().Data, ts->Data().Size}; SetGraphicsState(desc, options); desc.Flags = D3D12_PIPELINE_STATE_FLAG_DYNAMIC_DEPTH_BIAS; stream = CD3DX12_PIPELINE_STATE_STREAM2(desc); @@ -252,7 +252,7 @@ FShaderLayout* D3d12GraphicsShaderPipeline::GetLayout() noexcept FShaderStageFlags D3d12GraphicsShaderPipeline::GetStages() noexcept { - return m_shader->Stages; + return m_shader->Stages(); } const FGraphicsPipelineState* D3d12GraphicsShaderPipeline::GetGraphicsState() noexcept diff --git a/Coplt.Graphics.Native/D3d12/Src/Instance.cc b/Coplt.Graphics.Native/D3d12/Src/Instance.cc index 88cec45..6826f0a 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Instance.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Instance.cc @@ -77,7 +77,7 @@ void D3d12Instance::CreateAdapter(ComPtr&& adapter) m_adapters.push_back(new D3d12GpuAdapter(this->CloneThis(), std::move(adapter))); } -FResult D3d12Instance::CreateDevice(const FGpuAutoSelectDeviceCreateOptions& options, FGpuDevice** out) noexcept +FResult D3d12Instance::CreateDevice(const FGpuAutoSelectDeviceCreateOptions& options, FGpuDeviceCreateResult* out) noexcept { return feb([&] { @@ -89,7 +89,7 @@ FResult D3d12Instance::CreateDevice(const FGpuAutoSelectDeviceCreateOptions& opt continue; auto r = feb([&] { - *out = new D3d12GpuDevice(adapter.Clone(), options); + out->Device = new D3d12GpuDevice(adapter.Clone(), options, *out); }); if (!r.IsError()) goto end; diff --git a/Coplt.Graphics.Native/D3d12/Src/Instance.h b/Coplt.Graphics.Native/D3d12/Src/Instance.h index 5c0dfc3..2103359 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Instance.h +++ b/Coplt.Graphics.Native/D3d12/Src/Instance.h @@ -26,7 +26,7 @@ namespace Coplt void CreateAdapter(ComPtr&& adapter); - FResult CreateDevice(const FGpuAutoSelectDeviceCreateOptions& options, FGpuDevice** out) noexcept override; + FResult CreateDevice(const FGpuAutoSelectDeviceCreateOptions& options, FGpuDeviceCreateResult* out) noexcept override; FGpuAdapter* const* GetAdapters(u32* out_count) noexcept override; diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index 69d47c8..d6053cd 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -43,7 +43,7 @@ public void DoInitGraphics() Adapter.Features.ShaderModelLevel } ); - Isolate = Device.CreateIsolate(Name: "Main Isolate"); + Isolate = Device.MainIsolate; Output = Isolate.CreateSwapChainForHwnd( Handle, new() { diff --git a/Examples/HelloTriangleVertex/Example.cs b/Examples/HelloTriangleVertex/Example.cs index abc8d5a..21c2656 100644 --- a/Examples/HelloTriangleVertex/Example.cs +++ b/Examples/HelloTriangleVertex/Example.cs @@ -52,14 +52,14 @@ protected override async Task LoadResources(GpuRecord cmd) } }, MeshLayout, Name: Name ); - PositionColorBuffer = Isolate.CreateBuffer( + PositionColorBuffer = Device.CreateBuffer( new() { Purpose = ResourcePurpose.VertexBuffer, Size = sizeof(float) * 4 * 6, }, "Position and Color" ); - UvBuffer = Isolate.CreateBuffer( + UvBuffer = Device.CreateBuffer( new() { Purpose = ResourcePurpose.VertexBuffer, From 31e5b205534f6c2c955e15bfeef18f5f6b0569ed Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 1 Apr 2025 17:24:23 +0800 Subject: [PATCH 28/46] save --- Coplt.Graphics.Core/Core/GpuDevice.cs | 12 +-- Coplt.Graphics.Core/Core/ShaderLayout.cs | 49 +++++++---- Coplt.Graphics.Core/Native/Native.cs | 46 +++++++--- Coplt.Graphics.Native/Api/FFI/Device.h | 4 +- Coplt.Graphics.Native/Api/FFI/Layout.h | 12 ++- Coplt.Graphics.Native/D3d12/Src/Device.cc | 19 ++-- Coplt.Graphics.Native/D3d12/Src/Device.h | 14 +-- Coplt.Graphics.Native/D3d12/Src/Layout.cc | 5 ++ Coplt.Graphics.Native/D3d12/Src/Layout.h | 4 +- Examples/Colorful/Example.cs | 100 +++++++++++----------- Examples/HelloTriangle/HelloTriangle.md | 17 +++- 11 files changed, 169 insertions(+), 113 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuDevice.cs b/Coplt.Graphics.Core/Core/GpuDevice.cs index 8400eaa..a1a1988 100644 --- a/Coplt.Graphics.Core/Core/GpuDevice.cs +++ b/Coplt.Graphics.Core/Core/GpuDevice.cs @@ -131,9 +131,9 @@ public ShaderLayout CreateShaderLayout( Items = (FShaderLayoutItemDefine*)p_define, Flags = (FShaderLayoutFlags)Flags, }; - FShaderLayout* ptr; - Ptr->CreateShaderLayout(&f_options, &ptr).TryThrow(); - return new(ptr, Name, this); + FShaderLayoutCreateResult result; + Ptr->CreateShaderLayout(&f_options, &result).TryThrow(); + return new(result, Name, this); } } } @@ -148,9 +148,9 @@ public ShaderLayout GetEmptyShaderLayout(ShaderLayoutFlags Flags = ShaderLayoutF { Flags = (FShaderLayoutFlags)flags, }; - FShaderLayout* ptr; - self.Ptr->GetEmptyShaderLayout(&f_options, &ptr).TryThrow(); - return new(ptr, $"Empty Shader Layout ({flags})", self); + FShaderLayoutCreateResult result; + self.Ptr->GetEmptyShaderLayout(&f_options, &result).TryThrow(); + return new(result, $"Empty Shader Layout ({flags})", self); }, this ); diff --git a/Coplt.Graphics.Core/Core/ShaderLayout.cs b/Coplt.Graphics.Core/Core/ShaderLayout.cs index 876d3d8..e3c1b2f 100644 --- a/Coplt.Graphics.Core/Core/ShaderLayout.cs +++ b/Coplt.Graphics.Core/Core/ShaderLayout.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using Coplt.Dropping; using Coplt.Graphics.Native; namespace Coplt.Graphics.Core; @@ -104,10 +105,12 @@ public enum ShaderLayoutFlags : byte StreamOutput = 1 << 2, } -public sealed unsafe class ShaderLayout : DeviceChild +[Dropping(Unmanaged = true)] +public sealed unsafe partial class ShaderLayout : DeviceChild { #region Fields + internal FShaderLayoutData* m_data; internal readonly FRoSlice m_native_defines; internal readonly FRoSlice m_native_item_infos; internal readonly FRoSlice m_native_group_classes; @@ -117,6 +120,7 @@ public sealed unsafe class ShaderLayout : DeviceChild #region Props public new FShaderLayout* Ptr => (FShaderLayout*)m_ptr; + public ref readonly FShaderLayoutData Data => ref *m_data; public ReadOnlySpan NativeDefines => m_native_defines.Span; public ReadOnlySpan NativeItemInfos => m_native_item_infos.Span; public ReadOnlySpan NativeGroupClasses => m_native_group_classes.Span; @@ -125,26 +129,35 @@ public sealed unsafe class ShaderLayout : DeviceChild #region Ctor - internal ShaderLayout(FShaderLayout* ptr, string? name, GpuDevice device) : base((FGpuObject*)ptr, name, device) + internal ShaderLayout(FShaderLayoutCreateResult result, string? name, GpuDevice device) : base((FGpuObject*)result.Layout, name, device) { - if (ptr != null) + if (Ptr == null) return; + m_data = result.Data; { - { - uint count = 0; - var defines = ptr->GetItemDefines(&count); - m_native_defines = new(defines, count); - } - { - uint count = 0; - var defines = ptr->GetItemInfos(&count); - m_native_item_infos = new(defines, count); - } - { - uint count = 0; - var defines = ptr->GetGroupClasses(&count); - m_native_group_classes = new(defines, count); - } + uint count = 0; + var defines = Ptr->GetItemDefines(&count); + m_native_defines = new(defines, count); } + { + uint count = 0; + var defines = Ptr->GetItemInfos(&count); + m_native_item_infos = new(defines, count); + } + { + uint count = 0; + var defines = Ptr->GetGroupClasses(&count); + m_native_group_classes = new(defines, count); + } + } + + #endregion + + #region Drop + + [Drop] + private void Drop() + { + m_data = null; } #endregion diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 45690fe..1a47960 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1247,18 +1247,18 @@ public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOpti [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, FShaderLayout** @out) + public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, FShaderLayout** @out) + public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1339,10 +1339,10 @@ public interface Interface : FGpuObject.Interface FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, [NativeTypeName("Coplt::FShaderModuleCreateResult *")] FShaderModuleCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, FShaderLayout** @out); + FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] - FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, FShaderLayout** @out); + FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out); @@ -2617,9 +2617,6 @@ public unsafe partial struct FShaderLayout : FShaderLayout.Interface, INativeGui public void** lpVtbl; - [NativeTypeName("Coplt::FShaderLayoutFlags")] - public FShaderLayoutFlags Flags; - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { @@ -2661,29 +2658,39 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderLayout*)Unsafe.AsPointer(ref this), &result, name); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderLayoutData *")] + public FShaderLayoutData* ShaderLayoutData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderLayout*)Unsafe.AsPointer(ref this)); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("const FShaderLayoutItemDefine *")] public FShaderLayoutItemDefine* GetItemDefines([NativeTypeName("Coplt::u32 *")] uint* out_count) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((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[7]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); + return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((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[8]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); + return ((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); } public interface Interface : FGpuObject.Interface { + [return: NativeTypeName("Coplt::FShaderLayoutData *")] + FShaderLayoutData* ShaderLayoutData(); + [return: NativeTypeName("const FShaderLayoutItemDefine *")] FShaderLayoutItemDefine* GetItemDefines([NativeTypeName("Coplt::u32 *")] uint* out_count); @@ -4740,6 +4747,21 @@ public partial struct FGetEmptyShaderLayoutOptions public FShaderLayoutFlags Flags; } + public partial struct FShaderLayoutData + { + [NativeTypeName("Coplt::FShaderLayoutFlags")] + public FShaderLayoutFlags Flags; + } + + public unsafe partial struct FShaderLayoutCreateResult + { + [NativeTypeName("Coplt::FShaderLayout *")] + public FShaderLayout* Layout; + + [NativeTypeName("Coplt::FShaderLayoutData *")] + public FShaderLayoutData* Data; + } + public unsafe partial struct FShaderInputLayoutCreateOptions { [NativeTypeName("Coplt::FStr8or16")] diff --git a/Coplt.Graphics.Native/Api/FFI/Device.h b/Coplt.Graphics.Native/Api/FFI/Device.h index dce1699..c0cac4e 100644 --- a/Coplt.Graphics.Native/Api/FFI/Device.h +++ b/Coplt.Graphics.Native/Api/FFI/Device.h @@ -80,8 +80,8 @@ namespace Coplt virtual FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FGpuIsolateCreateResult& out) noexcept = 0; virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept = 0; - virtual FResult CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayout** out) noexcept = 0; - virtual FResult GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayout** out) noexcept = 0; + virtual FResult CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayoutCreateResult* out) noexcept = 0; + virtual FResult GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayoutCreateResult* out) noexcept = 0; virtual FResult CreateShaderInputLayout(const FShaderInputLayoutCreateOptions& options, FShaderInputLayout** out) noexcept = 0; virtual FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept = 0; virtual FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept = 0; diff --git a/Coplt.Graphics.Native/Api/FFI/Layout.h b/Coplt.Graphics.Native/Api/FFI/Layout.h index 7aab7a6..ad56ac2 100644 --- a/Coplt.Graphics.Native/Api/FFI/Layout.h +++ b/Coplt.Graphics.Native/Api/FFI/Layout.h @@ -212,10 +212,14 @@ namespace Coplt FShaderLayoutFlags Flags{}; }; - COPLT_INTERFACE_DEFINE(FShaderLayout, "552a498e-8f3a-47ff-a335-7af2de0901e8", FGpuObject) + struct FShaderLayoutData { FShaderLayoutFlags Flags{}; + }; + COPLT_INTERFACE_DEFINE(FShaderLayout, "552a498e-8f3a-47ff-a335-7af2de0901e8", FGpuObject) + { + virtual FShaderLayoutData* ShaderLayoutData() noexcept = 0; 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; @@ -241,6 +245,12 @@ namespace Coplt #endif }; + struct FShaderLayoutCreateResult + { + FShaderLayout* Layout{}; + FShaderLayoutData* Data{}; + }; + struct FShaderInputLayoutCreateOptions { FStr8or16 Name{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 658c681..8008903 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -181,25 +181,28 @@ FResult D3d12GpuDevice::CreateShaderModule(const FShaderModuleCreateOptions& opt }); } -FResult D3d12GpuDevice::CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayout** out) noexcept +FResult D3d12GpuDevice::CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayoutCreateResult* out) noexcept { return feb([&] { - *out = new D3d12ShaderLayout(this->CloneThis(), options); + const auto ptr = new D3d12ShaderLayout(this->CloneThis(), options); + out->Layout = ptr; + out->Data = ptr; }); } -FResult D3d12GpuDevice::GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayout** out) noexcept +FResult D3d12GpuDevice::GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayoutCreateResult* out) noexcept { return feb([&] { Rc r = GetEmptyLayout(options.Flags); - *out = r.leak(); + const auto ptr = r.leak(); + out->Layout = ptr; + out->Data = ptr; }); } -FResult D3d12GpuDevice::CreateShaderInputLayout(const FShaderInputLayoutCreateOptions& options, - FShaderInputLayout** out) noexcept +FResult D3d12GpuDevice::CreateShaderInputLayout(const FShaderInputLayoutCreateOptions& options, FShaderInputLayout** out) noexcept { return feb([&] { @@ -233,9 +236,7 @@ FResult D3d12GpuDevice::CreateMeshLayout(const FMeshLayoutCreateOptions& options }); } -FResult D3d12GpuDevice::CreateGraphicsPipeline( - const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out -) noexcept +FResult D3d12GpuDevice::CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept { return feb([&] { diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index c761c4c..4c9f3bf 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -50,21 +50,15 @@ namespace Coplt FGpuIsolateCreateResult CreateIsolate(const FGpuIsolateCreateOptions& options); FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept override; - FResult CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayout** out) noexcept override; - FResult GetEmptyShaderLayout( - const FGetEmptyShaderLayoutOptions& options, FShaderLayout** out - ) noexcept override; - FResult CreateShaderInputLayout( - const FShaderInputLayoutCreateOptions& options, FShaderInputLayout** out - ) noexcept override; + FResult CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayoutCreateResult* out) noexcept override; + FResult GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayoutCreateResult* out) noexcept override; + FResult CreateShaderInputLayout(const FShaderInputLayoutCreateOptions& options, FShaderInputLayout** out) noexcept override; FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept override; FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; FResult CreateMeshLayout(const FMeshLayoutCreateOptions& options, FMeshLayout** out) noexcept override; - FResult CreateGraphicsPipeline( - const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out - ) noexcept override; + FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept override; FResult CreateBuffer(const FGpuBufferCreateOptions& options, FGpuBuffer** out) noexcept override; FResult CreateImage(const FGpuImageCreateOptions& options, FGpuImage** out) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.cc b/Coplt.Graphics.Native/D3d12/Src/Layout.cc index 6282628..d97958b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.cc @@ -297,6 +297,11 @@ FResult D3d12ShaderLayout::SetName(const FStr8or16& name) noexcept }); } +FShaderLayoutData* D3d12ShaderLayout::ShaderLayoutData() noexcept +{ + return this; +} + void* D3d12ShaderLayout::GetRootSignaturePtr() noexcept { return m_root_signature.Get(); diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.h b/Coplt.Graphics.Native/D3d12/Src/Layout.h index d90e5a2..9692e1d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.h +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.h @@ -43,7 +43,7 @@ namespace Coplt virtual std::span GetTableGroups() noexcept = 0; }; - struct D3d12ShaderLayout final : GpuObject + struct D3d12ShaderLayout final : GpuObject, FShaderLayoutData { Rc m_device{}; ComPtr m_dx_device{}; @@ -58,6 +58,8 @@ namespace Coplt FResult SetName(const FStr8or16& name) noexcept override; + FShaderLayoutData* ShaderLayoutData() noexcept override; + void* GetRootSignaturePtr() noexcept override; const FShaderLayoutItemDefine* GetItemDefines(u32* out_count) noexcept override; diff --git a/Examples/Colorful/Example.cs b/Examples/Colorful/Example.cs index 73829bb..1696ad0 100644 --- a/Examples/Colorful/Example.cs +++ b/Examples/Colorful/Example.cs @@ -13,54 +13,54 @@ public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handl private GpuBuffer ArgBuffer = null!; public override string Name => "Colorful"; - // protected override async Task LoadResources(CommandList cmd) - // { - // var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); - // Layout = Device.CreateShaderLayout( - // [ - // new() - // { - // Slot = 0, - // Stage = ShaderStage.Pixel, - // View = ShaderLayoutItemView.Cbv, - // Type = ShaderLayoutItemType.ConstantBuffer, - // Usage = ShaderLayoutItemUsage.Persist, - // } - // ], - // Name: Name - // ); - // Shader = Device.CreateShader(modules, Layout); - // ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); - // Pipeline = Device.CreateGraphicsShaderPipeline( - // Shader, new() - // { - // DsvFormat = GraphicsFormat.Unknown, - // BlendState = - // { - // Rt0 = - // { - // Src = BlendType.SrcAlpha, - // Dst = BlendType.InvSrcAlpha, - // Op = BlendOp.Add, - // } - // }, - // Topology = PrimitiveTopologyType.TriangleStrip, - // }, Name: Name - // ); - // ArgBuffer = Device.CreateBuffer( - // new() - // { - // Purpose = ResourcePurpose.ConstantBuffer, - // Size = sizeof(float), - // }, - // Name: "Args" - // ); - // 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 Color(0.83f, 0.8f, 0.97f))]); - // render.Draw(Pipeline, 4, Binding: ShaderBinding); - // } + protected override async Task LoadResources(GpuRecord cmd) + { + var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); + Layout = Device.CreateShaderLayout( + [ + new() + { + Slot = 0, + Stage = ShaderStage.Pixel, + View = ShaderLayoutItemView.Cbv, + Type = ShaderLayoutItemType.ConstantBuffer, + Usage = ShaderLayoutItemUsage.Persist, + } + ], + Name: Name + ); + Shader = Device.CreateShader(modules, Layout); + // ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); + Pipeline = Device.CreateGraphicsShaderPipeline( + Shader, new() + { + DsvFormat = GraphicsFormat.Unknown, + BlendState = + { + Rt0 = + { + Src = BlendType.SrcAlpha, + Dst = BlendType.InvSrcAlpha, + Op = BlendOp.Add, + } + }, + Topology = PrimitiveTopologyType.TriangleStrip, + }, Name: Name + ); + ArgBuffer = Device.CreateBuffer( + new() + { + Purpose = ResourcePurpose.ConstantBuffer, + Size = sizeof(float), + }, + Name: "Args" + ); + // cmd.Bind(ShaderBinding, [new(0, ArgBuffer)]); + } + protected override void Render(GpuRecord cmd, Time time) + { + cmd.Upload(ArgBuffer, [(float)time.Total.TotalSeconds]); + // using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); + // render.Draw(Pipeline, 4, Binding: ShaderBinding); + } } diff --git a/Examples/HelloTriangle/HelloTriangle.md b/Examples/HelloTriangle/HelloTriangle.md index da899e9..a877525 100644 --- a/Examples/HelloTriangle/HelloTriangle.md +++ b/Examples/HelloTriangle/HelloTriangle.md @@ -12,8 +12,12 @@ No any resources, including vertex buffers. Graphics = GraphicsInstance.LoadD3d12(); // Creating a Graphics Device Device = Graphics.CreateDevice(Debug: true, Name: "Main Device"); +// Get the main isolate of the device, isolate contains multiple queues internally +Isolate = Device.MainIsolate; // Creating a swap chain -Output = Device.MainQueue.CreateOutputForHwnd(new() { Width = Width, Height = Height }, Hwnd); +Output = Isolate.CreateSwapChainForHwnd(new() { Width = Width, Height = Height }, Hwnd); +// Rent command recording object +Record = Isolate.RentRecord(); ``` ## 2 LoadResources @@ -45,14 +49,19 @@ Pipeline = Device.CreateGraphicsShaderPipeline( ## 3 Render ```cs -var cmd = Device.MainCommandList; while (!IsClosed) { - Render(cmd, CalcTime()); + Render(Record, CalcTime()); + // Split PreparePresent and Present so that Present can be done on a separate thread + Record.PreparePresent(Output); + // Recording objects can be reused immediately after submission + Isolate.Submit(Record); + // Present is a combination of PresentNoWait and Wait + // Using them separately can wait for multiple outputs in batches Output.Present(); } -void Render(CommandList cmd, Time time) +void Render(GpuRecord cmd, Time time) { using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f, 1f))]); render.Draw(Pipeline, 3); From 2fed8678db13c2e4832f978ffd58e16303cb556c Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 3 Apr 2025 00:12:32 +0800 Subject: [PATCH 29/46] save --- Coplt.Graphics.Core/Core/BindGroupLayout.cs | 160 +++ Coplt.Graphics.Core/Core/BindingLayout.cs | 36 + Coplt.Graphics.Core/Core/GpuDevice.cs | 220 ++-- .../Core/GraphicsShaderPipeline.cs | 4 +- Coplt.Graphics.Core/Core/Shader.cs | 6 +- Coplt.Graphics.Core/Core/ShaderLayout.cs | 68 +- Coplt.Graphics.Core/Core/ShaderPipeline.cs | 5 +- .../Native/FShaderLayoutGroupClass.cs | 6 - .../Native/FShaderLayoutItemDefine.cs | 195 --- Coplt.Graphics.Core/Native/Native.cs | 501 ++++++-- Coplt.Graphics.Native/Api/FFI/Device.h | 12 +- Coplt.Graphics.Native/Api/FFI/Layout.h | 206 +-- Coplt.Graphics.Native/Api/FFI/Pipeline.h | 3 +- Coplt.Graphics.Native/Api/FFI/Sampler.h | 25 + Coplt.Graphics.Native/Api/FFI/Shader.h | 54 + Coplt.Graphics.Native/Api/Include/HashMap.h | 4 +- Coplt.Graphics.Native/D3d12/CMakeLists.txt | 1 - Coplt.Graphics.Native/D3d12/FFI/Layout.h | 20 - Coplt.Graphics.Native/D3d12/Include/Sampler.h | 59 + Coplt.Graphics.Native/D3d12/Include/View.h | 30 +- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 128 -- Coplt.Graphics.Native/D3d12/Src/Binding.h | 40 - Coplt.Graphics.Native/D3d12/Src/Device.cc | 102 +- Coplt.Graphics.Native/D3d12/Src/Device.h | 25 +- .../D3d12/Src/GraphicsPipeline.cc | 38 +- .../D3d12/Src/GraphicsPipeline.h | 10 +- Coplt.Graphics.Native/D3d12/Src/Layout.cc | 409 +++--- Coplt.Graphics.Native/D3d12/Src/Layout.h | 165 ++- Coplt.Graphics.Native/D3d12/Src/Record.cc | 6 +- Coplt.Graphics.Native/D3d12/Src/Record.h | 4 +- Coplt.Graphics.Native/D3d12/Src/Sampler.cc | 27 +- Coplt.Graphics.Native/D3d12/Src/Sampler.h | 1 + Coplt.Graphics.Native/D3d12/Src/View.cc | 1140 ++++++++--------- Examples/Colorful/Example.cs | 27 +- 34 files changed, 2093 insertions(+), 1644 deletions(-) create mode 100644 Coplt.Graphics.Core/Core/BindGroupLayout.cs create mode 100644 Coplt.Graphics.Core/Core/BindingLayout.cs delete mode 100644 Coplt.Graphics.Core/Native/FShaderLayoutGroupClass.cs delete mode 100644 Coplt.Graphics.Core/Native/FShaderLayoutItemDefine.cs delete mode 100644 Coplt.Graphics.Native/D3d12/FFI/Layout.h diff --git a/Coplt.Graphics.Core/Core/BindGroupLayout.cs b/Coplt.Graphics.Core/Core/BindGroupLayout.cs new file mode 100644 index 0000000..556f582 --- /dev/null +++ b/Coplt.Graphics.Core/Core/BindGroupLayout.cs @@ -0,0 +1,160 @@ +using System.Diagnostics; +using Coplt.Dropping; +using Coplt.Graphics.Native; +using Coplt.Graphics.States; + +namespace Coplt.Graphics.Core; + +public enum StaticSamplerBorderColor : byte +{ + Transparent, + Black, + White, + BlackUInt, + WhiteUInt, +} + +public record struct StaticSamplerInfo() +{ + public uint MaxAnisotropy; + public float MipLodBias; + public float MinLod; + public float MaxLod = 3.402823466E38f; + public CmpFunc Cmp; + public FilterMode Mag; + public FilterMode Min; + public FilterMode Mipmap; + public AddressMode U; + public AddressMode V; + public AddressMode W; + public StaticSamplerBorderColor BorderColor; + + public static readonly SamplerInfo PointRepeat = new() + { + Mag = FilterMode.Linear, + Min = FilterMode.Linear, + Mipmap = FilterMode.Point, + }; + + public static readonly SamplerInfo LinearRepeat = new() + { + Mag = FilterMode.Linear, + Min = FilterMode.Linear, + Mipmap = FilterMode.Point, + }; + + public static readonly SamplerInfo TrilinearRepeat = new() + { + Mag = FilterMode.Linear, + Min = FilterMode.Linear, + Mipmap = FilterMode.Linear, + }; + + public static readonly SamplerInfo PointClamp = new() + { + Mag = FilterMode.Linear, + Min = FilterMode.Linear, + Mipmap = FilterMode.Point, + U = AddressMode.Clamp, + V = AddressMode.Clamp, + W = AddressMode.Clamp, + }; + + public static readonly SamplerInfo LinearClamp = new() + { + Mag = FilterMode.Linear, + Min = FilterMode.Linear, + Mipmap = FilterMode.Point, + U = AddressMode.Clamp, + V = AddressMode.Clamp, + W = AddressMode.Clamp, + }; + + public static readonly SamplerInfo TrilinearClamp = new() + { + Mag = FilterMode.Linear, + Min = FilterMode.Linear, + Mipmap = FilterMode.Linear, + U = AddressMode.Clamp, + V = AddressMode.Clamp, + W = AddressMode.Clamp, + }; +} + +public enum BindGroupUsage : byte +{ + /// + /// 一般组 + /// + Common = 0, + /// + /// 提示组的使用是频繁更改的,d3d12 将会尽可能使用根描述符 + /// + Dynamic = 1, +} + +public unsafe record struct BindGroupItem() +{ + /// + public required ulong Id; + /// + public ulong Scope; + /// + /// 数量,或者 StaticSamplers 中的 Index + /// + public uint Count = 1; + /// + /// StaticSamplers 中的 Index + /// + public uint StaticSamplerIndex; + public GraphicsFormat Format; + public required ShaderStageFlags Stages; + public required ShaderLayoutItemView View; + public required ShaderLayoutItemType Type; + public ResourceAccess UavAccess = ResourceAccess.Unknown; + + static BindGroupItem() + { + Debug.Assert(sizeof(FBindGroupItem) == sizeof(BindGroupItem)); + } +} + +[Dropping(Unmanaged = true)] +public sealed unsafe partial class BindGroupLayout : DeviceChild +{ + #region Fields + + internal FBindGroupLayoutData* m_data; + + #endregion + + #region Props + + public new FBindGroupLayout* Ptr => (FBindGroupLayout*)m_ptr; + public ref readonly FBindGroupLayoutData Data => ref *m_data; + public ReadOnlySpan Items => new(Data.Items, (int)Data.NumItems); + public ReadOnlySpan StaticSamplers => new(Data.StaticSamplers, (int)Data.NumStaticSamplers); + public BindGroupUsage Usage => (BindGroupUsage)Data.Usage; + + #endregion + + #region Ctor + + internal BindGroupLayout(FBindGroupLayoutCreateResult result, string? name, GpuDevice device) : base((FGpuObject*)result.Layout, name, device) + { + if (Ptr == null) return; + m_data = result.Data; + } + + #endregion + + #region Drop + + [Drop] + private void Drop() + { + m_data = null; + } + + #endregion +} diff --git a/Coplt.Graphics.Core/Core/BindingLayout.cs b/Coplt.Graphics.Core/Core/BindingLayout.cs new file mode 100644 index 0000000..9e293a5 --- /dev/null +++ b/Coplt.Graphics.Core/Core/BindingLayout.cs @@ -0,0 +1,36 @@ +using System.Runtime.InteropServices; +using Coplt.Dropping; +using Coplt.Graphics.Native; + +namespace Coplt.Graphics.Core; + +public sealed unsafe class BindingLayout : DeviceChild +{ + #region Fields + + internal readonly ShaderLayout m_shader_layout; + internal readonly BindGroupLayout[] m_bind_group_layouts; + + #endregion + + #region Props + + public new FBindingLayout* Ptr => (FBindingLayout*)m_ptr; + public ShaderLayout ShaderLayout => m_shader_layout; + public ReadOnlySpan BindGroupLayouts => m_bind_group_layouts; + + #endregion + + #region Ctor + + internal BindingLayout( + FBindingLayout* ptr, string? name, GpuDevice device, + ShaderLayout shader_layout, BindGroupLayout[] bind_group_layouts + ) : base((FGpuObject*)ptr, name, device) + { + m_shader_layout = shader_layout; + m_bind_group_layouts = bind_group_layouts; + } + + #endregion +} diff --git a/Coplt.Graphics.Core/Core/GpuDevice.cs b/Coplt.Graphics.Core/Core/GpuDevice.cs index a1a1988..fe38486 100644 --- a/Coplt.Graphics.Core/Core/GpuDevice.cs +++ b/Coplt.Graphics.Core/Core/GpuDevice.cs @@ -82,77 +82,116 @@ public GpuIsolate CreateIsolate(string? Name = null, ReadOnlySpan Name8 = #endregion - #region CreateShaderModule + #region CreateShaderLayout - public ShaderModule CreateShaderModule( - ShaderStage Stage, ReadOnlySpan Blob, - String8? EntryPoint = null, + public ShaderLayout CreateShaderLayout( + ReadOnlySpan Items, + ShaderLayoutFlags Flags = ShaderLayoutFlags.None, string? Name = null, ReadOnlySpan Name8 = default ) { fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) - fixed (byte* data = Blob) + fixed (ShaderLayoutItem* p_items = Items) { - FShaderModuleCreateOptions f_options = new() + FShaderLayoutCreateOptions f_options = new() { Name = new(Name, Name8, p_name, p_name8), - EntryPoint = EntryPoint == null ? null : EntryPoint.m_ptr, - Data = data, - Size = (nuint)Blob.Length, - Stage = Stage.ToFFI(), + NumItems = (uint)Items.Length, + Items = (FShaderLayoutItem*)p_items, + Flags = (FShaderLayoutFlags)Flags, }; - FShaderModuleCreateResult result; - Ptr->CreateShaderModule(&f_options, &result).TryThrow(); - return new(result, EntryPoint, Name, this); + FShaderLayoutCreateResult result; + Ptr->CreateShaderLayout(&f_options, &result).TryThrow(); + return new(result, Name, this); } } + private readonly ConcurrentDictionary m_empty_shader_layouts = new(); + + public ShaderLayout GetEmptyShaderLayout(ShaderLayoutFlags Flags = ShaderLayoutFlags.None) => + m_empty_shader_layouts.GetOrAdd( + Flags, static (flags, self) => + { + FGetEmptyShaderLayoutOptions f_options = new() + { + Flags = (FShaderLayoutFlags)flags, + }; + FShaderLayoutCreateResult result; + self.Ptr->GetEmptyShaderLayout(&f_options, &result).TryThrow(); + return new(result, $"Empty Shader Layout ({flags})", self); + }, this + ); + #endregion - #region CreateShaderLayout + #region CreateBindGroupLayout - public ShaderLayout CreateShaderLayout( - ReadOnlySpan Defines, - ReadOnlySpan Samplers = default, // todo - ShaderLayoutFlags Flags = ShaderLayoutFlags.None, + public BindGroupLayout CreateBindGroupLayout( + ReadOnlySpan Items, + ReadOnlySpan StaticSamplers = default, + BindGroupUsage Usage = BindGroupUsage.Common, string? Name = null, ReadOnlySpan Name8 = default ) { fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) + fixed (BindGroupItem* p_items = Items) + fixed (StaticSamplerInfo* p_static_samplers = StaticSamplers) { - fixed (ShaderLayoutItemDefine* p_define = Defines) + FBindGroupLayoutCreateOptions f_options = new() { - FShaderLayoutCreateOptions f_options = new() - { - Name = new(Name, Name8, p_name, p_name8), - Count = (uint)Defines.Length, - Items = (FShaderLayoutItemDefine*)p_define, - Flags = (FShaderLayoutFlags)Flags, - }; - FShaderLayoutCreateResult result; - Ptr->CreateShaderLayout(&f_options, &result).TryThrow(); - return new(result, Name, this); - } + Name = new(Name, Name8, p_name, p_name8), + NumItems = (uint)Items.Length, + Items = (FBindGroupItem*)p_items, + NumStaticSamplers = (uint)StaticSamplers.Length, + StaticSamplers = (FStaticSamplerInfo*)p_static_samplers, + Usage = (FBindGroupUsage)Usage, + }; + FBindGroupLayoutCreateResult result; + Ptr->CreateBindGroupLayout(&f_options, &result).TryThrow(); + return new(result, Name, this); } } - private readonly ConcurrentDictionary m_empty_shader_layouts = new(); + #endregion - public ShaderLayout GetEmptyShaderLayout(ShaderLayoutFlags Flags = ShaderLayoutFlags.None) => - m_empty_shader_layouts.GetOrAdd( - Flags, static (flags, self) => + #region CreateBindingLayout + + public BindingLayout CreateBindingLayout( + ShaderLayout ShaderLayout, + ReadOnlySpan GroupLayouts, + string? Name = null, ReadOnlySpan Name8 = default + ) + { + var groups = ArrayPool.Shared.Rent(GroupLayouts.Length); + try + { + for (var i = 0; i < GroupLayouts.Length; i++) { - FGetEmptyShaderLayoutOptions f_options = new() + groups[i] = (nuint)GroupLayouts[i].Ptr; + } + fixed (char* p_name = Name) + fixed (byte* p_name8 = Name8) + fixed (UIntPtr* p_groups = groups) + { + FBindingLayoutCreateOptions f_options = new() { - Flags = (FShaderLayoutFlags)flags, + Name = new(Name, Name8, p_name, p_name8), + ShaderLayout = ShaderLayout.Ptr, + Groups = (FBindGroupLayout**)p_groups, + NumGroups = (uint)GroupLayouts.Length, }; - FShaderLayoutCreateResult result; - self.Ptr->GetEmptyShaderLayout(&f_options, &result).TryThrow(); - return new(result, $"Empty Shader Layout ({flags})", self); - }, this - ); + FBindingLayout* ptr; + Ptr->CreateBindingLayout(&f_options, &ptr).TryThrow(); + return new(ptr, Name, this, ShaderLayout, GroupLayouts.ToArray()); + } + } + finally + { + ArrayPool.Shared.Return(groups); + } + } #endregion @@ -214,6 +253,63 @@ public ShaderInputLayout CreateShaderInputLayout( #endregion + #region CreateMeshLayout + + public MeshLayout CreateMeshLayout( + ReadOnlySpan Buffers, + ReadOnlySpan Elements, + string? Name = null, ReadOnlySpan Name8 = default + ) + { + fixed (MeshBufferDefine* p_buffers = Buffers) + fixed (MeshBufferElement* p_elements = Elements) + fixed (char* p_name = Name) + fixed (byte* p_name8 = Name8) + { + FMeshLayoutCreateOptions f_options = new() + { + Name = new(Name, Name8, p_name, p_name8), + Buffers = (FMeshBufferDefine*)p_buffers, + Elements = (FMeshBufferElement*)p_elements, + BufferCount = (uint)Buffers.Length, + ElementCount = (uint)Elements.Length, + }; + FMeshLayout* ptr; + Ptr->CreateMeshLayout(&f_options, &ptr).TryThrow(); + return new(ptr, Name, this); + } + } + + #endregion + + #region CreateShaderModule + + public ShaderModule CreateShaderModule( + ShaderStage Stage, ReadOnlySpan Blob, + String8? EntryPoint = null, + string? Name = null, ReadOnlySpan Name8 = default + ) + { + fixed (char* p_name = Name) + fixed (byte* p_name8 = Name8) + fixed (byte* data = Blob) + { + FShaderModuleCreateOptions f_options = new() + { + Name = new(Name, Name8, p_name, p_name8), + EntryPoint = EntryPoint == null ? null : EntryPoint.m_ptr, + Data = data, + Size = (nuint)Blob.Length, + Stage = Stage.ToFFI(), + }; + FShaderModuleCreateResult result; + Ptr->CreateShaderModule(&f_options, &result).TryThrow(); + return new(result, EntryPoint, Name, this); + } + } + + #endregion + #region CreateShader public Shader CreateShader( @@ -226,6 +322,7 @@ public Shader CreateShader( throw new ArgumentException( $"Too many shader modules, there can be a maximum of {FShader.MaxShaderModuleCount}" ); + Layout ??= GetEmptyShaderLayout(InputLayout == null ? ShaderLayoutFlags.None : ShaderLayoutFlags.InputAssembler); Shader.ShaderModuleArray arr = new(); var p_modules = stackalloc FShaderModule*[Modules.Length]; for (var i = 0; i < Modules.Length; i++) @@ -240,7 +337,7 @@ public Shader CreateShader( FShaderCreateOptions f_options = new() { Name = new(Name, Name8, p_name, p_name8), - Layout = Layout == null ? null : Layout.Ptr, + Layout = Layout.Ptr, InputLayout = InputLayout == null ? null : InputLayout.Ptr, Modules = p_modules, Count = (byte)Modules.Length, @@ -253,40 +350,16 @@ public Shader CreateShader( #endregion - #region CreateMeshLayout - - public MeshLayout CreateMeshLayout( - ReadOnlySpan Buffers, - ReadOnlySpan Elements, - string? Name = null, ReadOnlySpan Name8 = default - ) - { - fixed (MeshBufferDefine* p_buffers = Buffers) - fixed (MeshBufferElement* p_elements = Elements) - fixed (char* p_name = Name) - fixed (byte* p_name8 = Name8) - { - FMeshLayoutCreateOptions f_options = new() - { - Name = new(Name, Name8, p_name, p_name8), - Buffers = (FMeshBufferDefine*)p_buffers, - Elements = (FMeshBufferElement*)p_elements, - BufferCount = (uint)Buffers.Length, - ElementCount = (uint)Elements.Length, - }; - FMeshLayout* ptr; - Ptr->CreateMeshLayout(&f_options, &ptr).TryThrow(); - return new(ptr, Name, this); - } - } - - #endregion - #region CreateGraphicsShaderPipeline public GraphicsShaderPipeline CreateGraphicsShaderPipeline( Shader Shader, GraphicsPipelineState PipelineState, MeshLayout? MeshLayout = null, string? Name = null, ReadOnlySpan Name8 = default + ) => CreateGraphicsShaderPipeline(Shader, PipelineState, Shader.Layout.GetEmptyBindingLayout(), MeshLayout, Name, Name8); + + public GraphicsShaderPipeline CreateGraphicsShaderPipeline( + Shader Shader, GraphicsPipelineState PipelineState, BindingLayout BindingLayout, MeshLayout? MeshLayout = null, + string? Name = null, ReadOnlySpan Name8 = default ) { fixed (char* p_name = Name) @@ -298,15 +371,16 @@ public GraphicsShaderPipeline CreateGraphicsShaderPipeline( { Name = new(Name, Name8, p_name, p_name8), Shader = Shader.Ptr, + Layout = BindingLayout.Ptr, }, MeshLayout = MeshLayout == null ? null : MeshLayout.Ptr, GraphicsState = PipelineState.ToFFI(), }; FGraphicsShaderPipeline* ptr; Ptr->CreateGraphicsPipeline(&f_options, &ptr).TryThrow(); - return new(ptr, Name, Shader, PipelineState, MeshLayout); + return new(ptr, Name, Shader, PipelineState, BindingLayout, MeshLayout); } - } + } #endregion diff --git a/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs b/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs index bab5486..d526ab5 100644 --- a/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs +++ b/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs @@ -24,8 +24,8 @@ public sealed unsafe class GraphicsShaderPipeline : ShaderPipeline internal GraphicsShaderPipeline( FGraphicsShaderPipeline* ptr, string? name, - Shader shader, GraphicsPipelineState pipeline_state, MeshLayout? mesh_layout - ) : base((FShaderPipeline*)ptr, name, shader) + Shader shader, GraphicsPipelineState pipeline_state, BindingLayout binding_layout, MeshLayout? mesh_layout + ) : base((FShaderPipeline*)ptr, name, shader, binding_layout) { m_mesh_layout = mesh_layout; m_pipeline_state = pipeline_state; diff --git a/Coplt.Graphics.Core/Core/Shader.cs b/Coplt.Graphics.Core/Core/Shader.cs index f347f92..09cec6e 100644 --- a/Coplt.Graphics.Core/Core/Shader.cs +++ b/Coplt.Graphics.Core/Core/Shader.cs @@ -10,7 +10,7 @@ public sealed unsafe partial class Shader : DeviceChild #region Fields internal FShaderData* m_data; - internal readonly ShaderLayout? m_layout; + internal readonly ShaderLayout m_layout; internal readonly ShaderInputLayout? m_input_layout; internal ShaderModuleArray m_modules; @@ -26,7 +26,7 @@ internal struct ShaderModuleArray public new FShader* Ptr => (FShader*)m_ptr; public ref readonly FShaderData Data => ref *m_data; - public ShaderLayout? Layout => m_layout; + public ShaderLayout Layout => m_layout; public ShaderInputLayout? InputLayout => m_input_layout; public ReadOnlySpan Modules => m_modules; public ShaderStageFlags Stages => Data.Stages.FromFFI(); @@ -42,7 +42,7 @@ internal struct ShaderModuleArray #region Ctor internal Shader( - FShaderCreateResult result, ShaderModuleArray modules, ShaderLayout? layout, ShaderInputLayout? input_layout, string? name, GpuDevice device + FShaderCreateResult result, ShaderModuleArray modules, ShaderLayout layout, ShaderInputLayout? input_layout, string? name, GpuDevice device ) : base((FGpuObject*)result.Shader, name, device) { m_data = result.Data; diff --git a/Coplt.Graphics.Core/Core/ShaderLayout.cs b/Coplt.Graphics.Core/Core/ShaderLayout.cs index e3c1b2f..8c6ed45 100644 --- a/Coplt.Graphics.Core/Core/ShaderLayout.cs +++ b/Coplt.Graphics.Core/Core/ShaderLayout.cs @@ -47,43 +47,37 @@ public enum ShaderLayoutItemType : byte RayTracingAccelerationStructure, } -public enum ShaderLayoutItemUsage : byte +public unsafe record struct ShaderLayoutItem() { /// - /// 动态变量,每帧都可能会改变 + /// 绑定点的 Id,建议从名称缓存自增 id, 不同 stage 不同 scope 的 id 可以重复 /// - Dynamic, + public required ulong Id; /// - /// 持久变量,例如材质参数,一般很少改变,可以进行一定的静态优化,建议将所有材质绑定放到单独的 space 中区分 + /// 绑定点所属范围,和 Id 共同组成唯一定位 /// - Persist, + public ulong Scope; /// - /// 即时变量,例如每次绘制调用都会改变, dx 后端将直接在根签名内,类型是 Sampler 时表示是静态采样器,不支持纹理 + /// dx 后端无论什么时候都是 register, vk 后端一般情况是 binding,类型为 Constants 时是 push const 的 offset,为字节偏移 /// - Instant, -} - -public unsafe record struct ShaderLayoutItemDefine -{ + public required uint Slot; /// - /// dx 后端无论什么时候都是 register, vk 后端一般情况是 binding,类型为 Constants 时是 push const 的 offset,为字节偏移 + /// dx 的 space,vk 的 set,vk 建议尽可能多的拆分 set,dx 的 space 写不写都一样 /// - public uint Slot; public uint Space; /// - /// 类型是 Sampler并且 Usage 是 Static 时是静态采样器描述的索引;其他类型表示数量 + /// 数量,View 是 StaticSampler 时必须是 1,其他必须最少是 1, View 是 Constants 是 32 位值的数量,而不是 byte 的数量 /// - public uint CountOrIndex; + public uint Count = 1; public GraphicsFormat Format; - public ShaderStage Stage; - public ShaderLayoutItemView View; - public ShaderLayoutItemType Type; - public ShaderLayoutItemUsage Usage; - public ResourceAccess UavAccess; + public required ShaderStage Stage; + public required ShaderLayoutItemView View; + public required ShaderLayoutItemType Type; + public ResourceAccess UavAccess = ResourceAccess.Unknown; - static ShaderLayoutItemDefine() + static ShaderLayoutItem() { - Debug.Assert(sizeof(FShaderLayoutItemDefine) == sizeof(ShaderLayoutItemDefine)); + Debug.Assert(sizeof(FShaderLayoutItem) == sizeof(ShaderLayoutItem)); } } @@ -111,9 +105,7 @@ public sealed unsafe partial class ShaderLayout : DeviceChild #region Fields internal FShaderLayoutData* m_data; - internal readonly FRoSlice m_native_defines; - internal readonly FRoSlice m_native_item_infos; - internal readonly FRoSlice m_native_group_classes; + internal BindingLayout? m_empty_binding_layout; #endregion @@ -121,9 +113,8 @@ public sealed unsafe partial class ShaderLayout : DeviceChild public new FShaderLayout* Ptr => (FShaderLayout*)m_ptr; public ref readonly FShaderLayoutData Data => ref *m_data; - public ReadOnlySpan NativeDefines => m_native_defines.Span; - public ReadOnlySpan NativeItemInfos => m_native_item_infos.Span; - public ReadOnlySpan NativeGroupClasses => m_native_group_classes.Span; + public ReadOnlySpan NativeItems => new(Data.Items, (int)Data.NumItems); + public ShaderLayoutFlags Flags => (ShaderLayoutFlags)Data.Flags; #endregion @@ -133,21 +124,6 @@ internal ShaderLayout(FShaderLayoutCreateResult result, string? name, GpuDevice { if (Ptr == null) return; m_data = result.Data; - { - uint count = 0; - var defines = Ptr->GetItemDefines(&count); - m_native_defines = new(defines, count); - } - { - uint count = 0; - var defines = Ptr->GetItemInfos(&count); - m_native_item_infos = new(defines, count); - } - { - uint count = 0; - var defines = Ptr->GetGroupClasses(&count); - m_native_group_classes = new(defines, count); - } } #endregion @@ -161,4 +137,10 @@ private void Drop() } #endregion + + #region GetEmptyBindingLayout + + public BindingLayout GetEmptyBindingLayout() => m_empty_binding_layout ??= Device.CreateBindingLayout(this, [], $"Empty Binding Layout of [{this}]"); + + #endregion } diff --git a/Coplt.Graphics.Core/Core/ShaderPipeline.cs b/Coplt.Graphics.Core/Core/ShaderPipeline.cs index 744fb1c..b13f78a 100644 --- a/Coplt.Graphics.Core/Core/ShaderPipeline.cs +++ b/Coplt.Graphics.Core/Core/ShaderPipeline.cs @@ -7,6 +7,7 @@ public abstract unsafe class ShaderPipeline : DeviceChild #region Fields internal readonly Shader m_shader; + internal readonly BindingLayout m_binding_layout; #endregion @@ -14,14 +15,16 @@ public abstract unsafe class ShaderPipeline : DeviceChild public new FShaderPipeline* Ptr => (FShaderPipeline*)m_ptr; public Shader Shader => m_shader; + public BindingLayout BindingLayout => m_binding_layout; #endregion #region Ctor - internal ShaderPipeline(FShaderPipeline* ptr, string? name, Shader shader) : base((FGpuObject*)ptr, name, shader.Device) + internal ShaderPipeline(FShaderPipeline* ptr, string? name, Shader shader, BindingLayout binding_layout) : base((FGpuObject*)ptr, name, shader.Device) { m_shader = shader; + m_binding_layout = binding_layout; } #endregion diff --git a/Coplt.Graphics.Core/Native/FShaderLayoutGroupClass.cs b/Coplt.Graphics.Core/Native/FShaderLayoutGroupClass.cs deleted file mode 100644 index 8082b7c..0000000 --- a/Coplt.Graphics.Core/Native/FShaderLayoutGroupClass.cs +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index 6d1b8c9..0000000 --- a/Coplt.Graphics.Core/Native/FShaderLayoutItemDefine.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System.Diagnostics; -using Coplt.Graphics.Core; - -namespace Coplt.Graphics.Native; - -public partial struct FShaderLayoutItemDefine -{ - /// - /// 检查兼容性,不兼容将 throw - /// - 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: - { - 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}]." - ); - if (Type is FShaderLayoutItemType.Sampler or FShaderLayoutItemType.ConstantBuffer) - throw new ArgumentException( - $"Binding slot [{index}]: {View} does not support {Type}" - ); - break; - case FShaderLayoutItemView.Uav: - if (!buffer.TryUav()) - throw new ArgumentException( - $"Binding slot [{index}] required [{View}], but [{buffer}] cannot be used as [{View}]." - ); - if (Type is FShaderLayoutItemType.TextureCube or FShaderLayoutItemType.TextureCubeArray or FShaderLayoutItemType.Sampler - or FShaderLayoutItemType.RayTracingAccelerationStructure or FShaderLayoutItemType.ConstantBuffer) - throw new ArgumentException( - $"Binding slot [{index}]: {View} does not support {Type}" - ); - break; - case FShaderLayoutItemView.Sampler: - case FShaderLayoutItemView.Constants: - throw new UnreachableException(); - default: - throw new ArgumentOutOfRangeException(); - } - break; - } - case Core.View.Tags.Image: - { - var image = view.Image; - switch (Type) - { - case FShaderLayoutItemType.ConstantBuffer: - case FShaderLayoutItemType.Buffer: - case FShaderLayoutItemType.RawBuffer: - case FShaderLayoutItemType.StructureBuffer: - case FShaderLayoutItemType.StructureBufferWithCounter: - case FShaderLayoutItemType.Sampler: - case FShaderLayoutItemType.RayTracingAccelerationStructure: - throw new ArgumentException( - $"Binding slot [{index}] required [{Type}] but [{image}] is a {nameof(GpuImage)}." - ); - case FShaderLayoutItemType.Texture1D: - case FShaderLayoutItemType.Texture1DArray: - if (image.Dimension != ImageDimension.One) - throw new ArgumentException( - $"Binding slot [{index}] required [{Type}] but dimension of [{image}] is a {image.Dimension}." - ); - break; - case FShaderLayoutItemType.Texture2D: - case FShaderLayoutItemType.Texture2DArray: - if (image.Dimension != ImageDimension.Two) - throw new ArgumentException( - $"Binding slot [{index}] required [{Type}] but dimension of [{image}] is a {image.Dimension}." - ); - break; - case FShaderLayoutItemType.Texture2DMultisample: - case FShaderLayoutItemType.Texture2DArrayMultisample: - if (image.Dimension != ImageDimension.Two) - throw new ArgumentException( - $"Binding slot [{index}] required [{Type}] but dimension of [{image}] is a {image.Dimension}." - ); - if (image.MultisampleCount <= 1) - throw new ArgumentException( - $"Binding slot [{index}] required [{Type}] but dimension of [{image}] is not multisample." - ); - break; - case FShaderLayoutItemType.Texture3D: - if (image.Dimension != ImageDimension.Three) - throw new ArgumentException( - $"Binding slot [{index}] required [{Type}] but dimension of [{image}] is a {image.Dimension}." - ); - break; - case FShaderLayoutItemType.TextureCube: - case FShaderLayoutItemType.TextureCubeArray: - if (image.Dimension != ImageDimension.Cube) - throw new ArgumentException( - $"Binding slot [{index}] required [{Type}] but dimension of [{image}] is a {image.Dimension}." - ); - break; - default: - throw new ArgumentOutOfRangeException(); - } - switch (View) - { - case FShaderLayoutItemView.Srv: - if (!image.TrySrv()) - throw new ArgumentException( - $"Binding slot [{index}] required [{View}], but [{image}] cannot be used as [{View}]." - ); - if (Type is FShaderLayoutItemType.Sampler or FShaderLayoutItemType.ConstantBuffer) - throw new ArgumentException( - $"Binding slot [{index}]: {View} does not support {Type}" - ); - break; - case FShaderLayoutItemView.Uav: - if (!image.TryUav()) - throw new ArgumentException( - $"Binding slot [{index}] required [{View}], but [{image}] cannot be used as [{View}]." - ); - if (Type is FShaderLayoutItemType.TextureCube or FShaderLayoutItemType.TextureCubeArray or FShaderLayoutItemType.Sampler - or FShaderLayoutItemType.RayTracingAccelerationStructure or FShaderLayoutItemType.ConstantBuffer) - throw new ArgumentException( - $"Binding slot [{index}]: {View} does not support {Type}" - ); - break; - case FShaderLayoutItemView.Cbv: - case FShaderLayoutItemView.Sampler: - case FShaderLayoutItemView.Constants: - throw new UnreachableException(); - default: - throw new ArgumentOutOfRangeException(); - } - break; - } - case Core.View.Tags.Sampler: - { - var sampler = view.Sampler; - if (Type != FShaderLayoutItemType.Sampler) - throw new ArgumentException( - $"Binding slot [{index}] required [{Type}] but [{sampler}] is a {nameof(Sampler)}." - ); - break; - } - default: - throw new ArgumentOutOfRangeException(); - } - } -} diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 1a47960..d477ee2 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1239,18 +1239,26 @@ public FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &") [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, [NativeTypeName("Coplt::FShaderModuleCreateResult *")] FShaderModuleCreateResult* @out) + public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out) + public FResult CreateBindGroupLayout([NativeTypeName("const FBindGroupLayoutCreateOptions &")] FBindGroupLayoutCreateOptions* options, [NativeTypeName("Coplt::FBindGroupLayoutCreateResult *")] FBindGroupLayoutCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateBindingLayout([NativeTypeName("const FBindingLayoutCreateOptions &")] FBindingLayoutCreateOptions* options, FBindingLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1258,31 +1266,31 @@ public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOpti public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out) + public FResult GetEmptyBindGroupLayout([NativeTypeName("Coplt::FBindGroupLayoutCreateResult *")] FBindGroupLayoutCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, [NativeTypeName("Coplt::FShaderCreateResult *")] FShaderCreateResult* @out) + public FResult GetEmptyBindingLayout([NativeTypeName("const FGetEmptyBindingLayoutOptions &")] FGetEmptyBindingLayoutOptions* options, FBindingLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) + public FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1290,7 +1298,31 @@ public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOp public FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions &")] FMeshLayoutCreateOptions* options, FMeshLayout** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[16]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, [NativeTypeName("Coplt::FShaderModuleCreateResult *")] FShaderModuleCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[17]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, [NativeTypeName("Coplt::FShaderCreateResult *")] FShaderCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[18]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1298,7 +1330,7 @@ public FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[16]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[20]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1306,7 +1338,7 @@ public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipe public FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] FGpuBufferCreateOptions* options, FGpuBuffer** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[17]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[21]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1314,7 +1346,7 @@ public FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FGpuImageCreateOptions* options, FGpuImage** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[18]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[22]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1322,7 +1354,7 @@ public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FG public FResult CreateSampler([NativeTypeName("const FGpuSamplerCreateOptions &")] FGpuSamplerCreateOptions* options, FGpuSampler** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[23]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } public interface Interface : FGpuObject.Interface @@ -1336,26 +1368,38 @@ public interface Interface : FGpuObject.Interface FResult CreateIsolate([NativeTypeName("const FGpuIsolateCreateOptions &")] FGpuIsolateCreateOptions* options, [NativeTypeName("Coplt::FGpuIsolateCreateResult &")] FGpuIsolateCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, [NativeTypeName("Coplt::FShaderModuleCreateResult *")] FShaderModuleCreateResult* @out); + FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out); + FResult CreateBindGroupLayout([NativeTypeName("const FBindGroupLayoutCreateOptions &")] FBindGroupLayoutCreateOptions* options, [NativeTypeName("Coplt::FBindGroupLayoutCreateResult *")] FBindGroupLayoutCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateBindingLayout([NativeTypeName("const FBindingLayoutCreateOptions &")] FBindingLayoutCreateOptions* options, FBindingLayout** @out); [return: NativeTypeName("Coplt::FResult")] FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out); + FResult GetEmptyBindGroupLayout([NativeTypeName("Coplt::FBindGroupLayoutCreateResult *")] FBindGroupLayoutCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, [NativeTypeName("Coplt::FShaderCreateResult *")] FShaderCreateResult* @out); + FResult GetEmptyBindingLayout([NativeTypeName("const FGetEmptyBindingLayoutOptions &")] FGetEmptyBindingLayoutOptions* options, FBindingLayout** @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out); + FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out); [return: NativeTypeName("Coplt::FResult")] FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions &")] FMeshLayoutCreateOptions* options, FMeshLayout** @out); + [return: NativeTypeName("Coplt::FResult")] + FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, [NativeTypeName("Coplt::FShaderModuleCreateResult *")] FShaderModuleCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, [NativeTypeName("Coplt::FShaderCreateResult *")] FShaderCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out); + [return: NativeTypeName("Coplt::FResult")] FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out); @@ -2665,40 +2709,10 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderLayout*)Unsafe.AsPointer(ref this)); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("const FShaderLayoutItemDefine *")] - public FShaderLayoutItemDefine* GetItemDefines([NativeTypeName("Coplt::u32 *")] uint* out_count) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((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[8]))((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[9]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); - } - public interface Interface : FGpuObject.Interface { [return: NativeTypeName("Coplt::FShaderLayoutData *")] FShaderLayoutData* ShaderLayoutData(); - - [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); } } @@ -4585,15 +4599,7 @@ public enum FShaderLayoutItemView : byte Uav, Sampler, Constants, - } - - [NativeTypeName("Coplt::u8")] - public enum FShaderLayoutGroupView : byte - { - Cbv, - Srv, - Uav, - Sampler, + StaticSampler, } [NativeTypeName("Coplt::u8")] @@ -4617,23 +4623,14 @@ public enum FShaderLayoutItemType : byte RayTracingAccelerationStructure, } - [NativeTypeName("Coplt::u8")] - public enum FShaderLayoutItemUsage : byte + public partial struct FShaderLayoutItem { - Dynamic, - Persist, - Instant, - } + [NativeTypeName("Coplt::u64")] + public ulong Id; - [NativeTypeName("Coplt::u8")] - public enum FShaderLayoutGroupScope : byte - { - Dynamic, - Persist, - } + [NativeTypeName("Coplt::u64")] + public ulong Scope; - public partial struct FShaderLayoutItemDefine - { [NativeTypeName("Coplt::u32")] public uint Slot; @@ -4641,7 +4638,7 @@ public partial struct FShaderLayoutItemDefine public uint Space; [NativeTypeName("Coplt::u32")] - public uint CountOrIndex; + public uint Count; [NativeTypeName("Coplt::FGraphicsFormat")] public FGraphicsFormat Format; @@ -4655,111 +4652,281 @@ public partial struct FShaderLayoutItemDefine [NativeTypeName("Coplt::FShaderLayoutItemType")] public FShaderLayoutItemType Type; - [NativeTypeName("Coplt::FShaderLayoutItemUsage")] - public FShaderLayoutItemUsage Usage; - [NativeTypeName("Coplt::FResourceAccess")] public FResourceAccess UavAccess; } [NativeTypeName("Coplt::u8")] - public enum FShaderLayoutItemPlace : byte + public enum FShaderLayoutFlags : byte { - None, - Const, - Direct, - Grouped, - StaticSampler, + None = 0, + DynBindLess = 1 << 0, + InputAssembler = 1 << 1, + StreamOutput = 1 << 2, } - public partial struct FShaderLayoutItemInfo + public unsafe partial struct FShaderLayoutCreateOptions { - [NativeTypeName("Coplt::u32")] - public uint Index; + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; - [NativeTypeName("Coplt::u32")] - public uint Class; + [NativeTypeName("Coplt::FShaderLayoutItem *")] + public FShaderLayoutItem* Items; [NativeTypeName("Coplt::u32")] - public uint Group; + public uint NumItems; - [NativeTypeName("Coplt::FShaderLayoutItemPlace")] - public FShaderLayoutItemPlace Place; + [NativeTypeName("Coplt::FShaderLayoutFlags")] + public FShaderLayoutFlags Flags; } - public partial struct FShaderLayoutGroupInfo + public partial struct FGetEmptyShaderLayoutOptions { - [NativeTypeName("Coplt::u32")] - public uint Index; + [NativeTypeName("Coplt::FShaderLayoutFlags")] + public FShaderLayoutFlags Flags; + } + + public unsafe partial struct FShaderLayoutData + { + [NativeTypeName("const FShaderLayoutItem *")] + public FShaderLayoutItem* Items; [NativeTypeName("Coplt::u32")] - public uint Size; + public uint NumItems; - [NativeTypeName("Coplt::FShaderStage")] - public FShaderStage Stage; + [NativeTypeName("Coplt::FShaderLayoutFlags")] + public FShaderLayoutFlags Flags; + } + + public unsafe partial struct FShaderLayoutCreateResult + { + [NativeTypeName("Coplt::FShaderLayout *")] + public FShaderLayout* Layout; - [NativeTypeName("Coplt::FShaderLayoutGroupView")] - public FShaderLayoutGroupView View; + [NativeTypeName("Coplt::FShaderLayoutData *")] + public FShaderLayoutData* Data; } - public unsafe partial struct FShaderLayoutGroupClass + public partial struct FBindGroupItem { - [NativeTypeName("Coplt::FShaderLayoutGroupInfo *")] - public FShaderLayoutGroupInfo* Infos; + [NativeTypeName("Coplt::u64")] + public ulong Id; + + [NativeTypeName("Coplt::u64")] + public ulong Scope; [NativeTypeName("Coplt::u32")] - public uint Size; + public uint Count; + + [NativeTypeName("Coplt::u32")] + public uint StaticSamplerIndex; - [NativeTypeName("Coplt::FShaderLayoutGroupScope")] - public FShaderLayoutGroupScope Scope; + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat Format; - [NativeTypeName("Coplt::b8")] - public B8 Sampler; + [NativeTypeName("Coplt::FShaderStageFlags")] + public FShaderStageFlags Stages; + + [NativeTypeName("Coplt::FShaderLayoutItemView")] + public FShaderLayoutItemView View; + + [NativeTypeName("Coplt::FShaderLayoutItemType")] + public FShaderLayoutItemType Type; + + [NativeTypeName("Coplt::FResourceAccess")] + public FResourceAccess UavAccess; } [NativeTypeName("Coplt::u8")] - public enum FShaderLayoutFlags : byte + public enum FBindGroupUsage : byte { - None = 0, - BindLess = 1 << 0, - InputAssembler = 1 << 1, - StreamOutput = 1 << 2, + Common = 0, + Dynamic = 1, } - public unsafe partial struct FShaderLayoutCreateOptions + public unsafe partial struct FBindGroupLayoutCreateOptions { [NativeTypeName("Coplt::FStr8or16")] public FStr8or16 Name; + [NativeTypeName("Coplt::FBindGroupItem *")] + public FBindGroupItem* Items; + + [NativeTypeName("Coplt::FStaticSamplerInfo *")] + public FStaticSamplerInfo* StaticSamplers; + [NativeTypeName("Coplt::u32")] - public uint Count; + public uint NumItems; - [NativeTypeName("Coplt::FShaderLayoutItemDefine *")] - public FShaderLayoutItemDefine* Items; + [NativeTypeName("Coplt::u32")] + public uint NumStaticSamplers; - [NativeTypeName("Coplt::FShaderLayoutFlags")] - public FShaderLayoutFlags Flags; + [NativeTypeName("Coplt::FBindGroupUsage")] + public FBindGroupUsage Usage; } - public partial struct FGetEmptyShaderLayoutOptions + public unsafe partial struct FBindGroupLayoutData { - [NativeTypeName("Coplt::FShaderLayoutFlags")] - public FShaderLayoutFlags Flags; + [NativeTypeName("const FBindGroupItem *")] + public FBindGroupItem* Items; + + [NativeTypeName("const FStaticSamplerInfo *")] + public FStaticSamplerInfo* StaticSamplers; + + [NativeTypeName("Coplt::u32")] + public uint NumItems; + + [NativeTypeName("Coplt::u32")] + public uint NumStaticSamplers; + + [NativeTypeName("Coplt::FBindGroupUsage")] + public FBindGroupUsage Usage; + } + + [Guid("312C75EB-30F5-40B3-B79E-ACB5498CA9DC")] + [NativeTypeName("struct FBindGroupLayout : Coplt::FGpuObject")] + public unsafe partial struct FBindGroupLayout : FBindGroupLayout.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FBindGroupLayout)); + + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FBindGroupLayout*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FBindGroupLayout*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FBindGroupLayout*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FBindGroupLayout*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FBindGroupLayout*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FBindGroupLayout*)Unsafe.AsPointer(ref this), &result, name); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FBindGroupLayoutData *")] + public FBindGroupLayoutData* BindGroupLayoutData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FBindGroupLayout*)Unsafe.AsPointer(ref this)); + } + + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FBindGroupLayoutData *")] + FBindGroupLayoutData* BindGroupLayoutData(); + } + } + + public unsafe partial struct FBindGroupLayoutCreateResult + { + [NativeTypeName("Coplt::FBindGroupLayout *")] + public FBindGroupLayout* Layout; + + [NativeTypeName("Coplt::FBindGroupLayoutData *")] + public FBindGroupLayoutData* Data; + } + + public unsafe partial struct FBindingLayoutCreateOptions + { + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; + + [NativeTypeName("Coplt::FShaderLayout *")] + public FShaderLayout* ShaderLayout; + + public FBindGroupLayout** Groups; + + [NativeTypeName("Coplt::u32")] + public uint NumGroups; } - public partial struct FShaderLayoutData + public partial struct FGetEmptyBindingLayoutOptions { [NativeTypeName("Coplt::FShaderLayoutFlags")] public FShaderLayoutFlags Flags; } - public unsafe partial struct FShaderLayoutCreateResult + [Guid("BC0B662E-2918-4769-9D0C-1FEE25B32C5D")] + [NativeTypeName("struct FBindingLayout : Coplt::FGpuObject")] + public unsafe partial struct FBindingLayout : FBindingLayout.Interface, INativeGuid { - [NativeTypeName("Coplt::FShaderLayout *")] - public FShaderLayout* Layout; + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FBindingLayout)); - [NativeTypeName("Coplt::FShaderLayoutData *")] - public FShaderLayoutData* Data; + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FBindingLayout*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FBindingLayout*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FBindingLayout*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FBindingLayout*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FBindingLayout*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FBindingLayout*)Unsafe.AsPointer(ref this), &result, name); + } + + public interface Interface : FGpuObject.Interface + { + } } public unsafe partial struct FShaderInputLayoutCreateOptions @@ -4882,6 +5049,9 @@ public unsafe partial struct FShaderPipelineCreateOptions [NativeTypeName("Coplt::FShader *")] public FShader* Shader; + + [NativeTypeName("Coplt::FBindingLayout *")] + public FBindingLayout* Layout; } [Guid("356A2610-34E3-4C01-9904-22E3C5CE2F4E")] @@ -4941,10 +5111,10 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FShaderLayout *")] - public FShaderLayout* GetLayout() + [return: NativeTypeName("Coplt::FBindingLayout *")] + public FBindingLayout* GetLayout() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FShaderPipeline*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FShaderPipeline*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -4959,8 +5129,8 @@ public interface Interface : FGpuObject.Interface [return: NativeTypeName("Coplt::FShader *")] FShader* GetShader(); - [return: NativeTypeName("Coplt::FShaderLayout *")] - FShaderLayout* GetLayout(); + [return: NativeTypeName("Coplt::FBindingLayout *")] + FBindingLayout* GetLayout(); [return: NativeTypeName("Coplt::FShaderStageFlags")] FShaderStageFlags GetStages(); @@ -5024,10 +5194,10 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FShaderLayout *")] - public FShaderLayout* GetLayout() + [return: NativeTypeName("Coplt::FBindingLayout *")] + public FBindingLayout* GetLayout() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FComputeShaderPipeline*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FComputeShaderPipeline*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -5111,10 +5281,10 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FShaderLayout *")] - public FShaderLayout* GetLayout() + [return: NativeTypeName("Coplt::FBindingLayout *")] + public FBindingLayout* GetLayout() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGraphicsShaderPipeline*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGraphicsShaderPipeline*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -5626,6 +5796,55 @@ public interface Interface : FGpuObject.Interface } } + [NativeTypeName("Coplt::u8")] + public enum FStaticSamplerBorderColor : byte + { + Transparent, + Black, + White, + BlackUInt, + WhiteUInt, + } + + public partial struct FStaticSamplerInfo + { + [NativeTypeName("Coplt::u32")] + public uint MaxAnisotropy; + + [NativeTypeName("Coplt::f32")] + public float MipLodBias; + + [NativeTypeName("Coplt::f32")] + public float MinLod; + + [NativeTypeName("Coplt::f32")] + public float MaxLod; + + [NativeTypeName("Coplt::FCmpFunc")] + public FCmpFunc Cmp; + + [NativeTypeName("Coplt::FFilter")] + public FFilter Mag; + + [NativeTypeName("Coplt::FFilter")] + public FFilter Min; + + [NativeTypeName("Coplt::FFilter")] + public FFilter Mipmap; + + [NativeTypeName("Coplt::FAddressMode")] + public FAddressMode U; + + [NativeTypeName("Coplt::FAddressMode")] + public FAddressMode V; + + [NativeTypeName("Coplt::FAddressMode")] + public FAddressMode W; + + [NativeTypeName("Coplt::FStaticSamplerBorderColor")] + public FStaticSamplerBorderColor BorderColor; + } + public static partial class Native { public static readonly Guid IID_FUnknown = new Guid(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); @@ -5678,6 +5897,10 @@ public static partial class Native public static readonly Guid IID_FShaderLayout = new Guid(0x552A498E, 0x8F3A, 0x47FF, 0xA3, 0x35, 0x7A, 0xF2, 0xDE, 0x09, 0x01, 0xE8); + public static readonly Guid IID_FBindGroupLayout = new Guid(0x312C75EB, 0x30F5, 0x40B3, 0xB7, 0x9E, 0xAC, 0xB5, 0x49, 0x8C, 0xA9, 0xDC); + + public static readonly Guid IID_FBindingLayout = new Guid(0xBC0B662E, 0x2918, 0x4769, 0x9D, 0x0C, 0x1F, 0xEE, 0x25, 0xB3, 0x2C, 0x5D); + public static readonly Guid IID_FShaderInputLayout = new Guid(0x70229C9A, 0xFB3D, 0x46B4, 0xB5, 0x34, 0x72, 0xFD, 0xB1, 0x67, 0xD8, 0x07); public static readonly Guid IID_FMeshLayout = new Guid(0x8FE5121F, 0xC2CE, 0x46F5, 0xAA, 0x14, 0xF2, 0x85, 0x95, 0xF3, 0x53, 0x61); diff --git a/Coplt.Graphics.Native/Api/FFI/Device.h b/Coplt.Graphics.Native/Api/FFI/Device.h index c0cac4e..13ba874 100644 --- a/Coplt.Graphics.Native/Api/FFI/Device.h +++ b/Coplt.Graphics.Native/Api/FFI/Device.h @@ -79,15 +79,19 @@ namespace Coplt virtual FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FGpuIsolateCreateResult& out) noexcept = 0; - virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept = 0; virtual FResult CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayoutCreateResult* out) noexcept = 0; + virtual FResult CreateBindGroupLayout(const FBindGroupLayoutCreateOptions& options, FBindGroupLayoutCreateResult* out) noexcept = 0; + virtual FResult CreateBindingLayout(const FBindingLayoutCreateOptions& options, FBindingLayout** out) noexcept = 0; virtual FResult GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayoutCreateResult* out) noexcept = 0; + virtual FResult GetEmptyBindGroupLayout(FBindGroupLayoutCreateResult* out) noexcept = 0; + virtual FResult GetEmptyBindingLayout(const FGetEmptyBindingLayoutOptions& options, FBindingLayout** out) noexcept = 0; virtual FResult CreateShaderInputLayout(const FShaderInputLayoutCreateOptions& options, FShaderInputLayout** out) noexcept = 0; - virtual FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept = 0; - virtual FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept = 0; - virtual FResult CreateMeshLayout(const FMeshLayoutCreateOptions& options, FMeshLayout** out) noexcept = 0; + virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept = 0; + virtual FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept = 0; + + virtual FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept = 0; virtual FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept = 0; virtual FResult CreateBuffer(const FGpuBufferCreateOptions& options, FGpuBuffer** out) noexcept = 0; diff --git a/Coplt.Graphics.Native/Api/FFI/Layout.h b/Coplt.Graphics.Native/Api/FFI/Layout.h index ad56ac2..da87653 100644 --- a/Coplt.Graphics.Native/Api/FFI/Layout.h +++ b/Coplt.Graphics.Native/Api/FFI/Layout.h @@ -2,6 +2,7 @@ #include "Object.h" #include "Shader.h" +#include "Sampler.h" #if FFI_SRC #include @@ -26,14 +27,8 @@ namespace Coplt Sampler, // 将使用 Push Const / Root Const, 忽略 Usage,Type 必须是 ConstantBuffer Constants, - }; - - enum class FShaderLayoutGroupView : u8 - { - Cbv, - Srv, - Uav, - Sampler, + // 静态采样器, Type 必须是 Sampler + StaticSampler, }; enum class FShaderLayoutItemType : u8 @@ -74,34 +69,22 @@ namespace Coplt } #endif - enum class FShaderLayoutItemUsage : u8 - { - // 动态变量,每帧都可能会改变 - Dynamic, - // 持久变量,例如材质参数,一般很少改变,可以进行一定的静态优化,建议将所有材质绑定放到单独的 space 中区分 - Persist, - // 即时变量,例如每次绘制调用都会改变, dx 后端将直接在根签名内,类型是 Sampler 时表示是静态采样器,不支持纹理 - Instant, - }; - - enum class FShaderLayoutGroupScope : u8 - { - Dynamic, - Persist, - }; - - struct FShaderLayoutItemDefine + struct FShaderLayoutItem { + // 绑定点的 Id,建议从名称缓存自增 id, 不同 stage 不同 scope 的 id 可以重复 + u64 Id{}; + // 绑定点所属范围,和 Id 共同组成唯一定位 + u64 Scope{}; // dx 后端无论什么时候都是 register, vk 后端一般情况是 binding,类型为 Constants 时是 push const 的 offset,为字节偏移 u32 Slot{}; + // dx 的 space,vk 的 set,vk 建议尽可能多的拆分 set,dx 的 space 写不写都一样 // todo 引入 spv 修改器运行时修改 vk 的 set u32 Space{}; - // 类型是 Sampler并且 Usage 是 Static 时是静态采样器描述的索引;其他类型表示数量 - u32 CountOrIndex{}; + // 数量,View 是 StaticSampler 时必须是 1,其他必须最少是 1, View 是 Constants 是 32 位值的数量,而不是 byte 的数量 + u32 Count{}; FGraphicsFormat Format{}; FShaderStage Stage{}; FShaderLayoutItemView View{}; FShaderLayoutItemType Type{}; - FShaderLayoutItemUsage Usage{}; FResourceAccess UavAccess{}; #ifdef FFI_SRC @@ -140,117 +123,156 @@ namespace Coplt #endif }; - enum class FShaderLayoutItemPlace : u8 + COPLT_ENUM_FLAGS(FShaderLayoutFlags, u8) { - None, - Const, - Direct, - Grouped, - StaticSampler, + None = 0, + // 是否启用动态无绑定 + DynBindLess = 1 << 0, + // 是否启用输入组装 + InputAssembler = 1 << 1, + // 是否启用流输出 + StreamOutput = 1 << 2, }; - struct FShaderLayoutItemInfo + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FShaderLayoutCreateOptions { - // Const | Direct 时是 Root Index,Grouped 时是 Group 内的 Index - u32 Index{}; - // 所属哪个绑定组类 - u32 Class{}; - // 所属哪个绑定组 - u32 Group{}; - // 绑定放在哪 - FShaderLayoutItemPlace Place{}; + FStr8or16 Name{}; + FShaderLayoutItem* Items{}; + u32 NumItems{}; + + FShaderLayoutFlags Flags{}; }; - struct FShaderLayoutGroupInfo + struct FGetEmptyShaderLayoutOptions { - // Root Index - u32 Index{}; - // 包含多少个绑定 - u32 Size{}; - FShaderStage Stage{}; - FShaderLayoutGroupView View{}; + FShaderLayoutFlags Flags{}; }; - struct FShaderLayoutGroupClass + struct FShaderLayoutData { - FShaderLayoutGroupInfo* Infos{}; - u32 Size{}; - FShaderLayoutGroupScope Scope{}; - b8 Sampler{}; + const FShaderLayoutItem* Items{}; + u32 NumItems{}; + FShaderLayoutFlags Flags{}; + }; + + COPLT_INTERFACE_DEFINE(FShaderLayout, "552a498e-8f3a-47ff-a335-7af2de0901e8", FGpuObject) + { + virtual FShaderLayoutData* ShaderLayoutData() noexcept = 0; #if FFI_SRC - std::span AsSpan() const noexcept + std::span GetItems() noexcept { - return std::span{Infos, static_cast(Size)}; + const auto data = ShaderLayoutData(); + return std::span{data->Items, static_cast(data->NumItems)}; } #endif }; - COPLT_ENUM_FLAGS(FShaderLayoutFlags, u8) + struct FShaderLayoutCreateResult { - None = 0, - // 是否启用无绑定 - BindLess = 1 << 0, - // 是否启用输入组装 - InputAssembler = 1 << 1, - // 是否启用流输出 - StreamOutput = 1 << 2, + FShaderLayout* Layout{}; + FShaderLayoutData* Data{}; }; - struct FShaderLayoutCreateOptions + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FBindGroupItem { - FStr8or16 Name{}; + // 绑定点的 Id,建议从名称缓存自增 id, 不同 stage 不同 scope 的 id 可以重复 + u64 Id{}; + // 绑定点所属范围,和 Id 共同组成唯一定位 + u64 Scope{}; + // 数量 u32 Count{}; - FShaderLayoutItemDefine* Items{}; - // todo 静态采样器 + // StaticSamplers 中的 Index + u32 StaticSamplerIndex{}; + FGraphicsFormat Format{}; + FShaderStageFlags Stages{}; + FShaderLayoutItemView View{}; + FShaderLayoutItemType Type{}; + FResourceAccess UavAccess{}; + }; - FShaderLayoutFlags Flags{}; + enum class FBindGroupUsage : u8 + { + // 一般组 + Common = 0, + // 提示组的使用是频繁更改的,d3d12 将会尽可能使用根描述符 + Dynamic = 1, }; - struct FGetEmptyShaderLayoutOptions + struct FBindGroupLayoutCreateOptions { - FShaderLayoutFlags Flags{}; + FStr8or16 Name{}; + FBindGroupItem* Items{}; + FStaticSamplerInfo* StaticSamplers{}; + u32 NumItems{}; + u32 NumStaticSamplers{}; + FBindGroupUsage Usage{}; }; - struct FShaderLayoutData + struct FBindGroupLayoutData { - FShaderLayoutFlags Flags{}; + const FBindGroupItem* Items{}; + const FStaticSamplerInfo* StaticSamplers{}; + u32 NumItems{}; + u32 NumStaticSamplers{}; + FBindGroupUsage Usage{}; }; - COPLT_INTERFACE_DEFINE(FShaderLayout, "552a498e-8f3a-47ff-a335-7af2de0901e8", FGpuObject) + COPLT_INTERFACE_DEFINE(FBindGroupLayout, "312c75eb-30f5-40b3-b79e-acb5498ca9dc", FGpuObject) { - virtual FShaderLayoutData* ShaderLayoutData() noexcept = 0; - 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; + virtual FBindGroupLayoutData* BindGroupLayoutData() noexcept = 0; #if FFI_SRC - std::span GetItemDefines() noexcept + std::span GetItems() noexcept { - u32 count{}; - return std::span{GetItemDefines(&count), static_cast(count)}; + const auto data = BindGroupLayoutData(); + return std::span{data->Items, static_cast(data->NumItems)}; } - std::span GetItemInfos() noexcept + std::span GetStaticSamplers() noexcept { - u32 count{}; - return std::span{GetItemInfos(&count), static_cast(count)}; + const auto data = BindGroupLayoutData(); + return std::span{data->StaticSamplers, static_cast(data->NumStaticSamplers)}; } - std::span GetGroupClasses() noexcept + FBindGroupLayoutData& Data() noexcept { - u32 count{}; - return std::span{GetGroupClasses(&count), static_cast(count)}; + return *BindGroupLayoutData(); } #endif }; - struct FShaderLayoutCreateResult + struct FBindGroupLayoutCreateResult { - FShaderLayout* Layout{}; - FShaderLayoutData* Data{}; + FBindGroupLayout* Layout{}; + FBindGroupLayoutData* Data{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FBindingLayoutCreateOptions + { + FStr8or16 Name{}; + FShaderLayout* ShaderLayout{}; + FBindGroupLayout** Groups{}; + u32 NumGroups{}; + }; + + struct FGetEmptyBindingLayoutOptions + { + FShaderLayoutFlags Flags{}; }; + COPLT_INTERFACE_DEFINE(FBindingLayout, "bc0b662e-2918-4769-9d0c-1fee25b32c5d", FGpuObject) + { + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + struct FShaderInputLayoutCreateOptions { FStr8or16 Name{}; @@ -271,6 +293,8 @@ namespace Coplt #endif }; + //////////////////////////////////////////////////////////////////////////////////////////////////// + struct FMeshLayoutCreateOptions { FStr8or16 Name{}; diff --git a/Coplt.Graphics.Native/Api/FFI/Pipeline.h b/Coplt.Graphics.Native/Api/FFI/Pipeline.h index 03dad7b..6e5590e 100644 --- a/Coplt.Graphics.Native/Api/FFI/Pipeline.h +++ b/Coplt.Graphics.Native/Api/FFI/Pipeline.h @@ -10,12 +10,13 @@ namespace Coplt { FStr8or16 Name{}; FShader* Shader{}; + FBindingLayout* Layout{}; }; COPLT_INTERFACE_DEFINE(FShaderPipeline, "356a2610-34e3-4c01-9904-22e3c5ce2f4e", FGpuObject) { virtual FShader* GetShader() noexcept = 0; - virtual FShaderLayout* GetLayout() noexcept = 0; + virtual FBindingLayout* GetLayout() noexcept = 0; virtual FShaderStageFlags GetStages() noexcept = 0; }; diff --git a/Coplt.Graphics.Native/Api/FFI/Sampler.h b/Coplt.Graphics.Native/Api/FFI/Sampler.h index a7c8200..e4200fe 100644 --- a/Coplt.Graphics.Native/Api/FFI/Sampler.h +++ b/Coplt.Graphics.Native/Api/FFI/Sampler.h @@ -47,4 +47,29 @@ namespace Coplt { virtual const FSamplerInfo* Info() const noexcept = 0; }; + + enum class FStaticSamplerBorderColor : u8 + { + Transparent, + Black, + White, + BlackUInt, + WhiteUInt, + }; + + struct FStaticSamplerInfo + { + u32 MaxAnisotropy{0}; + f32 MipLodBias{}; + f32 MinLod{}; + f32 MaxLod{3.402823466E38}; + FCmpFunc Cmp{}; + FFilter Mag{}; + FFilter Min{}; + FFilter Mipmap{}; + FAddressMode U{}; + FAddressMode V{}; + FAddressMode W{}; + FStaticSamplerBorderColor BorderColor{}; + }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Shader.h b/Coplt.Graphics.Native/Api/FFI/Shader.h index 27c89c9..5c57543 100644 --- a/Coplt.Graphics.Native/Api/FFI/Shader.h +++ b/Coplt.Graphics.Native/Api/FFI/Shader.h @@ -1,5 +1,9 @@ #pragma once +#ifdef FFI_SRC +#include +#endif + #include "GpuObject.h" #include "PipelineState.h" @@ -128,4 +132,54 @@ namespace Coplt FShader* Shader{}; FShaderData* Data{}; }; + + #ifdef FFI_SRC + struct StageIterator final + { + FShaderStageFlags m_flags{}; + + StageIterator() = default; + + explicit StageIterator(const FShaderStageFlags flags) noexcept : m_flags(flags) + { + } + + bool operator!=(const StageIterator& rhs) const noexcept + { + return m_flags != rhs.m_flags; + } + + StageIterator& operator++() noexcept + { + m_flags &= static_cast(static_cast(m_flags) - 1); + return *this; + } + + FShaderStage operator*() const noexcept + { + return static_cast(std::countr_zero(static_cast(m_flags))); + } + }; + + struct IterStage final + { + FShaderStageFlags const m_flags{}; + + IterStage() = default; + + explicit IterStage(const FShaderStageFlags flags) noexcept : m_flags(flags) + { + } + + StageIterator begin() const noexcept + { + return StageIterator(m_flags); + } + + StageIterator end() const noexcept + { + return StageIterator(FShaderStageFlags::None); + } + }; + #endif } diff --git a/Coplt.Graphics.Native/Api/Include/HashMap.h b/Coplt.Graphics.Native/Api/Include/HashMap.h index 5c1c2c8..887306a 100644 --- a/Coplt.Graphics.Native/Api/Include/HashMap.h +++ b/Coplt.Graphics.Native/Api/Include/HashMap.h @@ -423,7 +423,7 @@ namespace Coplt Value* TryGet(const Key& key) const { auto entry = FindEntry(key); - if (entry) return std::addressof(entry->value); + if (entry) return std::addressof(entry->second); return nullptr; } @@ -567,7 +567,7 @@ namespace Coplt } // 返回是否添加 - template CreateValue> + template > CreateValue> bool TryAdd(const Key& key, CreateValue create_value) { return TryInsert( diff --git a/Coplt.Graphics.Native/D3d12/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index 7d1e6f8..bb56662 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -20,7 +20,6 @@ add_library(${target_name} SHARED FFI/Pipeline.h Src/GraphicsPipeline.h Src/GraphicsPipeline.cc - FFI/Layout.h Src/Layout.h Src/Layout.cc Include/ShaderVisibility.h diff --git a/Coplt.Graphics.Native/D3d12/FFI/Layout.h b/Coplt.Graphics.Native/D3d12/FFI/Layout.h deleted file mode 100644 index e071546..0000000 --- a/Coplt.Graphics.Native/D3d12/FFI/Layout.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "../../Api/FFI/Layout.h" - -namespace Coplt -{ - COPLT_INTERFACE_DEFINE(FD3d12ShaderLayout, "384259cf-c392-4903-8d2c-ec959c287912", FShaderLayout) - { - // 返回 ID3D12RootSignature* - virtual void* GetRootSignaturePtr() noexcept = 0; - }; - - COPLT_INTERFACE_DEFINE(FD3d12ShaderInputLayout, "3dfc8de2-bca2-48ae-b869-850cb11b3ee9", FShaderInputLayout) - { - }; - - COPLT_INTERFACE_DEFINE(FD3d12MeshLayout, "2c6e52e9-6fa1-457a-8f99-a734d63b62c2", FMeshLayout) - { - }; -} diff --git a/Coplt.Graphics.Native/D3d12/Include/Sampler.h b/Coplt.Graphics.Native/D3d12/Include/Sampler.h index 796fb87..fb79d08 100644 --- a/Coplt.Graphics.Native/D3d12/Include/Sampler.h +++ b/Coplt.Graphics.Native/D3d12/Include/Sampler.h @@ -3,6 +3,7 @@ #include #include "../../Api/FFI/Sampler.h" +#include "../Include/PipelineState.h" namespace Coplt { @@ -34,4 +35,62 @@ namespace Coplt a = a | b; return a; } + + inline void SetBorderColor(const FSamplerInfo& info, D3D12_SAMPLER_DESC& desc) + { + desc.BorderColor[0] = info.BorderColor[0]; + desc.BorderColor[1] = info.BorderColor[1]; + desc.BorderColor[2] = info.BorderColor[2]; + desc.BorderColor[3] = info.BorderColor[3]; + } + + inline void SetBorderColor(const FStaticSamplerInfo& info, D3D12_STATIC_SAMPLER_DESC& desc) + { + switch (info.BorderColor) + { + case FStaticSamplerBorderColor::Transparent: + desc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + return; + case FStaticSamplerBorderColor::Black: + desc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; + return; + case FStaticSamplerBorderColor::White: + desc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE; + return; + case FStaticSamplerBorderColor::BlackUInt: + desc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK_UINT; + return; + case FStaticSamplerBorderColor::WhiteUInt: + desc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE_UINT; + return; + } + desc.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + } + + void SetDesc(const auto& info, auto& desc) + { + desc.MaxLOD = info.MaxLod; + desc.MinLOD = info.MinLod; + SetBorderColor(info, desc); + desc.ComparisonFunc = ToDx(info.Cmp); + desc.MaxAnisotropy = info.MaxAnisotropy; + desc.MipLODBias = info.MipLodBias; + desc.AddressW = ToDx(info.W); + desc.AddressV = ToDx(info.V); + desc.AddressU = ToDx(info.U); + desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + if (desc.MaxAnisotropy > 0) + { + if (info.Cmp != FCmpFunc::Off) desc.Filter = D3D12_FILTER_COMPARISON_ANISOTROPIC; + else if (info.Mipmap == FFilter::Linear) desc.Filter = D3D12_FILTER_ANISOTROPIC; + else desc.Filter = D3D12_FILTER_MIN_MAG_ANISOTROPIC_MIP_POINT; + } + else + { + if (info.Mipmap == FFilter::Linear) desc.Filter |= D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR; + if (info.Mag == FFilter::Linear) desc.Filter |= D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; + if (info.Min == FFilter::Linear) desc.Filter |= D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT; + if (info.Cmp != FCmpFunc::Off) desc.Filter |= D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT; + } + } } diff --git a/Coplt.Graphics.Native/D3d12/Include/View.h b/Coplt.Graphics.Native/D3d12/Include/View.h index 180b249..c30d685 100644 --- a/Coplt.Graphics.Native/D3d12/Include/View.h +++ b/Coplt.Graphics.Native/D3d12/Include/View.h @@ -61,20 +61,20 @@ namespace Coplt View& operator=(const Rc& image); View& operator=(Rc&& image); - void CreateDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type - ) const; - static void CreateNullDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView view - ); - void CreateBufferDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type - ) const; - void CreateImageDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type - ) const; - void CreateSamplerDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type - ) const; + // void CreateDescriptor( + // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type + // ) const; + // static void CreateNullDescriptor( + // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView view + // ); + // void CreateBufferDescriptor( + // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type + // ) const; + // void CreateImageDescriptor( + // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type + // ) const; + // void CreateSamplerDescriptor( + // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type + // ) const; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index e5c23bc..26e1098 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -2,7 +2,6 @@ #include "Layout.h" #include "../../Api/Include/Error.h" -#include "../FFI/Layout.h" #include "Queue.h" #include "../../Api/Include/AllocObjectId.h" #include "../Include/GraphicsFormat.h" @@ -14,136 +13,9 @@ D3d12ShaderBinding::D3d12ShaderBinding( ) : m_device(std::move(device)) { m_dx_device = m_device->m_device; - - m_layout = Rc::UnsafeClone(options.Layout->QueryInterface()); - if (m_layout == nullptr) - COPLT_THROW("Layout from different backends"); - - const auto defs = m_layout->GetItemDefines(); - m_views = std::vector(defs.size(), {}); - - const auto classes = m_layout->GetTableGroups(); - m_item_indexes = std::vector>>(classes.size(), {}); - m_desc_heaps = std::vector>>(classes.size(), {}); - // m_allocations = std::vector>(classes.size(), {}); - for (size_t i = 0; i < classes.size(); ++i) - { - const auto& group = classes[i]; - m_desc_heaps[i] = std::vector>(group.Metas.size(), {}); - // m_allocations[i] = std::vector(group.Metas.size(), {}); - auto& items = m_item_indexes[i] = std::vector>(group.Metas.size(), {}); - for (size_t j = 0; j < group.Metas.size(); ++j) - { - const auto& meta = group.Metas[j]; - items[j].reserve(meta.Ranges.size()); - } - } - - const auto infos = m_layout->GetItemInfos(); - for (size_t i = 0; i < infos.size(); ++i) - { - const auto& info = infos[i]; - m_item_indexes[info.Class][info.Group].push_back(i); - } } FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept { return FResult::None(); } - -void D3d12ShaderBinding::Set(const std::span bindings) -{ - 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: - break; - case FViewType::Buffer: - if (!define.IsAllowBuffer()) - COPLT_THROW_FMT("Binding index {} is not allowed to bind to buffer.", Index); - break; - case FViewType::Image: - if (!define.IsAllowTexture()) - COPLT_THROW_FMT("Binding index {} is not allowed to bind to image.", Index); - break; - } - m_views[Index] = View; - if (info.Place == FShaderLayoutItemPlace::Grouped) - { - m_changed_groups.Add((static_cast(info.Class) << 32) | static_cast(info.Group)); - } - } -} - -const Rc& D3d12ShaderBinding::Layout() noexcept -{ - return m_layout; -} - -std::span D3d12ShaderBinding::Views() noexcept -{ - return m_views; -} - -bool D3d12ShaderBinding::Changed() noexcept -{ - return !m_changed_groups.IsEmpty(); -} - -const HashSet& D3d12ShaderBinding::ChangedGroups() noexcept -{ - return m_changed_groups; -} - -std::span>> D3d12ShaderBinding::DescHeaps() noexcept -{ - return m_desc_heaps; -} - -void D3d12ShaderBinding::Update(NonNull queue) -{ - if (!Changed()) return; - const auto defs = m_layout->GetItemDefines(); - const auto infos = m_layout->GetItemInfos(); - const auto classes = m_layout->GetTableGroups(); - // todo 改成 changed items - for (const auto [c, g] : IterChangedGroups()) - { - const auto& groups = classes[c]; - const auto& meta = groups.Metas[g]; - if (meta.Size == 0) continue; - auto& heap = m_desc_heaps[c][g]; - if (heap == nullptr) - heap = new DescriptorHeap( - m_dx_device, - groups.Sampler ? D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER : D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, - meta.Size, false - ); - heap->IncVersion(); - const auto& indexes = m_item_indexes[c][g]; - const auto handle_start = heap->GetLocalHandle(); - const auto stride = heap->Stride(); - for (const auto& i : indexes) - { - const auto& def = defs[i]; - const auto& info = infos[i]; - const auto& range = meta.Ranges[info.Index]; - const CD3DX12_CPU_DESCRIPTOR_HANDLE handle(handle_start, static_cast(range.OffsetInDescriptorsFromTableStart), stride); - const auto& view = m_views[i]; - view.CreateDescriptor(m_dx_device.Get(), def, handle, meta.View); - } - } -} - -void D3d12ShaderBinding::ApplyChange() -{ - m_changed_groups.Clear(); -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index 4c8000c..72130ef 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -7,7 +7,6 @@ #include "../../Api/Include/Object.h" #include "../../Api/Include/Ptr.h" #include "../FFI/Binding.h" -#include "../FFI/Layout.h" #include "../Include/View.h" namespace Coplt @@ -18,54 +17,15 @@ 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& ChangedGroups() noexcept = 0; - virtual std::span>> DescHeaps() noexcept = 0; - // virtual std::span> Allocations() noexcept = 0; - virtual void Set(std::span bindings) = 0; - - // 更新更改过的表,但是不会消除更新 - virtual void Update(NonNull queue) = 0; - // 实际消除更新 - virtual void ApplyChange() = 0; - - auto IterChangedGroups() noexcept - { - return ChangedGroups() | std::ranges::views::transform([](const u64 cg) - { - return std::pair{static_cast(cg >> 32), static_cast(cg & 0xFFFFFFFF)}; - }); - } }; struct D3d12ShaderBinding final : GpuObject { Rc m_device{}; ComPtr m_dx_device{}; - Rc m_layout{}; - std::vector m_views{}; - std::vector>> m_item_indexes{}; - std::vector>> m_desc_heaps{}; - // std::vector> m_allocations{}; - HashSet m_changed_groups{}; explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); - FResult SetName(const FStr8or16& name) noexcept override; - - void Set(std::span bindings) override; - - const Rc& Layout() noexcept override; - std::span Views() noexcept override; - bool Changed() noexcept override; - const HashSet& ChangedGroups() noexcept override; - std::span>> DescHeaps() noexcept override; - // std::span> Allocations() noexcept override; - - void Update(NonNull queue) override; - void ApplyChange() override; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 8008903..8ca5e9b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -128,21 +128,28 @@ void* D3d12GpuDevice::GetRawDevice() noexcept return m_device0.Get(); } - -const Rc& D3d12GpuDevice::GetEmptyLayout(FShaderLayoutFlags flags) +const Rc& D3d12GpuDevice::GetEmptyShaderLayout(FShaderLayoutFlags flags) { if (!m_empty_layouts) - m_empty_layouts = std::make_unique(); + m_empty_layouts = std::make_unique(); return m_empty_layouts->GetOrAdd(flags, [&](auto& p) { - const auto name = fmt::format(L"Empty Layout {}", static_cast(flags)); FShaderLayoutCreateOptions options{}; - options.Name = FStr8or16(name); options.Flags = flags; - p = Rc(new D3d12ShaderLayout(this->CloneThis(), options)); + p = Rc(new D3d12ShaderLayout(options)); }); } +const Rc& D3d12GpuDevice::GetEmptyBindGroupLayout() +{ + if (m_empty_bind_group_layout == nullptr) + { + constexpr FBindGroupLayoutCreateOptions options{}; + m_empty_bind_group_layout = Rc(new D3d12BindGroupLayout(options)); + } + return m_empty_bind_group_layout; +} + const Rc& D3d12GpuDevice::GetEmptyMeshLayout() { if (m_empty_mesh_layout == nullptr) @@ -154,6 +161,25 @@ const Rc& D3d12GpuDevice::GetEmptyMeshLayout() return m_empty_mesh_layout; } +const Rc& D3d12GpuDevice::GetEmptyBindingLayout(FShaderLayoutFlags flags) +{ + if (!m_empty_binding_layout) + m_empty_binding_layout = std::make_unique(); + return m_empty_binding_layout->GetOrAdd(flags, [&](auto& p) + { + const Rc shader_layout = GetEmptyShaderLayout(flags); + std::wstring name{}; + FBindingLayoutCreateOptions options{}; + if (Debug()) + { + name = fmt::format(L"Empty Binding Layout {}", static_cast(flags)); + options.Name = FStr8or16(name); + } + options.ShaderLayout = shader_layout.get(); + p = Rc(new D3d12BindingLayout(this->CloneThis(), options)); + }); +} + FResult D3d12GpuDevice::CreateIsolate(const FGpuIsolateCreateOptions& options, FGpuIsolateCreateResult& out) noexcept { return feb([&] @@ -171,37 +197,65 @@ FGpuIsolateCreateResult D3d12GpuDevice::CreateIsolate(const FGpuIsolateCreateOpt return out; } -FResult D3d12GpuDevice::CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept +FResult D3d12GpuDevice::CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayoutCreateResult* out) noexcept { return feb([&] { - const auto ptr = ShaderModule::Create(options); - out->ShaderModule = ptr; + const auto ptr = new D3d12ShaderLayout(options); + out->Layout = ptr; out->Data = ptr; }); } -FResult D3d12GpuDevice::CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayoutCreateResult* out) noexcept +FResult D3d12GpuDevice::CreateBindGroupLayout(const FBindGroupLayoutCreateOptions& options, FBindGroupLayoutCreateResult* out) noexcept { return feb([&] { - const auto ptr = new D3d12ShaderLayout(this->CloneThis(), options); + const auto ptr = new D3d12BindGroupLayout(options); out->Layout = ptr; out->Data = ptr; }); } +FResult D3d12GpuDevice::CreateBindingLayout(const FBindingLayoutCreateOptions& options, FBindingLayout** out) noexcept +{ + return feb([&] + { + *out = new D3d12BindingLayout(this->CloneThis(), options); + }); +} + FResult D3d12GpuDevice::GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayoutCreateResult* out) noexcept { return feb([&] { - Rc r = GetEmptyLayout(options.Flags); + Rc r = GetEmptyShaderLayout(options.Flags); + const auto ptr = r.leak(); + out->Layout = ptr; + out->Data = ptr; + }); +} + +FResult D3d12GpuDevice::GetEmptyBindGroupLayout(FBindGroupLayoutCreateResult* out) noexcept +{ + return feb([&] + { + Rc r = GetEmptyBindGroupLayout(); const auto ptr = r.leak(); out->Layout = ptr; out->Data = ptr; }); } +FResult D3d12GpuDevice::GetEmptyBindingLayout(const FGetEmptyBindingLayoutOptions& options, FBindingLayout** out) noexcept +{ + return feb([&] + { + Rc r = GetEmptyBindingLayout(options.Flags); + *out = r.leak(); + }); +} + FResult D3d12GpuDevice::CreateShaderInputLayout(const FShaderInputLayoutCreateOptions& options, FShaderInputLayout** out) noexcept { return feb([&] @@ -210,29 +264,39 @@ FResult D3d12GpuDevice::CreateShaderInputLayout(const FShaderInputLayoutCreateOp }); } -FResult D3d12GpuDevice::CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept +FResult D3d12GpuDevice::CreateMeshLayout(const FMeshLayoutCreateOptions& options, FMeshLayout** out) noexcept { return feb([&] { - const auto ptr = new Shader(this->CloneThis(), options); - out->Shader = ptr; + *out = new D3d12MeshLayout(this->CloneThis(), options); + }); +} + +FResult D3d12GpuDevice::CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept +{ + return feb([&] + { + const auto ptr = ShaderModule::Create(options); + out->ShaderModule = ptr; out->Data = ptr; }); } -FResult D3d12GpuDevice::CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept +FResult D3d12GpuDevice::CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept { return feb([&] { - *out = new D3d12ShaderBinding(this->CloneThis(), options); + const auto ptr = new Shader(this->CloneThis(), options); + out->Shader = ptr; + out->Data = ptr; }); } -FResult D3d12GpuDevice::CreateMeshLayout(const FMeshLayoutCreateOptions& options, FMeshLayout** out) noexcept +FResult D3d12GpuDevice::CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept { return feb([&] { - *out = new D3d12MeshLayout(this->CloneThis(), options); + *out = new D3d12ShaderBinding(this->CloneThis(), options); }); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index 4c9f3bf..6a0a3f7 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -13,11 +13,14 @@ namespace Coplt { struct D3d12GpuAdapter; struct D3d12ShaderLayout; + struct D3d12BindGroupLayout; + struct D3d12BindingLayout; struct D3d12MeshLayout; struct D3d12GpuDevice final : GpuObject { - using EmptyLayouts = HashMap>; + using EmptyShaderLayouts = HashMap>; + using EmptyBindingLayouts = HashMap>; Rc m_instance{}; Rc m_adapter{}; @@ -25,7 +28,9 @@ namespace Coplt ComPtr m_device0{}; ComPtr m_info_queue{}; ComPtr m_gpu_allocator{}; - Box m_empty_layouts{}; + Box m_empty_layouts{}; + Rc m_empty_bind_group_layout{}; + Box m_empty_binding_layout{}; Rc m_empty_mesh_layout{}; DWORD m_callback_cookie{}; @@ -43,21 +48,27 @@ namespace Coplt void* GetRawDevice() noexcept override; - const Rc& GetEmptyLayout(FShaderLayoutFlags flags); + const Rc& GetEmptyShaderLayout(FShaderLayoutFlags flags); + const Rc& GetEmptyBindGroupLayout(); const Rc& GetEmptyMeshLayout(); + const Rc& GetEmptyBindingLayout(FShaderLayoutFlags flags); FResult CreateIsolate(const FGpuIsolateCreateOptions& options, FGpuIsolateCreateResult& out) noexcept override; FGpuIsolateCreateResult CreateIsolate(const FGpuIsolateCreateOptions& options); - FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept override; FResult CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayoutCreateResult* out) noexcept override; + FResult CreateBindGroupLayout(const FBindGroupLayoutCreateOptions& options, FBindGroupLayoutCreateResult* out) noexcept override; + FResult CreateBindingLayout(const FBindingLayoutCreateOptions& options, FBindingLayout** out) noexcept override; FResult GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayoutCreateResult* out) noexcept override; + FResult GetEmptyBindGroupLayout(FBindGroupLayoutCreateResult* out) noexcept override; + FResult GetEmptyBindingLayout(const FGetEmptyBindingLayoutOptions& options, FBindingLayout** out) noexcept override; FResult CreateShaderInputLayout(const FShaderInputLayoutCreateOptions& options, FShaderInputLayout** out) noexcept override; - FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept override; - FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; - FResult CreateMeshLayout(const FMeshLayoutCreateOptions& options, FMeshLayout** out) noexcept override; + FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept override; + FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept override; + + FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept override; FResult CreateBuffer(const FGpuBufferCreateOptions& options, FGpuBuffer** out) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc index 3053860..720b8ef 100644 --- a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc +++ b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc @@ -87,8 +87,8 @@ namespace std::vector& tmp_strings, std::vector& dst, std::vector& input_slots, - FD3d12ShaderInputLayout* input_layout, - FD3d12MeshLayout* mesh_layout + FShaderInputLayout* input_layout, + FMeshLayout* mesh_layout ) { const auto buffers = mesh_layout->GetBuffers(); @@ -138,12 +138,14 @@ D3d12GraphicsShaderPipeline::D3d12GraphicsShaderPipeline( if (!HasFlags(m_shader->Stages(), FShaderStageFlags::Pixel)) COPLT_THROW("The shader is not graphics"); - if (auto layout = m_shader->Layout()) + if (m_shader->Layout()) { - auto dx_layout = layout->QueryInterface(); - if (dx_layout == nullptr) + auto layout = NonNull(options.Layout)->QueryInterface(); + if (layout == nullptr) COPLT_THROW("Shader layout from different backends"); - m_layout = Rc::UnsafeClone(dx_layout); + m_layout = Rc::UnsafeClone(layout); + if (m_layout->ShaderLayout()->ObjectId() != m_shader->Layout()->ObjectId()) + COPLT_THROW("Differences between binding layout and shader layout"); } else { @@ -152,10 +154,10 @@ D3d12GraphicsShaderPipeline::D3d12GraphicsShaderPipeline( { flags |= FShaderLayoutFlags::InputAssembler; } - m_layout = m_device->GetEmptyLayout(flags); + m_layout = m_device->GetEmptyBindingLayout(flags); } - auto root_signature = static_cast(m_layout->GetRootSignaturePtr()); + auto root_signature = m_layout->RootSignature().Get(); std::vector tmp_strings{}; std::vector input_element_desc{}; @@ -176,22 +178,16 @@ D3d12GraphicsShaderPipeline::D3d12GraphicsShaderPipeline( D3D12_PIPELINE_STATE_FLAG_DYNAMIC_INDEX_BUFFER_STRIP_CUT; if (auto input_layout = m_shader->InputLayout()) { - auto dx_input_layout = input_layout->QueryInterface(); - if (dx_input_layout == nullptr) - COPLT_THROW("Input layout from different backends"); - FD3d12MeshLayout* dx_mesh_layout{}; - if (options.MeshLayout != nullptr) + FMeshLayout* mesh_layout = options.MeshLayout; + if (options.MeshLayout == nullptr) { - dx_mesh_layout = options.MeshLayout->QueryInterface(); - if (dx_mesh_layout == nullptr) - COPLT_THROW("Mesh layout from different backends"); + mesh_layout = m_device->GetEmptyMeshLayout().get(); } - else dx_mesh_layout = m_device->GetEmptyMeshLayout().get(); - SetInputLayout(&m_device, tmp_strings, input_element_desc, input_slots, dx_input_layout, dx_mesh_layout); + SetInputLayout(&m_device, tmp_strings, input_element_desc, input_slots, input_layout, mesh_layout); desc.InputLayout.NumElements = input_element_desc.size(); desc.InputLayout.pInputElementDescs = input_element_desc.data(); - m_input_layout = Rc::UnsafeClone(dx_input_layout); - m_mesh_layout = Rc::UnsafeClone(dx_mesh_layout); + m_input_layout = Rc::UnsafeClone(input_layout); + m_mesh_layout = Rc::UnsafeClone(mesh_layout); } stream = CD3DX12_PIPELINE_STATE_STREAM2(desc); } @@ -245,7 +241,7 @@ FShader* D3d12GraphicsShaderPipeline::GetShader() noexcept return m_shader.get(); } -FShaderLayout* D3d12GraphicsShaderPipeline::GetLayout() noexcept +FBindingLayout* D3d12GraphicsShaderPipeline::GetLayout() noexcept { return m_layout.get(); } diff --git a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h index 79351d7..c805c5a 100644 --- a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h +++ b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h @@ -3,8 +3,8 @@ #include #include "Device.h" +#include "Layout.h" #include "../../Api/Include/Object.h" -#include "../FFI/Layout.h" #include "../Include/Utils.h" #include "../FFI/Pipeline.h" @@ -14,11 +14,11 @@ namespace Coplt { Rc m_device{}; Rc m_shader{}; - Rc m_layout{}; + Rc m_layout{}; // 可选 - Rc m_input_layout{}; + Rc m_input_layout{}; // 可选 - Rc m_mesh_layout{}; + Rc m_mesh_layout{}; ComPtr m_dx_device{}; ComPtr m_pipeline{}; std::vector m_input_slots{}; @@ -33,7 +33,7 @@ namespace Coplt void* GetPipelineStatePtr() noexcept override; FShader* GetShader() noexcept override; - FShaderLayout* GetLayout() noexcept override; + FBindingLayout* GetLayout() noexcept override; FShaderStageFlags GetStages() noexcept override; const FGraphicsPipelineState* GetGraphicsState() noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.cc b/Coplt.Graphics.Native/D3d12/Src/Layout.cc index d97958b..249675b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.cc @@ -4,89 +4,168 @@ #include "../../Api/Include/AllocObjectId.h" #include "../Include/ShaderVisibility.h" +#include "../Include/Sampler.h" using namespace Coplt; +using namespace Coplt::Layout; -namespace +D3D12_DESCRIPTOR_RANGE_TYPE Layout::ToTableType(const FShaderLayoutItemView view) { - struct TableKey + switch (view) { - FShaderStage Stage{}; - FShaderLayoutGroupView View{}; - - TableKey() = default; + case FShaderLayoutItemView::Cbv: + return D3D12_DESCRIPTOR_RANGE_TYPE_CBV; + case FShaderLayoutItemView::Srv: + return D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + case FShaderLayoutItemView::Uav: + return D3D12_DESCRIPTOR_RANGE_TYPE_UAV; + case FShaderLayoutItemView::Sampler: + return D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; + case FShaderLayoutItemView::Constants: + return D3D12_DESCRIPTOR_RANGE_TYPE_CBV; + case FShaderLayoutItemView::StaticSampler: + return D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; + } + return D3D12_DESCRIPTOR_RANGE_TYPE_CBV; +} - explicit TableKey(const FShaderStage Stage, const FShaderLayoutGroupView View) : Stage(Stage), View(View) +D3d12ShaderLayout::D3d12ShaderLayout(const FShaderLayoutCreateOptions& options) +{ + Flags = options.Flags; + m_items = std::vector(options.Items, options.Items + options.NumItems); + Items = m_items.data(); + NumItems = m_items.size(); + for (u32 i = 0; i < m_items.size(); ++i) + { + const auto& item = m_items[i]; + if (item.Count < 1) { + COPLT_THROW_FMT( + "Invalid binding define {{ Id = {}, Scope = {}, Stage = {} }} at [{}]; Count must >= 1", + item.Id, item.Scope, static_cast(item.Stage), i + ); } - - usize GetHashCode() const + if (item.View == FShaderLayoutItemView::StaticSampler && item.Count > 1) { - return std::hash{}(static_cast(Stage) | (static_cast(View) << 8)); + COPLT_THROW_FMT( + "Invalid binding define {{ Id = {}, Scope = {}, Stage = {} }} at [{}]; Count when StaticSampler must == 1", + item.Id, item.Scope, static_cast(item.Stage), i + ); } + } +} - bool operator==(const TableKey& other) const - { - return Stage == other.Stage && View == other.View; - } - }; +FResult D3d12ShaderLayout::SetName(const FStr8or16& name) noexcept +{ + return FResult::None(); +} - using TableMeta = ID3d12ShaderLayout::TableMeta; +FShaderLayoutData* D3d12ShaderLayout::ShaderLayoutData() noexcept +{ + return this; +} - struct TableGroupKey - { - FShaderLayoutGroupScope Scope{}; - bool Sampler{}; +D3d12BindGroupLayout::D3d12BindGroupLayout(const FBindGroupLayoutCreateOptions& options) +{ + m_items = std::vector(options.Items, options.Items + options.NumItems); + m_static_samplers = std::vector(options.StaticSamplers, options.StaticSamplers + options.NumStaticSamplers); + Items = m_items.data(); + StaticSamplers = m_static_samplers.data(); + NumItems = m_items.size(); + NumStaticSamplers = m_static_samplers.size(); + Usage = options.Usage; +} - TableGroupKey() = default; +FResult D3d12BindGroupLayout::SetName(const FStr8or16& name) noexcept +{ + return FResult::None(); +} - explicit TableGroupKey(const FShaderLayoutGroupScope Scope, const bool Sampler) : Scope(Scope), Sampler(Sampler) - { - } +FBindGroupLayoutData* D3d12BindGroupLayout::BindGroupLayoutData() noexcept +{ + return this; +} - struct Hasher - { - size_t operator()(const TableGroupKey& value) const - { - return std::hash{}(static_cast(value.Scope) | (static_cast(value.Sampler) << 8)); - } - }; +D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindingLayoutCreateOptions& options) + : m_device(device) +{ + m_shader_layout = Rc::UnsafeClone(options.ShaderLayout); + m_groups.reserve(options.NumGroups); + for (u32 i = 0; i < options.NumGroups; i++) + { + m_groups.push_back(Rc::UnsafeClone(options.Groups[i])); + } - struct Eq + const auto defines = m_shader_layout->GetItems(); + for (u32 i = 0; i < defines.size(); ++i) + { + const auto& item = defines[i]; + BindSlot slot(item); + const auto is_new = m_slot_to_info.TryAdd(slot, [&](auto& p) { - bool operator()(const TableGroupKey& lhs, const TableGroupKey& rhs) const + p.put(m_slot_infos.size()); + m_slot_infos.push_back(SlotInfo(i)); + }); + if (!is_new) + { + COPLT_THROW_FMT( + "Duplicate binding slot {{ Id = {}, Scope = {}, Stage = {} }} at [{}]", + slot.Id, slot.Scope, static_cast(slot.Stage), i + ); + } + } + for (u32 g = 0; g < options.NumGroups; g++) + { + const auto& group = m_groups[g]; + const auto items = group->GetItems(); + for (u32 i = 0; i < items.size(); ++i) + { + for (const auto& item = items[i]; const auto stage : IterStage(item.Stages)) { - return lhs.Scope == rhs.Scope && lhs.Sampler == rhs.Sampler; + BindSlot slot(item, stage); + const auto info_index = m_slot_to_info.TryGet(slot); + if (!info_index) continue; + auto& info = m_slot_infos[*info_index]; + if (info.Group != COPLT_U32_MAX) + { + COPLT_THROW_FMT( + "Duplicate binding slot {{ Id = {}, Scope = {}, Stage = {} }} at Group {} [{}]", + slot.Id, slot.Scope, static_cast(slot.Stage), g, i + ); + } + const auto& def = defines[info.Index]; + if ( + def.View != item.View || (item.View == FShaderLayoutItemView::StaticSampler ? false : def.Count != item.Count) + || def.Type != item.Type || def.Format != item.Format + ) + { + COPLT_THROW_FMT( + "Incompatible binding slot {{ Id = {}, Scope = {}, Stage = {} }} at Group {} [{}]", + slot.Id, slot.Scope, static_cast(slot.Stage), g, i + ); + } + if (item.Count < def.Count) + { + COPLT_THROW_FMT( + "Incompatible binding slot {{ Id = {}, Scope = {}, Stage = {} }} at Group {} [{}]; The group provides fewer bindings than the shader requires", + slot.Id, slot.Scope, static_cast(slot.Stage), g, i + ); + } + info.Group = g; + info.IndexInGroup = i; } - }; - }; - - struct TableDefine - { - u8 Index{}; - u32 IndexInc{}; - HashMap Map{}; - }; -} - -D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderLayoutCreateOptions& options) - : m_device(std::move(device)) -{ - m_dx_device = m_device->m_device; - - Flags = options.Flags; - - m_layout_item_defines = std::vector(options.Items, options.Items + options.Count); - m_item_infos = std::vector(options.Count, {}); + } + } std::vector root_parameters{}; + std::vector static_samplers{}; + std::vector> tables{}; + tables.reserve(m_groups.size()); + for (u32 i = 0; i < m_groups.size(); i++) tables.push_back({}); - HashMap tables{}; - u8 TableGroupIndexInc{}; - - for (u32 i = 0; i < m_layout_item_defines.size(); i++) + for (auto& info : m_slot_infos) { - const auto& item = m_layout_item_defines[i]; + const auto& item = defines[info.Index]; if (item.View == FShaderLayoutItemView::Constants) { @@ -97,31 +176,30 @@ D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderL param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; param.Constants.ShaderRegister = item.Slot; param.Constants.RegisterSpace = item.Space; - param.Constants.Num32BitValues = std::max(1u, item.CountOrIndex); + param.Constants.Num32BitValues = std::max(1u, item.Count); param.ShaderVisibility = ToDxVisibility(item.Stage); - m_item_infos[i] = FShaderLayoutItemInfo{ - .Index = static_cast(root_parameters.size()), - .Place = FShaderLayoutItemPlace::Const, - }; + info.SigIndex = static_cast(root_parameters.size()); + info.SigPlace = SigPlace::Const; root_parameters.push_back(param); continue; } + // 组未提供绑定,使用隐藏组创建描述符,并且永远保持默认值 + if (info.Group == COPLT_U32_MAX) + COPLT_THROW("TODO"); + D3D12_ROOT_PARAMETER_TYPE type; - FShaderLayoutGroupScope table_scope; + const auto& group = m_groups[info.Group]; - switch (item.Usage) - { - case FShaderLayoutItemUsage::Dynamic: - table_scope = FShaderLayoutGroupScope::Dynamic; + if (item.View == FShaderLayoutItemView::StaticSampler) + goto DefineStaticSampler; + if (item.View == FShaderLayoutItemView::Sampler) goto DefineDescriptorTable; - case FShaderLayoutItemUsage::Persist: - table_scope = FShaderLayoutGroupScope::Persist; - goto DefineDescriptorTable; - case FShaderLayoutItemUsage::Instant: - if (item.CountOrIndex > 1 || !IsBuffer(item.Type)) + + if (group->Data().Usage == FBindGroupUsage::Dynamic) + { + if (item.Count > 1 || !IsBuffer(item.Type)) { - table_scope = FShaderLayoutGroupScope::Dynamic; goto DefineDescriptorTable; } switch (item.View) @@ -135,17 +213,41 @@ D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderL case FShaderLayoutItemView::Uav: type = D3D12_ROOT_PARAMETER_TYPE_UAV; goto DefineDescriptor; + case FShaderLayoutItemView::StaticSampler: case FShaderLayoutItemView::Sampler: - COPLT_THROW("TODO"); // 静态采样器 + case FShaderLayoutItemView::Constants: default: COPLT_THROW_FMT("Unknown shader layout item type {}", static_cast(item.Type)); } - default: - COPLT_THROW_FMT("Unknown shader layout item usage {}", static_cast(item.Usage)); } - continue; - + DefineDescriptorTable: + { + const auto group_items = group->GetItems(); + const auto& group_item = group_items[info.IndexInGroup]; + D3D12_DESCRIPTOR_RANGE1 range{}; + const auto range_type = ToTableType(item.View); + range.RangeType = range_type; + auto& table = tables[info.Group].GetOrAdd(TableKey(item.Stage, range_type), [&](auto& p) + { + p.put(TableDefine{ + .Info = TableInfo{ + .Group = info.Group, + .Stage = item.Stage, + .Type = range_type, + } + }); + }); + range.NumDescriptors = std::max(1u, item.Count); + range.BaseShaderRegister = item.Slot; + range.RegisterSpace = item.Space; + range.OffsetInDescriptorsFromTableStart = table.Info.Size; + info.SigIndex = static_cast(table.Ranges.size()); + info.SigPlace = SigPlace::Grouped; + table.Ranges.push_back(range); + table.Info.Size += group_item.Count; + continue; + } DefineDescriptor: { D3D12_ROOT_PARAMETER1 param{}; @@ -154,100 +256,47 @@ 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_infos[i] = FShaderLayoutItemInfo{ - .Index = static_cast(root_parameters.size()), - .Place = FShaderLayoutItemPlace::Direct, - }; + info.SigIndex = static_cast(root_parameters.size()); + info.SigPlace = SigPlace::Direct; root_parameters.push_back(param); continue; } - DefineDescriptorTable: + DefineStaticSampler: { - 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; - group_view = FShaderLayoutGroupView::Cbv; - break; - case FShaderLayoutItemView::Srv: - range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; - group_view = FShaderLayoutGroupView::Srv; - break; - case FShaderLayoutItemView::Uav: - range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV; - group_view = FShaderLayoutGroupView::Uav; - break; - case FShaderLayoutItemView::Sampler: - range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; - group_view = FShaderLayoutGroupView::Sampler; - break; - default: - COPLT_THROW_FMT("Unknown shader layout item type {}", static_cast(item.Type)); - } - auto& meta = table.Map.GetOrAdd(TableKey(item.Stage, group_view), [&](auto& p) - { - 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 = meta.Size; - // range.Flags = D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE; - 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.Size += range.NumDescriptors; + const auto group_items = group->GetItems(); + const auto samplers = group->GetStaticSamplers(); + const auto& group_item = group_items[info.IndexInGroup]; + const auto& sampler = samplers[group_item.StaticSamplerIndex]; + D3D12_STATIC_SAMPLER_DESC desc{}; + desc.ShaderRegister = item.Slot; + desc.RegisterSpace = item.Space; + desc.ShaderVisibility = ToDxVisibility(item.Stage); + SetDesc(sampler, desc); + info.SigIndex = static_cast(static_samplers.size()); + info.SigPlace = SigPlace::StaticSampler; + static_samplers.push_back(desc); continue; } } - m_table_groups = std::vector(tables.Count(), {}); - m_group_classes = std::vector(tables.Count(), {}); - for (auto& [key, table] : tables) + m_tables.reserve(tables.size()); + for (usize i = 0; i < tables.size(); ++i) { - 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()), - .Scope = key.Scope, - .Sampler = key.Sampler - }; - for (auto& item : table.Map | std::views::values) + auto& table = tables[i]; + std::vector infos{}; + infos.reserve(table.Count()); + for (auto& [Ranges, Info] : table | std::views::values) { + Info.RootIndex = static_cast(root_parameters.size()); D3D12_ROOT_PARAMETER1 param{}; param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - - 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.ShaderVisibility = ToDxVisibility(Info.Stage); + param.DescriptorTable.NumDescriptorRanges = Ranges.size(); + param.DescriptorTable.pDescriptorRanges = Ranges.data(); root_parameters.push_back(param); + infos.push_back(Info); } + m_tables.push_back(std::move(infos)); } D3D12_VERSIONED_ROOT_SIGNATURE_DESC desc{}; @@ -258,11 +307,12 @@ D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderL desc.Desc_1_1.pStaticSamplers = nullptr; desc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; - if (HasFlags(options.Flags, FShaderLayoutFlags::InputAssembler)) + const auto layout = *NonNull(m_shader_layout->ShaderLayoutData()); + if (HasFlags(layout.Flags, FShaderLayoutFlags::InputAssembler)) desc.Desc_1_1.Flags |= D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - if (HasFlags(options.Flags, FShaderLayoutFlags::StreamOutput)) + if (HasFlags(layout.Flags, FShaderLayoutFlags::StreamOutput)) desc.Desc_1_1.Flags |= D3D12_ROOT_SIGNATURE_FLAG_ALLOW_STREAM_OUTPUT; - if (HasFlags(options.Flags, FShaderLayoutFlags::BindLess)) + if (HasFlags(layout.Flags, FShaderLayoutFlags::DynBindLess)) desc.Desc_1_1.Flags |= D3D12_ROOT_SIGNATURE_FLAG_CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED | D3D12_ROOT_SIGNATURE_FLAG_SAMPLER_HEAP_DIRECTLY_INDEXED; @@ -278,7 +328,7 @@ D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderL chr | r; } - chr | m_dx_device->CreateRootSignature( + chr | m_device->m_device->CreateRootSignature( 0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&m_root_signature) ); @@ -288,7 +338,7 @@ D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderL } } -FResult D3d12ShaderLayout::SetName(const FStr8or16& name) noexcept +FResult D3d12BindingLayout::SetName(const FStr8or16& name) noexcept { return feb([&] { @@ -297,37 +347,24 @@ FResult D3d12ShaderLayout::SetName(const FStr8or16& name) noexcept }); } -FShaderLayoutData* D3d12ShaderLayout::ShaderLayoutData() noexcept -{ - return this; -} - -void* D3d12ShaderLayout::GetRootSignaturePtr() noexcept -{ - return m_root_signature.Get(); -} - -const FShaderLayoutItemDefine* D3d12ShaderLayout::GetItemDefines(u32* out_count) noexcept +const Rc& D3d12BindingLayout::ShaderLayout() const noexcept { - *out_count = static_cast(m_layout_item_defines.size()); - return m_layout_item_defines.data(); + return m_shader_layout; } -const FShaderLayoutItemInfo* D3d12ShaderLayout::GetItemInfos(u32* out_count) noexcept +std::span> D3d12BindingLayout::Groups() const noexcept { - *out_count = static_cast(m_item_infos.size()); - return m_item_infos.data(); + return m_groups; } -const FShaderLayoutGroupClass* D3d12ShaderLayout::GetGroupClasses(u32* out_count) noexcept +const ComPtr& D3d12BindingLayout::RootSignature() const noexcept { - *out_count = static_cast(m_group_classes.size()); - return m_group_classes.data(); + return m_root_signature; } -std::span D3d12ShaderLayout::GetTableGroups() noexcept +std::span D3d12BindingLayout::SlotInfos() const noexcept { - return m_table_groups; + return m_slot_infos; } D3d12ShaderInputLayout::D3d12ShaderInputLayout( diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.h b/Coplt.Graphics.Native/D3d12/Src/Layout.h index 9692e1d..be4ff96 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.h +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.h @@ -7,69 +7,164 @@ #include "Device.h" #include "../../Api/Include/Object.h" -#include "../FFI/Layout.h" namespace Coplt { - COPLT_INTERFACE_DEFINE(ID3d12ShaderLayout, "d8cea40e-7b0c-4a5f-98a9-88fd3abf9ddc", FD3d12ShaderLayout) + namespace Layout { - struct TableMeta + D3D12_DESCRIPTOR_RANGE_TYPE ToTableType(FShaderLayoutItemView view); + + struct TableInfo final { - std::vector Ranges{}; u32 Size{}; - u32 Index{}; + u32 Group{}; u32 RootIndex{}; FShaderStage Stage{}; - FShaderLayoutGroupView View{}; + D3D12_DESCRIPTOR_RANGE_TYPE Type{}; + }; - TableMeta() = default; + struct TableDefine final + { + std::vector Ranges{}; + TableInfo Info{}; + }; + + struct TableKey final + { + FShaderStage Stage{}; + D3D12_DESCRIPTOR_RANGE_TYPE Type{}; + + TableKey() = default; + + TableKey(const FShaderStage Stage, const D3D12_DESCRIPTOR_RANGE_TYPE Type) : Stage(Stage), Type(Type) + { + } + + usize GetHashCode() const + { + return hash_multi(static_cast(Stage), static_cast(Type)); + } - explicit TableMeta(const u32 index, const FShaderStage stage, const FShaderLayoutGroupView view) + bool operator==(const TableKey& other) const { - Index = index; - Stage = stage; - View = view; + return Stage == other.Stage && Type == other.Type; } }; - struct TableGroup + struct BindSlot final { - std::vector Metas{}; - std::vector Infos{}; - FShaderLayoutGroupScope Scope{}; - bool Sampler{}; + u64 Id{}; + u64 Scope{}; + FShaderStage Stage{}; + + BindSlot() = default; + + BindSlot(const u64 Id, const u64 Scope, const FShaderStage Stage) : Id(Id), Scope(Scope), Stage(Stage) + { + } + + explicit BindSlot(const FShaderLayoutItem& item) : BindSlot(item.Id, item.Scope, item.Stage) + { + } + + explicit BindSlot(const FBindGroupItem& item, const FShaderStage Stage) : BindSlot(item.Id, item.Scope, Stage) + { + } + + usize GetHashCode() const + { + return hash_multi(Id, Scope, static_cast(Stage)); + } + + bool operator==(const BindSlot& other) const + { + return Id == other.Id && Scope == other.Scope && Stage == other.Stage; + } }; - virtual std::span GetTableGroups() noexcept = 0; - }; + enum class SigPlace : u8 + { + None, + Const, + Direct, + Grouped, + StaticSampler, + }; + + struct SlotInfo final + { + u32 Index{}; + u32 Group{COPLT_U32_MAX}; + u32 IndexInGroup{COPLT_U32_MAX}; + // Place 为 Grouped 时是组内的 Index,StaticSampler 时是 StaticSampler 的 Index, 其他是 Root 的 Index + u32 SigIndex{}; + SigPlace SigPlace{}; + + SlotInfo() = default; - struct D3d12ShaderLayout final : GpuObject, FShaderLayoutData + explicit SlotInfo(const u32 index) : Index(index) + { + } + }; + } + + struct D3d12ShaderLayout final : GpuObject, FShaderLayoutData { - Rc m_device{}; - ComPtr m_dx_device{}; - ComPtr m_root_signature{}; - std::vector m_layout_item_defines{}; - // 长度和 m_layout_item_defines 相同 - std::vector m_item_infos{}; - std::vector m_group_classes{}; - std::vector m_table_groups{}; + std::vector m_items{}; - explicit D3d12ShaderLayout(Rc&& device, const FShaderLayoutCreateOptions& options); + explicit D3d12ShaderLayout(const FShaderLayoutCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; FShaderLayoutData* ShaderLayoutData() noexcept override; + }; + + struct D3d12BindGroupLayout final : GpuObject, FBindGroupLayoutData + { + std::vector m_items{}; + std::vector m_static_samplers{}; + + explicit D3d12BindGroupLayout(const FBindGroupLayoutCreateOptions& options); + + FResult SetName(const FStr8or16& name) noexcept override; + + FBindGroupLayoutData* BindGroupLayoutData() noexcept override; + }; + + COPLT_INTERFACE_DEFINE(ID3d12BindingLayout, "dcebfaa2-44d9-4c3c-95e7-28189ce7d5c4", FBindingLayout) + { + using SlotInfo = Layout::SlotInfo; - void* GetRootSignaturePtr() noexcept override; + virtual const Rc& ShaderLayout() const noexcept = 0; + virtual std::span> Groups() const noexcept = 0; + virtual const ComPtr& RootSignature() const noexcept = 0; + virtual std::span SlotInfos() const noexcept = 0; + }; + + struct D3d12BindingLayout final : GpuObject + { + using BindSlot = Layout::BindSlot; + using TableInfo = Layout::TableInfo; + + Rc m_device{}; + ComPtr m_root_signature{}; + Rc m_shader_layout{}; + std::vector> m_groups{}; + std::vector m_slot_infos{}; + HashMap m_slot_to_info{}; + std::vector> m_tables{}; - const FShaderLayoutItemDefine* GetItemDefines(u32* out_count) noexcept override; - const FShaderLayoutItemInfo* GetItemInfos(u32* out_count) noexcept override; - const FShaderLayoutGroupClass* GetGroupClasses(u32* out_count) noexcept override; + explicit D3d12BindingLayout(Rc&& device, const FBindingLayoutCreateOptions& options); + + FResult SetName(const FStr8or16& name) noexcept override; - std::span GetTableGroups() noexcept override; + const Rc& ShaderLayout() const noexcept override; + std::span> Groups() const noexcept override; + const ComPtr& RootSignature() const noexcept override; + std::span SlotInfos() const noexcept override; }; - struct D3d12ShaderInputLayout final : GpuObject + struct D3d12ShaderInputLayout final : GpuObject { Rc m_device{}; std::vector> m_slot_names{}; @@ -82,7 +177,7 @@ namespace Coplt const FShaderInputLayoutElement* GetElements(u32* out_count) noexcept override; }; - struct D3d12MeshLayout final : GpuObject + struct D3d12MeshLayout final : GpuObject { Rc m_device{}; std::vector m_buffers{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index c81ba53..ff94034 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -33,7 +33,7 @@ void D3d12GpuRecord::PipelineContext::SetPipeline(NonNull pipel static_cast(pipeline), i ); } - Layout = pipeline->GetLayout()->QueryInterface(); + Layout = pipeline->GetLayout()->QueryInterface(); if (!Layout) COPLT_THROW("Shader layout from different backends"); const auto stages = pipeline->GetStages(); @@ -765,13 +765,13 @@ void D3d12GpuRecord::SetPipeline(const CmdList& list, NonNull p const auto stages = pipeline->GetStages(); if (HasFlags(stages, FShaderStageFlags::Compute)) { - list->g0->SetComputeRootSignature(static_cast(m_pipeline_context.Layout->GetRootSignaturePtr())); + list->g0->SetComputeRootSignature(m_pipeline_context.Layout->RootSignature().Get()); } else if (HasFlags(stages, FShaderStageFlags::Pixel)) { const auto& states = m_pipeline_context.GPipeline->GetGraphicsState(); list->g0->IASetPrimitiveTopology(ToDx(states->Topology)); - list->g0->SetGraphicsRootSignature(static_cast(m_pipeline_context.Layout->GetRootSignaturePtr())); + list->g0->SetGraphicsRootSignature(m_pipeline_context.Layout->RootSignature().Get()); } list->g0->SetPipelineState(static_cast(m_pipeline_context.Pipeline->GetPipelineStatePtr())); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 4a20e78..1b5f2c0 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -3,10 +3,10 @@ #include "Barrier.h" #include "Context.h" #include "Isolate.h" +#include "Layout.h" #include "../../Api/FFI/Record.h" #include "../../Api/Include/GpuObject.h" #include "../FFI/Pipeline.h" -#include "../FFI/Layout.h" namespace Coplt { @@ -60,7 +60,7 @@ namespace Coplt struct PipelineContext { Ptr Pipeline{}; - Ptr Layout{}; + Ptr Layout{}; // 如果不是图形管线将不会设置 Ptr GPipeline{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Sampler.cc b/Coplt.Graphics.Native/D3d12/Src/Sampler.cc index 75486f9..f1df7aa 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Sampler.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Sampler.cc @@ -7,32 +7,7 @@ using namespace Coplt; D3d12GpuSampler::D3d12GpuSampler(const FGpuSamplerCreateOptions& options) : m_info(options.Info) { - m_desc.MaxLOD = m_info.MaxLod; - m_desc.MinLOD = m_info.MinLod; - m_desc.BorderColor[0] = m_info.BorderColor[0]; - m_desc.BorderColor[1] = m_info.BorderColor[1]; - m_desc.BorderColor[2] = m_info.BorderColor[2]; - m_desc.BorderColor[3] = m_info.BorderColor[3]; - m_desc.ComparisonFunc = ToDx(m_info.Cmp); - m_desc.MaxAnisotropy = m_info.MaxAnisotropy; - m_desc.MipLODBias = m_info.MipLodBias; - m_desc.AddressW = ToDx(m_info.W); - m_desc.AddressV = ToDx(m_info.V); - m_desc.AddressU = ToDx(m_info.U); - m_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; - if (m_desc.MaxAnisotropy > 0) - { - if (m_info.Cmp != FCmpFunc::Off) m_desc.Filter = D3D12_FILTER_COMPARISON_ANISOTROPIC; - else if (m_info.Mipmap == FFilter::Linear) m_desc.Filter = D3D12_FILTER_ANISOTROPIC; - else m_desc.Filter = D3D12_FILTER_MIN_MAG_ANISOTROPIC_MIP_POINT; - } - else - { - if (m_info.Mipmap == FFilter::Linear) m_desc.Filter |= D3D12_FILTER_MIN_MAG_POINT_MIP_LINEAR; - if (m_info.Mag == FFilter::Linear) m_desc.Filter |= D3D12_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; - if (m_info.Min == FFilter::Linear) m_desc.Filter |= D3D12_FILTER_MIN_LINEAR_MAG_MIP_POINT; - if (m_info.Cmp != FCmpFunc::Off) m_desc.Filter |= D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT; - } + SetDesc(m_info, m_desc); } FResult D3d12GpuSampler::SetName(const FStr8or16& name) noexcept diff --git a/Coplt.Graphics.Native/D3d12/Src/Sampler.h b/Coplt.Graphics.Native/D3d12/Src/Sampler.h index 7c622d8..3277a05 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Sampler.h +++ b/Coplt.Graphics.Native/D3d12/Src/Sampler.h @@ -4,6 +4,7 @@ #include "../../Api/Include/GpuObject.h" #include "../FFI/Sampler.h" +#include "../Include/Sampler.h" namespace Coplt { diff --git a/Coplt.Graphics.Native/D3d12/Src/View.cc b/Coplt.Graphics.Native/D3d12/Src/View.cc index 1f4ff39..70879ad 100644 --- a/Coplt.Graphics.Native/D3d12/Src/View.cc +++ b/Coplt.Graphics.Native/D3d12/Src/View.cc @@ -220,573 +220,573 @@ View& View::operator=(Rc&& image) new(this) View(std::forward>(image)); return *this; } - -void View::CreateDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, const CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView type -) const -{ - switch (Type()) - { - case Type::None: - CreateNullDescriptor(device, def, handle, type); - break; - case Type::Buffer: - CreateBufferDescriptor(device, def, handle, type); - break; - case Type::Image: - CreateImageDescriptor(device, def, handle, type); - break; - case Type::Sampler: - CreateSamplerDescriptor(device, def, handle, type); - break; - } -} - -void View::CreateNullDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView view -) -{ - switch (view) - { - case FShaderLayoutGroupView::Cbv: - { - device->CreateConstantBufferView(nullptr, handle); - break; - } - case FShaderLayoutGroupView::Srv: - { - D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; - desc.Format = ToDx(def.Format); - desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - switch (def.Type) - { - case FShaderLayoutItemType::ConstantBuffer: - COPLT_THROW("Srv does not support ConstantBuffer"); - case FShaderLayoutItemType::Buffer: - desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - break; - case FShaderLayoutItemType::RawBuffer: - desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; - break; - case FShaderLayoutItemType::StructureBuffer: - case FShaderLayoutItemType::StructureBufferWithCounter: - desc.Format = DXGI_FORMAT_UNKNOWN; - desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - desc.Buffer.FirstElement = 0; - desc.Buffer.NumElements = 1; - desc.Buffer.StructureByteStride = 1; - break; - case FShaderLayoutItemType::Texture1D: - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; - desc.Texture1D.MostDetailedMip = 0; - desc.Texture1D.MipLevels = 1; - desc.Texture1D.ResourceMinLODClamp = 0; - break; - case FShaderLayoutItemType::Texture1DArray: - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; - desc.Texture1DArray.MostDetailedMip = 0; - desc.Texture1DArray.MipLevels = 1; - desc.Texture1DArray.FirstArraySlice = 0; - desc.Texture1DArray.ArraySize = 1; - desc.Texture1DArray.ResourceMinLODClamp = 0; - break; - case FShaderLayoutItemType::Texture2D: - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - desc.Texture2D.MostDetailedMip = 0; - desc.Texture2D.MipLevels = 1; - desc.Texture2D.PlaneSlice = 0; - desc.Texture2D.ResourceMinLODClamp = 0; - break; - case FShaderLayoutItemType::Texture2DArray: - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; - desc.Texture2DArray.MostDetailedMip = 0; - desc.Texture2DArray.MipLevels = 1; - desc.Texture2DArray.FirstArraySlice = 0; - desc.Texture2DArray.ArraySize = 1; - desc.Texture2DArray.PlaneSlice = 0; - desc.Texture2DArray.ResourceMinLODClamp = 0; - break; - case FShaderLayoutItemType::Texture2DMultisample: - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; - break; - case FShaderLayoutItemType::Texture2DArrayMultisample: - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; - desc.Texture2DMSArray.FirstArraySlice = 0; - desc.Texture2DMSArray.ArraySize = 1; - break; - case FShaderLayoutItemType::Texture3D: - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; - desc.Texture3D.MostDetailedMip = 0; - desc.Texture3D.MipLevels = 1; - desc.Texture3D.ResourceMinLODClamp = 0; - break; - case FShaderLayoutItemType::TextureCube: - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; - desc.TextureCube.MostDetailedMip = 0; - desc.TextureCube.MipLevels = 1; - desc.TextureCube.ResourceMinLODClamp = 0; - break; - case FShaderLayoutItemType::TextureCubeArray: - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; - desc.TextureCubeArray.MostDetailedMip = 0; - desc.TextureCubeArray.MipLevels = 1; - desc.TextureCubeArray.First2DArrayFace = 0; - desc.TextureCubeArray.NumCubes = 1; - desc.TextureCubeArray.ResourceMinLODClamp = 0; - break; - case FShaderLayoutItemType::Sampler: - COPLT_THROW("Srv does does not support sampler"); - case FShaderLayoutItemType::RayTracingAccelerationStructure: - desc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; - break; - } - device->CreateShaderResourceView(nullptr, &desc, handle); - break; - } - case FShaderLayoutGroupView::Uav: - { - D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; - desc.Format = ToDx(def.Format); - switch (def.Type) - { - case FShaderLayoutItemType::ConstantBuffer: - COPLT_THROW("Uav does not support ConstantBuffer"); - case FShaderLayoutItemType::Buffer: - desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - break; - case FShaderLayoutItemType::RawBuffer: - desc.Format = DXGI_FORMAT_R32_TYPELESS; - desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; - break; - case FShaderLayoutItemType::StructureBuffer: - case FShaderLayoutItemType::StructureBufferWithCounter: - desc.Format = DXGI_FORMAT_UNKNOWN; - desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - desc.Buffer.FirstElement = 0; - desc.Buffer.NumElements = 1; - desc.Buffer.StructureByteStride = 1; - desc.Buffer.CounterOffsetInBytes = 0; - break; - case FShaderLayoutItemType::Texture1D: - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D; - desc.Texture1D.MipSlice = 0; - break; - case FShaderLayoutItemType::Texture1DArray: - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY; - desc.Texture1DArray.MipSlice = 0; - desc.Texture1DArray.FirstArraySlice = 0; - desc.Texture1DArray.ArraySize = 1; - break; - case FShaderLayoutItemType::Texture2D: - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; - desc.Texture2D.MipSlice = 0; - desc.Texture2D.PlaneSlice = 0; - break; - case FShaderLayoutItemType::Texture2DArray: - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY; - desc.Texture2DArray.MipSlice = 0; - desc.Texture2DArray.FirstArraySlice = 0; - desc.Texture2DArray.ArraySize = 1; - desc.Texture2DArray.PlaneSlice = 0; - break; - case FShaderLayoutItemType::Texture2DMultisample: - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMS; - break; - case FShaderLayoutItemType::Texture2DArrayMultisample: - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY; - desc.Texture2DMSArray.FirstArraySlice = 0; - desc.Texture2DMSArray.ArraySize = 1; - break; - case FShaderLayoutItemType::Texture3D: - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D; - desc.Texture3D.MipSlice = 0; - desc.Texture3D.FirstWSlice = 0; - desc.Texture3D.WSize = 1; - break; - case FShaderLayoutItemType::TextureCube: - COPLT_THROW("Uav does not support TextureCube"); - case FShaderLayoutItemType::TextureCubeArray: - COPLT_THROW("Uav does not support TextureCubeArray"); - case FShaderLayoutItemType::Sampler: - COPLT_THROW("Uav does not support Sampler"); - case FShaderLayoutItemType::RayTracingAccelerationStructure: - COPLT_THROW("Uav does not support RayTracingAccelerationStructure"); - } - device->CreateUnorderedAccessView(nullptr, nullptr, &desc, handle); - break; - } - case FShaderLayoutGroupView::Sampler: - { - D3D12_SAMPLER_DESC desc{}; - desc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; - desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - desc.MaxLOD = FLT_MAX; - device->CreateSampler(&desc, handle); - break; - } - default: - std::unreachable(); - } -} - -void View::CreateBufferDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type -) const -{ - const auto buffer = Buffer().get(); - const auto resource = buffer->GetResourcePtr(); - const auto data = buffer->GpuBufferData(); - switch (type) - { - case FShaderLayoutGroupView::Cbv: - { - D3D12_CONSTANT_BUFFER_VIEW_DESC desc{}; - desc.BufferLocation = resource->GetGPUVirtualAddress(); - desc.SizeInBytes = data->m_size; - device->CreateConstantBufferView(&desc, handle); - break; - } - case FShaderLayoutGroupView::Srv: - { - D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; - desc.Format = ToDx(def.Format); - desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - switch (def.Type) - { - case FShaderLayoutItemType::ConstantBuffer: - COPLT_THROW("Srv does not support ConstantBuffer"); - case FShaderLayoutItemType::Buffer: - desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - break; - case FShaderLayoutItemType::RawBuffer: - if (data->m_usage != FBufferUsage::Raw) - COPLT_THROW("Buffer not a Raw Buffer"); - desc.Format = DXGI_FORMAT_R32_TYPELESS; - desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; - break; - case FShaderLayoutItemType::StructureBuffer: - case FShaderLayoutItemType::StructureBufferWithCounter: - if (data->m_usage != FBufferUsage::Structured) - COPLT_THROW("Buffer not a Structured Buffer"); - desc.Format = DXGI_FORMAT_UNKNOWN; - desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - desc.Buffer.FirstElement = 0; - desc.Buffer.NumElements = data->m_count; - desc.Buffer.StructureByteStride = data->m_stride; - 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: - COPLT_THROW("Buffer Srv does not support Texture"); - case FShaderLayoutItemType::Sampler: - COPLT_THROW("Buffer Srv does not support Sampler"); - case FShaderLayoutItemType::RayTracingAccelerationStructure: - desc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; - desc.RaytracingAccelerationStructure.Location = resource->GetGPUVirtualAddress(); - break; - } - device->CreateShaderResourceView(resource, &desc, handle); - break; - } - case FShaderLayoutGroupView::Uav: - { - D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; - desc.Format = ToDx(def.Format); - switch (def.Type) - { - case FShaderLayoutItemType::ConstantBuffer: - COPLT_THROW("Uav does not support ConstantBuffer"); - case FShaderLayoutItemType::Buffer: - desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - break; - case FShaderLayoutItemType::RawBuffer: - if (data->m_usage != FBufferUsage::Raw) - COPLT_THROW("Buffer not a Raw Buffer"); - desc.Format = DXGI_FORMAT_R32_TYPELESS; - desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; - break; - case FShaderLayoutItemType::StructureBuffer: - case FShaderLayoutItemType::StructureBufferWithCounter: - if (data->m_usage != FBufferUsage::Structured) - COPLT_THROW("Buffer not a Structured Buffer"); - desc.Format = DXGI_FORMAT_UNKNOWN; - desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; - desc.Buffer.FirstElement = 0; - desc.Buffer.NumElements = data->m_count; - desc.Buffer.StructureByteStride = data->m_stride; - desc.Buffer.CounterOffsetInBytes = 0; - 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: - COPLT_THROW("Buffer Uav does not support Texture"); - case FShaderLayoutItemType::Sampler: - COPLT_THROW("Buffer Uav does not support Sampler"); - case FShaderLayoutItemType::RayTracingAccelerationStructure: - COPLT_THROW("Buffer Uav does not support RayTracingAccelerationStructure"); - } - device->CreateUnorderedAccessView(resource, nullptr, &desc, handle); - break; - } - case FShaderLayoutGroupView::Sampler: - COPLT_THROW("Buffer cannot be used as a sampler"); - } -} - -void View::CreateImageDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type -) const -{ - const auto image = Image().get(); - const auto resource = image->GetResourcePtr(); - const auto data = image->GpuImageData(); - switch (type) - { - case FShaderLayoutGroupView::Cbv: - COPLT_THROW("Image cannot be used as a Cbv"); - case FShaderLayoutGroupView::Srv: - { - D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; - desc.Format = ToDx(data->m_format); - desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - switch (def.Type) - { - case FShaderLayoutItemType::ConstantBuffer: - COPLT_THROW("Srv does not support ConstantBuffer"); - case FShaderLayoutItemType::Buffer: - case FShaderLayoutItemType::RawBuffer: - case FShaderLayoutItemType::StructureBuffer: - case FShaderLayoutItemType::StructureBufferWithCounter: - COPLT_THROW("Image Srv does not support Buffer"); - case FShaderLayoutItemType::Texture1D: - { - if (data->m_dimension != FImageDimension::One) - COPLT_THROW("Bind required Texture1D, but the actual resources provided are not"); - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; - desc.Texture1D.MostDetailedMip = 0; - desc.Texture1D.MipLevels = data->m_mip_levels; - desc.Texture1D.ResourceMinLODClamp = 0; - break; - } - case FShaderLayoutItemType::Texture1DArray: - { - if (data->m_dimension != FImageDimension::One) - COPLT_THROW("Bind required Texture1DArray, but the actual resources provided are not"); - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; - desc.Texture1DArray.MostDetailedMip = 0; - desc.Texture1DArray.MipLevels = data->m_mip_levels; - desc.Texture1DArray.FirstArraySlice = 0; - desc.Texture1DArray.ArraySize = data->m_depth_or_length; - desc.Texture1DArray.ResourceMinLODClamp = 0; - break; - } - case FShaderLayoutItemType::Texture2D: - { - if (data->m_dimension != FImageDimension::Two) - COPLT_THROW("Bind required Texture2D, but the actual resources provided are not"); - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - desc.Texture2D.MostDetailedMip = 0; - desc.Texture2D.MipLevels = data->m_mip_levels; - desc.Texture2D.PlaneSlice = 0; - desc.Texture2D.ResourceMinLODClamp = 0; - break; - } - case FShaderLayoutItemType::Texture2DArray: - { - if (data->m_dimension != FImageDimension::Two) - COPLT_THROW("Bind required Texture2DArray, but the actual resources provided are not"); - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; - desc.Texture2DArray.MostDetailedMip = 0; - desc.Texture2DArray.MipLevels = data->m_mip_levels; - desc.Texture2DArray.FirstArraySlice = 0; - desc.Texture2DArray.ArraySize = data->m_depth_or_length; - desc.Texture2DArray.PlaneSlice = 0; - desc.Texture2DArray.ResourceMinLODClamp = 0; - break; - } - case FShaderLayoutItemType::Texture2DMultisample: - { - if (data->m_dimension != FImageDimension::Two) - COPLT_THROW("Bind required Texture2DMultisample, but the actual resources provided are not"); - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; - break; - } - case FShaderLayoutItemType::Texture2DArrayMultisample: - { - if (data->m_dimension != FImageDimension::Two) - COPLT_THROW("Bind required Texture2DArrayMultisample, but the actual resources provided are not"); - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; - desc.Texture2DMSArray.FirstArraySlice = 0; - desc.Texture2DMSArray.ArraySize = data->m_depth_or_length; - break; - } - case FShaderLayoutItemType::Texture3D: - { - if (data->m_dimension != FImageDimension::Three) - COPLT_THROW("Bind required Texture3D, but the actual resources provided are not"); - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; - desc.Texture3D.MostDetailedMip = 0; - desc.Texture3D.MipLevels = data->m_mip_levels; - desc.Texture3D.ResourceMinLODClamp = 0; - break; - } - case FShaderLayoutItemType::TextureCube: - { - if (data->m_dimension != FImageDimension::Cube) - COPLT_THROW("Bind required TextureCube, but the actual resources provided are not"); - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; - desc.TextureCube.MostDetailedMip = 0; - desc.TextureCube.MipLevels = data->m_mip_levels; - desc.TextureCube.ResourceMinLODClamp = 0; - break; - } - case FShaderLayoutItemType::TextureCubeArray: - { - if (data->m_dimension != FImageDimension::Cube) - COPLT_THROW("Bind required TextureCubeArray, but the actual resources provided are not"); - desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; - desc.TextureCubeArray.MostDetailedMip = 0; - desc.TextureCubeArray.MipLevels = data->m_mip_levels; - desc.TextureCubeArray.First2DArrayFace = 0; - desc.TextureCubeArray.NumCubes = (data->m_depth_or_length + 5) / 6; - desc.TextureCubeArray.ResourceMinLODClamp = 0; - break; - } - case FShaderLayoutItemType::Sampler: - COPLT_THROW("Srv does not support sampler"); - case FShaderLayoutItemType::RayTracingAccelerationStructure: - COPLT_THROW("Image Srv does not support RayTracingAccelerationStructure"); - } - device->CreateShaderResourceView(resource, &desc, handle); - break; - } - case FShaderLayoutGroupView::Uav: - { - D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; - desc.Format = ToDx(data->m_format); - switch (def.Type) - { - case FShaderLayoutItemType::ConstantBuffer: - COPLT_THROW("Uav not support ConstantBuffer"); - - case FShaderLayoutItemType::Buffer: - case FShaderLayoutItemType::RawBuffer: - case FShaderLayoutItemType::StructureBuffer: - case FShaderLayoutItemType::StructureBufferWithCounter: - COPLT_THROW("Image Srv does not support Buffer"); - case FShaderLayoutItemType::Texture1D: - { - if (data->m_dimension != FImageDimension::One) - COPLT_THROW("Bind required Texture1D, but the actual resources provided are not"); - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D; - desc.Texture1D.MipSlice = 0; - break; - } - case FShaderLayoutItemType::Texture1DArray: - { - if (data->m_dimension != FImageDimension::One) - COPLT_THROW("Bind required Texture1DArray, but the actual resources provided are not"); - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY; - desc.Texture1DArray.MipSlice = 0; - desc.Texture1DArray.FirstArraySlice = 0; - desc.Texture1DArray.ArraySize = data->m_depth_or_length; - break; - } - case FShaderLayoutItemType::Texture2D: - { - if (data->m_dimension != FImageDimension::Two) - COPLT_THROW("Bind required Texture2D, but the actual resources provided are not"); - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; - desc.Texture2D.MipSlice = 0; - desc.Texture2D.PlaneSlice = 0; - break; - } - case FShaderLayoutItemType::Texture2DArray: - { - if (data->m_dimension != FImageDimension::Two) - COPLT_THROW("Bind required Texture2DArray, but the actual resources provided are not"); - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY; - desc.Texture2DArray.MipSlice = 0; - desc.Texture2DArray.FirstArraySlice = 0; - desc.Texture2DArray.ArraySize = data->m_depth_or_length; - desc.Texture2DArray.PlaneSlice = 0; - break; - } - case FShaderLayoutItemType::Texture2DMultisample: - { - if (data->m_dimension != FImageDimension::Two) - COPLT_THROW("Bind required Texture2DMultisample, but the actual resources provided are not"); - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMS; - break; - } - case FShaderLayoutItemType::Texture2DArrayMultisample: - { - if (data->m_dimension != FImageDimension::Two) - COPLT_THROW("Bind required Texture2DArrayMultisample, but the actual resources provided are not"); - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY; - desc.Texture2DMSArray.FirstArraySlice = 0; - desc.Texture2DMSArray.ArraySize = data->m_depth_or_length; - break; - } - case FShaderLayoutItemType::Texture3D: - { - if (data->m_dimension != FImageDimension::Three) - COPLT_THROW("Bind required Texture3D, but the actual resources provided are not"); - desc.Texture3D.MipSlice = 0; - desc.Texture3D.FirstWSlice = 0; - desc.Texture3D.WSize = data->m_depth_or_length; - break; - } - case FShaderLayoutItemType::TextureCube: - COPLT_THROW("Uav not support TextureCube"); - case FShaderLayoutItemType::TextureCubeArray: - COPLT_THROW("Uav not support TextureCubeArray"); - case FShaderLayoutItemType::Sampler: - COPLT_THROW("Uav not support Sampler"); - case FShaderLayoutItemType::RayTracingAccelerationStructure: - COPLT_THROW("Uav not support RayTracingAccelerationStructure"); - } - device->CreateUnorderedAccessView(resource, nullptr, &desc, handle); - break; - } - case FShaderLayoutGroupView::Sampler: - COPLT_THROW("Image cannot be used as a sampler"); - } -} - -void View::CreateSamplerDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type -) const -{ - const auto sampler = Sampler().get(); - switch (type) - { - case FShaderLayoutGroupView::Cbv: - COPLT_THROW("Sampler cannot be used as a Cbv"); - case FShaderLayoutGroupView::Srv: - COPLT_THROW("Sampler cannot be used as a Srv"); - case FShaderLayoutGroupView::Uav: - COPLT_THROW("Sampler cannot be used as a Uav"); - case FShaderLayoutGroupView::Sampler: - device->CreateSampler(sampler->Desc(), handle); - break; - } -} +// +// void View::CreateDescriptor( +// NonNull device, const FShaderLayoutItemDefine& def, const CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView type +// ) const +// { +// switch (Type()) +// { +// case Type::None: +// CreateNullDescriptor(device, def, handle, type); +// break; +// case Type::Buffer: +// CreateBufferDescriptor(device, def, handle, type); +// break; +// case Type::Image: +// CreateImageDescriptor(device, def, handle, type); +// break; +// case Type::Sampler: +// CreateSamplerDescriptor(device, def, handle, type); +// break; +// } +// } +// +// void View::CreateNullDescriptor( +// NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView view +// ) +// { +// switch (view) +// { +// case FShaderLayoutGroupView::Cbv: +// { +// device->CreateConstantBufferView(nullptr, handle); +// break; +// } +// case FShaderLayoutGroupView::Srv: +// { +// D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; +// desc.Format = ToDx(def.Format); +// desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; +// switch (def.Type) +// { +// case FShaderLayoutItemType::ConstantBuffer: +// COPLT_THROW("Srv does not support ConstantBuffer"); +// case FShaderLayoutItemType::Buffer: +// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; +// break; +// case FShaderLayoutItemType::RawBuffer: +// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; +// desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; +// break; +// case FShaderLayoutItemType::StructureBuffer: +// case FShaderLayoutItemType::StructureBufferWithCounter: +// desc.Format = DXGI_FORMAT_UNKNOWN; +// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; +// desc.Buffer.FirstElement = 0; +// desc.Buffer.NumElements = 1; +// desc.Buffer.StructureByteStride = 1; +// break; +// case FShaderLayoutItemType::Texture1D: +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; +// desc.Texture1D.MostDetailedMip = 0; +// desc.Texture1D.MipLevels = 1; +// desc.Texture1D.ResourceMinLODClamp = 0; +// break; +// case FShaderLayoutItemType::Texture1DArray: +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; +// desc.Texture1DArray.MostDetailedMip = 0; +// desc.Texture1DArray.MipLevels = 1; +// desc.Texture1DArray.FirstArraySlice = 0; +// desc.Texture1DArray.ArraySize = 1; +// desc.Texture1DArray.ResourceMinLODClamp = 0; +// break; +// case FShaderLayoutItemType::Texture2D: +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; +// desc.Texture2D.MostDetailedMip = 0; +// desc.Texture2D.MipLevels = 1; +// desc.Texture2D.PlaneSlice = 0; +// desc.Texture2D.ResourceMinLODClamp = 0; +// break; +// case FShaderLayoutItemType::Texture2DArray: +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; +// desc.Texture2DArray.MostDetailedMip = 0; +// desc.Texture2DArray.MipLevels = 1; +// desc.Texture2DArray.FirstArraySlice = 0; +// desc.Texture2DArray.ArraySize = 1; +// desc.Texture2DArray.PlaneSlice = 0; +// desc.Texture2DArray.ResourceMinLODClamp = 0; +// break; +// case FShaderLayoutItemType::Texture2DMultisample: +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; +// break; +// case FShaderLayoutItemType::Texture2DArrayMultisample: +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; +// desc.Texture2DMSArray.FirstArraySlice = 0; +// desc.Texture2DMSArray.ArraySize = 1; +// break; +// case FShaderLayoutItemType::Texture3D: +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; +// desc.Texture3D.MostDetailedMip = 0; +// desc.Texture3D.MipLevels = 1; +// desc.Texture3D.ResourceMinLODClamp = 0; +// break; +// case FShaderLayoutItemType::TextureCube: +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; +// desc.TextureCube.MostDetailedMip = 0; +// desc.TextureCube.MipLevels = 1; +// desc.TextureCube.ResourceMinLODClamp = 0; +// break; +// case FShaderLayoutItemType::TextureCubeArray: +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; +// desc.TextureCubeArray.MostDetailedMip = 0; +// desc.TextureCubeArray.MipLevels = 1; +// desc.TextureCubeArray.First2DArrayFace = 0; +// desc.TextureCubeArray.NumCubes = 1; +// desc.TextureCubeArray.ResourceMinLODClamp = 0; +// break; +// case FShaderLayoutItemType::Sampler: +// COPLT_THROW("Srv does does not support sampler"); +// case FShaderLayoutItemType::RayTracingAccelerationStructure: +// desc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; +// break; +// } +// device->CreateShaderResourceView(nullptr, &desc, handle); +// break; +// } +// case FShaderLayoutGroupView::Uav: +// { +// D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; +// desc.Format = ToDx(def.Format); +// switch (def.Type) +// { +// case FShaderLayoutItemType::ConstantBuffer: +// COPLT_THROW("Uav does not support ConstantBuffer"); +// case FShaderLayoutItemType::Buffer: +// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; +// break; +// case FShaderLayoutItemType::RawBuffer: +// desc.Format = DXGI_FORMAT_R32_TYPELESS; +// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; +// desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; +// break; +// case FShaderLayoutItemType::StructureBuffer: +// case FShaderLayoutItemType::StructureBufferWithCounter: +// desc.Format = DXGI_FORMAT_UNKNOWN; +// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; +// desc.Buffer.FirstElement = 0; +// desc.Buffer.NumElements = 1; +// desc.Buffer.StructureByteStride = 1; +// desc.Buffer.CounterOffsetInBytes = 0; +// break; +// case FShaderLayoutItemType::Texture1D: +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D; +// desc.Texture1D.MipSlice = 0; +// break; +// case FShaderLayoutItemType::Texture1DArray: +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY; +// desc.Texture1DArray.MipSlice = 0; +// desc.Texture1DArray.FirstArraySlice = 0; +// desc.Texture1DArray.ArraySize = 1; +// break; +// case FShaderLayoutItemType::Texture2D: +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; +// desc.Texture2D.MipSlice = 0; +// desc.Texture2D.PlaneSlice = 0; +// break; +// case FShaderLayoutItemType::Texture2DArray: +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY; +// desc.Texture2DArray.MipSlice = 0; +// desc.Texture2DArray.FirstArraySlice = 0; +// desc.Texture2DArray.ArraySize = 1; +// desc.Texture2DArray.PlaneSlice = 0; +// break; +// case FShaderLayoutItemType::Texture2DMultisample: +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMS; +// break; +// case FShaderLayoutItemType::Texture2DArrayMultisample: +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY; +// desc.Texture2DMSArray.FirstArraySlice = 0; +// desc.Texture2DMSArray.ArraySize = 1; +// break; +// case FShaderLayoutItemType::Texture3D: +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D; +// desc.Texture3D.MipSlice = 0; +// desc.Texture3D.FirstWSlice = 0; +// desc.Texture3D.WSize = 1; +// break; +// case FShaderLayoutItemType::TextureCube: +// COPLT_THROW("Uav does not support TextureCube"); +// case FShaderLayoutItemType::TextureCubeArray: +// COPLT_THROW("Uav does not support TextureCubeArray"); +// case FShaderLayoutItemType::Sampler: +// COPLT_THROW("Uav does not support Sampler"); +// case FShaderLayoutItemType::RayTracingAccelerationStructure: +// COPLT_THROW("Uav does not support RayTracingAccelerationStructure"); +// } +// device->CreateUnorderedAccessView(nullptr, nullptr, &desc, handle); +// break; +// } +// case FShaderLayoutGroupView::Sampler: +// { +// D3D12_SAMPLER_DESC desc{}; +// desc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; +// desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; +// desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; +// desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; +// desc.MaxLOD = FLT_MAX; +// device->CreateSampler(&desc, handle); +// break; +// } +// default: +// std::unreachable(); +// } +// } +// +// void View::CreateBufferDescriptor( +// NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type +// ) const +// { +// const auto buffer = Buffer().get(); +// const auto resource = buffer->GetResourcePtr(); +// const auto data = buffer->GpuBufferData(); +// switch (type) +// { +// case FShaderLayoutGroupView::Cbv: +// { +// D3D12_CONSTANT_BUFFER_VIEW_DESC desc{}; +// desc.BufferLocation = resource->GetGPUVirtualAddress(); +// desc.SizeInBytes = data->m_size; +// device->CreateConstantBufferView(&desc, handle); +// break; +// } +// case FShaderLayoutGroupView::Srv: +// { +// D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; +// desc.Format = ToDx(def.Format); +// desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; +// switch (def.Type) +// { +// case FShaderLayoutItemType::ConstantBuffer: +// COPLT_THROW("Srv does not support ConstantBuffer"); +// case FShaderLayoutItemType::Buffer: +// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; +// break; +// case FShaderLayoutItemType::RawBuffer: +// if (data->m_usage != FBufferUsage::Raw) +// COPLT_THROW("Buffer not a Raw Buffer"); +// desc.Format = DXGI_FORMAT_R32_TYPELESS; +// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; +// desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; +// break; +// case FShaderLayoutItemType::StructureBuffer: +// case FShaderLayoutItemType::StructureBufferWithCounter: +// if (data->m_usage != FBufferUsage::Structured) +// COPLT_THROW("Buffer not a Structured Buffer"); +// desc.Format = DXGI_FORMAT_UNKNOWN; +// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; +// desc.Buffer.FirstElement = 0; +// desc.Buffer.NumElements = data->m_count; +// desc.Buffer.StructureByteStride = data->m_stride; +// 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: +// COPLT_THROW("Buffer Srv does not support Texture"); +// case FShaderLayoutItemType::Sampler: +// COPLT_THROW("Buffer Srv does not support Sampler"); +// case FShaderLayoutItemType::RayTracingAccelerationStructure: +// desc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; +// desc.RaytracingAccelerationStructure.Location = resource->GetGPUVirtualAddress(); +// break; +// } +// device->CreateShaderResourceView(resource, &desc, handle); +// break; +// } +// case FShaderLayoutGroupView::Uav: +// { +// D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; +// desc.Format = ToDx(def.Format); +// switch (def.Type) +// { +// case FShaderLayoutItemType::ConstantBuffer: +// COPLT_THROW("Uav does not support ConstantBuffer"); +// case FShaderLayoutItemType::Buffer: +// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; +// break; +// case FShaderLayoutItemType::RawBuffer: +// if (data->m_usage != FBufferUsage::Raw) +// COPLT_THROW("Buffer not a Raw Buffer"); +// desc.Format = DXGI_FORMAT_R32_TYPELESS; +// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; +// desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; +// break; +// case FShaderLayoutItemType::StructureBuffer: +// case FShaderLayoutItemType::StructureBufferWithCounter: +// if (data->m_usage != FBufferUsage::Structured) +// COPLT_THROW("Buffer not a Structured Buffer"); +// desc.Format = DXGI_FORMAT_UNKNOWN; +// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; +// desc.Buffer.FirstElement = 0; +// desc.Buffer.NumElements = data->m_count; +// desc.Buffer.StructureByteStride = data->m_stride; +// desc.Buffer.CounterOffsetInBytes = 0; +// 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: +// COPLT_THROW("Buffer Uav does not support Texture"); +// case FShaderLayoutItemType::Sampler: +// COPLT_THROW("Buffer Uav does not support Sampler"); +// case FShaderLayoutItemType::RayTracingAccelerationStructure: +// COPLT_THROW("Buffer Uav does not support RayTracingAccelerationStructure"); +// } +// device->CreateUnorderedAccessView(resource, nullptr, &desc, handle); +// break; +// } +// case FShaderLayoutGroupView::Sampler: +// COPLT_THROW("Buffer cannot be used as a sampler"); +// } +// } +// +// void View::CreateImageDescriptor( +// NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type +// ) const +// { +// const auto image = Image().get(); +// const auto resource = image->GetResourcePtr(); +// const auto data = image->GpuImageData(); +// switch (type) +// { +// case FShaderLayoutGroupView::Cbv: +// COPLT_THROW("Image cannot be used as a Cbv"); +// case FShaderLayoutGroupView::Srv: +// { +// D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; +// desc.Format = ToDx(data->m_format); +// desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; +// switch (def.Type) +// { +// case FShaderLayoutItemType::ConstantBuffer: +// COPLT_THROW("Srv does not support ConstantBuffer"); +// case FShaderLayoutItemType::Buffer: +// case FShaderLayoutItemType::RawBuffer: +// case FShaderLayoutItemType::StructureBuffer: +// case FShaderLayoutItemType::StructureBufferWithCounter: +// COPLT_THROW("Image Srv does not support Buffer"); +// case FShaderLayoutItemType::Texture1D: +// { +// if (data->m_dimension != FImageDimension::One) +// COPLT_THROW("Bind required Texture1D, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; +// desc.Texture1D.MostDetailedMip = 0; +// desc.Texture1D.MipLevels = data->m_mip_levels; +// desc.Texture1D.ResourceMinLODClamp = 0; +// break; +// } +// case FShaderLayoutItemType::Texture1DArray: +// { +// if (data->m_dimension != FImageDimension::One) +// COPLT_THROW("Bind required Texture1DArray, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; +// desc.Texture1DArray.MostDetailedMip = 0; +// desc.Texture1DArray.MipLevels = data->m_mip_levels; +// desc.Texture1DArray.FirstArraySlice = 0; +// desc.Texture1DArray.ArraySize = data->m_depth_or_length; +// desc.Texture1DArray.ResourceMinLODClamp = 0; +// break; +// } +// case FShaderLayoutItemType::Texture2D: +// { +// if (data->m_dimension != FImageDimension::Two) +// COPLT_THROW("Bind required Texture2D, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; +// desc.Texture2D.MostDetailedMip = 0; +// desc.Texture2D.MipLevels = data->m_mip_levels; +// desc.Texture2D.PlaneSlice = 0; +// desc.Texture2D.ResourceMinLODClamp = 0; +// break; +// } +// case FShaderLayoutItemType::Texture2DArray: +// { +// if (data->m_dimension != FImageDimension::Two) +// COPLT_THROW("Bind required Texture2DArray, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; +// desc.Texture2DArray.MostDetailedMip = 0; +// desc.Texture2DArray.MipLevels = data->m_mip_levels; +// desc.Texture2DArray.FirstArraySlice = 0; +// desc.Texture2DArray.ArraySize = data->m_depth_or_length; +// desc.Texture2DArray.PlaneSlice = 0; +// desc.Texture2DArray.ResourceMinLODClamp = 0; +// break; +// } +// case FShaderLayoutItemType::Texture2DMultisample: +// { +// if (data->m_dimension != FImageDimension::Two) +// COPLT_THROW("Bind required Texture2DMultisample, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; +// break; +// } +// case FShaderLayoutItemType::Texture2DArrayMultisample: +// { +// if (data->m_dimension != FImageDimension::Two) +// COPLT_THROW("Bind required Texture2DArrayMultisample, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; +// desc.Texture2DMSArray.FirstArraySlice = 0; +// desc.Texture2DMSArray.ArraySize = data->m_depth_or_length; +// break; +// } +// case FShaderLayoutItemType::Texture3D: +// { +// if (data->m_dimension != FImageDimension::Three) +// COPLT_THROW("Bind required Texture3D, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; +// desc.Texture3D.MostDetailedMip = 0; +// desc.Texture3D.MipLevels = data->m_mip_levels; +// desc.Texture3D.ResourceMinLODClamp = 0; +// break; +// } +// case FShaderLayoutItemType::TextureCube: +// { +// if (data->m_dimension != FImageDimension::Cube) +// COPLT_THROW("Bind required TextureCube, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; +// desc.TextureCube.MostDetailedMip = 0; +// desc.TextureCube.MipLevels = data->m_mip_levels; +// desc.TextureCube.ResourceMinLODClamp = 0; +// break; +// } +// case FShaderLayoutItemType::TextureCubeArray: +// { +// if (data->m_dimension != FImageDimension::Cube) +// COPLT_THROW("Bind required TextureCubeArray, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; +// desc.TextureCubeArray.MostDetailedMip = 0; +// desc.TextureCubeArray.MipLevels = data->m_mip_levels; +// desc.TextureCubeArray.First2DArrayFace = 0; +// desc.TextureCubeArray.NumCubes = (data->m_depth_or_length + 5) / 6; +// desc.TextureCubeArray.ResourceMinLODClamp = 0; +// break; +// } +// case FShaderLayoutItemType::Sampler: +// COPLT_THROW("Srv does not support sampler"); +// case FShaderLayoutItemType::RayTracingAccelerationStructure: +// COPLT_THROW("Image Srv does not support RayTracingAccelerationStructure"); +// } +// device->CreateShaderResourceView(resource, &desc, handle); +// break; +// } +// case FShaderLayoutGroupView::Uav: +// { +// D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; +// desc.Format = ToDx(data->m_format); +// switch (def.Type) +// { +// case FShaderLayoutItemType::ConstantBuffer: +// COPLT_THROW("Uav not support ConstantBuffer"); +// +// case FShaderLayoutItemType::Buffer: +// case FShaderLayoutItemType::RawBuffer: +// case FShaderLayoutItemType::StructureBuffer: +// case FShaderLayoutItemType::StructureBufferWithCounter: +// COPLT_THROW("Image Srv does not support Buffer"); +// case FShaderLayoutItemType::Texture1D: +// { +// if (data->m_dimension != FImageDimension::One) +// COPLT_THROW("Bind required Texture1D, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D; +// desc.Texture1D.MipSlice = 0; +// break; +// } +// case FShaderLayoutItemType::Texture1DArray: +// { +// if (data->m_dimension != FImageDimension::One) +// COPLT_THROW("Bind required Texture1DArray, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY; +// desc.Texture1DArray.MipSlice = 0; +// desc.Texture1DArray.FirstArraySlice = 0; +// desc.Texture1DArray.ArraySize = data->m_depth_or_length; +// break; +// } +// case FShaderLayoutItemType::Texture2D: +// { +// if (data->m_dimension != FImageDimension::Two) +// COPLT_THROW("Bind required Texture2D, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; +// desc.Texture2D.MipSlice = 0; +// desc.Texture2D.PlaneSlice = 0; +// break; +// } +// case FShaderLayoutItemType::Texture2DArray: +// { +// if (data->m_dimension != FImageDimension::Two) +// COPLT_THROW("Bind required Texture2DArray, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY; +// desc.Texture2DArray.MipSlice = 0; +// desc.Texture2DArray.FirstArraySlice = 0; +// desc.Texture2DArray.ArraySize = data->m_depth_or_length; +// desc.Texture2DArray.PlaneSlice = 0; +// break; +// } +// case FShaderLayoutItemType::Texture2DMultisample: +// { +// if (data->m_dimension != FImageDimension::Two) +// COPLT_THROW("Bind required Texture2DMultisample, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMS; +// break; +// } +// case FShaderLayoutItemType::Texture2DArrayMultisample: +// { +// if (data->m_dimension != FImageDimension::Two) +// COPLT_THROW("Bind required Texture2DArrayMultisample, but the actual resources provided are not"); +// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY; +// desc.Texture2DMSArray.FirstArraySlice = 0; +// desc.Texture2DMSArray.ArraySize = data->m_depth_or_length; +// break; +// } +// case FShaderLayoutItemType::Texture3D: +// { +// if (data->m_dimension != FImageDimension::Three) +// COPLT_THROW("Bind required Texture3D, but the actual resources provided are not"); +// desc.Texture3D.MipSlice = 0; +// desc.Texture3D.FirstWSlice = 0; +// desc.Texture3D.WSize = data->m_depth_or_length; +// break; +// } +// case FShaderLayoutItemType::TextureCube: +// COPLT_THROW("Uav not support TextureCube"); +// case FShaderLayoutItemType::TextureCubeArray: +// COPLT_THROW("Uav not support TextureCubeArray"); +// case FShaderLayoutItemType::Sampler: +// COPLT_THROW("Uav not support Sampler"); +// case FShaderLayoutItemType::RayTracingAccelerationStructure: +// COPLT_THROW("Uav not support RayTracingAccelerationStructure"); +// } +// device->CreateUnorderedAccessView(resource, nullptr, &desc, handle); +// break; +// } +// case FShaderLayoutGroupView::Sampler: +// COPLT_THROW("Image cannot be used as a sampler"); +// } +// } +// +// void View::CreateSamplerDescriptor( +// NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type +// ) const +// { +// const auto sampler = Sampler().get(); +// switch (type) +// { +// case FShaderLayoutGroupView::Cbv: +// COPLT_THROW("Sampler cannot be used as a Cbv"); +// case FShaderLayoutGroupView::Srv: +// COPLT_THROW("Sampler cannot be used as a Srv"); +// case FShaderLayoutGroupView::Uav: +// COPLT_THROW("Sampler cannot be used as a Uav"); +// case FShaderLayoutGroupView::Sampler: +// device->CreateSampler(sampler->Desc(), handle); +// break; +// } +// } diff --git a/Examples/Colorful/Example.cs b/Examples/Colorful/Example.cs index 1696ad0..20434e2 100644 --- a/Examples/Colorful/Example.cs +++ b/Examples/Colorful/Example.cs @@ -6,7 +6,8 @@ namespace Examples; public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handle, Width, Height) { - private ShaderLayout Layout = null!; + private ShaderLayout ShaderLayout = null!; + private BindingLayout BindingLayout = null!; private Shader Shader = null!; private GraphicsShaderPipeline Pipeline = null!; private ShaderBinding ShaderBinding = null!; @@ -16,20 +17,34 @@ public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handl protected override async Task LoadResources(GpuRecord cmd) { var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); - Layout = Device.CreateShaderLayout( + ShaderLayout = Device.CreateShaderLayout( [ new() { + Id = 0, Slot = 0, Stage = ShaderStage.Pixel, View = ShaderLayoutItemView.Cbv, Type = ShaderLayoutItemType.ConstantBuffer, - Usage = ShaderLayoutItemUsage.Persist, } - ], - Name: Name + ] ); - Shader = Device.CreateShader(modules, Layout); + BindingLayout = Device.CreateBindingLayout( + ShaderLayout, [ + Device.CreateBindGroupLayout( + [ + new() + { + Id = 0, + Stages = ShaderStageFlags.Pixel, + View = ShaderLayoutItemView.Cbv, + Type = ShaderLayoutItemType.ConstantBuffer, + } + ] + ) + ], Name: Name + ); + Shader = Device.CreateShader(modules, ShaderLayout); // ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); Pipeline = Device.CreateGraphicsShaderPipeline( Shader, new() From d1b99de7716c9ff3e4e7fcb061d319b06f30ba21 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 3 Apr 2025 15:49:44 +0800 Subject: [PATCH 30/46] save --- Coplt.Graphics.Core/Core/Barrier.cs | 238 --------- Coplt.Graphics.Core/Core/GpuIsolate.cs | 15 +- Coplt.Graphics.Core/Core/GpuResource.cs | 32 +- Coplt.Graphics.Core/Core/GpuViewable.cs | 26 +- Coplt.Graphics.Core/Core/LegacyState.cs | 63 --- Coplt.Graphics.Core/Core/ResState.cs | 162 ------ Coplt.Graphics.Core/Core/Sampler.cs | 4 +- Coplt.Graphics.Core/Core/ShaderStage.cs | 2 +- Coplt.Graphics.Core/Core/View.cs | 6 +- Coplt.Graphics.Core/Native/Native.cs | 501 +++++++------------ Coplt.Graphics.Core/Native/ResState.cs | 128 ----- Coplt.Graphics.Native/Api/CMakeLists.txt | 2 +- Coplt.Graphics.Native/Api/FFI/Binding.h | 20 +- Coplt.Graphics.Native/Api/FFI/Device.h | 3 +- Coplt.Graphics.Native/Api/FFI/Resource.h | 137 ++--- Coplt.Graphics.Native/Api/FFI/Sampler.h | 3 +- Coplt.Graphics.Native/Api/FFI/States.h | 205 -------- Coplt.Graphics.Native/Api/FFI/View.h | 24 + Coplt.Graphics.Native/D3d12/CMakeLists.txt | 1 - Coplt.Graphics.Native/D3d12/FFI/Binding.h | 10 - Coplt.Graphics.Native/D3d12/Include/States.h | 293 ----------- Coplt.Graphics.Native/D3d12/Include/View.h | 52 +- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 14 +- Coplt.Graphics.Native/D3d12/Src/Binding.h | 22 +- Coplt.Graphics.Native/D3d12/Src/Buffer.cc | 16 +- Coplt.Graphics.Native/D3d12/Src/Buffer.h | 2 - Coplt.Graphics.Native/D3d12/Src/Device.cc | 20 +- Coplt.Graphics.Native/D3d12/Src/Device.h | 5 +- Coplt.Graphics.Native/D3d12/Src/Image.cc | 15 +- Coplt.Graphics.Native/D3d12/Src/Image.h | 2 - Coplt.Graphics.Native/D3d12/Src/Resource.cc | 49 +- Coplt.Graphics.Native/D3d12/Src/Resource.h | 8 +- Coplt.Graphics.Native/D3d12/Src/View.cc | 217 +------- Examples/Colorful/Example.cs | 5 +- 34 files changed, 398 insertions(+), 1904 deletions(-) delete mode 100644 Coplt.Graphics.Core/Core/Barrier.cs delete mode 100644 Coplt.Graphics.Core/Core/LegacyState.cs delete mode 100644 Coplt.Graphics.Core/Core/ResState.cs delete mode 100644 Coplt.Graphics.Core/Native/ResState.cs delete mode 100644 Coplt.Graphics.Native/Api/FFI/States.h create mode 100644 Coplt.Graphics.Native/Api/FFI/View.h delete mode 100644 Coplt.Graphics.Native/D3d12/FFI/Binding.h diff --git a/Coplt.Graphics.Core/Core/Barrier.cs b/Coplt.Graphics.Core/Core/Barrier.cs deleted file mode 100644 index 5e2e513..0000000 --- a/Coplt.Graphics.Core/Core/Barrier.cs +++ /dev/null @@ -1,238 +0,0 @@ -using Coplt.Graphics.Native; -using Coplt.Union; - -namespace Coplt.Graphics.Core; - -[Union] -public partial struct Barrier -{ - [UnionTemplate] - private interface Template - { - void None(); - GlobalBarrier Global(); - BufferBarrier Buffer(); - ImageBarrier Image(); - } - - public static implicit operator Barrier(GlobalBarrier value) => MakeGlobal(value); - - public static implicit operator Barrier(BufferBarrier value) => MakeBuffer(value); - - public static implicit operator Barrier(ImageBarrier value) => MakeImage(value); -} - -public record struct GlobalBarrier( - ResAccess AccessBefore, - ResAccess AccessAfter, - ShaderStageFlags StagesBefore, - ShaderStageFlags StagesAfter -) -{ - public ResAccess AccessBefore = AccessBefore; - public ResAccess AccessAfter = AccessAfter; - public ShaderStageFlags StagesBefore = StagesBefore; - public ShaderStageFlags StagesAfter = StagesAfter; -} - -public record struct BufferBarrier( - IGpuResource Buffer, - ulong Offset, - ulong Size, - LegacyState LegacyBefore, - LegacyState LegacyAfter, - ResAccess AccessBefore, - ResAccess AccessAfter, - ShaderStageFlags StagesBefore = ShaderStageFlags.None, - ShaderStageFlags StagesAfter = ShaderStageFlags.None -) -{ - public IGpuResource Buffer = Buffer; - public ulong Offset = Offset; - public ulong Size = Size; - public LegacyState LegacyBefore = LegacyBefore; - public LegacyState LegacyAfter = LegacyAfter; - public ResAccess AccessBefore = AccessBefore; - public ResAccess AccessAfter = AccessAfter; - public ShaderStageFlags StagesBefore = StagesBefore; - public ShaderStageFlags StagesAfter = StagesAfter; - - public BufferBarrier( - IGpuResource Buffer, - LegacyState LegacyBefore, - LegacyState LegacyAfter, - ResAccess AccessBefore, - ResAccess AccessAfter, - ShaderStageFlags StagesBefore = ShaderStageFlags.None, - ShaderStageFlags StagesAfter = ShaderStageFlags.None - ) : this( - Buffer, 0, Buffer.Size, - LegacyBefore, LegacyAfter, AccessBefore, AccessAfter, StagesBefore, StagesAfter - ) { } - - public BufferBarrier( - IGpuResource Buffer, - LegacyState LegacyBefore, - LegacyState LegacyAfter - ) : this( - Buffer, 0, Buffer.Size, - LegacyBefore, LegacyAfter, default, default, default, default - ) { } - - public BufferBarrier( - IGpuResource Buffer, - ulong Offset, - ulong Size, - LegacyState LegacyBefore, - LegacyState LegacyAfter - ) : this( - Buffer, Offset, Size, - LegacyBefore, LegacyAfter, default, default, default, default - ) { } - - public BufferBarrier( - IGpuResource Buffer, - ResAccess AccessBefore, - ResAccess AccessAfter, - ShaderStageFlags StagesBefore = ShaderStageFlags.None, - ShaderStageFlags StagesAfter = ShaderStageFlags.None - ) : this( - Buffer, 0, Buffer.Size, - default, default, AccessBefore, AccessAfter, StagesBefore, StagesAfter - ) { } - - public BufferBarrier( - IGpuResource Buffer, - ulong Offset, - ulong Size, - ResAccess AccessBefore, - ResAccess AccessAfter, - ShaderStageFlags StagesBefore = ShaderStageFlags.None, - ShaderStageFlags StagesAfter = ShaderStageFlags.None - ) : this( - Buffer, Offset, Size, - default, default, AccessBefore, AccessAfter, StagesBefore, StagesAfter - ) { } -} - -public record struct ImageBarrier( - IGpuResource Image, - SubResourceRange SubResourceRange, - LegacyState LegacyBefore, - LegacyState LegacyAfter, - ResLayout LayoutBefore, - ResLayout LayoutAfter, - ResAccess AccessBefore, - ResAccess AccessAfter, - ShaderStageFlags StagesBefore = ShaderStageFlags.None, - ShaderStageFlags StagesAfter = ShaderStageFlags.None, - ImageBarrierFlags Flags = ImageBarrierFlags.None -) -{ - public IGpuResource Image = Image; - public SubResourceRange SubResourceRange = SubResourceRange; - public LegacyState LegacyBefore = LegacyBefore; - public LegacyState LegacyAfter = LegacyAfter; - public ResLayout LayoutBefore = LayoutBefore; - public ResLayout LayoutAfter = LayoutAfter; - public ResAccess AccessBefore = AccessBefore; - public ResAccess AccessAfter = AccessAfter; - public ShaderStageFlags StagesBefore = StagesBefore; - public ShaderStageFlags StagesAfter = StagesAfter; - public ImageBarrierFlags Flags = Flags; - - public ImageBarrier( - IGpuResource Image, - LegacyState LegacyBefore, - LegacyState LegacyAfter, - ResLayout LayoutBefore, - ResLayout LayoutAfter, - ResAccess AccessBefore, - ResAccess AccessAfter, - ShaderStageFlags StagesBefore = ShaderStageFlags.None, - ShaderStageFlags StagesAfter = ShaderStageFlags.None, - ImageBarrierFlags Flags = ImageBarrierFlags.None - ) : this( - Image, new(Image), - LegacyBefore, LegacyAfter, LayoutBefore, LayoutAfter, AccessBefore, AccessAfter, StagesBefore, StagesAfter, - Flags - ) { } - - public ImageBarrier( - IGpuResource Image, - SubResourceRange SubResourceRange, - LegacyState LegacyBefore, - LegacyState LegacyAfter, - ImageBarrierFlags Flags = ImageBarrierFlags.None - ) : this( - Image, SubResourceRange, - LegacyBefore, LegacyAfter, default, default, default, default, default, default, Flags - ) { } - - public ImageBarrier( - IGpuResource Image, - LegacyState LegacyBefore, - LegacyState LegacyAfter, - ImageBarrierFlags Flags = ImageBarrierFlags.None - ) : this( - Image, new(Image), - LegacyBefore, LegacyAfter, default, default, default, default, default, default, Flags - ) { } - - public ImageBarrier( - IGpuResource Image, - ResLayout LayoutBefore, - ResLayout LayoutAfter, - ResAccess AccessBefore, - ResAccess AccessAfter, - ShaderStageFlags StagesBefore = ShaderStageFlags.None, - ShaderStageFlags StagesAfter = ShaderStageFlags.None, - ImageBarrierFlags Flags = ImageBarrierFlags.None - ) : this( - Image, new(Image), - default, default, LayoutBefore, LayoutAfter, AccessBefore, AccessAfter, StagesBefore, StagesAfter, Flags - ) { } - - public ImageBarrier( - IGpuResource Image, - SubResourceRange SubResourceRange, - ResLayout LayoutBefore, - ResLayout LayoutAfter, - ResAccess AccessBefore, - ResAccess AccessAfter, - ShaderStageFlags StagesBefore = ShaderStageFlags.None, - ShaderStageFlags StagesAfter = ShaderStageFlags.None, - ImageBarrierFlags Flags = ImageBarrierFlags.None - ) : this( - Image, SubResourceRange, - default, default, LayoutBefore, LayoutAfter, AccessBefore, AccessAfter, StagesBefore, StagesAfter, Flags - ) { } -} - -[Flags] -public enum ImageBarrierFlags : uint -{ - None, - Discard = 1 << 0, - CrossQueue = 1 << 1, -} - -public record struct SubResourceRange( - uint IndexOrFirstMipLevel, - uint NumMipLevels, - uint FirstArraySlice, - uint NumArraySlices, - uint FirstPlane, - uint NumPlanes -) -{ - public uint IndexOrFirstMipLevel = IndexOrFirstMipLevel; - public uint NumMipLevels = NumMipLevels; - public uint FirstArraySlice = FirstArraySlice; - public uint NumArraySlices = NumArraySlices; - public uint FirstPlane = FirstPlane; - public uint NumPlanes = NumPlanes; - - public SubResourceRange(IGpuResource Image) - : this(0, Image.MipLevels, 0, Image.DepthOrLength, 0, Image.Planes) { } -} diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 029e84c..0a7311d 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -3,6 +3,7 @@ using System.Runtime.CompilerServices; using Coplt.Dropping; using Coplt.Graphics.Native; +using Coplt.Graphics.States; namespace Coplt.Graphics.Core; @@ -292,11 +293,8 @@ public GpuBuffer CreateBuffer( { Base = { - Base = - { - Name = new(Name, Name8, p_name, p_name8), - Purpose = options.Purpose.ToFFI(), - }, + Name = new(Name, Name8, p_name, p_name8), + Purpose = options.Purpose.ToFFI(), CpuAccess = options.CpuAccess.ToFFI(), }, Size = options.Size, @@ -330,11 +328,8 @@ public GpuImage CreateImage( { Base = { - Base = - { - Name = new(Name, Name8, p_name, p_name8), - Purpose = options.Purpose.ToFFI(), - }, + Name = new(Name, Name8, p_name, p_name8), + Purpose = options.Purpose.ToFFI(), CpuAccess = options.CpuAccess.ToFFI(), }, Format = options.Format.ToFFI(), diff --git a/Coplt.Graphics.Core/Core/GpuResource.cs b/Coplt.Graphics.Core/Core/GpuResource.cs index ed7b4c1..5ed2299 100644 --- a/Coplt.Graphics.Core/Core/GpuResource.cs +++ b/Coplt.Graphics.Core/Core/GpuResource.cs @@ -5,29 +5,41 @@ namespace Coplt.Graphics.Core; [Dropping(Unmanaged = true)] -public abstract unsafe partial class GpuResource : GpuViewable +public abstract unsafe partial class GpuResource : GpuViewable, IIsolateChild { - #region Props + #region Fields + + internal FGpuResourceData* m_data; + #endregion + + #region Props + + public GpuIsolate Isolate { get; } public new FGpuResource* Ptr => (FGpuResource*)m_ptr; - internal new ref readonly FGpuResourceData Data => ref *(FGpuResourceData*)m_data; + internal ref readonly FGpuResourceData Data => ref *m_data; + public ResourcePurpose Purpose => (ResourcePurpose)Data.m_purpose; public CpuAccess CpuAccess => (CpuAccess)Data.m_cpu_access; #endregion #region Ctor - internal GpuResource(FGpuResource* ptr, FGpuResourceData* data, string? name, GpuIsolate isolate) - : base((FGpuViewable*)ptr, (FGpuViewableData*)data, name, isolate) { } + internal GpuResource(FGpuResource* ptr, FGpuResourceData* data, string? name, GpuIsolate isolate) : base((FGpuViewable*)ptr, name, isolate.Device) + { + Isolate = isolate; + m_data = data; + } #endregion - #region ToString + #region Drop - public override string ToString() => - m_name is null - ? $"{nameof(GpuResource)}(0x{(nuint)m_ptr:X})" - : $"{nameof(GpuResource)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; + [Drop] + private void Drop() + { + m_data = null; + } #endregion } diff --git a/Coplt.Graphics.Core/Core/GpuViewable.cs b/Coplt.Graphics.Core/Core/GpuViewable.cs index 0b96832..e3f9f49 100644 --- a/Coplt.Graphics.Core/Core/GpuViewable.cs +++ b/Coplt.Graphics.Core/Core/GpuViewable.cs @@ -4,39 +4,17 @@ namespace Coplt.Graphics.Core; -[Dropping(Unmanaged = true)] -public abstract unsafe partial class GpuViewable : IsolateChild +public abstract unsafe class GpuViewable : DeviceChild { - #region Fields - - internal FGpuViewableData* m_data; - - #endregion - #region Props public new FGpuViewable* Ptr => (FGpuViewable*)m_ptr; - internal ref readonly FGpuViewableData Data => ref *m_data; - public ResourcePurpose Purpose => (ResourcePurpose)Data.m_purpose; #endregion #region Ctor - internal GpuViewable(FGpuViewable* ptr, FGpuViewableData* data, string? name, GpuIsolate isolate) : base((FGpuObject*)ptr, name, isolate) - { - m_data = data; - } - - #endregion - - #region Drop - - [Drop] - private void Drop() - { - m_data = null; - } + internal GpuViewable(FGpuViewable* ptr, string? name, GpuDevice device) : base((FGpuObject*)ptr, name, device) { } #endregion } diff --git a/Coplt.Graphics.Core/Core/LegacyState.cs b/Coplt.Graphics.Core/Core/LegacyState.cs deleted file mode 100644 index 0d847c5..0000000 --- a/Coplt.Graphics.Core/Core/LegacyState.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Runtime.CompilerServices; -using Coplt.Graphics.Native; - -namespace Coplt.Graphics.Core; - -[Flags] -public enum LegacyState : uint -{ - Manual = uint.MaxValue, - Common = 1 << 0, - Present = 1 << 1, - VertexBuffer = 1 << 2, - IndexBuffer = 1 << 3, - ConstantBuffer = 1 << 4, - IndirectBuffer = 1 << 5, - RenderTarget = 1 << 6, - DepthRead = 1 << 7, - DepthWrite = 1 << 8, - ShaderResource = 1 << 9, - UnorderedAccess = 1 << 10, - CopySrc = 1 << 11, - CopyDst = 1 << 12, - ResolveSrc = 1 << 13, - ResolveDst = 1 << 14, - RayTracing = 1 << 15, - ShadingRate = 1 << 16, - StreamOutput = 1 << 17, - - GenericRead = VertexBuffer | ConstantBuffer | ShaderResource | IndirectBuffer | CopySrc, -} - -public static partial class GraphicsExtensions -{ - public static FLegacyState ToFFI(this LegacyState value) => (FLegacyState)value; - - public static LegacyState FromFFI(this FLegacyState value) => (LegacyState)value; - - public static bool ContainsOnly(this LegacyState value, LegacyState other) => (value & ~other) == 0; - public static bool Contains(this LegacyState value, LegacyState other) => (value & other) != 0; - - public static bool IsReadOnly(this LegacyState value) => value.ContainsOnly( - LegacyState.IndexBuffer | LegacyState.VertexBuffer | LegacyState.ConstantBuffer | - LegacyState.IndirectBuffer | LegacyState.CopySrc | LegacyState.ResolveSrc | - LegacyState.ShaderResource | LegacyState.DepthRead | LegacyState.ShadingRate - ); - - public static bool IsCompatible(this LegacyState value, LegacyState other) - { - if (value == LegacyState.Manual || other == LegacyState.Manual) return false; - if (value == other) return true; - if (value.IsReadOnly() && other.IsReadOnly()) return true; - return false; - } - - public static void ChangeState(this ref LegacyState value, LegacyState state) - { - if (value.IsCompatible(state)) value |= state; - else value = state; - } - - public static void ChangeState(this ref FLegacyState value, FLegacyState state) => - ChangeState(ref Unsafe.As(ref value), (LegacyState)state); -} diff --git a/Coplt.Graphics.Core/Core/ResState.cs b/Coplt.Graphics.Core/Core/ResState.cs deleted file mode 100644 index e5cfd20..0000000 --- a/Coplt.Graphics.Core/Core/ResState.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System.Diagnostics; -using Coplt.Graphics.Native; - -namespace Coplt.Graphics.Core; - -public enum ResLayout : uint -{ - None = 0, - Common, - Present = Common, - GenericRead, - RenderTarget, - UnorderedAccess, - DepthStencilRead, - DepthStencilWrite, - ShaderResource, - CopySrc, - CopyDst, - ResolveSrc, - ResolveDst, - ShadingRate, - VideoDecodeRead, - VideoDecodeWrite, - VideoProcessRead, - VideoProcessWrite, - VideoEncodeRead, - VideoEncodeWrite, -} - -[Flags] -public enum ResAccess : uint -{ - NoAccess = 1u << 31, - Common = 0, - ConstantBuffer = 1 << 0, - VertexBuffer = 1 << 1, - IndexBuffer = 1 << 2, - RenderTarget = 1 << 3, - UnorderedAccess = 1 << 4, - DepthStencilRead = 1 << 5, - DepthStencilWrite = 1 << 6, - ShaderResource = 1 << 7, - StreamOutput = 1 << 8, - IndirectOrPredicationBuffer = 1 << 9, - CopySrc = 1 << 10, - CopyDst = 1 << 11, - ResolveSrc = 1 << 12, - ResolveDst = 1 << 13, - RayTracingAccelerationStructureRead = 1 << 14, - RayTracingAccelerationStructureWrite = 1 << 15, - ShadingRate = 1 << 16, - VideoDecodeRead = 1 << 17, - VideoDecodeWrite = 1 << 18, - VideoProcessRead = 1 << 19, - VideoProcessWrite = 1 << 20, - VideoEncodeRead = 1 << 21, - VideoEncodeWrite = 1 << 22, -} - -public record struct ResState -{ - public ResLayout Layout; - public ResAccess Access; - public ShaderStageFlags Stages; - public LegacyState Legacy; - public bool CrossQueue; -} - -public static partial class GraphicsExtensions -{ - public static FResAccess ToFFI(this ResAccess value) => (FResAccess)value; - - public static ResAccess FromFFI(this FResAccess value) => (ResAccess)value; - - public static FResLayout ToFFI(this ResLayout value) => value switch - { - ResLayout.None => FResLayout.None, - ResLayout.Common => FResLayout.Common, - ResLayout.GenericRead => FResLayout.GenericRead, - ResLayout.RenderTarget => FResLayout.RenderTarget, - ResLayout.UnorderedAccess => FResLayout.UnorderedAccess, - ResLayout.DepthStencilRead => FResLayout.DepthStencilRead, - ResLayout.DepthStencilWrite => FResLayout.DepthStencilWrite, - ResLayout.ShaderResource => FResLayout.ShaderResource, - ResLayout.CopySrc => FResLayout.CopySrc, - ResLayout.CopyDst => FResLayout.CopyDst, - ResLayout.ResolveSrc => FResLayout.ResolveSrc, - ResLayout.ResolveDst => FResLayout.ResolveDst, - ResLayout.ShadingRate => FResLayout.ShadingRate, - ResLayout.VideoDecodeRead => FResLayout.VideoDecodeRead, - ResLayout.VideoDecodeWrite => FResLayout.VideoDecodeWrite, - ResLayout.VideoProcessRead => FResLayout.VideoProcessRead, - ResLayout.VideoProcessWrite => FResLayout.VideoProcessWrite, - ResLayout.VideoEncodeRead => FResLayout.VideoEncodeRead, - ResLayout.VideoEncodeWrite => FResLayout.VideoEncodeWrite, - _ => throw new ArgumentOutOfRangeException(nameof(value), value, null) - }; - - public static ResLayout FromFFI(this FResLayout value) => value switch - { - FResLayout.None => ResLayout.None, - FResLayout.Common => ResLayout.Common, - FResLayout.GenericRead => ResLayout.GenericRead, - FResLayout.RenderTarget => ResLayout.RenderTarget, - FResLayout.UnorderedAccess => ResLayout.UnorderedAccess, - FResLayout.DepthStencilRead => ResLayout.DepthStencilRead, - FResLayout.DepthStencilWrite => ResLayout.DepthStencilWrite, - FResLayout.ShaderResource => ResLayout.ShaderResource, - FResLayout.CopySrc => ResLayout.CopySrc, - FResLayout.CopyDst => ResLayout.CopyDst, - FResLayout.ResolveSrc => ResLayout.ResolveSrc, - FResLayout.ResolveDst => ResLayout.ResolveDst, - FResLayout.ShadingRate => ResLayout.ShadingRate, - FResLayout.VideoDecodeRead => ResLayout.VideoDecodeRead, - FResLayout.VideoDecodeWrite => ResLayout.VideoDecodeWrite, - FResLayout.VideoProcessRead => ResLayout.VideoProcessRead, - FResLayout.VideoProcessWrite => ResLayout.VideoProcessWrite, - FResLayout.VideoEncodeRead => ResLayout.VideoEncodeRead, - FResLayout.VideoEncodeWrite => ResLayout.VideoEncodeWrite, - _ => throw new ArgumentOutOfRangeException(nameof(value), value, null) - }; - - public static FResState ToFFI(this in ResState value) => new() - { - Layout = value.Layout.ToFFI(), - Access = value.Access.ToFFI(), - Stages = value.Stages.ToFFI(), - Legacy = value.Legacy.ToFFI(), - CrossQueue = value.CrossQueue, - }; - - public static ResState FromFFI(this in FResState value) => new() - { - Layout = value.Layout.FromFFI(), - Access = value.Access.FromFFI(), - Stages = value.Stages.FromFFI(), - 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/Sampler.cs b/Coplt.Graphics.Core/Core/Sampler.cs index b9486d7..038f1c8 100644 --- a/Coplt.Graphics.Core/Core/Sampler.cs +++ b/Coplt.Graphics.Core/Core/Sampler.cs @@ -90,7 +90,7 @@ public record struct SamplerInfo() namespace Coplt.Graphics.Core { [Dropping(Unmanaged = true)] - public sealed unsafe partial class Sampler : DeviceChild + public sealed unsafe partial class Sampler : GpuViewable { #region Fields @@ -107,7 +107,7 @@ public sealed unsafe partial class Sampler : DeviceChild #region Ctor - internal Sampler(FGpuSampler* ptr, string? name, GpuDevice device) : base((FGpuObject*)ptr, name, device) + internal Sampler(FGpuSampler* ptr, string? name, GpuDevice device) : base((FGpuViewable*)ptr, name, device) { m_info = ptr->Info(); } diff --git a/Coplt.Graphics.Core/Core/ShaderStage.cs b/Coplt.Graphics.Core/Core/ShaderStage.cs index cfb67f9..4c323d8 100644 --- a/Coplt.Graphics.Core/Core/ShaderStage.cs +++ b/Coplt.Graphics.Core/Core/ShaderStage.cs @@ -12,7 +12,7 @@ public enum ShaderStage : byte } [Flags] - public enum ShaderStageFlags : byte + public enum ShaderStageFlags : uint { None = 0, Compute = 1 << 0, diff --git a/Coplt.Graphics.Core/Core/View.cs b/Coplt.Graphics.Core/Core/View.cs index a6d8675..782db61 100644 --- a/Coplt.Graphics.Core/Core/View.cs +++ b/Coplt.Graphics.Core/Core/View.cs @@ -24,9 +24,9 @@ private interface Template public FView ToFFI() => Tag switch { Tags.None => new FView { Type = FViewType.None }, - Tags.Buffer => new FView { Type = FViewType.Buffer, Buffer = Buffer.Ptr }, - Tags.Image => new FView { Type = FViewType.Image, Image = Image.Ptr }, - Tags.Sampler => new FView { Type = FViewType.Sampler, Sampler = Sampler.Ptr }, + Tags.Buffer => new FView { Type = FViewType.Buffer, Viewable = ((GpuViewable)Buffer).Ptr }, + Tags.Image => new FView { Type = FViewType.Image, Viewable = ((GpuViewable)Image).Ptr }, + Tags.Sampler => new FView { Type = FViewType.Sampler, Viewable = ((GpuViewable)Sampler).Ptr }, _ => throw new ArgumentOutOfRangeException() }; } diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index d477ee2..d8eb8e4 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1319,10 +1319,18 @@ public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FSh [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) + public FResult CreateBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, FShaderBindGroup** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[20]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1330,7 +1338,7 @@ public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOp public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[20]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[21]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1338,7 +1346,7 @@ public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipe public FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] FGpuBufferCreateOptions* options, FGpuBuffer** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[21]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[22]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1346,7 +1354,7 @@ public FResult CreateBuffer([NativeTypeName("const FGpuBufferCreateOptions &")] public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FGpuImageCreateOptions* options, FGpuImage** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[22]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[23]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1354,7 +1362,7 @@ public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FG public FResult CreateSampler([NativeTypeName("const FGpuSamplerCreateOptions &")] FGpuSamplerCreateOptions* options, FGpuSampler** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[23]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[24]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } public interface Interface : FGpuObject.Interface @@ -1398,7 +1406,10 @@ public interface Interface : FGpuObject.Interface FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, [NativeTypeName("Coplt::FShaderCreateResult *")] FShaderCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out); + FResult CreateBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, FShaderBindGroup** @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out); [return: NativeTypeName("Coplt::FResult")] FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out); @@ -2951,22 +2962,85 @@ public unsafe partial struct FShaderCreateResult public FShaderData* Data; } - public unsafe partial struct FShaderBindingCreateOptions + public partial struct FBindItem + { + [NativeTypeName("Coplt::FView")] + public FView View; + + [NativeTypeName("Coplt::u32")] + public uint Index; + } + + public unsafe partial struct FShaderBindGroupCreateOptions { [NativeTypeName("Coplt::FStr8or16")] public FStr8or16 Name; - [NativeTypeName("Coplt::FShaderLayout *")] - public FShaderLayout* Layout; + [NativeTypeName("Coplt::FBindGroupLayout *")] + public FBindGroupLayout* Layout; } - public partial struct FBindItem + [Guid("AE54EFE5-C372-4291-B995-55298758D2B2")] + [NativeTypeName("struct FShaderBindGroup : Coplt::FGpuObject")] + public unsafe partial struct FShaderBindGroup : FShaderBindGroup.Interface, INativeGuid { - [NativeTypeName("Coplt::FView")] - public FView View; + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShaderBindGroup)); - [NativeTypeName("Coplt::u32")] - public uint Index; + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShaderBindGroup*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FShaderBindGroup*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FShaderBindGroup*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FShaderBindGroup*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FShaderBindGroup*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderBindGroup*)Unsafe.AsPointer(ref this), &result, name); + } + + public interface Interface : FGpuObject.Interface + { + } + } + + public unsafe partial struct FShaderBindingCreateOptions + { + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; + + [NativeTypeName("Coplt::FBindingLayout *")] + public FBindingLayout* Layout; } [Guid("A3CA644A-0E02-4D25-9A18-8835D66600F7")] @@ -3274,76 +3348,6 @@ public interface Interface : FGpuObject.Interface } } - [NativeTypeName("Coplt::u8")] - public enum ResourceType : byte - { - Unknown = 0, - Buffer = 1, - Image = 2, - } - - [NativeTypeName("Coplt::u8")] - public enum FResourceViewType : byte - { - None = 0, - ConstantBuffer, - ShaderResource, - UnorderedAccess, - RenderTarget, - DepthStencil, - IndexBuffer, - VertexBuffer, - StreamOutput, - } - - [NativeTypeName("Coplt::u32")] - public enum FResourcePurpose : uint - { - None = 0, - ConstantBuffer = 1 << 0, - ShaderResource = 1 << 1, - UnorderedAccess = 1 << 2, - RenderTarget = 1 << 3, - DepthStencil = 1 << 4, - IndexBuffer = 1 << 5, - VertexBuffer = 1 << 6, - StreamOutput = 1 << 7, - RayTracing = 1 << 8, - ShadingRate = 1 << 9, - IndirectDrawArgs = 1 << 10, - } - - [NativeTypeName("Coplt::u8")] - public enum FCpuAccess : byte - { - None = 0, - Write = 1, - Read = 2, - } - - [NativeTypeName("Coplt::u8")] - public enum FBufferUsage : byte - { - Undefined, - Structured, - Raw, - } - - public partial struct FGpuViewCreateOptions - { - [NativeTypeName("Coplt::FStr8or16")] - public FStr8or16 Name; - - [NativeTypeName("Coplt::FResourcePurpose")] - public FResourcePurpose Purpose; - } - - public partial struct FGpuViewableData - { - [NativeTypeName("Coplt::FResourcePurpose")] - public FResourcePurpose m_purpose; - } - [Guid("B3AEB8A5-1FA6-4866-97EF-1A5FA401E18F")] [NativeTypeName("struct FGpuViewable : Coplt::FGpuObject")] public unsafe partial struct FGpuViewable : FGpuViewable.Interface, INativeGuid @@ -3393,39 +3397,87 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuViewable*)Unsafe.AsPointer(ref this), &result, name); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuViewableData *")] - public FGpuViewableData* GpuViewableData() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuViewable*)Unsafe.AsPointer(ref this)); - } - public interface Interface : FGpuObject.Interface { - [return: NativeTypeName("Coplt::FGpuViewableData *")] - FGpuViewableData* GpuViewableData(); } } - [NativeTypeName("struct FGpuResourceCreateOptions : Coplt::FGpuViewCreateOptions")] + [NativeTypeName("Coplt::u8")] + public enum FViewType : byte + { + None = 0, + Buffer = 1, + Image = 2, + Sampler = 3, + } + + public unsafe partial struct FView + { + [NativeTypeName("Coplt::FGpuViewable *")] + public FGpuViewable* Viewable; + + [NativeTypeName("Coplt::FViewType")] + public FViewType Type; + } + + [NativeTypeName("Coplt::u8")] + public enum FCpuAccess : byte + { + None = 0, + Write = 1, + Read = 2, + ReadWrite = 3, + } + + [NativeTypeName("Coplt::u32")] + public enum FResourcePurpose : uint + { + None = 0, + ConstantBuffer = 1 << 0, + ShaderResource = 1 << 1, + UnorderedAccess = 1 << 2, + RenderTarget = 1 << 3, + DepthStencil = 1 << 4, + IndexBuffer = 1 << 5, + VertexBuffer = 1 << 6, + StreamOutput = 1 << 7, + RayTracing = 1 << 8, + ShadingRate = 1 << 9, + IndirectDrawArgs = 1 << 10, + } + public partial struct FGpuResourceCreateOptions { - public FGpuViewCreateOptions Base; + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; [NativeTypeName("Coplt::FCpuAccess")] public FCpuAccess CpuAccess; + + [NativeTypeName("Coplt::FResourcePurpose")] + public FResourcePurpose Purpose; } - [NativeTypeName("struct FGpuResourceData : Coplt::FGpuViewableData")] - public partial struct FGpuResourceData + [NativeTypeName("Coplt::u8")] + public enum ResourceType : byte { - public FGpuViewableData Base; + Unknown = 0, + Buffer = 1, + Image = 2, + } - [NativeTypeName("Coplt::FResState")] - public FResState m_state; + public unsafe partial struct FGpuResourceData + { + public void* m_raw_resource_ptr; + + [NativeTypeName("Coplt::FResourcePurpose")] + public FResourcePurpose m_purpose; [NativeTypeName("Coplt::FCpuAccess")] public FCpuAccess m_cpu_access; + + [NativeTypeName("Coplt::ResourceType")] + public ResourceType m_resource_type; } [Guid("F99DCEEC-2F0C-4A28-B666-BEB7C35219D6")] @@ -3477,37 +3529,28 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuResource*)Unsafe.AsPointer(ref this), &result, name); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuViewableData *")] - public FGpuViewableData* GpuViewableData() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuResource*)Unsafe.AsPointer(ref this)); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FGpuResourceData *")] public FGpuResourceData* GpuResourceData() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuResource*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::ResourceType")] - public ResourceType GetResourceType() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuResource*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuResource*)Unsafe.AsPointer(ref this)); } public interface Interface : FGpuViewable.Interface { [return: NativeTypeName("Coplt::FGpuResourceData *")] FGpuResourceData* GpuResourceData(); - - [return: NativeTypeName("Coplt::ResourceType")] - ResourceType GetResourceType(); } } + [NativeTypeName("Coplt::u8")] + public enum FBufferUsage : byte + { + Undefined, + Structured, + Raw, + } + [NativeTypeName("struct FGpuBufferCreateOptions : Coplt::FGpuResourceCreateOptions")] public partial struct FGpuBufferCreateOptions { @@ -3593,48 +3636,34 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, name); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuViewableData *")] - public FGpuViewableData* GpuViewableData() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FGpuResourceData *")] public FGpuResourceData* GpuResourceData() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::ResourceType")] - public ResourceType GetResourceType() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FGpuBufferData *")] public FGpuBufferData* GpuBufferData() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult Map(void** ptr, [NativeTypeName("Coplt::b8")] B8 Discard) + public FResult Map(void** ptr, [NativeTypeName("Coplt::b8")] B8 discard) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, ptr, Discard); + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, ptr, discard); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult Unmap([NativeTypeName("Coplt::b8")] B8 Discard) + public FResult Unmap([NativeTypeName("Coplt::b8")] B8 discard) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, Discard); + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, discard); } public interface Interface : FGpuResource.Interface @@ -3643,10 +3672,10 @@ public interface Interface : FGpuResource.Interface FGpuBufferData* GpuBufferData(); [return: NativeTypeName("Coplt::FResult")] - FResult Map(void** ptr, [NativeTypeName("Coplt::b8")] B8 Discard); + FResult Map(void** ptr, [NativeTypeName("Coplt::b8")] B8 discard); [return: NativeTypeName("Coplt::FResult")] - FResult Unmap([NativeTypeName("Coplt::b8")] B8 Discard); + FResult Unmap([NativeTypeName("Coplt::b8")] B8 discard); } } @@ -3655,7 +3684,7 @@ public partial struct FOptimizedClearColor [NativeTypeName("Coplt::FGraphicsFormat")] public FGraphicsFormat Format; - [NativeTypeName("__AnonymousRecord_Resource_L175_C9")] + [NativeTypeName("__AnonymousRecord_Resource_L120_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -3696,7 +3725,7 @@ public partial struct _Anonymous_e__Union public _Color_e__FixedBuffer Color; [FieldOffset(0)] - [NativeTypeName("__AnonymousRecord_Resource_L179_C13")] + [NativeTypeName("__AnonymousRecord_Resource_L124_C13")] public _Anonymous_e__Struct Anonymous; public partial struct _Anonymous_e__Struct @@ -3852,32 +3881,18 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuImage*)Unsafe.AsPointer(ref this), &result, name); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuViewableData *")] - public FGpuViewableData* GpuViewableData() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuImage*)Unsafe.AsPointer(ref this)); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FGpuResourceData *")] public FGpuResourceData* GpuResourceData() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuImage*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::ResourceType")] - public ResourceType GetResourceType() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuImage*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuImage*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FGpuImageData *")] public FGpuImageData* GpuImageData() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuImage*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuImage*)Unsafe.AsPointer(ref this)); } public interface Interface : FGpuResource.Interface @@ -3887,70 +3902,6 @@ public interface Interface : FGpuResource.Interface } } - [NativeTypeName("Coplt::u8")] - public enum FViewType : byte - { - None, - Buffer, - Image, - Sampler, - } - - public unsafe partial struct FView - { - [NativeTypeName("__AnonymousRecord_Resource_L268_C9")] - public _Anonymous_e__Union Anonymous; - - [NativeTypeName("Coplt::FViewType")] - public FViewType Type; - - [UnscopedRef] - public ref FGpuBuffer* Buffer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Buffer; - } - } - - [UnscopedRef] - public ref FGpuImage* Image - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Image; - } - } - - [UnscopedRef] - public ref FGpuSampler* Sampler - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Sampler; - } - } - - [StructLayout(LayoutKind.Explicit)] - public unsafe partial struct _Anonymous_e__Union - { - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuBuffer *")] - public FGpuBuffer* Buffer; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuImage *")] - public FGpuImage* Image; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuSampler *")] - public FGpuSampler* Sampler; - } - } - [NativeTypeName("Coplt::u8")] public enum FPresentMode : byte { @@ -4484,104 +4435,6 @@ public enum FGraphicsFormat Astc_12x12_sRGB = 184, } - [NativeTypeName("Coplt::u32")] - public enum FLegacyState : uint - { - Manual = 0, - Common = 1 << 0, - Present = 1 << 1, - VertexBuffer = 1 << 2, - IndexBuffer = 1 << 3, - ConstantBuffer = 1 << 4, - IndirectBuffer = 1 << 5, - RenderTarget = 1 << 6, - DepthRead = 1 << 7, - DepthWrite = 1 << 8, - ShaderResource = 1 << 9, - UnorderedAccess = 1 << 10, - CopySrc = 1 << 11, - CopyDst = 1 << 12, - ResolveSrc = 1 << 13, - ResolveDst = 1 << 14, - RayTracing = 1 << 15, - ShadingRate = 1 << 16, - StreamOutput = 1 << 17, - GenericRead = VertexBuffer | ConstantBuffer | ShaderResource | IndirectBuffer | CopySrc, - } - - [NativeTypeName("Coplt::u32")] - public enum FResLayout : uint - { - None = 0, - Common, - Present = Common, - GenericRead, - RenderTarget, - UnorderedAccess, - DepthStencilRead, - DepthStencilWrite, - ShaderResource, - CopySrc, - CopyDst, - ResolveSrc, - ResolveDst, - ShadingRate, - VideoDecodeRead, - VideoDecodeWrite, - VideoProcessRead, - VideoProcessWrite, - VideoEncodeRead, - VideoEncodeWrite, - } - - [NativeTypeName("Coplt::u32")] - public enum FResAccess : uint - { - NoAccess = 1U << 31, - Common = 0, - ConstantBuffer = 1 << 0, - VertexBuffer = 1 << 1, - IndexBuffer = 1 << 2, - RenderTarget = 1 << 3, - UnorderedAccess = 1 << 4, - DepthStencilRead = 1 << 5, - DepthStencilWrite = 1 << 6, - ShaderResource = 1 << 7, - StreamOutput = 1 << 8, - IndirectOrPredicationBuffer = 1 << 9, - CopySrc = 1 << 10, - CopyDst = 1 << 11, - ResolveSrc = 1 << 12, - ResolveDst = 1 << 13, - RayTracingAccelerationStructureRead = 1 << 14, - RayTracingAccelerationStructureWrite = 1 << 15, - ShadingRate = 1 << 16, - VideoDecodeRead = 1 << 17, - VideoDecodeWrite = 1 << 18, - VideoProcessRead = 1 << 19, - VideoProcessWrite = 1 << 20, - VideoEncodeRead = 1 << 21, - VideoEncodeWrite = 1 << 22, - } - - public partial struct FResState - { - [NativeTypeName("Coplt::FResLayout")] - public FResLayout Layout; - - [NativeTypeName("Coplt::FResAccess")] - public FResAccess Access; - - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags Stages; - - [NativeTypeName("Coplt::FLegacyState")] - public FLegacyState Legacy; - - [NativeTypeName("Coplt::b8")] - public B8 CrossQueue; - } - [NativeTypeName("Coplt::u8")] public enum FResourceAccess : byte { @@ -5734,7 +5587,7 @@ public partial struct FGpuSamplerCreateOptions } [Guid("16A5B373-AD9E-4033-89FD-6A5B4AABAEF2")] - [NativeTypeName("struct FGpuSampler : Coplt::FGpuObject")] + [NativeTypeName("struct FGpuSampler : Coplt::FGpuViewable")] public unsafe partial struct FGpuSampler : FGpuSampler.Interface, INativeGuid { static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuSampler)); @@ -5789,7 +5642,7 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuSampler*)Unsafe.AsPointer(ref this)); } - public interface Interface : FGpuObject.Interface + public interface Interface : FGpuViewable.Interface { [return: NativeTypeName("const FSamplerInfo *")] FSamplerInfo* Info(); @@ -5875,6 +5728,8 @@ public static partial class Native public static readonly Guid IID_FShader = new Guid(0xDE1352D5, 0x023D, 0x42B0, 0xBE, 0xAC, 0x12, 0x2B, 0x3B, 0x29, 0x6C, 0x9C); + public static readonly Guid IID_FShaderBindGroup = new Guid(0xAE54EFE5, 0xC372, 0x4291, 0xB9, 0x95, 0x55, 0x29, 0x87, 0x58, 0xD2, 0xB2); + public static readonly Guid IID_FShaderBinding = new Guid(0xA3CA644A, 0x0E02, 0x4D25, 0x9A, 0x18, 0x88, 0x35, 0xD6, 0x66, 0x00, 0xF7); public static readonly Guid IID_FRecordContext = new Guid(0x15B4821D, 0x0648, 0x4B78, 0x9C, 0x21, 0xC6, 0xA5, 0xB6, 0xA5, 0xED, 0x75); diff --git a/Coplt.Graphics.Core/Native/ResState.cs b/Coplt.Graphics.Core/Native/ResState.cs deleted file mode 100644 index 76e8bda..0000000 --- a/Coplt.Graphics.Core/Native/ResState.cs +++ /dev/null @@ -1,128 +0,0 @@ -using Coplt.Graphics.Core; -using Coplt.Graphics.Native; - -namespace Coplt.Graphics.Native -{ - public partial struct FResState - { - /// - /// 判断状态是否兼容 - /// - public readonly bool IsCompatible(in FResState other, bool legacy, /* 顺序 */ bool b2a, out bool same) - { - if (legacy) - { - same = Legacy == other.Legacy; - return Legacy.FromFFI().IsCompatible(other.Legacy.FromFFI()); - } - if (!Layout.FromFFI().IsCompatible(other.Layout.FromFFI()) || CrossQueue != other.CrossQueue) goto no; - if (Access != other.Access) - { - same = false; - var sna = (Access.FromFFI() & ResAccess.NoAccess) != 0; - var ona = (other.Access.FromFFI() & ResAccess.NoAccess) != 0; - if (sna && ona) return true; - if (sna || ona) - { - if (b2a) - { - if (sna && !ona) return true; - else if (!sna && ona) return false; - } - else - { - if (!sna && ona) return true; - else if (sna && !ona) return false; - } - } - if (!Access.FromFFI().IsReadOnly() || !other.Access.FromFFI().IsReadOnly()) goto no; - } - else - { - same = Stages == other.Stages; - } - return true; - no: - same = false; - return false; - } - - /// - /// 在兼容的时候合并,不兼容的话是未定义行为 - /// - public readonly FResState Merge(in FResState other, bool legacy, /* 顺序 */ bool b2a) - { - if (legacy) - { - return new() - { - Layout = Layout, - Access = Access, - Stages = Stages, - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - Legacy = Legacy | other.Legacy, - CrossQueue = CrossQueue, - }; - } - var sna = (Access.FromFFI() & ResAccess.NoAccess) != 0; - 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() - { - Layout = Layout, - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - Access = other.Access, - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - Stages = Stages | other.Stages, - Legacy = Legacy, - CrossQueue = CrossQueue, - }; - } - else - { - var Layout = this.Layout.FromFFI().Merge(other.Layout.FromFFI(), ona).ToFFI(); - if (ona) - return new() - { - Layout = Layout, - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - Access = Access, - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - Stages = Stages | other.Stages, - Legacy = Legacy, - CrossQueue = CrossQueue, - }; - } - return new() - { - Layout = this.Layout.FromFFI().Merge(other.Layout.FromFFI(), false).ToFFI(), - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - Access = Access | other.Access, - // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags - Stages = Stages | other.Stages, - Legacy = Legacy, - CrossQueue = CrossQueue, - }; - } - - public override string ToString() => - $"{{ {nameof(Layout)} = {Layout}, {nameof(Access)} = {Access}, {nameof(Stages)} = {Stages}, {nameof(Legacy)} = {Legacy}, {nameof(CrossQueue)} = {CrossQueue} }}"; - } -} - -namespace Coplt.Graphics.Core -{ - public static partial class GraphicsExtensions - { - public static bool ContainsOnly(this ResAccess value, ResAccess other) => (value & ~other) == 0; - public static bool Contains(this ResAccess value, ResAccess other) => (value & other) != 0; - public static bool IsReadOnly(this ResAccess value) => value.ContainsOnly( - ResAccess.IndexBuffer | ResAccess.ConstantBuffer | ResAccess.VertexBuffer | ResAccess.CopySrc | - ResAccess.ResolveSrc | ResAccess.DepthStencilRead | ResAccess.IndirectOrPredicationBuffer | - ResAccess.ShaderResource | ResAccess.ShadingRate - ); - } -} diff --git a/Coplt.Graphics.Native/Api/CMakeLists.txt b/Coplt.Graphics.Native/Api/CMakeLists.txt index 6840bd0..e346225 100644 --- a/Coplt.Graphics.Native/Api/CMakeLists.txt +++ b/Coplt.Graphics.Native/Api/CMakeLists.txt @@ -21,7 +21,6 @@ add_library(${target_name} STATIC FFI/Output.h FFI/Queue.h FFI/GraphicsFormat.h - FFI/States.h Src/Allocator.cc Src/Allocator.h FFI/List.h @@ -61,6 +60,7 @@ add_library(${target_name} STATIC FFI/Cmd.h FFI/Structs.h FFI/Chunked.h + FFI/View.h ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) add_library(Coplt::Graphics::Api ALIAS ${target_name}) diff --git a/Coplt.Graphics.Native/Api/FFI/Binding.h b/Coplt.Graphics.Native/Api/FFI/Binding.h index 65e737f..004702c 100644 --- a/Coplt.Graphics.Native/Api/FFI/Binding.h +++ b/Coplt.Graphics.Native/Api/FFI/Binding.h @@ -6,16 +6,26 @@ namespace Coplt { - struct FShaderBindingCreateOptions + struct FBindItem + { + FView View{}; + u32 Index{}; + }; + + struct FShaderBindGroupCreateOptions { FStr8or16 Name{}; - FShaderLayout* Layout{}; + FBindGroupLayout* Layout{}; }; - struct FBindItem + COPLT_INTERFACE_DEFINE(FShaderBindGroup, "ae54efe5-c372-4291-b995-55298758d2b2", FGpuObject) { - FView View{}; - u32 Index{}; + }; + + struct FShaderBindingCreateOptions + { + FStr8or16 Name{}; + FBindingLayout* Layout{}; }; COPLT_INTERFACE_DEFINE(FShaderBinding, "a3ca644a-0e02-4d25-9a18-8835d66600f7", FGpuObject) diff --git a/Coplt.Graphics.Native/Api/FFI/Device.h b/Coplt.Graphics.Native/Api/FFI/Device.h index 13ba874..d87aee2 100644 --- a/Coplt.Graphics.Native/Api/FFI/Device.h +++ b/Coplt.Graphics.Native/Api/FFI/Device.h @@ -91,7 +91,8 @@ namespace Coplt virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept = 0; virtual FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept = 0; - virtual FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept = 0; + virtual FResult CreateBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept = 0; + virtual FResult CreateBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept = 0; virtual FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept = 0; virtual FResult CreateBuffer(const FGpuBufferCreateOptions& options, FGpuBuffer** out) noexcept = 0; diff --git a/Coplt.Graphics.Native/Api/FFI/Resource.h b/Coplt.Graphics.Native/Api/FFI/Resource.h index 9f659bf..0f2401b 100644 --- a/Coplt.Graphics.Native/Api/FFI/Resource.h +++ b/Coplt.Graphics.Native/Api/FFI/Resource.h @@ -1,29 +1,17 @@ #pragma once #include "GpuObject.h" -#include "Sampler.h" -#include "States.h" +#include "View.h" namespace Coplt { - enum class ResourceType : u8 - { - Unknown = 0, - Buffer = 1, - Image = 2, - }; - - enum class FResourceViewType : u8 + enum class FCpuAccess : u8 { None = 0, - ConstantBuffer, - ShaderResource, - UnorderedAccess, - RenderTarget, - DepthStencil, - IndexBuffer, - VertexBuffer, - StreamOutput, + Write = 1, + Read = 2, + // 只能在 Uma 架构上创建 + ReadWrite = 3, }; COPLT_ENUM_FLAGS(FResourcePurpose, u32) @@ -53,60 +41,43 @@ namespace Coplt IndirectDrawArgs = 1 << 10, }; - enum class FCpuAccess : u8 - { - None = 0, - Write = 1, - Read = 2, - }; - - enum class FBufferUsage : u8 - { - // 未定义用法 - Undefined, - // 按结构化缓冲区使用 - Structured, - // 按原始缓冲区使用 - Raw, - }; - - struct FGpuViewCreateOptions + struct FGpuResourceCreateOptions { FStr8or16 Name{}; + FCpuAccess CpuAccess{}; FResourcePurpose Purpose{}; }; - struct FGpuViewableData - { - FResourcePurpose m_purpose{}; - }; - - COPLT_INTERFACE_DEFINE(FGpuViewable, "b3aeb8a5-1fa6-4866-97ef-1a5fa401e18f", FGpuObject) - { - virtual FGpuViewableData* GpuViewableData() noexcept = 0; - }; - - struct FGpuResourceCreateOptions : FGpuViewCreateOptions + enum class ResourceType : u8 { - FCpuAccess CpuAccess{}; + Unknown = 0, + Buffer = 1, + Image = 2, }; - struct FGpuResourceData : FGpuViewableData + struct FGpuResourceData { - FResState m_state{}; + // 在 D3d12 时是 ID3D12Resource* + void* m_raw_resource_ptr{}; + FResourcePurpose m_purpose{}; FCpuAccess m_cpu_access{}; + ResourceType m_resource_type{}; }; COPLT_INTERFACE_DEFINE(FGpuResource, "f99dceec-2f0c-4a28-b666-beb7c35219d6", FGpuViewable) { virtual FGpuResourceData* GpuResourceData() noexcept = 0; - - virtual ResourceType GetResourceType() noexcept = 0; }; - // COPLT_INTERFACE_DEFINE(FGpuTransientView, "f7dfc622-972b-49b2-8999-8fb129c61ac6", FGpuViewable) - // { - // }; + enum class FBufferUsage : u8 + { + // 未定义用法 + Undefined, + // 按结构化缓冲区使用 + Structured, + // 按原始缓冲区使用 + Raw, + }; struct FGpuBufferCreateOptions : FGpuResourceCreateOptions { @@ -136,42 +107,16 @@ namespace Coplt { virtual FGpuBufferData* GpuBufferData() noexcept = 0; - virtual FResult Map(void** ptr, b8 Discard) noexcept = 0; - virtual FResult Unmap(b8 Discard) noexcept = 0; + // discard 为 true 表示之前内容无关紧要, 上传应为 true + virtual FResult Map(void** ptr, b8 discard) noexcept = 0; + // discard 为 true 表示之后内容无关紧要,下载应为 true + virtual FResult Unmap(b8 discard) noexcept = 0; }; - // struct FGpuUploadBufferCreateOptions : FGpuViewCreateOptions - // { - // // 字节大小 - // u64 Size{}; - // // 默认的 Structured Buffer 元素数量 - // u32 Count{}; - // // 默认的 Structured Buffer 元素步幅 - // u32 Stride{}; - // // 指示默认用法 - // FBufferUsage Usage{}; - // }; - // - // struct FGpuUploadBufferData - // { - // // 字节大小 - // u64 m_size{}; - // // 默认的 Structured Buffer 元素数量 - // u32 m_count{}; - // // 默认的 Structured Buffer 元素步幅 - // u32 m_stride{}; - // // 指示默认用法 - // FBufferUsage m_usage{}; - // }; - // - // COPLT_INTERFACE_DEFINE(FGpuUploadBuffer, "3e85392d-8fd3-49eb-9872-cf7a0d7c8e4c", FGpuTransientView) - // { - // virtual FGpuUploadBufferData* GpuUploadBufferData(); - // }; - struct FOptimizedClearColor { FGraphicsFormat Format; + union { f32 Color[4]; @@ -254,24 +199,4 @@ namespace Coplt { virtual FGpuImageData* GpuImageData() noexcept = 0; }; - - enum class FViewType : u8 - { - None, - Buffer, - Image, - Sampler, - }; - - struct FView - { - union - { - FGpuBuffer* Buffer; - FGpuImage* Image; - FGpuSampler* Sampler; - }; - - FViewType Type; - }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Sampler.h b/Coplt.Graphics.Native/Api/FFI/Sampler.h index e4200fe..f60fb17 100644 --- a/Coplt.Graphics.Native/Api/FFI/Sampler.h +++ b/Coplt.Graphics.Native/Api/FFI/Sampler.h @@ -3,6 +3,7 @@ #include "Common.h" #include "GpuObject.h" #include "PipelineState.h" +#include "View.h" namespace Coplt { @@ -43,7 +44,7 @@ namespace Coplt FSamplerInfo Info{}; }; - COPLT_INTERFACE_DEFINE(FGpuSampler, "16a5b373-ad9e-4033-89fd-6a5b4aabaef2", FGpuObject) + COPLT_INTERFACE_DEFINE(FGpuSampler, "16a5b373-ad9e-4033-89fd-6a5b4aabaef2", FGpuViewable) { virtual const FSamplerInfo* Info() const noexcept = 0; }; diff --git a/Coplt.Graphics.Native/Api/FFI/States.h b/Coplt.Graphics.Native/Api/FFI/States.h deleted file mode 100644 index c3ef5fd..0000000 --- a/Coplt.Graphics.Native/Api/FFI/States.h +++ /dev/null @@ -1,205 +0,0 @@ -#pragma once - -#include "Common.h" -#include "Layout.h" -#include "Types.h" - -namespace Coplt -{ - #pragma region LegacyState - - COPLT_ENUM_FLAGS(FLegacyState, u32) - { - // 手动管理资源状态,自动过渡时将忽略 - Manual = 0, - Common = 1 << 0, - Present = 1 << 1, - VertexBuffer = 1 << 2, - IndexBuffer = 1 << 3, - ConstantBuffer = 1 << 4, - IndirectBuffer = 1 << 5, - RenderTarget = 1 << 6, - DepthRead = 1 << 7, - DepthWrite = 1 << 8, - ShaderResource = 1 << 9, - UnorderedAccess = 1 << 10, - CopySrc = 1 << 11, - CopyDst = 1 << 12, - ResolveSrc = 1 << 13, - ResolveDst = 1 << 14, - RayTracing = 1 << 15, - ShadingRate = 1 << 16, - StreamOutput = 1 << 17, - - GenericRead = VertexBuffer | ConstantBuffer | ShaderResource | IndirectBuffer | CopySrc, - }; - - #ifdef FFI_SRC - - inline bool ContainsOnly(const FLegacyState value, const FLegacyState other) - { - return (value & ~other) == 0; - } - - inline bool Contains(const FLegacyState value, const FLegacyState other) - { - return (value & other) != 0; - } - - inline bool IsReadOnly(const FLegacyState value) - { - return ContainsOnly( - value, - FLegacyState::IndexBuffer | FLegacyState::VertexBuffer | - FLegacyState::ConstantBuffer | FLegacyState::IndirectBuffer | FLegacyState::CopySrc | - FLegacyState::ResolveSrc | FLegacyState::ShaderResource | FLegacyState::DepthRead - ); - } - - inline bool IsCompatible(const FLegacyState value, const FLegacyState other) - { - if (value == FLegacyState::Manual || other == FLegacyState::Manual) - return false; - if (value == other) - return true; - if (IsReadOnly(value) && IsReadOnly(other)) - return true; - return false; - } - - inline FLegacyState ChangeState(const FLegacyState value, const FLegacyState state) - { - if (IsCompatible(value, state)) - return value | state; - return state; - } - #endif - - #pragma endregion - - enum class FResLayout: u32 - { - None = 0, - Common, - Present = Common, - GenericRead, - RenderTarget, - UnorderedAccess, - DepthStencilRead, - DepthStencilWrite, - ShaderResource, - CopySrc, - CopyDst, - ResolveSrc, - ResolveDst, - ShadingRate, - VideoDecodeRead, - VideoDecodeWrite, - VideoProcessRead, - VideoProcessWrite, - VideoEncodeRead, - VideoEncodeWrite, - }; - - COPLT_ENUM_FLAGS(FResAccess, u32) - { - NoAccess = 1u << 31, - Common = 0, - ConstantBuffer = 1 << 0, - VertexBuffer = 1 << 1, - IndexBuffer = 1 << 2, - RenderTarget = 1 << 3, - UnorderedAccess = 1 << 4, - DepthStencilRead = 1 << 5, - DepthStencilWrite = 1 << 6, - ShaderResource = 1 << 7, - StreamOutput = 1 << 8, - IndirectOrPredicationBuffer = 1 << 9, - CopySrc = 1 << 10, - CopyDst = 1 << 11, - ResolveSrc = 1 << 12, - ResolveDst = 1 << 13, - RayTracingAccelerationStructureRead = 1 << 14, - RayTracingAccelerationStructureWrite = 1 << 15, - ShadingRate = 1 << 16, - VideoDecodeRead = 1 << 17, - VideoDecodeWrite = 1 << 18, - VideoProcessRead = 1 << 19, - VideoProcessWrite = 1 << 20, - VideoEncodeRead = 1 << 21, - VideoEncodeWrite = 1 << 22, - }; - - struct FResState - { - FResLayout Layout{}; - FResAccess Access{}; - FShaderStageFlags Stages{}; - FLegacyState Legacy{}; - b8 CrossQueue{}; - - #ifdef FFI_SRC - - static FResState BufferCommon() - { - return FResState{ - .Layout = FResLayout::None, - .Access = FResAccess::Common, - .Stages = FShaderStageFlags::None, - .Legacy = FLegacyState::Common, - }; - } - - static FResState ImageCommon() - { - return FResState{ - .Layout = FResLayout::None, - .Access = FResAccess::Common, - .Stages = FShaderStageFlags::None, - .Legacy = FLegacyState::Common, - }; - } - - static FResState BufferGenericRead() - { - return FResState{ - .Layout = FResLayout::None, - .Access = FResAccess::Common, - .Stages = FShaderStageFlags::None, - .Legacy = FLegacyState::GenericRead, - }; - } - - static FResState ImageGenericRead() - { - return FResState{ - .Layout = FResLayout::GenericRead, - .Access = FResAccess::Common, - .Stages = FShaderStageFlags::None, - .Legacy = FLegacyState::GenericRead, - }; - } - - static FResState BufferCopyDst() - { - return FResState{ - .Layout = FResLayout::None, - .Access = FResAccess::CopyDst, - .Stages = FShaderStageFlags::None, - .Legacy = FLegacyState::CopyDst, - }; - } - - static FResState ImageCopyDst() - { - return FResState{ - .Layout = FResLayout::CopyDst, - .Access = FResAccess::CopyDst, - .Stages = FShaderStageFlags::None, - .Legacy = FLegacyState::CopyDst, - }; - } - - #endif - }; -} diff --git a/Coplt.Graphics.Native/Api/FFI/View.h b/Coplt.Graphics.Native/Api/FFI/View.h new file mode 100644 index 0000000..ee9ddbc --- /dev/null +++ b/Coplt.Graphics.Native/Api/FFI/View.h @@ -0,0 +1,24 @@ +#pragma once + +#include "GpuObject.h" + +namespace Coplt +{ + COPLT_INTERFACE_DEFINE(FGpuViewable, "b3aeb8a5-1fa6-4866-97ef-1a5fa401e18f", FGpuObject) + { + }; + + enum class FViewType : u8 + { + None = 0, + Buffer = 1, + Image = 2, + Sampler = 3, + }; + + struct FView + { + FGpuViewable* Viewable{}; + FViewType Type{}; + }; +} diff --git a/Coplt.Graphics.Native/D3d12/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index bb56662..cf9d021 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -32,7 +32,6 @@ add_library(${target_name} SHARED Src/Context.h Src/Context.cc Include/States.h - FFI/Binding.h Src/Binding.h Src/Binding.cc Src/DescriptorManager.h diff --git a/Coplt.Graphics.Native/D3d12/FFI/Binding.h b/Coplt.Graphics.Native/D3d12/FFI/Binding.h deleted file mode 100644 index 92a58a8..0000000 --- a/Coplt.Graphics.Native/D3d12/FFI/Binding.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "../../Api/FFI/Binding.h" - -namespace Coplt -{ - COPLT_INTERFACE_DEFINE(FD3d12ShaderBinding, "aace0f36-a59e-45ea-88c7-7807d20d2750", FShaderBinding) - { - }; -} diff --git a/Coplt.Graphics.Native/D3d12/Include/States.h b/Coplt.Graphics.Native/D3d12/Include/States.h index e2cefbe..1a3a8b3 100644 --- a/Coplt.Graphics.Native/D3d12/Include/States.h +++ b/Coplt.Graphics.Native/D3d12/Include/States.h @@ -6,299 +6,6 @@ namespace Coplt { - constexpr D3D12_RESOURCE_STATES AllReadStates = - D3D12_RESOURCE_STATE_GENERIC_READ | D3D12_RESOURCE_STATE_DEPTH_READ | - D3D12_RESOURCE_STATE_RESOLVE_SOURCE | D3D12_RESOURCE_STATE_SHADING_RATE_SOURCE; - - inline bool ContainsOnly(const D3D12_RESOURCE_STATES value, const D3D12_RESOURCE_STATES other) - { - return (value & ~other) == 0; - } - - inline bool Contains(const D3D12_RESOURCE_STATES value, const D3D12_RESOURCE_STATES other) - { - return (value & other) != 0; - } - - inline bool IsReadOnly(const D3D12_RESOURCE_STATES value) - { - return ContainsOnly(value, AllReadStates); - } - - inline bool IsCompatible(const D3D12_RESOURCE_STATES value, const D3D12_RESOURCE_STATES other) - { - if (value == other) return true; - if (IsReadOnly(value) && IsReadOnly(other)) return true; - return false; - } - - inline D3D12_RESOURCE_STATES ChangeState(const D3D12_RESOURCE_STATES value, const D3D12_RESOURCE_STATES state) - { - if (IsCompatible(value, state)) return value | state; - return state; - } - - inline D3D12_RESOURCE_STATES ToDx(const FLegacyState state) - { - switch (state) - { - case FLegacyState::Common: - case FLegacyState::Present: - return D3D12_RESOURCE_STATE_COMMON; - case FLegacyState::RenderTarget: - return D3D12_RESOURCE_STATE_RENDER_TARGET; - case FLegacyState::DepthWrite: - return D3D12_RESOURCE_STATE_DEPTH_WRITE; - case FLegacyState::UnorderedAccess: - return D3D12_RESOURCE_STATE_UNORDERED_ACCESS; - case FLegacyState::CopyDst: - return D3D12_RESOURCE_STATE_COPY_DEST; - case FLegacyState::ResolveDst: - return D3D12_RESOURCE_STATE_RESOLVE_DEST; - case FLegacyState::RayTracing: - return D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE; - case FLegacyState::ShadingRate: - return D3D12_RESOURCE_STATE_SHADING_RATE_SOURCE; - case FLegacyState::StreamOutput: - return D3D12_RESOURCE_STATE_STREAM_OUT; - default: - break; - } - D3D12_RESOURCE_STATES r = D3D12_RESOURCE_STATE_COMMON; - if (HasAnyFlags(state, FLegacyState::ConstantBuffer | FLegacyState::VertexBuffer)) - r |= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; - if (HasFlags(state, FLegacyState::IndexBuffer)) r |= D3D12_RESOURCE_STATE_INDEX_BUFFER; - if (HasFlags(state, FLegacyState::IndirectBuffer)) r |= D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT; - if (HasFlags(state, FLegacyState::DepthRead)) r |= D3D12_RESOURCE_STATE_DEPTH_READ; - if (HasFlags(state, FLegacyState::ShaderResource)) r |= D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE; - if (HasFlags(state, FLegacyState::CopySrc)) r |= D3D12_RESOURCE_STATE_COPY_SOURCE; - if (HasFlags(state, FLegacyState::ResolveSrc)) r |= D3D12_RESOURCE_STATE_RESOLVE_SOURCE; - return r; - } - - inline D3D12_BARRIER_LAYOUT ToDx(const FResLayout value, const std::optional queue) - { - if (queue.has_value()) - { - switch (queue.value()) - { - case FGpuQueueType::Direct: - switch (value) - { - case FResLayout::Common: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COMMON; - case FResLayout::GenericRead: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_GENERIC_READ; - case FResLayout::UnorderedAccess: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_UNORDERED_ACCESS; - case FResLayout::ShaderResource: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_SHADER_RESOURCE; - case FResLayout::CopySrc: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_SOURCE; - case FResLayout::CopyDst: - return D3D12_BARRIER_LAYOUT_DIRECT_QUEUE_COPY_DEST; - default: - break; - } - break; - case FGpuQueueType::Compute: - switch (value) - { - case FResLayout::Common: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COMMON; - case FResLayout::GenericRead: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_GENERIC_READ; - case FResLayout::UnorderedAccess: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_UNORDERED_ACCESS; - case FResLayout::ShaderResource: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_SHADER_RESOURCE; - case FResLayout::CopySrc: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_SOURCE; - case FResLayout::CopyDst: - return D3D12_BARRIER_LAYOUT_COMPUTE_QUEUE_COPY_DEST; - default: - break; - } - break; - case FGpuQueueType::Copy: - break; - case FGpuQueueType::VideoEncode: - case FGpuQueueType::VideoDecode: - case FGpuQueueType::VideoProcess: - switch (value) - { - case FResLayout::Common: - return D3D12_BARRIER_LAYOUT_VIDEO_QUEUE_COMMON; - default: - break; - } - break; - } - } - switch (value) - { - case FResLayout::None: - return D3D12_BARRIER_LAYOUT_UNDEFINED; - case FResLayout::Common: - return D3D12_BARRIER_LAYOUT_COMMON; - case FResLayout::GenericRead: - return D3D12_BARRIER_LAYOUT_GENERIC_READ; - case FResLayout::RenderTarget: - return D3D12_BARRIER_LAYOUT_RENDER_TARGET; - case FResLayout::UnorderedAccess: - return D3D12_BARRIER_LAYOUT_UNORDERED_ACCESS; - case FResLayout::DepthStencilRead: - return D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_READ; - case FResLayout::DepthStencilWrite: - return D3D12_BARRIER_LAYOUT_DEPTH_STENCIL_WRITE; - case FResLayout::ShaderResource: - return D3D12_BARRIER_LAYOUT_SHADER_RESOURCE; - case FResLayout::CopySrc: - return D3D12_BARRIER_LAYOUT_COPY_SOURCE; - case FResLayout::CopyDst: - return D3D12_BARRIER_LAYOUT_COPY_DEST; - case FResLayout::ResolveSrc: - return D3D12_BARRIER_LAYOUT_RESOLVE_SOURCE; - case FResLayout::ResolveDst: - return D3D12_BARRIER_LAYOUT_RESOLVE_DEST; - case FResLayout::ShadingRate: - return D3D12_BARRIER_LAYOUT_SHADING_RATE_SOURCE; - case FResLayout::VideoDecodeRead: - return D3D12_BARRIER_LAYOUT_VIDEO_DECODE_READ; - case FResLayout::VideoDecodeWrite: - return D3D12_BARRIER_LAYOUT_VIDEO_DECODE_WRITE; - case FResLayout::VideoProcessRead: - return D3D12_BARRIER_LAYOUT_VIDEO_PROCESS_READ; - case FResLayout::VideoProcessWrite: - return D3D12_BARRIER_LAYOUT_VIDEO_PROCESS_WRITE; - case FResLayout::VideoEncodeRead: - return D3D12_BARRIER_LAYOUT_VIDEO_ENCODE_READ; - case FResLayout::VideoEncodeWrite: - return D3D12_BARRIER_LAYOUT_VIDEO_ENCODE_WRITE; - } - return D3D12_BARRIER_LAYOUT_UNDEFINED; - } - - inline D3D12_BARRIER_ACCESS ToDx(const FResAccess value) - { - if (HasFlags(value, FResAccess::NoAccess)) return D3D12_BARRIER_ACCESS_NO_ACCESS; - D3D12_BARRIER_ACCESS r = D3D12_BARRIER_ACCESS_COMMON; - if (HasFlags(value, FResAccess::ConstantBuffer)) r |= D3D12_BARRIER_ACCESS_CONSTANT_BUFFER; - if (HasFlags(value, FResAccess::VertexBuffer)) r |= D3D12_BARRIER_ACCESS_VERTEX_BUFFER; - if (HasFlags(value, FResAccess::IndexBuffer)) r |= D3D12_BARRIER_ACCESS_INDEX_BUFFER; - if (HasFlags(value, FResAccess::RenderTarget)) r |= D3D12_BARRIER_ACCESS_RENDER_TARGET; - if (HasFlags(value, FResAccess::UnorderedAccess)) r |= D3D12_BARRIER_ACCESS_UNORDERED_ACCESS; - if (HasFlags(value, FResAccess::DepthStencilRead)) r |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_READ; - if (HasFlags(value, FResAccess::DepthStencilWrite)) r |= D3D12_BARRIER_ACCESS_DEPTH_STENCIL_WRITE; - if (HasFlags(value, FResAccess::ShaderResource)) r |= D3D12_BARRIER_ACCESS_SHADER_RESOURCE; - if (HasFlags(value, FResAccess::StreamOutput)) r |= D3D12_BARRIER_ACCESS_STREAM_OUTPUT; - if (HasFlags(value, FResAccess::IndirectOrPredicationBuffer)) r |= D3D12_BARRIER_ACCESS_INDIRECT_ARGUMENT; - if (HasFlags(value, FResAccess::CopySrc)) r |= D3D12_BARRIER_ACCESS_COPY_SOURCE; - if (HasFlags(value, FResAccess::CopyDst)) r |= D3D12_BARRIER_ACCESS_COPY_DEST; - if (HasFlags(value, FResAccess::ResolveSrc)) r |= D3D12_BARRIER_ACCESS_RESOLVE_SOURCE; - if (HasFlags(value, FResAccess::ResolveDst)) r |= D3D12_BARRIER_ACCESS_RESOLVE_DEST; - if (HasFlags(value, FResAccess::RayTracingAccelerationStructureRead)) r |= D3D12_BARRIER_ACCESS_RAYTRACING_ACCELERATION_STRUCTURE_READ; - if (HasFlags(value, FResAccess::RayTracingAccelerationStructureWrite)) r |= D3D12_BARRIER_ACCESS_RAYTRACING_ACCELERATION_STRUCTURE_WRITE; - if (HasFlags(value, FResAccess::ShadingRate)) r |= D3D12_BARRIER_ACCESS_SHADING_RATE_SOURCE; - if (HasFlags(value, FResAccess::VideoDecodeRead)) r |= D3D12_BARRIER_ACCESS_VIDEO_DECODE_READ; - if (HasFlags(value, FResAccess::VideoDecodeWrite)) r |= D3D12_BARRIER_ACCESS_VIDEO_DECODE_WRITE; - if (HasFlags(value, FResAccess::VideoProcessRead)) r |= D3D12_BARRIER_ACCESS_VIDEO_PROCESS_READ; - if (HasFlags(value, FResAccess::VideoProcessWrite)) r |= D3D12_BARRIER_ACCESS_VIDEO_PROCESS_WRITE; - if (HasFlags(value, FResAccess::VideoEncodeRead)) r |= D3D12_BARRIER_ACCESS_VIDEO_ENCODE_READ; - if (HasFlags(value, FResAccess::VideoEncodeWrite)) r |= D3D12_BARRIER_ACCESS_VIDEO_ENCODE_WRITE; - return r; - } - - inline bool Diff(const FResAccess self, const FResAccess other, const FResAccess cmp) - { - return (self & ~other & cmp) != 0; - } - - inline D3D12_BARRIER_SYNC CalcSync( - const FShaderStageFlags stages, - const FResAccess access, - const FResAccess access2 - ) - { - if (access == FResAccess::Common) return D3D12_BARRIER_SYNC_ALL; - if (HasFlags(access, FResAccess::NoAccess)) return D3D12_BARRIER_SYNC_NONE; - - D3D12_BARRIER_SYNC r = D3D12_BARRIER_SYNC_NONE; - - constexpr auto ib_acc = FResAccess::IndexBuffer; - if (Diff(access, access2, ib_acc)) - r |= D3D12_BARRIER_SYNC_INDEX_INPUT; - - constexpr auto vs_acc = FResAccess::VertexBuffer | FResAccess::ConstantBuffer - | FResAccess::UnorderedAccess | FResAccess::ShaderResource | FResAccess::StreamOutput; - if ( - Diff(access, access2, vs_acc) - && HasAnyFlags(stages, FShaderStageFlags::Vertex | FShaderStageFlags::Mesh | FShaderStageFlags::Task) - ) - r |= D3D12_BARRIER_SYNC_VERTEX_SHADING; - - constexpr auto ps_acc = FResAccess::ConstantBuffer | FResAccess::UnorderedAccess - | FResAccess::ShadingRate | FResAccess::ShaderResource; - if ( - Diff(access, access2, ps_acc) - && HasAnyFlags(stages, FShaderStageFlags::Pixel) - ) - r |= D3D12_BARRIER_SYNC_PIXEL_SHADING; - - constexpr auto ds_acc = FResAccess::DepthStencilRead | FResAccess::DepthStencilWrite; - if (Diff(access, access2, ds_acc)) - r |= D3D12_BARRIER_SYNC_DEPTH_STENCIL; - - constexpr auto rt_acc = FResAccess::RenderTarget; - if (Diff(access, access2, rt_acc)) - r |= D3D12_BARRIER_SYNC_RENDER_TARGET; - - constexpr auto cs_acc = FResAccess::RenderTarget; - if ( - Diff(access, access2, cs_acc) - && HasAnyFlags(stages, FShaderStageFlags::Compute) - ) - r |= D3D12_BARRIER_SYNC_COMPUTE_SHADING; - - constexpr auto ray_acc = FResAccess::RayTracingAccelerationStructureRead | FResAccess::RayTracingAccelerationStructureWrite; - if (Diff(access, access2, ray_acc)) - r |= D3D12_BARRIER_SYNC_RAYTRACING; - - constexpr auto copy_acc = FResAccess::CopySrc | FResAccess::CopyDst; - if (Diff(access, access2, copy_acc)) - r |= D3D12_BARRIER_SYNC_COPY; - - constexpr auto resolve_acc = FResAccess::ResolveSrc | FResAccess::ResolveDst; - if (Diff(access, access2, resolve_acc)) - r |= D3D12_BARRIER_SYNC_RESOLVE; - - constexpr auto ind_acc = FResAccess::IndirectOrPredicationBuffer; - if (Diff(access, access2, ind_acc)) - r |= D3D12_BARRIER_SYNC_EXECUTE_INDIRECT; - - constexpr auto vd_acc = FResAccess::VideoDecodeRead | FResAccess::VideoDecodeWrite; - if (Diff(access, access2, vd_acc)) - r |= D3D12_BARRIER_SYNC_VIDEO_DECODE; - - constexpr auto vp_acc = FResAccess::VideoProcessRead | FResAccess::VideoProcessWrite; - if (Diff(access, access2, vp_acc)) - r |= D3D12_BARRIER_SYNC_VIDEO_PROCESS; - - constexpr auto ve_acc = FResAccess::VideoEncodeRead | FResAccess::VideoEncodeWrite; - if (Diff(access, access2, ve_acc)) - r |= D3D12_BARRIER_SYNC_VIDEO_ENCODE; - - constexpr auto ray_build_acc = FResAccess::RayTracingAccelerationStructureRead; - if (Diff(access, access2, ray_build_acc)) - r |= D3D12_BARRIER_SYNC_BUILD_RAYTRACING_ACCELERATION_STRUCTURE | D3D12_BARRIER_SYNC_COPY_RAYTRACING_ACCELERATION_STRUCTURE; - - constexpr auto clear_uav_acc = FResAccess::UnorderedAccess; - if (Diff(access, access2, clear_uav_acc)) - r |= D3D12_BARRIER_SYNC_CLEAR_UNORDERED_ACCESS_VIEW; - - return r; - } - template F> inline D3D12_RENDER_PASS_BEGINNING_ACCESS ToDx(const FLoadOp load, F SetClearValue) { diff --git a/Coplt.Graphics.Native/D3d12/Include/View.h b/Coplt.Graphics.Native/D3d12/Include/View.h index c30d685..2472729 100644 --- a/Coplt.Graphics.Native/D3d12/Include/View.h +++ b/Coplt.Graphics.Native/D3d12/Include/View.h @@ -10,56 +10,18 @@ namespace Coplt { - struct View final + COPLT_INTERFACE_DEFINE(ID3d12GpuViewable, "78155a99-1110-42f8-a1ef-c70fc23dbc52", FGpuViewable) { - enum class Type : u8 - { - None, - Buffer, - Image, - Sampler, - }; - - private: - union - { - Rc m_buffer; - Rc m_image; - Rc m_sampler; - }; - - Type m_type; - - public: - Type Type() const; - Rc& Buffer(); - const Rc& Buffer() const; - Rc& Image(); - const Rc& Image() const; - Rc& Sampler(); - const Rc& Sampler() const; - - ~View(); - - View(); + }; - View(const View& other); - View(View&& other) noexcept; - View& operator=(const View& view) noexcept; - View& operator=(View&& view) noexcept; + struct View final + { + Rc m_viewable{}; + FViewType m_type{}; View(const FView& view); - View& operator=(const FView& view); - - View(const Rc& buffer); - View(Rc&& buffer); - View& operator=(const Rc& buffer); - View& operator=(Rc&& buffer); - View(const Rc& image); - View(Rc&& image); - View& operator=(const Rc& image); - View& operator=(Rc&& image); + operator bool() const; // void CreateDescriptor( // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index 26e1098..27d3a0b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -8,11 +8,17 @@ using namespace Coplt; -D3d12ShaderBinding::D3d12ShaderBinding( - Rc&& device, const FShaderBindingCreateOptions& options -) : m_device(std::move(device)) +D3d12ShaderBindGroup::D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options) : m_device(std::move(device)) +{ +} + +FResult D3d12ShaderBindGroup::SetName(const FStr8or16& name) noexcept +{ + return FResult::None(); +} + +D3d12ShaderBinding::D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options) : m_device(std::move(device)) { - m_dx_device = m_device->m_device; } FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index 72130ef..e84f519 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -2,12 +2,12 @@ #include -#include "Device.h" -#include "Layout.h" +#include "../../Api/FFI/Binding.h" #include "../../Api/Include/Object.h" #include "../../Api/Include/Ptr.h" -#include "../FFI/Binding.h" #include "../Include/View.h" +#include "Device.h" +#include "Layout.h" namespace Coplt { @@ -15,7 +15,20 @@ namespace Coplt struct D3d12GpuQueue; struct DescriptorAllocation; - COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "84f2b3e2-bb16-4276-ba3f-5da54eda462d", FD3d12ShaderBinding) + COPLT_INTERFACE_DEFINE(ID3d12ShaderBindGroup, "5bb948b9-ad31-4eb8-b881-98017e048259", FShaderBindGroup) + { + + }; + + struct D3d12ShaderBindGroup final : GpuObject + { + Rc m_device{}; + + explicit D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options); + FResult SetName(const FStr8or16& name) noexcept override; + }; + + COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "5073f785-cfb7-414d-9a84-1602d3bf378d", FShaderBinding) { }; @@ -23,7 +36,6 @@ namespace Coplt struct D3d12ShaderBinding final : GpuObject { Rc m_device{}; - ComPtr m_dx_device{}; explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Buffer.cc b/Coplt.Graphics.Native/D3d12/Src/Buffer.cc index a180dbd..3617a65 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Buffer.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Buffer.cc @@ -9,7 +9,7 @@ D3d12GpuBuffer::D3d12GpuBuffer(Rc&& device, const FGpuBufferCrea { m_allocator = m_device->m_gpu_allocator; - m_state = FResState::BufferCommon(); + m_resource_type = ResourceType::Buffer; m_purpose = options.Purpose; m_cpu_access = options.CpuAccess; m_size = options.Size; @@ -38,12 +38,14 @@ D3d12GpuBuffer::D3d12GpuBuffer(Rc&& device, const FGpuBufferCrea m_desc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE; } - m_resource = box(m_device.get(), m_allocator.Get(), m_cpu_access, m_state, &m_desc, nullptr, false); + m_resource = box(m_device.get(), m_allocator.Get(), m_cpu_access, m_layout_state.Layout, &m_desc, nullptr, false); + m_raw_resource_ptr = GetRawResourcePtr(); if (m_device->Debug()) { chr | m_resource->m_resource >> SetNameEx(options.Name); } + } FResult D3d12GpuBuffer::SetName(const FStr8or16& name) noexcept @@ -55,16 +57,6 @@ FResult D3d12GpuBuffer::SetName(const FStr8or16& name) noexcept }); } -ResourceType D3d12GpuBuffer::GetResourceType() noexcept -{ - return ResourceType::Buffer; -} - -FGpuViewableData* D3d12GpuBuffer::GpuViewableData() noexcept -{ - return this; -} - FGpuResourceData* D3d12GpuBuffer::GpuResourceData() noexcept { return this; diff --git a/Coplt.Graphics.Native/D3d12/Src/Buffer.h b/Coplt.Graphics.Native/D3d12/Src/Buffer.h index 4497dd7..f07d80e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Buffer.h +++ b/Coplt.Graphics.Native/D3d12/Src/Buffer.h @@ -33,8 +33,6 @@ namespace Coplt FResult SetName(const FStr8or16& name) noexcept override; - ResourceType GetResourceType() noexcept override; - FGpuViewableData* GpuViewableData() noexcept override; FGpuResourceData* GpuResourceData() noexcept override; FGpuBufferData* GpuBufferData() noexcept override; NonNull Data() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 8ca5e9b..4a5a06b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -63,6 +63,16 @@ D3d12GpuDevice::D3d12GpuDevice(Rc&& adapter, const FGpuDeviceCr allocator_desc.pAllocationCallbacks = &allocation_callbacks; chr | CreateAllocator(&allocator_desc, &m_gpu_allocator); + if (m_adapter->m_feature_support.CacheCoherentUMA()) + { + D3D12MA::POOL_DESC pool_desc{}; + pool_desc.Flags = D3D12MA::POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED; + pool_desc.HeapProperties.Type = D3D12_HEAP_TYPE_CUSTOM; + pool_desc.HeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + pool_desc.HeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_L0; + chr | m_gpu_allocator->CreatePool(&pool_desc, &m_uma_pool); + } + if (Debug()) { chr | m_device >> SetNameEx(options.Name); @@ -292,7 +302,15 @@ FResult D3d12GpuDevice::CreateShader(const FShaderCreateOptions& options, FShade }); } -FResult D3d12GpuDevice::CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept +FResult D3d12GpuDevice::CreateBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept +{ + return feb([&] + { + *out = new D3d12ShaderBindGroup(this->CloneThis(), options); + }); +} + +FResult D3d12GpuDevice::CreateBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept { return feb([&] { diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index 6a0a3f7..64ffdac 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -28,6 +28,7 @@ namespace Coplt ComPtr m_device0{}; ComPtr m_info_queue{}; ComPtr m_gpu_allocator{}; + ComPtr m_uma_pool{}; Box m_empty_layouts{}; Rc m_empty_bind_group_layout{}; Box m_empty_binding_layout{}; @@ -68,7 +69,9 @@ namespace Coplt FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept override; FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept override; - FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; + FResult CreateBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept override; + FResult CreateBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; + FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept override; FResult CreateBuffer(const FGpuBufferCreateOptions& options, FGpuBuffer** out) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Image.cc b/Coplt.Graphics.Native/D3d12/Src/Image.cc index da27e88..514e816 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Image.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Image.cc @@ -10,7 +10,7 @@ D3d12GpuImage::D3d12GpuImage(Rc&& device, const FGpuImageCreateO { m_allocator = m_device->m_gpu_allocator; - m_state = FResState::BufferCommon(); + m_resource_type = ResourceType::Image; m_purpose = options.Purpose; m_cpu_access = options.CpuAccess; m_format = options.Format; @@ -84,9 +84,10 @@ D3d12GpuImage::D3d12GpuImage(Rc&& device, const FGpuImageCreateO } m_resource = box( - m_device.get(), m_allocator.Get(), m_cpu_access, m_state, &m_desc, + m_device.get(), m_allocator.Get(), m_cpu_access, m_layout_state.Layout, &m_desc, options.HasOptimizedClearValue ? &clear_value : nullptr, true ); + m_raw_resource_ptr = GetRawResourcePtr(); if (m_device->Debug()) { @@ -103,16 +104,6 @@ FResult D3d12GpuImage::SetName(const FStr8or16& name) noexcept }); } -ResourceType D3d12GpuImage::GetResourceType() noexcept -{ - return ResourceType::Image; -} - -FGpuViewableData* D3d12GpuImage::GpuViewableData() noexcept -{ - return this; -} - FGpuResourceData* D3d12GpuImage::GpuResourceData() noexcept { return this; diff --git a/Coplt.Graphics.Native/D3d12/Src/Image.h b/Coplt.Graphics.Native/D3d12/Src/Image.h index 5a037b2..cc710d6 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Image.h +++ b/Coplt.Graphics.Native/D3d12/Src/Image.h @@ -33,8 +33,6 @@ namespace Coplt explicit D3d12GpuImage(Rc&& device, const FGpuImageCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; - ResourceType GetResourceType() noexcept override; - FGpuViewableData* GpuViewableData() noexcept override; FGpuResourceData* GpuResourceData() noexcept override; FGpuImageData* GpuImageData() noexcept override; NonNull Data() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Resource.cc b/Coplt.Graphics.Native/D3d12/Src/Resource.cc index bb5ef0c..a0a695b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Resource.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Resource.cc @@ -6,50 +6,64 @@ using namespace Coplt; ResourcePack::ResourcePack( - D3d12GpuDevice* device, D3D12MA::Allocator* allocator, const FCpuAccess cpu_access, - FResState& state, const D3D12_RESOURCE_DESC1* desc, const D3D12_CLEAR_VALUE* clear_value, - bool image + D3d12GpuDevice* device, D3D12MA::Allocator* allocator, const FCpuAccess cpu_access, ResLayout& layout, + const D3D12_RESOURCE_DESC1* desc, const D3D12_CLEAR_VALUE* clear_value, bool image ) { D3D12MA::ALLOCATION_DESC alloc_desc{}; alloc_desc.Flags = D3D12MA::ALLOCATION_FLAG_NONE; + if (device->m_uma_pool) + { + alloc_desc.CustomPool = device->m_uma_pool.Get(); + } + else + { + switch (cpu_access) + { + case FCpuAccess::Write: + alloc_desc.HeapType = D3D12_HEAP_TYPE_UPLOAD; + break; + case FCpuAccess::Read: + alloc_desc.HeapType = D3D12_HEAP_TYPE_READBACK; + break; + case FCpuAccess::ReadWrite: + COPLT_THROW("Non-UMA devices cannot create read write resources"); + default: + alloc_desc.HeapType = D3D12_HEAP_TYPE_DEFAULT; + break; + } + } - D3D12_BARRIER_LAYOUT layout = D3D12_BARRIER_LAYOUT_UNDEFINED; + D3D12_BARRIER_LAYOUT init_layout = D3D12_BARRIER_LAYOUT_UNDEFINED; D3D12_RESOURCE_STATES init_state{}; switch (cpu_access) { case FCpuAccess::Write: - alloc_desc.HeapType = D3D12_HEAP_TYPE_UPLOAD; init_state = D3D12_RESOURCE_STATE_GENERIC_READ; if (image) { - state = FResState::ImageGenericRead(); - layout = D3D12_BARRIER_LAYOUT_GENERIC_READ; + layout = ResLayout::GenericRead; + init_layout = D3D12_BARRIER_LAYOUT_GENERIC_READ; } - else state = FResState::BufferGenericRead(); break; case FCpuAccess::Read: - alloc_desc.HeapType = D3D12_HEAP_TYPE_READBACK; init_state = D3D12_RESOURCE_STATE_COPY_DEST; if (image) { - state = FResState::ImageCopyDst(); - layout = D3D12_BARRIER_LAYOUT_COPY_DEST; + layout = ResLayout::CopyDest; + init_layout = D3D12_BARRIER_LAYOUT_COPY_DEST; } - else state = FResState::BufferCopyDst(); break; + case FCpuAccess::ReadWrite: default: - alloc_desc.HeapType = D3D12_HEAP_TYPE_DEFAULT; init_state = D3D12_RESOURCE_STATE_COMMON; - if (image) state = FResState::ImageCommon(); - else state = FResState::BufferCommon(); break; } if (device->m_adapter->m_features.EnhancedBarriers) { chr | allocator->CreateResource3( - &alloc_desc, desc, layout, clear_value, + &alloc_desc, desc, init_layout, clear_value, 0, nullptr, &m_allocation, IID_PPV_ARGS(&m_resource) ); } @@ -79,6 +93,7 @@ BufferPack::BufferPack( const u64 size, const D3D12_RESOURCE_FLAGS Flags ) : m_size(size) { + ResLayout layout{}; const auto desc = CD3DX12_RESOURCE_DESC1::Buffer(size, Flags); - m_resource = ResourcePack(device, allocator, cpu_access, m_state, &desc, nullptr, false); + m_resource = ResourcePack(device, allocator, cpu_access, layout, &desc, nullptr, false); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Resource.h b/Coplt.Graphics.Native/D3d12/Src/Resource.h index 708ebd3..28a4919 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Resource.h +++ b/Coplt.Graphics.Native/D3d12/Src/Resource.h @@ -1,7 +1,7 @@ #pragma once -#include "../../Api/Include/Object.h" #include "../FFI/Resource.h" +#include "../Include/ResState.h" #include "Device.h" namespace Coplt @@ -14,9 +14,8 @@ namespace Coplt ResourcePack() = default; explicit ResourcePack( - D3d12GpuDevice* device, D3D12MA::Allocator* allocator, FCpuAccess cpu_access, - FResState& state, const D3D12_RESOURCE_DESC1* desc, const D3D12_CLEAR_VALUE* clear_value, - bool image + D3d12GpuDevice* device, D3D12MA::Allocator* allocator, FCpuAccess cpu_access, ResLayout& layout, + const D3D12_RESOURCE_DESC1* desc, const D3D12_CLEAR_VALUE* clear_value, bool image ); }; @@ -24,7 +23,6 @@ namespace Coplt { ResourcePack m_resource{}; u64 m_size{}; - FResState m_state{}; BufferPack() = default; diff --git a/Coplt.Graphics.Native/D3d12/Src/View.cc b/Coplt.Graphics.Native/D3d12/Src/View.cc index 70879ad..1f9c945 100644 --- a/Coplt.Graphics.Native/D3d12/Src/View.cc +++ b/Coplt.Graphics.Native/D3d12/Src/View.cc @@ -3,224 +3,23 @@ using namespace Coplt; -enum View::Type View::Type() const -{ - return m_type; -} - -Rc& View::Buffer() -{ - if (m_type != Type::Buffer) - COPLT_THROW("null"); - return m_buffer; -} - -const Rc& View::Buffer() const -{ - if (m_type != Type::Buffer) - COPLT_THROW("null"); - return m_buffer; -} - -Rc& View::Image() -{ - if (m_type != Type::Image) - COPLT_THROW("null"); - return m_image; -} - -const Rc& View::Image() const -{ - if (m_type != Type::Image) - COPLT_THROW("null"); - return m_image; -} - -Rc& View::Sampler() -{ - if (m_type != Type::Sampler) - COPLT_THROW("null"); - return m_sampler; -} - -const Rc& View::Sampler() const -{ - if (m_type != Type::Sampler) - COPLT_THROW("null"); - return m_sampler; -} - -View::~View() -{ - // ReSharper disable once CppDefaultCaseNotHandledInSwitchStatement - switch (m_type) - { - case Type::None: - return; - case Type::Buffer: - m_buffer.~Rc(); - return; - case Type::Image: - m_image.~Rc(); - return; - case Type::Sampler: - m_sampler.~Rc(); - break; - } - std::unreachable(); -} - -// ReSharper disable once CppPossiblyUninitializedMember -View::View() : m_type(Type::None) -{ -} - -View::View(const View& other) : m_type(other.m_type) -{ - switch (m_type) - { - case Type::None: - break; - case Type::Buffer: - new(std::addressof(m_buffer)) Rc(other.m_buffer); - break; - case Type::Image: - new(std::addressof(m_image)) Rc(other.m_image); - break; - case Type::Sampler: - new(std::addressof(m_sampler)) Rc(other.m_sampler); - break; - } -} - -View::View(View&& other) noexcept : m_type(std::exchange(other.m_type, Type::None)) -{ - switch (m_type) - { - case Type::None: - break; - case Type::Buffer: - new(std::addressof(m_buffer)) Rc(std::move(other.m_buffer)); - break; - case Type::Image: - new(std::addressof(m_image)) Rc(std::move(other.m_image)); - break; - case Type::Sampler: - new(std::addressof(m_sampler)) Rc(std::move(other.m_sampler)); - break; - } -} - -View& View::operator=(const View& view) noexcept -{ - this->~View(); - new(this) View(view); - return *this; -} - -View& View::operator=(View&& view) noexcept -{ - this->~View(); - new(this) View(std::forward(view)); - return *this; -} - View::View(const FView& view) { - switch (view.Type) + if (view.Type != FViewType::None && view.Viewable) { - case FViewType::None: - m_type = Type::None; - break; - case FViewType::Buffer: - { - m_type = Type::Buffer; - if (view.Buffer == nullptr) new(std::addressof(m_buffer)) Rc(); - const auto db = view.Buffer->QueryInterface(); - if (db == nullptr) - COPLT_THROW("GpuBuffer from different backends."); - new(std::addressof(m_buffer)) Rc(Rc::UnsafeClone(db)); - break; - } - case FViewType::Image: - { - m_type = Type::Image; - if (view.Image == nullptr) new(std::addressof(m_image)) Rc(); - const auto db = view.Image->QueryInterface(); - if (db == nullptr) - COPLT_THROW("GpuImage from different backends."); - new(std::addressof(m_image)) Rc(Rc::UnsafeClone(db)); - break; - } - case FViewType::Sampler: - { - m_type = Type::Sampler; - if (view.Sampler == nullptr) new(std::addressof(m_sampler)) Rc(); - const auto db = view.Sampler->QueryInterface(); - if (db == nullptr) - COPLT_THROW("GpuSampler from different backends."); - new(std::addressof(m_sampler)) Rc(Rc::UnsafeClone(db)); - break; - } - break; + const auto viewable = view.Viewable->QueryInterface(); + if (!viewable) + COPLT_THROW("Viewable from different backends"); + m_viewable = Rc::UnsafeClone(viewable); + m_type = view.Type; } } -View& View::operator=(const FView& view) -{ - this->~View(); - new(this) View(view); - return *this; -} - -View::View(const Rc& buffer) : m_type(Type::Buffer) -{ - new(std::addressof(m_buffer)) Rc(buffer); -} - -View::View(Rc&& buffer) : m_type(Type::Buffer) -{ - new(std::addressof(m_buffer)) Rc(std::move(buffer)); -} - -View& View::operator=(const Rc& buffer) -{ - this->~View(); - new(this) View(buffer); - return *this; -} - -View& View::operator=(Rc&& buffer) +View::operator bool() const { - this->~View(); - new(this) View(std::forward>(buffer)); - return *this; + return m_viewable && m_type != FViewType::None; } -View::View(const Rc& image) : m_type(Type::Image) -{ - new(std::addressof(m_image)) Rc(image); -} - -View::View(Rc&& image) : m_type(Type::Image) -{ - new(std::addressof(m_image)) Rc(std::move(image)); -} - -View& View::operator=(const Rc& image) -{ - this->~View(); - new(this) View(image); - return *this; -} - -View& View::operator=(Rc&& image) -{ - this->~View(); - new(this) View(std::forward>(image)); - return *this; -} -// // void View::CreateDescriptor( // NonNull device, const FShaderLayoutItemDefine& def, const CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView type // ) const diff --git a/Examples/Colorful/Example.cs b/Examples/Colorful/Example.cs index 20434e2..1f173c0 100644 --- a/Examples/Colorful/Example.cs +++ b/Examples/Colorful/Example.cs @@ -60,7 +60,7 @@ protected override async Task LoadResources(GpuRecord cmd) } }, Topology = PrimitiveTopologyType.TriangleStrip, - }, Name: Name + }, BindingLayout, Name: Name ); ArgBuffer = Device.CreateBuffer( new() @@ -75,7 +75,8 @@ protected override async Task LoadResources(GpuRecord cmd) protected override void Render(GpuRecord cmd, Time time) { cmd.Upload(ArgBuffer, [(float)time.Total.TotalSeconds]); - // using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); + using var render = cmd.Render([new(Output, LoadOp.Discard)]); // render.Draw(Pipeline, 4, Binding: ShaderBinding); + render.Draw(Pipeline, 4); } } From fcae3df6ba98806f7982e0f0159ccd59bbcafabe Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 3 Apr 2025 16:31:34 +0800 Subject: [PATCH 31/46] save --- Coplt.Graphics.Core/Core/DeviceRequires.cs | 10 +++++++ Coplt.Graphics.Core/Core/GpuAdapter.cs | 1 - Coplt.Graphics.Core/Native/Native.cs | 6 ++++ Coplt.Graphics.Native/Api/FFI/Features.h | 4 +++ Coplt.Graphics.Native/D3d12/Src/Adapter.cc | 3 ++ Coplt.Graphics.Native/D3d12/Src/Device.cc | 4 +-- Coplt.Graphics.Native/D3d12/Src/Resource.cc | 31 +++++++++------------ Examples/ExampleBase/ExampleBase.cs | 7 +++-- 8 files changed, 43 insertions(+), 23 deletions(-) diff --git a/Coplt.Graphics.Core/Core/DeviceRequires.cs b/Coplt.Graphics.Core/Core/DeviceRequires.cs index 59ce7a3..d6a04ec 100644 --- a/Coplt.Graphics.Core/Core/DeviceRequires.cs +++ b/Coplt.Graphics.Core/Core/DeviceRequires.cs @@ -129,6 +129,14 @@ public record struct DeviceFeatures /// 真 · 无绑定, dx 使用 dynamic resource,vk 使用 VK_EXT_mutable_descriptor_type /// public bool DynBindless; + /// + /// 设备是否是统一内存访问架构 + /// + public bool UMA; + /// + /// 设备是否是缓存一致的统一内存访问架构 + /// + public bool CacheCoherentUMA; public DeviceFeatures(in FDeviceFeatures native) { @@ -139,5 +147,7 @@ public DeviceFeatures(in FDeviceFeatures native) EnhancedBarriers = native.EnhancedBarriers; ArrBindless = native.ArrBindless; DynBindless = native.DynBindless; + UMA = native.UMA; + CacheCoherentUMA = native.CacheCoherentUMA; } } diff --git a/Coplt.Graphics.Core/Core/GpuAdapter.cs b/Coplt.Graphics.Core/Core/GpuAdapter.cs index 37c3f33..d82c2d3 100644 --- a/Coplt.Graphics.Core/Core/GpuAdapter.cs +++ b/Coplt.Graphics.Core/Core/GpuAdapter.cs @@ -31,7 +31,6 @@ public sealed unsafe partial class GpuAdapter public DeviceType DeviceType => (DeviceType)m_ptr->m_device_type; public Backend Backend => (Backend)m_ptr->m_backend; public DeviceFeatures Features => new(m_ptr->m_features); - public bool UseLegacyState => !m_ptr->m_features.EnhancedBarriers; #endregion diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index d8eb8e4..7c863df 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1106,6 +1106,12 @@ public partial struct FDeviceFeatures [NativeTypeName("Coplt::b8")] public B8 ExtraIsolate; + + [NativeTypeName("Coplt::b8")] + public B8 UMA; + + [NativeTypeName("Coplt::b8")] + public B8 CacheCoherentUMA; } [NativeTypeName("Coplt::i32")] diff --git a/Coplt.Graphics.Native/Api/FFI/Features.h b/Coplt.Graphics.Native/Api/FFI/Features.h index 286500e..6656c36 100644 --- a/Coplt.Graphics.Native/Api/FFI/Features.h +++ b/Coplt.Graphics.Native/Api/FFI/Features.h @@ -60,5 +60,9 @@ namespace Coplt b8 DynBindlessOnly{}; // 可以任意创建隔离,dx12 永远为 true,vk 永远为 false b8 ExtraIsolate{}; + // 是否是缓存一致的 UMA 架构 + b8 UMA{}; + // 是否是缓存一致的 UMA 架构 + b8 CacheCoherentUMA{}; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Adapter.cc b/Coplt.Graphics.Native/D3d12/Src/Adapter.cc index e209a4e..55cbdd3 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Adapter.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Adapter.cc @@ -58,6 +58,9 @@ D3d12GpuAdapter::D3d12GpuAdapter( 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; + + if (m_feature_support.UMA())m_features.UMA = true; + if (m_feature_support.CacheCoherentUMA())m_features.CacheCoherentUMA = true; } FResult D3d12GpuAdapter::CreateDevice(const FGpuDeviceCreateOptions& options, FGpuDeviceCreateResult* out) noexcept diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 4a5a06b..f0d5391 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -63,12 +63,12 @@ D3d12GpuDevice::D3d12GpuDevice(Rc&& adapter, const FGpuDeviceCr allocator_desc.pAllocationCallbacks = &allocation_callbacks; chr | CreateAllocator(&allocator_desc, &m_gpu_allocator); - if (m_adapter->m_feature_support.CacheCoherentUMA()) + if (m_adapter->m_feature_support.UMA()) { D3D12MA::POOL_DESC pool_desc{}; pool_desc.Flags = D3D12MA::POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED; pool_desc.HeapProperties.Type = D3D12_HEAP_TYPE_CUSTOM; - pool_desc.HeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + pool_desc.HeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_BACK; pool_desc.HeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_L0; chr | m_gpu_allocator->CreatePool(&pool_desc, &m_uma_pool); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Resource.cc b/Coplt.Graphics.Native/D3d12/Src/Resource.cc index a0a695b..53fe97d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Resource.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Resource.cc @@ -12,26 +12,21 @@ ResourcePack::ResourcePack( { D3D12MA::ALLOCATION_DESC alloc_desc{}; alloc_desc.Flags = D3D12MA::ALLOCATION_FLAG_NONE; - if (device->m_uma_pool) - { - alloc_desc.CustomPool = device->m_uma_pool.Get(); - } - else + switch (cpu_access) { - switch (cpu_access) - { - case FCpuAccess::Write: - alloc_desc.HeapType = D3D12_HEAP_TYPE_UPLOAD; - break; - case FCpuAccess::Read: - alloc_desc.HeapType = D3D12_HEAP_TYPE_READBACK; - break; - case FCpuAccess::ReadWrite: + case FCpuAccess::Write: + alloc_desc.HeapType = D3D12_HEAP_TYPE_UPLOAD; + break; + case FCpuAccess::Read: + alloc_desc.HeapType = D3D12_HEAP_TYPE_READBACK; + break; + case FCpuAccess::ReadWrite: + if (device->m_uma_pool) alloc_desc.CustomPool = device->m_uma_pool.Get(); + else COPLT_THROW("Non-UMA devices cannot create read write resources"); - default: - alloc_desc.HeapType = D3D12_HEAP_TYPE_DEFAULT; - break; - } + default: + alloc_desc.HeapType = D3D12_HEAP_TYPE_DEFAULT; + break; } D3D12_BARRIER_LAYOUT init_layout = D3D12_BARRIER_LAYOUT_UNDEFINED; diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index d6053cd..751408c 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -33,14 +33,17 @@ public void DoInitGraphics() (level, _) => Log.IsEnabled(level.ToLogEventLevel()), (level, scope, msg) => Log.Write(level.ToLogEventLevel(), "[{Scope}] {Msg}", scope, msg) ); - Device = Graphics.CreateDevice(Name: "Main Device"); + Device = Graphics.CreateDevice(new() + { + // DeviceType = DeviceTypeRequire.IntegratedGpu, + }, Name: "Main Device"); var Adapter = Device.Adapter; Log.Information( "Selected device: {@Info}", new { Adapter.Name, Adapter.VendorId, Adapter.DeviceId, Adapter.Driver, Adapter.Backend, - Adapter.Features.ShaderModelLevel + Adapter.Features.ShaderModelLevel, Adapter.Features.UMA, Adapter.Features.CacheCoherentUMA } ); Isolate = Device.MainIsolate; From 1acf17c194f29645b491cd1652bfe3b6d407f447 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 3 Apr 2025 23:01:15 +0800 Subject: [PATCH 32/46] save --- Coplt.Graphics.Native/Api/FFI/Binding.h | 8 + Coplt.Graphics.Native/Api/Include/Utils.h | 3 + Coplt.Graphics.Native/D3d12/CMakeLists.txt | 4 +- Coplt.Graphics.Native/D3d12/Include/View.h | 21 +- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 62 ++++- Coplt.Graphics.Native/D3d12/Src/Binding.h | 9 +- Coplt.Graphics.Native/D3d12/Src/Buffer.cc | 6 + Coplt.Graphics.Native/D3d12/Src/Buffer.h | 5 +- .../D3d12/Src/DescriptorManager.cc | 252 +++--------------- .../D3d12/Src/DescriptorManager.h | 151 +++-------- Coplt.Graphics.Native/D3d12/Src/Device.cc | 2 - Coplt.Graphics.Native/D3d12/Src/Device.h | 3 +- Coplt.Graphics.Native/D3d12/Src/Image.cc | 6 + Coplt.Graphics.Native/D3d12/Src/Image.h | 5 +- Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 2 + Coplt.Graphics.Native/D3d12/Src/Isolate.h | 1 + Coplt.Graphics.Native/D3d12/Src/Queue.h | 1 - Coplt.Graphics.Native/D3d12/Src/Record.cc | 2 +- Coplt.Graphics.Native/D3d12/Src/Record.h | 7 +- Coplt.Graphics.Native/D3d12/Src/Sampler.cc | 9 + Coplt.Graphics.Native/D3d12/Src/Sampler.h | 5 +- Coplt.Graphics.Native/D3d12/Src/View.cc | 26 ++ 22 files changed, 243 insertions(+), 347 deletions(-) diff --git a/Coplt.Graphics.Native/Api/FFI/Binding.h b/Coplt.Graphics.Native/Api/FFI/Binding.h index 004702c..52c9452 100644 --- a/Coplt.Graphics.Native/Api/FFI/Binding.h +++ b/Coplt.Graphics.Native/Api/FFI/Binding.h @@ -8,7 +8,11 @@ namespace Coplt { struct FBindItem { + // 绑定内容 FView View{}; + // 绑定槽的索引 + u32 Slot{}; + // 如果绑定是数组的话,数组中的索引 u32 Index{}; }; @@ -16,6 +20,8 @@ namespace Coplt { FStr8or16 Name{}; FBindGroupLayout* Layout{}; + FBindItem* InitBindings{}; + u32 NumInitBindings{}; }; COPLT_INTERFACE_DEFINE(FShaderBindGroup, "ae54efe5-c372-4291-b995-55298758d2b2", FGpuObject) @@ -26,6 +32,8 @@ namespace Coplt { FStr8or16 Name{}; FBindingLayout* Layout{}; + FShaderBindGroup** InitBindGroups{}; + u32 NumInitBindGroups{}; }; COPLT_INTERFACE_DEFINE(FShaderBinding, "a3ca644a-0e02-4d25-9a18-8835d66600f7", FGpuObject) diff --git a/Coplt.Graphics.Native/Api/Include/Utils.h b/Coplt.Graphics.Native/Api/Include/Utils.h index 557bcee..fdde845 100644 --- a/Coplt.Graphics.Native/Api/Include/Utils.h +++ b/Coplt.Graphics.Native/Api/Include/Utils.h @@ -1,6 +1,9 @@ #pragma once +#include #include +#include "../../Api/FFI/Common.h" + namespace Coplt { template diff --git a/Coplt.Graphics.Native/D3d12/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index cf9d021..760b079 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -34,8 +34,6 @@ add_library(${target_name} SHARED Include/States.h Src/Binding.h Src/Binding.cc - Src/DescriptorManager.h - Src/DescriptorManager.cc Include/View.h FFI/Adapter.h Src/Adapter.h @@ -58,6 +56,8 @@ add_library(${target_name} SHARED Src/Barrier.cc Include/ResState.h Src/ResState.cc + Src/DescriptorManager.h + Src/DescriptorManager.cc ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "Coplt.Graphics.Native.D3d12") diff --git a/Coplt.Graphics.Native/D3d12/Include/View.h b/Coplt.Graphics.Native/D3d12/Include/View.h index 2472729..14a6184 100644 --- a/Coplt.Graphics.Native/D3d12/Include/View.h +++ b/Coplt.Graphics.Native/D3d12/Include/View.h @@ -3,15 +3,13 @@ #include #include "../../Api/FFI/Resource.h" -#include "../../Api/Include/Ptr.h" -#include "../Src/Buffer.h" -#include "../Src/Image.h" -#include "../Src/Sampler.h" +#include "../../Api/FFI/Binding.h" namespace Coplt { - COPLT_INTERFACE_DEFINE(ID3d12GpuViewable, "78155a99-1110-42f8-a1ef-c70fc23dbc52", FGpuViewable) + COPLT_INTERFACE_DEFINE(ID3d12GpuViewable, "597cbbb5-add9-45e3-bbba-802f63465c8e", FGpuViewable) { + virtual bool IsCompatible(const FBindGroupItem& def) const = 0; }; struct View final @@ -19,10 +17,23 @@ namespace Coplt Rc m_viewable{}; FViewType m_type{}; + View() = default; + + View& swap(View& other) noexcept; + + View(const View& other) noexcept = default; + View& operator=(const View& view) = default; + + View(View&& other) noexcept = default; + View& operator=(View&& view) = default; + View(const FView& view); + View& operator=(const FView& view); operator bool() const; + bool IsCompatible(const FBindGroupItem& def) const; + // void CreateDescriptor( // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type // ) const; diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index 27d3a0b..8b3ad7a 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -10,15 +10,75 @@ using namespace Coplt; D3d12ShaderBindGroup::D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options) : m_device(std::move(device)) { + m_layout = Rc::UnsafeClone(NonNull(options.Layout)); + const auto items = m_layout->GetItems(); + usize sum_count = 0; + for (const auto& item : items) + { + sum_count += std::max(1u, item.Count); + } + m_views = std::vector(sum_count, View{}); + m_item_indexes.reserve(items.size()); + for (u32 i = 0, off = 0; i < items.size(); ++i) + { + m_item_indexes.push_back(off); + off += std::max(1u, items[i].Count); + } + Set(std::span(options.InitBindings, options.InitBindings + options.NumInitBindings)); + if (!options.Name.is_null()) + { + m_name = options.Name.ToString(); + } } FResult D3d12ShaderBindGroup::SetName(const FStr8or16& name) noexcept { - return FResult::None(); + return feb([&] + { + m_name = name.ToString(); + }); +} + +void D3d12ShaderBindGroup::Set(const std::span items) +{ + const auto defs = m_layout->GetItems(); + for (const auto& item : items) + { + if (item.Slot >= defs.size()) + COPLT_THROW("Index out of range"); + const auto& def = defs[item.Slot]; + if (item.Index >= def.Count) + COPLT_THROW("Index out of range"); + const auto index = m_item_indexes[item.Slot] + item.Index; + View view(item.View); + if (!view.IsCompatible(def)) + { + const auto id = ObjectId(); + if (m_device->Debug() && m_device->Logger().IsEnable(FLogLevel::Error)) + { + const auto name = m_name->GetStr(); + if (name.is_null()) + m_device->Logger().Log(FLogLevel::Error, fmt::format("Incompatible bindings in BindGroup({})", id)); + else if (name.is8()) + m_device->Logger().Log(FLogLevel::Error, fmt::format("Incompatible bindings in BindGroup({}, \"{}\")", id, name.str8)); + else + m_device->Logger().LogW( + FLogLevel::Error, + fmt::format( + L"Incompatible bindings in BindGroup({}, \"{}\")", id, + reinterpret_cast(name.str16) + ) + ); + } + COPLT_THROW_FMT("Incompatible bindings [{},{}] in BindGroup({})", item.Slot, item.Index, id); + } + m_views[index] = std::move(view); + } } D3d12ShaderBinding::D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options) : m_device(std::move(device)) { + // todo } FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index e84f519..0874a0f 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -17,25 +17,30 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12ShaderBindGroup, "5bb948b9-ad31-4eb8-b881-98017e048259", FShaderBindGroup) { - }; struct D3d12ShaderBindGroup final : GpuObject { + Rc m_name{}; Rc m_device{}; + Rc m_layout{}; + std::vector m_views{}; + std::vector m_item_indexes{}; explicit D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; + + void Set(std::span items); }; COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "5073f785-cfb7-414d-9a84-1602d3bf378d", FShaderBinding) { - }; struct D3d12ShaderBinding final : GpuObject { Rc m_device{}; + std::vector> m_groups{}; explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Buffer.cc b/Coplt.Graphics.Native/D3d12/Src/Buffer.cc index 3617a65..166303e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Buffer.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Buffer.cc @@ -104,3 +104,9 @@ FResult D3d12GpuBuffer::Unmap(const b8 Discard) noexcept m_resource->m_resource->Unmap(0, Discard ? &range : nullptr); }); } + +bool D3d12GpuBuffer::IsCompatible(const FBindGroupItem& def) const +{ + // todo + return true; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Buffer.h b/Coplt.Graphics.Native/D3d12/Src/Buffer.h index f07d80e..cb45a96 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Buffer.h +++ b/Coplt.Graphics.Native/D3d12/Src/Buffer.h @@ -10,10 +10,11 @@ #include "../../Api/Include/GpuObject.h" #include "../../Api/Include/Ptr.h" #include "../Include/ResState.h" +#include "../Include/View.h" namespace Coplt { - COPLT_INTERFACE_DEFINE(ID3d12GpuBuffer, "6edf3bc5-dfc7-461a-ab6b-0e5f5a9d71e7", FD3d12GpuBuffer) + COPLT_INTERFACE_DEFINE(ID3d12GpuBuffer, "6edf3bc5-dfc7-461a-ab6b-0e5f5a9d71e7", FD3d12GpuBuffer, ID3d12GpuViewable) { virtual NonNull Data() = 0; virtual NonNull GetResourcePtr() = 0; @@ -43,5 +44,7 @@ namespace Coplt FResult Map(void** ptr, b8 Discard) noexcept override; FResult Unmap(b8 Discard) noexcept override; + + bool IsCompatible(const FBindGroupItem& def) const override; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc index 3d0a0c9..2ee10d1 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc @@ -1,239 +1,75 @@ #include "DescriptorManager.h" -#include "../../Api/Include/AllocObjectId.h" +#include "Device.h" using namespace Coplt; -DescriptorHeap::DescriptorHeap(const ComPtr& device, const D3D12_DESCRIPTOR_HEAP_TYPE type, const u32 size, const bool gpu) - : m_device(device), m_id(AllocObjectId()), m_type(type), - m_stride(m_device->GetDescriptorHandleIncrementSize(type)), m_size(size), m_gpu(gpu) +DescriptorAllocation::DescriptorAllocation(DescriptorHeap& heap, const D3D12MA::VirtualAllocation allocation, const u64 offset) + : m_heap(heap.CloneThis()), m_version(heap.m_version), m_allocation(allocation), m_offset(offset) { - D3D12_DESCRIPTOR_HEAP_DESC desc{}; - desc.Type = type; - desc.NumDescriptors = size; - if (gpu) desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - chr | m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_heap)); } -const ComPtr& DescriptorHeap::Heap() const +DescriptorAllocation::~DescriptorAllocation() { - return m_heap; + if (!m_heap) return; + if (m_heap->m_version != m_version) return; + m_heap->m_virtual_block->FreeAllocation(m_allocation); + m_heap = {}; } -u64 DescriptorHeap::Id() const +CD3DX12_CPU_DESCRIPTOR_HANDLE DescriptorAllocation::GetCpuHandle() const { - return m_id; + if (m_heap->m_version != m_version) + COPLT_THROW("This allocation has expired"); + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_heap->m_heap->GetCPUDescriptorHandleForHeapStart(), m_offset, m_heap->m_inc); } -u64 DescriptorHeap::Version() const +CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorAllocation::GetGpuHandle() const { - return m_version; + if (m_heap->m_version != m_version) + COPLT_THROW("This allocation has expired"); + return CD3DX12_GPU_DESCRIPTOR_HANDLE(m_heap->m_heap->GetGPUDescriptorHandleForHeapStart(), m_offset, m_heap->m_inc); } -D3D12_DESCRIPTOR_HEAP_TYPE DescriptorHeap::Type() const +DescriptorHeap::DescriptorHeap(NonNull device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 init_size) + : m_device(device->m_device), m_type(type) { - return m_type; -} - -u32 DescriptorHeap::Stride() const -{ - return m_stride; -} - -bool DescriptorHeap::IsRemote() const -{ - return m_gpu; -} - -u32 DescriptorHeap::Size() const -{ - return m_size; -} - -CD3DX12_CPU_DESCRIPTOR_HANDLE DescriptorHeap::GetLocalHandle(const u32 offset) const -{ - return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_heap->GetCPUDescriptorHandleForHeapStart(), static_cast(offset), m_stride); -} - -CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::GetRemoteHandle(const u32 offset) const -{ - return CD3DX12_GPU_DESCRIPTOR_HANDLE(m_heap->GetGPUDescriptorHandleForHeapStart(), static_cast(offset), m_stride); -} - -void DescriptorHeap::IncVersion() -{ - m_version++; -} - -DescriptorAllocator::DescriptorAllocator(const ComPtr& device, const D3D12_DESCRIPTOR_HEAP_TYPE type) - : m_device(device), m_type(type), m_stride(device->GetDescriptorHandleIncrementSize(type)) -{ -} - -const Rc& DescriptorAllocator::Heap() const -{ - return m_heap; -} - -const Rc& DescriptorAllocator::TmpHeap() const -{ - return m_tmp_heap; -} - -D3D12_DESCRIPTOR_HEAP_TYPE DescriptorAllocator::Type() const -{ - return m_type; -} - -u32 DescriptorAllocator::Stride() const -{ - return m_stride; -} - -CD3DX12_CPU_DESCRIPTOR_HANDLE DescriptorAllocator::GetTmpLocalHandle(const u32 offset) const -{ - return m_tmp_heap->GetLocalHandle(offset); -} - -CD3DX12_CPU_DESCRIPTOR_HANDLE DescriptorAllocator::GetLocalHandle(const u32 offset) const -{ - return m_heap->GetLocalHandle(offset); -} - -CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorAllocator::GetRemoteHandle(const u32 offset) const -{ - return m_heap->GetRemoteHandle(offset); -} - -void DescriptorAllocator::InitFrame(const u32 GrowthCapacity) -{ - if (m_heap == nullptr || m_persist_offset < GrowthCapacity) { - const auto cap_req = std::max(8u, (m_heap == nullptr ? 0 : m_heap->Size() - m_persist_offset) + GrowthCapacity); - m_heap = new DescriptorHeap(m_device, m_type, std::bit_ceil(cap_req), true); - m_persist_offset = m_heap->Size(); - m_persist_allocations.Clear(); - } - if (GrowthCapacity > 0 && (m_tmp_heap == nullptr || m_tmp_heap->Size() < GrowthCapacity)) - { - m_tmp_heap = new DescriptorHeap(m_device, m_type, std::bit_ceil(GrowthCapacity), false); - } - m_dynamic_offset = 0; - m_version++; -} + D3D12_DESCRIPTOR_HEAP_DESC desc{}; + desc.Type = type; + desc.NumDescriptors = init_size; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + chr | m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_heap)); -void DescriptorAllocator::AllocateTransient(u32 Size, DescriptorAllocation*& al) -{ - if (Size == 0) - { - *al = DescriptorAllocation(0, 0); - return; + m_inc = m_device->GetDescriptorHandleIncrementSize(type); } - if (!m_heap) - COPLT_THROW("Descriptor heap is null"); - const auto offset = m_dynamic_offset; - const auto new_offset = offset + Size; - if (new_offset >= m_persist_offset) - COPLT_THROW("Out of descriptor heap"); - m_dynamic_offset = new_offset; - *al = DescriptorAllocation(offset, Size); -} -void DescriptorAllocator::AllocatePersistent(NonNull Heap, PersistDescriptorAllocation*& al, bool& IsOld) -{ - if (Heap->Size() == 0) { - IsOld = true; - *al = PersistDescriptorAllocation(0, 0, 0); - return; + D3D12MA::VIRTUAL_BLOCK_DESC desc{}; + D3D12MA::ALLOCATION_CALLBACKS allocation_callbacks{}; + allocation_callbacks.pAllocate = [](auto size, auto align, auto data) { return mi_malloc_aligned(size, align); }; + allocation_callbacks.pFree = [](auto ptr, auto data) { return mi_free(ptr); }; + desc.Size = init_size; + desc.pAllocationCallbacks = &allocation_callbacks; + chr | CreateVirtualBlock(&desc, &m_virtual_block); } - if (!m_heap) - COPLT_THROW("Descriptor heap is null"); - auto& ref = m_persist_allocations.GetOrAdd(Heap->Id(), IsOld, [&](auto& p) - { - const auto offset = m_persist_offset; - const auto new_offset = offset - Heap->Size(); - if (new_offset < m_dynamic_offset) - COPLT_THROW("Out of descriptor heap"); - m_persist_offset = new_offset; - p = PersistDescriptorAllocation_Internal(0, new_offset, Heap->Size(), m_version); - }); - ref.AllocatorVersion = m_version; - al = &ref; } -void DescriptorAllocator::Upload(const DescriptorAllocation& Al, const Rc& Heap, const u32 Offset) const +Rc DescriptorHeap::Allocate(const u32 size) { - if (Al.Size == 0) return; - m_device->CopyDescriptorsSimple( - Al.Size, - GetLocalHandle(Al.Offset), - Heap->GetLocalHandle(Offset), - m_type - ); + D3D12MA::VIRTUAL_ALLOCATION_DESC desc{}; + desc.Alignment = 1; + desc.Size = size; + D3D12MA::VirtualAllocation allocation{}; + u64 offset{}; + const auto hr = m_virtual_block->Allocate(&desc, &allocation, &offset); + // todo 处理不够的情况 + chr | hr; + return new DescriptorAllocation(*this, allocation, offset); } -// void DescriptorAllocator::StoreTmp(const DescriptorAllocation& Al, const Rc& Heap, const u32 Offset) const -// { -// if (Al.Size == 0) return; -// m_device->CopyDescriptorsSimple( -// Al.Size, -// GetTmpLocalHandle(Al.Offset), -// Heap->GetLocalHandle(Offset), -// m_type -// ); -// } -// -// void DescriptorAllocator::SyncTmp() const -// { -// if (m_dynamic_offset == 0) return; -// m_device->CopyDescriptorsSimple( -// m_dynamic_offset, -// GetLocalHandle(), -// GetTmpLocalHandle(), -// m_type -// ); -// } - -DescriptorContext::DescriptorContext(const ComPtr& device) : m_device(device) -{ - m_resource = new DescriptorAllocator(m_device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - m_sampler = new DescriptorAllocator(m_device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); -} - -NonNull DescriptorContext::ResourceHeap() const -{ - if (!m_in_frame) [[unlikely]] - COPLT_THROW("Frame not started"); - return m_resource.get(); -} - -NonNull DescriptorContext::SamplerHeap() const -{ - if (!m_in_frame) [[unlikely]] - COPLT_THROW("Frame not started"); - return m_sampler.get(); -} - -void DescriptorContext::InitFrame(const u32 ResourceCap, const u32 SamplerCap) -{ - m_resource->InitFrame(ResourceCap); - m_sampler->InitFrame(SamplerCap); - m_in_frame = true; -} - -void DescriptorContext::EndFrame() -{ - m_in_frame = false; -} - -// void DescriptorContext::SyncTmp() const -// { -// m_resource->SyncTmp(); -// m_sampler->SyncTmp(); -// } - -std::array DescriptorContext::GetDescriptorHeaps() const +DescriptorManager::DescriptorManager(NonNull device) { - return {m_resource->Heap()->Heap().Get(), m_sampler->Heap()->Heap().Get()}; + m_res = new DescriptorHeap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, InitResHeapSize); + m_smp = new DescriptorHeap(device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, InitSmpHeapSize); } diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h index 3290395..d917e17 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h @@ -1,143 +1,56 @@ #pragma once -#include "directx/d3dx12.h" - -#include -#include -#include - -#include "Device.h" +#include +#include +#include "D3D12MemAlloc.h" #include "../../Api/Include/Ptr.h" +#include "../../Api/Include/Utils.h" + +#include "../Include/Utils.h" namespace Coplt { - struct DescriptorHeap final : Object - { - private: - ComPtr m_device{}; - ComPtr m_heap{}; - u64 const m_id{}; - u64 m_version{}; - D3D12_DESCRIPTOR_HEAP_TYPE const m_type{}; - u32 const m_stride{}; - u32 const m_size{}; - bool const m_gpu{}; - - public: - explicit DescriptorHeap(const ComPtr& device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 size, bool gpu); - - const ComPtr& Heap() const; - - u64 Id() const; - u64 Version() const; + struct D3d12GpuDevice; + struct DescriptorHeap; - D3D12_DESCRIPTOR_HEAP_TYPE Type() const; - u32 Stride() const; - bool IsRemote() const; - - u32 Size() const; - - CD3DX12_CPU_DESCRIPTOR_HANDLE GetLocalHandle(u32 offset = 0) const; - CD3DX12_GPU_DESCRIPTOR_HANDLE GetRemoteHandle(u32 offset = 0) const; - - void IncVersion(); - }; - - struct DescriptorAllocation + struct DescriptorAllocation final : Object { - u32 Offset{COPLT_U32_MAX}; - u32 Size{}; - - DescriptorAllocation() = default; - - explicit DescriptorAllocation(u32 Offset, u32 Size) : Offset(Offset), Size(Size) - { - } - - operator bool() const { return Offset != COPLT_U32_MAX; } - }; - - struct PersistDescriptorAllocation : DescriptorAllocation - { - u64 Version{}; - PersistDescriptorAllocation() = default; - - explicit PersistDescriptorAllocation(u64 Version, u32 Offset, u32 Size) - : DescriptorAllocation(Offset, Size), Version(Version) - { - } - }; - - struct PersistDescriptorAllocation_Internal : PersistDescriptorAllocation - { - u64 AllocatorVersion{}; + Rc m_heap{}; + u64 m_version{}; + D3D12MA::VirtualAllocation m_allocation{}; + u64 m_offset{}; - PersistDescriptorAllocation_Internal() = default; + explicit DescriptorAllocation(DescriptorHeap& heap, D3D12MA::VirtualAllocation allocation, u64 offset); + ~DescriptorAllocation() override; - explicit PersistDescriptorAllocation_Internal(u64 Version, u32 Offset, u32 Size, u64 AllocatorVersion) - : PersistDescriptorAllocation(Version, Offset, Size), AllocatorVersion(AllocatorVersion) - { - } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetCpuHandle() const; + CD3DX12_GPU_DESCRIPTOR_HANDLE GetGpuHandle() const; }; - struct DescriptorAllocator final : Object + struct DescriptorHeap final : Object { - private: - ComPtr m_device{}; - Rc m_tmp_heap{}; - Rc m_heap{}; u64 m_version{}; - HashMap m_persist_allocations{}; - D3D12_DESCRIPTOR_HEAP_TYPE const m_type{}; - u32 const m_stride{}; - u32 m_persist_offset{}; - u32 m_dynamic_offset{}; - - public: - explicit DescriptorAllocator(const ComPtr& device, D3D12_DESCRIPTOR_HEAP_TYPE type); - - const Rc& Heap() const; - const Rc& TmpHeap() const; - - D3D12_DESCRIPTOR_HEAP_TYPE Type() const; - u32 Stride() const; - - CD3DX12_CPU_DESCRIPTOR_HANDLE GetTmpLocalHandle(u32 offset = 0) const; - - CD3DX12_CPU_DESCRIPTOR_HANDLE GetLocalHandle(u32 offset = 0) const; - CD3DX12_GPU_DESCRIPTOR_HANDLE GetRemoteHandle(u32 offset = 0) const; + ComPtr m_device{}; + ComPtr m_heap{}; + ComPtr m_virtual_block{}; + u32 m_inc{}; + D3D12_DESCRIPTOR_HEAP_TYPE m_type{}; - void InitFrame(u32 GrowthCapacity); + explicit DescriptorHeap(NonNull device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 init_size); - void AllocateTransient(u32 Size, DescriptorAllocation*& al); - void AllocatePersistent(NonNull Heap, PersistDescriptorAllocation*& al, bool& IsOld); - void Upload(const DescriptorAllocation& Al, const Rc& Heap, u32 Offset = 0) const; - // void StoreTmp(const DescriptorAllocation& Al, const Rc& Heap, u32 Offset = 0) const; - // - // // 将临时堆复制到 gpu 可见堆 - // void SyncTmp() const; + Rc Allocate(u32 size); }; - struct DescriptorContext final : Object + struct DescriptorManager final { - private: - ComPtr m_device{}; - Rc m_resource{}; - Rc m_sampler{}; - bool m_in_frame{}; - - public: - explicit DescriptorContext(const ComPtr& device); - - NonNull ResourceHeap() const; - NonNull SamplerHeap() const; + constexpr static u32 InitResHeapSize = 65536; + constexpr static u32 InitSmpHeapSize = 1024; - void InitFrame(u32 ResourceCap, u32 SamplerCap); - void EndFrame(); + Rc m_res{}; + Rc m_smp{}; - // // 将临时堆复制到 gpu 可见堆 - // void SyncTmp() const; + DescriptorManager() = default; - std::array GetDescriptorHeaps() const; + explicit DescriptorManager(NonNull device); }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index f0d5391..3486c33 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -4,7 +4,6 @@ #include "../../Api/Src/Shader.h" #include "Adapter.h" -#include "DescriptorManager.h" #include "Buffer.h" #include "GraphicsPipeline.h" #include "Image.h" @@ -12,7 +11,6 @@ #include "Layout.h" #include "Queue.h" #include "Sampler.h" -#include "../../Api/Include/AllocObjectId.h" using namespace Coplt; diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index 64ffdac..de46a48 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -1,13 +1,14 @@ #pragma once #include - #include "D3D12MemAlloc.h" + #include "Instance.h" #include "../../Api/Include/GpuObject.h" #include "../../Api/Include/HashMap.h" #include "../../Api/Include/Object.h" #include "../FFI/Device.h" +#include "DescriptorManager.h" namespace Coplt { diff --git a/Coplt.Graphics.Native/D3d12/Src/Image.cc b/Coplt.Graphics.Native/D3d12/Src/Image.cc index 514e816..fc561a6 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Image.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Image.cc @@ -133,3 +133,9 @@ NonNull D3d12GpuImage::GetResourcePtr() { return m_resource->m_resource.Get(); } + +bool D3d12GpuImage::IsCompatible(const FBindGroupItem& def) const +{ + // todo + return true; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Image.h b/Coplt.Graphics.Native/D3d12/Src/Image.h index cc710d6..d619494 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Image.h +++ b/Coplt.Graphics.Native/D3d12/Src/Image.h @@ -11,10 +11,11 @@ #include "../../Api/Include/GpuObject.h" #include "../../Api/Include/Ptr.h" #include "../Include/ResState.h" +#include "../Include/View.h" namespace Coplt { - COPLT_INTERFACE_DEFINE(ID3d12GpuImage, "12748625-44ab-48e0-a40f-9b1d5685ce88", FD3d12GpuImage) + COPLT_INTERFACE_DEFINE(ID3d12GpuImage, "12748625-44ab-48e0-a40f-9b1d5685ce88", FD3d12GpuImage, ID3d12GpuViewable) { virtual NonNull Data() = 0; virtual NonNull GetResourcePtr() = 0; @@ -40,5 +41,7 @@ namespace Coplt void* GetRawResourcePtr() noexcept override; NonNull GetResourcePtr() override; + + bool IsCompatible(const FBindGroupItem& def) const override; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index 3c83567..e8f6257 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -17,6 +17,8 @@ D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCre m_record_pool = box(); m_device = std::move(device); + m_descriptor_manager = DescriptorManager(m_device.get()); + #pragma region 创建队列 m_main_queue = new D3d12GpuQueue2(this, FGpuQueueType::Direct); diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index 6dde66c..1417665 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -29,6 +29,7 @@ namespace Coplt using RecordQueue = moodycamel::ConcurrentQueue>; SRc m_config{}; + DescriptorManager m_descriptor_manager{}; Rc m_main_queue{}; Rc m_compute_queue{}; Rc m_copy_queue{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Queue.h b/Coplt.Graphics.Native/D3d12/Src/Queue.h index 5b3686d..161eaa3 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -9,7 +9,6 @@ #include "../Include/Utils.h" #include "../../Api/Include/Object.h" #include "../FFI/Queue.h" -#include "DescriptorManager.h" namespace Coplt { diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index ff94034..89a7465 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -17,7 +17,7 @@ void D3d12GpuRecord::PipelineContext::Reset() Pipeline = nullptr; Layout = nullptr; GPipeline = nullptr; - // Binding = nullptr; + Binding = nullptr; PipelineChanged = false; BindingChanged = false; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 1b5f2c0..b7063e2 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -1,6 +1,9 @@ #pragma once +#include + #include "Barrier.h" +#include "Binding.h" #include "Context.h" #include "Isolate.h" #include "Layout.h" @@ -64,7 +67,7 @@ namespace Coplt // 如果不是图形管线将不会设置 Ptr GPipeline{}; - // Ptr Binding{}; + Ptr Binding{}; bool PipelineChanged{}; bool BindingChanged{}; @@ -126,7 +129,7 @@ namespace Coplt void Analyze_ComputeEnd(u32 i, const FCmdCompute& cmd); void Analyze_SetPipeline(u32 i, const FCmdSetPipeline& cmd); void Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd); - void Analyze_Dispatch( u32 i, const FCmdDispatch& cmd) const; + void Analyze_Dispatch(u32 i, const FCmdDispatch& cmd) const; void Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) override; void Interpret_Label(const CmdList& list, u32 i, const FCmdLabel& cmd) const; diff --git a/Coplt.Graphics.Native/D3d12/Src/Sampler.cc b/Coplt.Graphics.Native/D3d12/Src/Sampler.cc index f1df7aa..b95887f 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Sampler.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Sampler.cc @@ -24,3 +24,12 @@ NonNull D3d12GpuSampler::Desc() const noexcept { return &m_desc; } + +bool D3d12GpuSampler::IsCompatible(const FBindGroupItem& def) const +{ + if (def.View != FShaderLayoutItemView::Sampler) + return false; + if (def.Type != FShaderLayoutItemType::Sampler) + return false; + return true; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Sampler.h b/Coplt.Graphics.Native/D3d12/Src/Sampler.h index 3277a05..010c48c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Sampler.h +++ b/Coplt.Graphics.Native/D3d12/Src/Sampler.h @@ -5,10 +5,11 @@ #include "../../Api/Include/GpuObject.h" #include "../FFI/Sampler.h" #include "../Include/Sampler.h" +#include "../Include/View.h" namespace Coplt { - COPLT_INTERFACE_DEFINE(ID3d12GpuSampler, "0d342b3b-5960-4e5b-97c0-4028feab682e", FD3d12GpuSampler) + COPLT_INTERFACE_DEFINE(ID3d12GpuSampler, "0d342b3b-5960-4e5b-97c0-4028feab682e", FD3d12GpuSampler, ID3d12GpuViewable) { virtual NonNull Desc() const noexcept = 0; }; @@ -23,5 +24,7 @@ namespace Coplt FResult SetName(const FStr8or16& name) noexcept override; const FSamplerInfo* Info() const noexcept override; NonNull Desc() const noexcept override; + + bool IsCompatible(const FBindGroupItem& def) const override; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/View.cc b/Coplt.Graphics.Native/D3d12/Src/View.cc index 1f9c945..1e1e080 100644 --- a/Coplt.Graphics.Native/D3d12/Src/View.cc +++ b/Coplt.Graphics.Native/D3d12/Src/View.cc @@ -3,6 +3,13 @@ using namespace Coplt; +View& View::swap(View& other) noexcept +{ + std::swap(m_viewable, other.m_viewable); + std::swap(m_type, other.m_type); + return *this; +} + View::View(const FView& view) { if (view.Type != FViewType::None && view.Viewable) @@ -15,11 +22,30 @@ View::View(const FView& view) } } +View& View::operator=(const FView& view) +{ + return View(view).swap(*this); +} + View::operator bool() const { return m_viewable && m_type != FViewType::None; } +bool View::IsCompatible(const FBindGroupItem& def) const +{ + switch (m_type) + { + case FViewType::None: + break; + case FViewType::Buffer: + case FViewType::Image: + case FViewType::Sampler: + return m_viewable->IsCompatible(def); + } + return true; +} + // void View::CreateDescriptor( // NonNull device, const FShaderLayoutItemDefine& def, const CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView type // ) const From e891fee09e26f041261d69f369a2115b985b7cde Mon Sep 17 00:00:00 2001 From: U2A5F Date: Sat, 5 Apr 2025 16:34:12 +0800 Subject: [PATCH 33/46] save --- Coplt.Graphics.Core/Core/GpuDevice.cs | 26 +++- Coplt.Graphics.Core/Core/GpuIsolate.cs | 89 ++++++++++++- Coplt.Graphics.Core/Core/GpuRecord.cs | 119 +++++++++++++----- .../Core/GraphicsShaderPipeline.cs | 2 +- Coplt.Graphics.Core/Core/ShaderBindGroup.cs | 34 +++++ ...roupLayout.cs => ShaderBindGroupLayout.cs} | 4 +- Coplt.Graphics.Core/Core/ShaderBinding.cs | 27 ++-- ...indingLayout.cs => ShaderBindingLayout.cs} | 10 +- Coplt.Graphics.Core/Core/ShaderLayout.cs | 4 +- Coplt.Graphics.Core/Core/ShaderPipeline.cs | 6 +- Coplt.Graphics.Core/Native/Native.cs | 34 ++++- Coplt.Graphics.Native/Api/FFI/Binding.h | 12 +- Coplt.Graphics.Native/Api/FFI/Cmd.h | 1 + Coplt.Graphics.Native/Api/FFI/Device.h | 5 +- Coplt.Graphics.Native/D3d12/CMakeLists.txt | 2 +- Coplt.Graphics.Native/D3d12/FFI/Pipeline.h | 18 --- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 42 ++++++- Coplt.Graphics.Native/D3d12/Src/Binding.h | 12 +- .../D3d12/Src/DescriptorManager.cc | 8 +- .../D3d12/Src/DescriptorManager.h | 10 +- Coplt.Graphics.Native/D3d12/Src/Device.cc | 4 +- Coplt.Graphics.Native/D3d12/Src/Device.h | 4 +- .../D3d12/Src/GraphicsPipeline.cc | 9 +- .../D3d12/Src/GraphicsPipeline.h | 14 +-- Coplt.Graphics.Native/D3d12/Src/Pipeline.h | 19 +++ Coplt.Graphics.Native/D3d12/Src/Record.cc | 78 +++++++++--- Coplt.Graphics.Native/D3d12/Src/Record.h | 17 ++- Examples/Colorful/Example.cs | 15 +-- 28 files changed, 481 insertions(+), 144 deletions(-) create mode 100644 Coplt.Graphics.Core/Core/ShaderBindGroup.cs rename Coplt.Graphics.Core/Core/{BindGroupLayout.cs => ShaderBindGroupLayout.cs} (94%) rename Coplt.Graphics.Core/Core/{BindingLayout.cs => ShaderBindingLayout.cs} (65%) delete mode 100644 Coplt.Graphics.Native/D3d12/FFI/Pipeline.h create mode 100644 Coplt.Graphics.Native/D3d12/Src/Pipeline.h diff --git a/Coplt.Graphics.Core/Core/GpuDevice.cs b/Coplt.Graphics.Core/Core/GpuDevice.cs index fe38486..93c8519 100644 --- a/Coplt.Graphics.Core/Core/GpuDevice.cs +++ b/Coplt.Graphics.Core/Core/GpuDevice.cs @@ -127,7 +127,7 @@ public ShaderLayout GetEmptyShaderLayout(ShaderLayoutFlags Flags = ShaderLayoutF #region CreateBindGroupLayout - public BindGroupLayout CreateBindGroupLayout( + public ShaderBindGroupLayout CreateBindGroupLayout( ReadOnlySpan Items, ReadOnlySpan StaticSamplers = default, BindGroupUsage Usage = BindGroupUsage.Common, @@ -158,9 +158,9 @@ public BindGroupLayout CreateBindGroupLayout( #region CreateBindingLayout - public BindingLayout CreateBindingLayout( + public ShaderBindingLayout CreateBindingLayout( ShaderLayout ShaderLayout, - ReadOnlySpan GroupLayouts, + ReadOnlySpan GroupLayouts, string? Name = null, ReadOnlySpan Name8 = default ) { @@ -358,7 +358,7 @@ public GraphicsShaderPipeline CreateGraphicsShaderPipeline( ) => CreateGraphicsShaderPipeline(Shader, PipelineState, Shader.Layout.GetEmptyBindingLayout(), MeshLayout, Name, Name8); public GraphicsShaderPipeline CreateGraphicsShaderPipeline( - Shader Shader, GraphicsPipelineState PipelineState, BindingLayout BindingLayout, MeshLayout? MeshLayout = null, + Shader Shader, GraphicsPipelineState PipelineState, ShaderBindingLayout BindingLayout, MeshLayout? MeshLayout = null, string? Name = null, ReadOnlySpan Name8 = default ) { @@ -384,6 +384,24 @@ public GraphicsShaderPipeline CreateGraphicsShaderPipeline( #endregion + #region CreateBindGroup + + public ShaderBindGroup CreateBindGroup( + ShaderBindGroupLayout layout, ReadOnlySpan items, + string? Name = null, ReadOnlySpan Name8 = default + ) => MainIsolate.CreateBindGroup(layout, items, Name, Name8); + + #endregion + + #region CreateBinding + + public ShaderBinding CreateBinding( + ShaderBindingLayout layout, ReadOnlySpan items, + string? Name = null, ReadOnlySpan Name8 = default + ) => MainIsolate.CreateBinding(layout, items, Name, Name8); + + #endregion + #region CreateBuffer public GpuBuffer CreateBuffer( diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 0a7311d..39e19a4 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -278,7 +278,94 @@ public GpuSwapChain CreateSwapChainForHwnd(IntPtr Hwnd, in GpuSwapChainCreateOpt } #endregion - + + #region CreateBindGroup + + public ShaderBindGroup CreateBindGroup( + ShaderBindGroupLayout layout, ReadOnlySpan items, + string? Name = null, ReadOnlySpan Name8 = default + ) + { + var f_items = ArrayPool.Shared.Rent(items.Length); + try + { + for (var i = 0; i < items.Length; i++) + { + ref readonly var item = ref items[i]; + f_items[i] = new() + { + View = item.View.ToFFI(), + Slot = item.Slot, + Index = item.Index, + }; + } + fixed (char* p_name = Name) + fixed (byte* p_name8 = Name8) + fixed (FSetBindItem* p_items = f_items) + { + FShaderBindGroupCreateOptions f_options = new() + { + Name = new(Name, Name8, p_name, p_name8), + Layout = layout.Ptr, + InitBindings = p_items, + NumInitBindings = (uint)items.Length, + }; + FShaderBindGroup* ptr; + Device.Ptr->CreateShaderBindGroup(&f_options, &ptr).TryThrow(); + return new(ptr, Name, this, layout); + } + } + finally + { + ArrayPool.Shared.Return(f_items); + } + } + + #endregion + + #region CreateBinding + + public ShaderBinding CreateBinding( + ShaderBindingLayout layout, ReadOnlySpan items, + string? Name = null, ReadOnlySpan Name8 = default + ) + { + var f_items = ArrayPool.Shared.Rent(items.Length); + try + { + for (var i = 0; i < items.Length; i++) + { + ref readonly var item = ref items[i]; + f_items[i] = new() + { + BindGroup = item.Group.Ptr, + Index = item.Index, + }; + } + fixed (char* p_name = Name) + fixed (byte* p_name8 = Name8) + fixed (FSetBindGroupItem* p_items = f_items) + { + FShaderBindingCreateOptions f_options = new() + { + Name = new(Name, Name8, p_name, p_name8), + Layout = layout.Ptr, + InitBindGroups = p_items, + NumInitBindGroups = (uint)items.Length, + }; + FShaderBinding* ptr; + Device.Ptr->CreateShaderBinding(&f_options, &ptr).TryThrow(); + return new(ptr, Name, this, layout); + } + } + finally + { + ArrayPool.Shared.Return(f_items); + } + } + + #endregion + #region CreateBuffer public GpuBuffer CreateBuffer( diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 2d3ef41..43c87d9 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -771,6 +771,56 @@ public void Dispose() #endregion +#region PipelineContext + +internal unsafe struct PipelineContext +{ + internal ShaderPipeline? m_current_pipeline; + internal ShaderBinding? m_current_binding; + + #region SetPipeline + + public void SetPipeline(GpuRecord self, ShaderPipeline Pipeline) + { + m_current_pipeline = Pipeline; + self.AddObject(m_current_pipeline); + var cmd = new FCmdSetPipeline + { + Base = { Type = FCmdType.SetPipeline }, + Pipeline = Pipeline.Ptr, + }; + self.Data.Commands.Add(new() { SetPipeline = cmd }); + if (m_current_binding != null && m_current_binding.Layout != Pipeline.BindingLayout) m_current_binding = null; + } + + #endregion + + #region SetBinding + + public void SetBinding(GpuRecord self, ShaderBinding Binding) + { + Binding.AssertSameIsolate(self.Isolate); + if (m_current_binding == Binding) return; + if (m_current_pipeline != null) + { + if (Binding.Layout != m_current_pipeline.BindingLayout) + throw new InvalidOperationException("The binding layout is not compatible with the currently set pipeline"); + } + m_current_binding = Binding; + self.AddObject(m_current_binding); + var cmd = new FCmdSetBinding + { + Base = { Type = FCmdType.SetBinding }, + Binding = Binding.Ptr, + }; + self.Data.Commands.Add(new() { SetBinding = cmd }); + } + + #endregion +} + +#endregion + #region RenderScope public unsafe struct RenderScope2( @@ -783,9 +833,8 @@ uint debug_scope_count { #region Fields - internal ShaderPipeline? m_current_pipeline; + PipelineContext m_pipeline_context; internal bool m_disposed; - internal bool m_has_uav_writes; #endregion @@ -806,8 +855,6 @@ public void Dispose() throw new InvalidOperationException( "There is still Debug scope not ended, please check whether Dispose is missed." ); - ref var info = ref Info; - info.HasUavWrites = m_has_uav_writes; Cmd.CommandCount = (uint)self.m_data->Commands.LongLength - cmd_index; self.m_in_render_or_compute_scope = false; self.Data.Commands.Add(new() { Type = FCmdType.End }); @@ -841,17 +888,20 @@ public void Dispose() public void SetPipeline(ShaderPipeline Pipeline) { self.AssertNotEnded(); - if (m_current_pipeline == Pipeline) return; + if (m_pipeline_context.m_current_pipeline == Pipeline) return; if (!Pipeline.Shader.Stages.HasAnyFlags(ShaderStageFlags.Pixel)) throw new ArgumentException("Only shaders with a Pixel stage can be used for rendering"); - m_current_pipeline = Pipeline; - self.AddObject(m_current_pipeline); - var cmd = new FCmdSetPipeline - { - Base = { Type = FCmdType.SetPipeline }, - Pipeline = Pipeline.Ptr, - }; - self.Data.Commands.Add(new() { SetPipeline = cmd }); + m_pipeline_context.SetPipeline(self, Pipeline); + } + + #endregion + + #region SetBinding + + public void SetBinding(ShaderBinding Binding) + { + self.AssertNotEnded(); + m_pipeline_context.SetBinding(self, Binding); } #endregion @@ -1000,11 +1050,11 @@ public void Draw( } else { - if (m_current_pipeline == null) throw new InvalidOperationException("Pipeline is not set"); - if (!m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Vertex)) + if (m_pipeline_context.m_current_pipeline == null) throw new InvalidOperationException("Pipeline is not set"); + if (!m_pipeline_context.m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Vertex)) throw new ArgumentException("Only shaders with a vertex stage can use Draw"); } - // if (Binding != null) SetBinding(Binding); + if (Binding != null) SetBinding(Binding); var cmd = new FCmdDraw { Base = { Type = FCmdType.Draw }, @@ -1042,12 +1092,11 @@ public void DispatchMesh( } else { - if (m_current_pipeline == null) throw new InvalidOperationException("Pipeline is not set"); - if (!m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) + if (m_pipeline_context.m_current_pipeline == null) throw new InvalidOperationException("Pipeline is not set"); + if (!m_pipeline_context.m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) throw new ArgumentException("Only shaders with a mesh stage can use DispatchMesh"); } - // if (Binding != null) SetBinding(Binding); - // self.SyncBinding(ref m_context, this); + if (Binding != null) SetBinding(Binding); var cmd = new FCmdDispatch { Base = { Type = FCmdType.Dispatch }, @@ -1075,7 +1124,7 @@ uint debug_scope_count { #region Fields - internal ShaderPipeline? m_current_pipeline; + PipelineContext m_pipeline_context; internal bool m_disposed; #endregion @@ -1129,17 +1178,20 @@ public void Dispose() public void SetPipeline(ShaderPipeline Pipeline) { self.AssertNotEnded(); - if (m_current_pipeline == Pipeline) return; + if (m_pipeline_context.m_current_pipeline == Pipeline) return; if (!Pipeline.Shader.Stages.HasAnyFlags(ShaderStageFlags.Compute)) throw new ArgumentException("Only shaders with a Compute stage can be used for computing"); - m_current_pipeline = Pipeline; - self.AddObject(m_current_pipeline); - var cmd = new FCmdSetPipeline - { - Base = { Type = FCmdType.SetPipeline }, - Pipeline = Pipeline.Ptr, - }; - self.Data.Commands.Add(new() { SetPipeline = cmd }); + m_pipeline_context.SetPipeline(self, Pipeline); + } + + #endregion + + #region SetBinding + + public void SetBinding(ShaderBinding Binding) + { + self.AssertNotEnded(); + m_pipeline_context.SetBinding(self, Binding); } #endregion @@ -1166,12 +1218,11 @@ public void Dispatch( } else { - if (m_current_pipeline == null) throw new InvalidOperationException("Pipeline is not set"); - if (!m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Compute)) + if (m_pipeline_context.m_current_pipeline == null) throw new InvalidOperationException("Pipeline is not set"); + if (!m_pipeline_context.m_current_pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Compute)) throw new ArgumentException("Only shaders with a Compute stage can use Dispatch"); } - // if (Binding != null) SetBinding(Binding); - // self.SyncBinding(ref m_context, this); + if (Binding != null) SetBinding(Binding); var cmd = new FCmdDispatch { Base = { Type = FCmdType.Dispatch }, diff --git a/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs b/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs index d526ab5..f05c240 100644 --- a/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs +++ b/Coplt.Graphics.Core/Core/GraphicsShaderPipeline.cs @@ -24,7 +24,7 @@ public sealed unsafe class GraphicsShaderPipeline : ShaderPipeline internal GraphicsShaderPipeline( FGraphicsShaderPipeline* ptr, string? name, - Shader shader, GraphicsPipelineState pipeline_state, BindingLayout binding_layout, MeshLayout? mesh_layout + Shader shader, GraphicsPipelineState pipeline_state, ShaderBindingLayout binding_layout, MeshLayout? mesh_layout ) : base((FShaderPipeline*)ptr, name, shader, binding_layout) { m_mesh_layout = mesh_layout; diff --git a/Coplt.Graphics.Core/Core/ShaderBindGroup.cs b/Coplt.Graphics.Core/Core/ShaderBindGroup.cs new file mode 100644 index 0000000..b434a9a --- /dev/null +++ b/Coplt.Graphics.Core/Core/ShaderBindGroup.cs @@ -0,0 +1,34 @@ +using Coplt.Graphics.Native; + +namespace Coplt.Graphics.Core; + +/// 绑定槽的索引 +/// 如果绑定是数组的话,数组中的索引 +/// 绑定内容 +public record struct SetShaderBindItem(uint Slot, uint Index, View View) +{ + /// 绑定槽的索引 + /// 绑定内容 + public SetShaderBindItem(uint Slot, View View) : this(Slot, 0, View) { } +} + +public sealed unsafe class ShaderBindGroup : IsolateChild +{ + #region Props + + public new FShaderBindGroup* Ptr => (FShaderBindGroup*)base.Ptr; + public ShaderBindGroupLayout Layout { get; } + + #endregion + + #region Ctor + + internal ShaderBindGroup( + FShaderBindGroup* ptr, string? name, GpuIsolate isolate, ShaderBindGroupLayout layout + ) : base((FGpuObject*)ptr, name, isolate) + { + Layout = layout; + } + + #endregion +} diff --git a/Coplt.Graphics.Core/Core/BindGroupLayout.cs b/Coplt.Graphics.Core/Core/ShaderBindGroupLayout.cs similarity index 94% rename from Coplt.Graphics.Core/Core/BindGroupLayout.cs rename to Coplt.Graphics.Core/Core/ShaderBindGroupLayout.cs index 556f582..1825b79 100644 --- a/Coplt.Graphics.Core/Core/BindGroupLayout.cs +++ b/Coplt.Graphics.Core/Core/ShaderBindGroupLayout.cs @@ -120,7 +120,7 @@ static BindGroupItem() } [Dropping(Unmanaged = true)] -public sealed unsafe partial class BindGroupLayout : DeviceChild +public sealed unsafe partial class ShaderBindGroupLayout : DeviceChild { #region Fields @@ -140,7 +140,7 @@ public sealed unsafe partial class BindGroupLayout : DeviceChild #region Ctor - internal BindGroupLayout(FBindGroupLayoutCreateResult result, string? name, GpuDevice device) : base((FGpuObject*)result.Layout, name, device) + internal ShaderBindGroupLayout(FBindGroupLayoutCreateResult result, string? name, GpuDevice device) : base((FGpuObject*)result.Layout, name, device) { if (Ptr == null) return; m_data = result.Data; diff --git a/Coplt.Graphics.Core/Core/ShaderBinding.cs b/Coplt.Graphics.Core/Core/ShaderBinding.cs index 26b77de..88256aa 100644 --- a/Coplt.Graphics.Core/Core/ShaderBinding.cs +++ b/Coplt.Graphics.Core/Core/ShaderBinding.cs @@ -1,13 +1,26 @@ -using System.Buffers; -using Coplt.Dropping; -using Coplt.Graphics.Native; +using Coplt.Graphics.Native; namespace Coplt.Graphics.Core; -public record struct ShaderBindingSetItem(uint Index, View View); +public record struct SetShaderBindGroupItem(uint Index, ShaderBindGroup Group); -[Dropping(Unmanaged = true)] -public sealed unsafe partial class ShaderBinding +public sealed unsafe class ShaderBinding : IsolateChild { - + #region Props + + public new FShaderBinding* Ptr => (FShaderBinding*)base.Ptr; + public ShaderBindingLayout Layout { get; } + + #endregion + + #region Ctor + + internal ShaderBinding( + FShaderBinding* ptr, string? name, GpuIsolate isolate, ShaderBindingLayout layout + ) : base((FGpuObject*)ptr, name, isolate) + { + Layout = layout; + } + + #endregion } diff --git a/Coplt.Graphics.Core/Core/BindingLayout.cs b/Coplt.Graphics.Core/Core/ShaderBindingLayout.cs similarity index 65% rename from Coplt.Graphics.Core/Core/BindingLayout.cs rename to Coplt.Graphics.Core/Core/ShaderBindingLayout.cs index 9e293a5..5a111d3 100644 --- a/Coplt.Graphics.Core/Core/BindingLayout.cs +++ b/Coplt.Graphics.Core/Core/ShaderBindingLayout.cs @@ -4,12 +4,12 @@ namespace Coplt.Graphics.Core; -public sealed unsafe class BindingLayout : DeviceChild +public sealed unsafe class ShaderBindingLayout : DeviceChild { #region Fields internal readonly ShaderLayout m_shader_layout; - internal readonly BindGroupLayout[] m_bind_group_layouts; + internal readonly ShaderBindGroupLayout[] m_bind_group_layouts; #endregion @@ -17,15 +17,15 @@ public sealed unsafe class BindingLayout : DeviceChild public new FBindingLayout* Ptr => (FBindingLayout*)m_ptr; public ShaderLayout ShaderLayout => m_shader_layout; - public ReadOnlySpan BindGroupLayouts => m_bind_group_layouts; + public ReadOnlySpan BindGroupLayouts => m_bind_group_layouts; #endregion #region Ctor - internal BindingLayout( + internal ShaderBindingLayout( FBindingLayout* ptr, string? name, GpuDevice device, - ShaderLayout shader_layout, BindGroupLayout[] bind_group_layouts + ShaderLayout shader_layout, ShaderBindGroupLayout[] bind_group_layouts ) : base((FGpuObject*)ptr, name, device) { m_shader_layout = shader_layout; diff --git a/Coplt.Graphics.Core/Core/ShaderLayout.cs b/Coplt.Graphics.Core/Core/ShaderLayout.cs index 8c6ed45..6d8baf9 100644 --- a/Coplt.Graphics.Core/Core/ShaderLayout.cs +++ b/Coplt.Graphics.Core/Core/ShaderLayout.cs @@ -105,7 +105,7 @@ public sealed unsafe partial class ShaderLayout : DeviceChild #region Fields internal FShaderLayoutData* m_data; - internal BindingLayout? m_empty_binding_layout; + internal ShaderBindingLayout? m_empty_binding_layout; #endregion @@ -140,7 +140,7 @@ private void Drop() #region GetEmptyBindingLayout - public BindingLayout GetEmptyBindingLayout() => m_empty_binding_layout ??= Device.CreateBindingLayout(this, [], $"Empty Binding Layout of [{this}]"); + public ShaderBindingLayout GetEmptyBindingLayout() => m_empty_binding_layout ??= Device.CreateBindingLayout(this, [], $"Empty Binding Layout of [{this}]"); #endregion } diff --git a/Coplt.Graphics.Core/Core/ShaderPipeline.cs b/Coplt.Graphics.Core/Core/ShaderPipeline.cs index b13f78a..0840ed9 100644 --- a/Coplt.Graphics.Core/Core/ShaderPipeline.cs +++ b/Coplt.Graphics.Core/Core/ShaderPipeline.cs @@ -7,7 +7,7 @@ public abstract unsafe class ShaderPipeline : DeviceChild #region Fields internal readonly Shader m_shader; - internal readonly BindingLayout m_binding_layout; + internal readonly ShaderBindingLayout m_binding_layout; #endregion @@ -15,13 +15,13 @@ public abstract unsafe class ShaderPipeline : DeviceChild public new FShaderPipeline* Ptr => (FShaderPipeline*)m_ptr; public Shader Shader => m_shader; - public BindingLayout BindingLayout => m_binding_layout; + public ShaderBindingLayout BindingLayout => m_binding_layout; #endregion #region Ctor - internal ShaderPipeline(FShaderPipeline* ptr, string? name, Shader shader, BindingLayout binding_layout) : base((FGpuObject*)ptr, name, shader.Device) + internal ShaderPipeline(FShaderPipeline* ptr, string? name, Shader shader, ShaderBindingLayout binding_layout) : base((FGpuObject*)ptr, name, shader.Device) { m_shader = shader; m_binding_layout = binding_layout; diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 7c863df..f07a3b5 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1325,7 +1325,7 @@ public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FSh [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, FShaderBindGroup** @out) + public FResult CreateShaderBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, FShaderBindGroup** @out) { FResult result; return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); @@ -1333,7 +1333,7 @@ public FResult CreateBindGroup([NativeTypeName("const FShaderBindGroupCreateOpti [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) + public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) { FResult result; return *((delegate* unmanaged[Thiscall])(lpVtbl[20]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); @@ -1412,10 +1412,10 @@ public interface Interface : FGpuObject.Interface FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, [NativeTypeName("Coplt::FShaderCreateResult *")] FShaderCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, FShaderBindGroup** @out); + FResult CreateShaderBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, FShaderBindGroup** @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out); + FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out); [return: NativeTypeName("Coplt::FResult")] FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out); @@ -2968,11 +2968,14 @@ public unsafe partial struct FShaderCreateResult public FShaderData* Data; } - public partial struct FBindItem + public partial struct FSetBindItem { [NativeTypeName("Coplt::FView")] public FView View; + [NativeTypeName("Coplt::u32")] + public uint Slot; + [NativeTypeName("Coplt::u32")] public uint Index; } @@ -2984,6 +2987,12 @@ public unsafe partial struct FShaderBindGroupCreateOptions [NativeTypeName("Coplt::FBindGroupLayout *")] public FBindGroupLayout* Layout; + + [NativeTypeName("Coplt::FSetBindItem *")] + public FSetBindItem* InitBindings; + + [NativeTypeName("Coplt::u32")] + public uint NumInitBindings; } [Guid("AE54EFE5-C372-4291-B995-55298758D2B2")] @@ -3040,6 +3049,15 @@ public interface Interface : FGpuObject.Interface } } + public unsafe partial struct FSetBindGroupItem + { + [NativeTypeName("Coplt::FShaderBindGroup *")] + public FShaderBindGroup* BindGroup; + + [NativeTypeName("Coplt::u32")] + public uint Index; + } + public unsafe partial struct FShaderBindingCreateOptions { [NativeTypeName("Coplt::FStr8or16")] @@ -3047,6 +3065,12 @@ public unsafe partial struct FShaderBindingCreateOptions [NativeTypeName("Coplt::FBindingLayout *")] public FBindingLayout* Layout; + + [NativeTypeName("Coplt::FSetBindGroupItem *")] + public FSetBindGroupItem* InitBindGroups; + + [NativeTypeName("Coplt::u32")] + public uint NumInitBindGroups; } [Guid("A3CA644A-0E02-4D25-9A18-8835D66600F7")] diff --git a/Coplt.Graphics.Native/Api/FFI/Binding.h b/Coplt.Graphics.Native/Api/FFI/Binding.h index 52c9452..77daefd 100644 --- a/Coplt.Graphics.Native/Api/FFI/Binding.h +++ b/Coplt.Graphics.Native/Api/FFI/Binding.h @@ -6,7 +6,7 @@ namespace Coplt { - struct FBindItem + struct FSetBindItem { // 绑定内容 FView View{}; @@ -20,7 +20,7 @@ namespace Coplt { FStr8or16 Name{}; FBindGroupLayout* Layout{}; - FBindItem* InitBindings{}; + FSetBindItem* InitBindings{}; u32 NumInitBindings{}; }; @@ -28,11 +28,17 @@ namespace Coplt { }; + struct FSetBindGroupItem + { + FShaderBindGroup* BindGroup{}; + u32 Index{}; + }; + struct FShaderBindingCreateOptions { FStr8or16 Name{}; FBindingLayout* Layout{}; - FShaderBindGroup** InitBindGroups{}; + FSetBindGroupItem* InitBindGroups{}; u32 NumInitBindGroups{}; }; diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index 39b0712..c88daf8 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -1,5 +1,6 @@ #pragma once +#include "List.h" #include "Structs.h" #include "Output.h" #include "Binding.h" diff --git a/Coplt.Graphics.Native/Api/FFI/Device.h b/Coplt.Graphics.Native/Api/FFI/Device.h index d87aee2..a0e3306 100644 --- a/Coplt.Graphics.Native/Api/FFI/Device.h +++ b/Coplt.Graphics.Native/Api/FFI/Device.h @@ -91,8 +91,9 @@ namespace Coplt virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept = 0; virtual FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept = 0; - virtual FResult CreateBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept = 0; - virtual FResult CreateBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept = 0; + virtual FResult CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept = 0; + virtual FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept = 0; + virtual FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept = 0; virtual FResult CreateBuffer(const FGpuBufferCreateOptions& options, FGpuBuffer** out) noexcept = 0; diff --git a/Coplt.Graphics.Native/D3d12/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index 760b079..aea41f4 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -17,7 +17,6 @@ add_library(${target_name} SHARED Src/Output.cc Src/Output.h Include/GraphicsFormat.h - FFI/Pipeline.h Src/GraphicsPipeline.h Src/GraphicsPipeline.cc Src/Layout.h @@ -58,6 +57,7 @@ add_library(${target_name} SHARED Src/ResState.cc Src/DescriptorManager.h Src/DescriptorManager.cc + Src/Pipeline.h ) set_target_properties(${target_name} PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(${target_name} PROPERTIES OUTPUT_NAME "Coplt.Graphics.Native.D3d12") diff --git a/Coplt.Graphics.Native/D3d12/FFI/Pipeline.h b/Coplt.Graphics.Native/D3d12/FFI/Pipeline.h deleted file mode 100644 index 245cc0a..0000000 --- a/Coplt.Graphics.Native/D3d12/FFI/Pipeline.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "../../Api/FFI/Pipeline.h" - -namespace Coplt -{ - COPLT_INTERFACE_DEFINE(FD3d12PipelineState, "6d9c7db7-3261-4d79-bd21-1f1bb5e01e4d", FShaderPipeline) - { - // 返回 ID3D12PipelineState* - virtual void* GetPipelineStatePtr() noexcept = 0; - }; - - COPLT_INTERFACE_DEFINE( - FD3d12GraphicsShaderPipeline, "a1c6b8a9-1e4c-4e6c-85ea-2e64ac89afc6", FGraphicsShaderPipeline - ) - { - }; -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index 8b3ad7a..7161c5e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -39,7 +39,12 @@ FResult D3d12ShaderBindGroup::SetName(const FStr8or16& name) noexcept }); } -void D3d12ShaderBindGroup::Set(const std::span items) +const Rc& D3d12ShaderBindGroup::Layout() const noexcept +{ + return m_layout; +} + +void D3d12ShaderBindGroup::Set(const std::span items) { const auto defs = m_layout->GetItems(); for (const auto& item : items) @@ -78,10 +83,43 @@ void D3d12ShaderBindGroup::Set(const std::span items) D3d12ShaderBinding::D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options) : m_device(std::move(device)) { - // todo + const auto layout = NonNull(options.Layout)->QueryInterface(); + if (layout == nullptr) + COPLT_THROW("Layout from different backends"); + m_layout = Rc::UnsafeClone(layout); + const auto groups = m_layout->Groups(); + m_groups = std::vector(groups.size(), Rc{}); + Set(std::span(options.InitBindGroups, options.InitBindGroups + options.NumInitBindGroups)); } FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept { return FResult::None(); } + +const Rc& D3d12ShaderBinding::Layout() const noexcept +{ + return m_layout; +} + +void D3d12ShaderBinding::Set(const std::span items) +{ + const auto groups = m_layout->Groups(); + for (const auto& item : items) + { + if (item.Index >= groups.size()) + COPLT_THROW("Index out of range"); + if (item.BindGroup) + { + const auto bind_group = item.BindGroup->QueryInterface(); + if (bind_group == nullptr) + COPLT_THROW("BindGroup from different backends"); + m_groups[item.Index] = Rc::UnsafeClone(bind_group); + } + else + { + m_groups[item.Index] = nullptr; + } + m_changed_groups.Add(item.Index); + } +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index 0874a0f..d47b4bb 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -17,6 +17,7 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12ShaderBindGroup, "5bb948b9-ad31-4eb8-b881-98017e048259", FShaderBindGroup) { + virtual const Rc& Layout() const noexcept = 0; }; struct D3d12ShaderBindGroup final : GpuObject @@ -30,19 +31,28 @@ namespace Coplt explicit D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; - void Set(std::span items); + const Rc& Layout() const noexcept override; + + void Set(std::span items); }; COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "5073f785-cfb7-414d-9a84-1602d3bf378d", FShaderBinding) { + virtual const Rc& Layout() const noexcept = 0; }; struct D3d12ShaderBinding final : GpuObject { Rc m_device{}; + Rc m_layout{}; std::vector> m_groups{}; + HashSet m_changed_groups{}; explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; + + const Rc& Layout() const noexcept override; + + void Set(std::span items); }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc index 2ee10d1..a6ff74c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc @@ -55,17 +55,15 @@ DescriptorHeap::DescriptorHeap(NonNull device, D3D12_DESCRIPTOR_ } } -Rc DescriptorHeap::Allocate(const u32 size) +DescriptorAllocation DescriptorHeap::Allocate(const u32 size) { D3D12MA::VIRTUAL_ALLOCATION_DESC desc{}; desc.Alignment = 1; desc.Size = size; D3D12MA::VirtualAllocation allocation{}; u64 offset{}; - const auto hr = m_virtual_block->Allocate(&desc, &allocation, &offset); - // todo 处理不够的情况 - chr | hr; - return new DescriptorAllocation(*this, allocation, offset); + chr | m_virtual_block->Allocate(&desc, &allocation, &offset); + return DescriptorAllocation(*this, allocation, offset); } DescriptorManager::DescriptorManager(NonNull device) diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h index d917e17..cc84d1d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h @@ -13,7 +13,7 @@ namespace Coplt struct D3d12GpuDevice; struct DescriptorHeap; - struct DescriptorAllocation final : Object + struct DescriptorAllocation { Rc m_heap{}; u64 m_version{}; @@ -21,7 +21,7 @@ namespace Coplt u64 m_offset{}; explicit DescriptorAllocation(DescriptorHeap& heap, D3D12MA::VirtualAllocation allocation, u64 offset); - ~DescriptorAllocation() override; + ~DescriptorAllocation(); CD3DX12_CPU_DESCRIPTOR_HANDLE GetCpuHandle() const; CD3DX12_GPU_DESCRIPTOR_HANDLE GetGpuHandle() const; @@ -38,13 +38,13 @@ namespace Coplt explicit DescriptorHeap(NonNull device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 init_size); - Rc Allocate(u32 size); + DescriptorAllocation Allocate(u32 size); }; struct DescriptorManager final { - constexpr static u32 InitResHeapSize = 65536; - constexpr static u32 InitSmpHeapSize = 1024; + constexpr static u32 InitResHeapSize = 1024; + constexpr static u32 InitSmpHeapSize = 128; Rc m_res{}; Rc m_smp{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 3486c33..110e3be 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -300,7 +300,7 @@ FResult D3d12GpuDevice::CreateShader(const FShaderCreateOptions& options, FShade }); } -FResult D3d12GpuDevice::CreateBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept +FResult D3d12GpuDevice::CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept { return feb([&] { @@ -308,7 +308,7 @@ FResult D3d12GpuDevice::CreateBindGroup(const FShaderBindGroupCreateOptions& opt }); } -FResult D3d12GpuDevice::CreateBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept +FResult D3d12GpuDevice::CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept { return feb([&] { diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index de46a48..c0da1ed 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -70,8 +70,8 @@ namespace Coplt FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept override; FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept override; - FResult CreateBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept override; - FResult CreateBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; + FResult CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept override; + FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc index 720b8ef..67f6131 100644 --- a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc +++ b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc @@ -231,9 +231,14 @@ FResult D3d12GraphicsShaderPipeline::SetName(const FStr8or16& name) noexcept }); } -void* D3d12GraphicsShaderPipeline::GetPipelineStatePtr() noexcept +const Rc& D3d12GraphicsShaderPipeline::Layout() const noexcept { - return m_pipeline.Get(); + return m_layout; +} + +const ComPtr& D3d12GraphicsShaderPipeline::GetPipelineState() const noexcept +{ + return m_pipeline; } FShader* D3d12GraphicsShaderPipeline::GetShader() noexcept diff --git a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h index c805c5a..56d7d58 100644 --- a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h +++ b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h @@ -2,15 +2,14 @@ #include +#include "../../Api/Include/Object.h" #include "Device.h" #include "Layout.h" -#include "../../Api/Include/Object.h" -#include "../Include/Utils.h" -#include "../FFI/Pipeline.h" +#include "Pipeline.h" namespace Coplt { - struct D3d12GraphicsShaderPipeline final : GpuObject + struct D3d12GraphicsShaderPipeline final : GpuObject { Rc m_device{}; Rc m_shader{}; @@ -24,13 +23,12 @@ namespace Coplt std::vector m_input_slots{}; FGraphicsPipelineState m_graphics_state{}; - explicit D3d12GraphicsShaderPipeline( - Rc&& device, const FGraphicsShaderPipelineCreateOptions& options - ); + explicit D3d12GraphicsShaderPipeline(Rc&& device, const FGraphicsShaderPipelineCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; - void* GetPipelineStatePtr() noexcept override; + const Rc& Layout() const noexcept override; + const ComPtr& GetPipelineState() const noexcept override; FShader* GetShader() noexcept override; FBindingLayout* GetLayout() noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Pipeline.h b/Coplt.Graphics.Native/D3d12/Src/Pipeline.h new file mode 100644 index 0000000..b2b2c70 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Pipeline.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include "../../Api/FFI/Pipeline.h" +#include "../Include/Utils.h" + +namespace Coplt +{ + COPLT_INTERFACE_DEFINE(ID3d12ShaderPipeline, "c35a7e1e-278a-4655-bcab-eb3f7dff0124", FShaderPipeline) + { + virtual const Rc& Layout() const noexcept = 0; + virtual const ComPtr& GetPipelineState() const noexcept = 0; + }; + + COPLT_INTERFACE_DEFINE(ID3d12GraphicsShaderPipeline, "345aeb23-3dc9-4365-babc-dfc7badf4ff8", FGraphicsShaderPipeline) + { + }; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 89a7465..bd29709 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -2,13 +2,14 @@ #include -#include "../FFI/Pipeline.h" #include "../Include/GraphicsFormat.h" #include "../Include/PipelineState.h" #include "../Include/States.h" #include "Output.h" #include "Image.h" #include "Buffer.h" +#include "Pipeline.h" +#include "GraphicsPipeline.h" using namespace Coplt; @@ -24,27 +25,51 @@ void D3d12GpuRecord::PipelineContext::Reset() void D3d12GpuRecord::PipelineContext::SetPipeline(NonNull pipeline, u32 i) { - if (pipeline == Pipeline) return; - Pipeline = pipeline->QueryInterface(); - if (!Pipeline) + if (Pipeline && pipeline->ObjectId() == Pipeline->ObjectId()) return; + const auto dx_pipeline = pipeline->QueryInterface(); + if (!dx_pipeline) { COPLT_THROW_FMT( - "Pipeline({:#x}) comes from different backends at cmd {}", - static_cast(pipeline), i + "[{}] Pipeline({:#x}) from different backends", + i, static_cast(pipeline) ); } - Layout = pipeline->GetLayout()->QueryInterface(); - if (!Layout) - COPLT_THROW("Shader layout from different backends"); + Pipeline = Rc::UnsafeClone(dx_pipeline); + Layout = Pipeline->Layout(); const auto stages = pipeline->GetStages(); GPipeline = nullptr; if (HasFlags(stages, FShaderStageFlags::Pixel)) { - GPipeline = pipeline->QueryInterface(); - if (!GPipeline) - COPLT_THROW("Pipeline from different backends or pipeline not a graphics pipeline"); + const auto g_pipeline = pipeline->QueryInterface(); + if (!g_pipeline) + { + COPLT_THROW_FMT("[{}] Invalid pipeline: pipeline is not a graphics pipeline, but there is a pixel shader in the stages.", i); + } + GPipeline = Rc::UnsafeClone(g_pipeline); } PipelineChanged = true; + if (Binding && Binding->Layout()->ObjectId() != Layout->ObjectId()) + { + Binding = nullptr; + } +} + +void D3d12GpuRecord::PipelineContext::SetBinding(NonNull binding, u32 i) +{ + if (Binding && binding->ObjectId() == Binding->ObjectId()) return; + const auto dx_binding = binding->QueryInterface(); + if (!dx_binding) + { + COPLT_THROW_FMT( + "[{}] Binding({:#x}) from different backends", + i, static_cast(binding) + ); + } + if (Layout && dx_binding->Layout()->ObjectId() != Layout->ObjectId()) + { + COPLT_THROW_FMT("[{}] The binding layout is not compatible with the currently set pipeline", i); + } + Binding = Rc::UnsafeClone(dx_binding); } D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) @@ -226,7 +251,8 @@ void D3d12GpuRecord::Analyze() Analyze_SetPipeline(i, command.SetPipeline); break; case FCmdType::SetBinding: - COPLT_THROW("TODO"); + Analyze_SetBinding(i, command.SetBinding); + break; case FCmdType::SetMeshBuffers: Analyze_SetMeshBuffers(i, command.SetMeshBuffers); break; @@ -354,6 +380,14 @@ void D3d12GpuRecord::Analyze_SetPipeline(u32 i, const FCmdSetPipeline& cmd) SetPipeline(cmd.Pipeline, i); } +void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) +{ + if (m_state != RecordState::Render && m_state != RecordState::Compute) + COPLT_THROW_FMT("[{}] Cannot use SetBinding in main scope", i); + // todo + SetBinding(cmd.Binding, i); +} + void D3d12GpuRecord::Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd) { if (m_state != RecordState::Render) @@ -431,7 +465,8 @@ void D3d12GpuRecord::Interpret(const D3d12RentedCommandList& list, u32 offset, u Interpret_SetPipeline(list, i, command.SetPipeline); break; case FCmdType::SetBinding: - COPLT_THROW("TODO"); + Interpret_SetBinding(list, i, command.SetBinding); + break; case FCmdType::SetViewportScissor: Interpret_SetViewportScissor(list, i, command.SetViewportScissor); break; @@ -680,6 +715,11 @@ void D3d12GpuRecord::Interpret_SetPipeline(const CmdList& list, const u32 i, con SetPipeline(list, cmd.Pipeline, i); } +void D3d12GpuRecord::Interpret_SetBinding(const CmdList& list, u32 i, const FCmdSetBinding& cmd) +{ + // todo +} + void D3d12GpuRecord::Interpret_SetViewportScissor(const CmdList& list, u32 i, const FCmdSetViewportScissor& cmd) const { if (m_state != RecordState::Render) @@ -754,10 +794,16 @@ void D3d12GpuRecord::Interpret_Dispatch(const CmdList& list, u32 i, const FCmdDi void D3d12GpuRecord::SetPipeline(NonNull pipeline, u32 i) { - if (pipeline == m_pipeline_context.Pipeline) return; + if (m_pipeline_context.Pipeline && pipeline->ObjectId() == m_pipeline_context.Pipeline->ObjectId()) return; m_pipeline_context.SetPipeline(pipeline, i); } +void D3d12GpuRecord::SetBinding(NonNull binding, u32 i) +{ + if (m_pipeline_context.Binding && binding->ObjectId() == m_pipeline_context.Binding->ObjectId()) return; + m_pipeline_context.SetBinding(binding, i); +} + void D3d12GpuRecord::SetPipeline(const CmdList& list, NonNull pipeline, u32 i) { if (pipeline == m_pipeline_context.Pipeline) return; @@ -773,7 +819,7 @@ void D3d12GpuRecord::SetPipeline(const CmdList& list, NonNull p list->g0->IASetPrimitiveTopology(ToDx(states->Topology)); list->g0->SetGraphicsRootSignature(m_pipeline_context.Layout->RootSignature().Get()); } - list->g0->SetPipelineState(static_cast(m_pipeline_context.Pipeline->GetPipelineStatePtr())); + list->g0->SetPipelineState(m_pipeline_context.Pipeline->GetPipelineState().Get()); } D3D12_COMMAND_LIST_TYPE Coplt::GetType(const FGpuRecordMode Mode) diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index b7063e2..12baa4a 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -2,18 +2,16 @@ #include +#include "../../Api/Include/GpuObject.h" +#include "../../Api/FFI/Record.h" #include "Barrier.h" #include "Binding.h" #include "Context.h" #include "Isolate.h" #include "Layout.h" -#include "../../Api/FFI/Record.h" -#include "../../Api/Include/GpuObject.h" -#include "../FFI/Pipeline.h" namespace Coplt { - struct FD3d12PipelineState; COPLT_INTERFACE_DEFINE(ID3d12GpuRecord, "57a9c7f9-1ec0-4d78-89b9-e547667c50b3", FGpuRecord) { virtual FGpuRecordData* Data() noexcept = 0; @@ -37,6 +35,9 @@ namespace Coplt virtual void AfterSubmit() = 0; }; + struct ID3d12ShaderPipeline; + struct ID3d12GraphicsShaderPipeline; + struct D3d12GpuRecord final : GpuObject, FGpuRecordData { using CmdList = D3d12RentedCommandList; @@ -62,10 +63,10 @@ namespace Coplt struct PipelineContext { - Ptr Pipeline{}; + Ptr Pipeline{}; Ptr Layout{}; // 如果不是图形管线将不会设置 - Ptr GPipeline{}; + Ptr GPipeline{}; Ptr Binding{}; @@ -74,6 +75,7 @@ namespace Coplt void Reset(); void SetPipeline(NonNull pipeline, u32 i); + void SetBinding(NonNull binding, u32 i); }; u64 m_isolate_id{}; @@ -128,6 +130,7 @@ namespace Coplt void Analyze_Compute(u32 i, const FCmdCompute& cmd); void Analyze_ComputeEnd(u32 i, const FCmdCompute& cmd); void Analyze_SetPipeline(u32 i, const FCmdSetPipeline& cmd); + void Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd); void Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd); void Analyze_Dispatch(u32 i, const FCmdDispatch& cmd) const; @@ -143,12 +146,14 @@ namespace Coplt void Interpret_Compute(const CmdList& list, u32 i, const FCmdCompute& cmd); void Interpret_ComputeEnd(const CmdList& list, u32 i, const FCmdCompute& cmd); void Interpret_SetPipeline(const CmdList& list, u32 i, const FCmdSetPipeline& cmd); + void Interpret_SetBinding(const CmdList& list, u32 i, const FCmdSetBinding& cmd); void Interpret_SetViewportScissor(const CmdList& list, u32 i, const FCmdSetViewportScissor& cmd) const; void Interpret_SetMeshBuffers(const CmdList& list, u32 i, const FCmdSetMeshBuffers& cmd) const; void Interpret_Draw(const CmdList& list, u32 i, const FCmdDraw& cmd) const; void Interpret_Dispatch(const CmdList& list, u32 i, const FCmdDispatch& cmd) const; void SetPipeline(NonNull pipeline, u32 i); + void SetBinding(NonNull binding, u32 i); void SetPipeline(const CmdList& list, NonNull pipeline, u32 i); }; diff --git a/Examples/Colorful/Example.cs b/Examples/Colorful/Example.cs index 1f173c0..a8b6c6b 100644 --- a/Examples/Colorful/Example.cs +++ b/Examples/Colorful/Example.cs @@ -7,11 +7,13 @@ namespace Examples; public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handle, Width, Height) { private ShaderLayout ShaderLayout = null!; - private BindingLayout BindingLayout = null!; + private ShaderBindGroupLayout BindGroupLayout = null!; + private ShaderBindingLayout BindingLayout = null!; private Shader Shader = null!; private GraphicsShaderPipeline Pipeline = null!; - private ShaderBinding ShaderBinding = null!; private GpuBuffer ArgBuffer = null!; + private ShaderBindGroup BindGroup = null!; + private ShaderBinding Binding = null!; public override string Name => "Colorful"; protected override async Task LoadResources(GpuRecord cmd) @@ -31,7 +33,7 @@ protected override async Task LoadResources(GpuRecord cmd) ); BindingLayout = Device.CreateBindingLayout( ShaderLayout, [ - Device.CreateBindGroupLayout( + BindGroupLayout = Device.CreateBindGroupLayout( [ new() { @@ -45,7 +47,6 @@ protected override async Task LoadResources(GpuRecord cmd) ], Name: Name ); Shader = Device.CreateShader(modules, ShaderLayout); - // ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); Pipeline = Device.CreateGraphicsShaderPipeline( Shader, new() { @@ -70,13 +71,13 @@ protected override async Task LoadResources(GpuRecord cmd) }, Name: "Args" ); - // cmd.Bind(ShaderBinding, [new(0, ArgBuffer)]); + BindGroup = Device.CreateBindGroup(BindGroupLayout, [new(0, ArgBuffer)]); + Binding = Device.CreateBinding(BindingLayout, [new(0, BindGroup)]); } protected override void Render(GpuRecord cmd, Time time) { cmd.Upload(ArgBuffer, [(float)time.Total.TotalSeconds]); using var render = cmd.Render([new(Output, LoadOp.Discard)]); - // render.Draw(Pipeline, 4, Binding: ShaderBinding); - render.Draw(Pipeline, 4); + render.Draw(Pipeline, 4, Binding: Binding); } } From 086bba493916776cba4ba90fa9073efe3d04e05b Mon Sep 17 00:00:00 2001 From: U2A5F Date: Mon, 7 Apr 2025 17:34:13 +0800 Subject: [PATCH 34/46] save --- Coplt.Graphics.Core/Core/GpuDevice.cs | 38 ------- Coplt.Graphics.Core/Core/GpuIsolate.cs | 104 ++++++++++++------ Coplt.Graphics.Core/Core/GpuRecord.cs | 9 +- Coplt.Graphics.Core/Core/ShaderBindGroup.cs | 48 +++++++- Coplt.Graphics.Core/Core/ShaderBinding.cs | 34 +++++- .../Core/UnrecoverableException.cs | 9 ++ Coplt.Graphics.Core/Native/Native.cs | 67 ++++++++--- Coplt.Graphics.Native/Api/FFI/Binding.h | 19 +++- Coplt.Graphics.Native/Api/FFI/Cmd.h | 12 +- Coplt.Graphics.Native/Api/FFI/Device.h | 2 +- Coplt.Graphics.Native/Api/FFI/Record.h | 6 +- Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 6 +- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 7 +- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 41 ++++--- Coplt.Graphics.Native/D3d12/Src/Binding.h | 11 +- Coplt.Graphics.Native/D3d12/Src/Context.cc | 1 + Coplt.Graphics.Native/D3d12/Src/Context.h | 1 + .../D3d12/Src/DescriptorManager.h | 2 +- Coplt.Graphics.Native/D3d12/Src/Device.cc | 6 +- Coplt.Graphics.Native/D3d12/Src/Device.h | 2 +- Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 2 - Coplt.Graphics.Native/D3d12/Src/Isolate.h | 1 - Coplt.Graphics.Native/D3d12/Src/Record.cc | 36 ++++-- Coplt.Graphics.Native/D3d12/Src/Record.h | 9 +- Examples/Colorful/Example.cs | 6 +- Examples/ExampleBase/ExampleBase.cs | 2 + Examples/HelloTriangleVertex/Example.cs | 4 +- .../HelloTriangleVertex.md | 4 +- 28 files changed, 332 insertions(+), 157 deletions(-) create mode 100644 Coplt.Graphics.Core/Core/UnrecoverableException.cs diff --git a/Coplt.Graphics.Core/Core/GpuDevice.cs b/Coplt.Graphics.Core/Core/GpuDevice.cs index 93c8519..4802036 100644 --- a/Coplt.Graphics.Core/Core/GpuDevice.cs +++ b/Coplt.Graphics.Core/Core/GpuDevice.cs @@ -1,8 +1,6 @@ using System.Buffers; using System.Collections.Concurrent; -using System.Diagnostics; using System.Runtime.CompilerServices; -using System.Text; using Coplt.Dropping; using Coplt.Graphics.Native; using Coplt.Graphics.States; @@ -384,42 +382,6 @@ public GraphicsShaderPipeline CreateGraphicsShaderPipeline( #endregion - #region CreateBindGroup - - public ShaderBindGroup CreateBindGroup( - ShaderBindGroupLayout layout, ReadOnlySpan items, - string? Name = null, ReadOnlySpan Name8 = default - ) => MainIsolate.CreateBindGroup(layout, items, Name, Name8); - - #endregion - - #region CreateBinding - - public ShaderBinding CreateBinding( - ShaderBindingLayout layout, ReadOnlySpan items, - string? Name = null, ReadOnlySpan Name8 = default - ) => MainIsolate.CreateBinding(layout, items, Name, Name8); - - #endregion - - #region CreateBuffer - - public GpuBuffer CreateBuffer( - in GpuBufferCreateOptions options, - string? Name = null, ReadOnlySpan Name8 = default - ) => MainIsolate.CreateBuffer(in options, Name, Name8); - - #endregion - - #region CreateImage - - public GpuImage CreateImage( - in GpuImageCreateOptions options, - string? Name = null, ReadOnlySpan Name8 = default - ) => MainIsolate.CreateImage(in options, Name, Name8); - - #endregion - #region CreateSampler public Sampler CreateSampler( diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 39e19a4..50eae23 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -157,12 +157,19 @@ public void Submit(params ReadOnlySpan records) if ((p[i] = records[i].Ptr) == null) throw new NullReferenceException(); records[i].AssertEndOrCanEnd(); } - Ptr->Submit((uint)records.Length, p, o).TryThrow(); - for (var i = 0; i < records.Length; i++) + try + { + Ptr->Submit((uint)records.Length, p, o).TryThrow(); + for (var i = 0; i < records.Length; i++) + { + records[i].m_ptr = (FUnknown*)o[i].Record; + records[i].m_data = o[i].Data; + records[i].Reset(); + } + } + catch (Exception e) { - records[i].m_ptr = (FUnknown*)o[i].Record; - records[i].m_data = o[i].Data; - records[i].Reset(); + throw new UnrecoverableException(e); } } else @@ -179,12 +186,24 @@ public void Submit(params ReadOnlySpan records) fixed (IntPtr* p = arr) fixed (FGpuRecordCreateResult* o = @out) { - Ptr->Submit((uint)records.Length, (FGpuRecord**)p, o).TryThrow(); for (var i = 0; i < records.Length; i++) { - records[i].m_ptr = (FUnknown*)o[i].Record; - records[i].m_data = o[i].Data; - records[i].Reset(); + if ((p[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); + records[i].AssertEndOrCanEnd(); + } + try + { + Ptr->Submit((uint)records.Length, (FGpuRecord**)p, o).TryThrow(); + for (var i = 0; i < records.Length; i++) + { + records[i].m_ptr = (FUnknown*)o[i].Record; + records[i].m_data = o[i].Data; + records[i].Reset(); + } + } + catch (Exception e) + { + throw new UnrecoverableException(e); } } } @@ -209,13 +228,21 @@ public void SubmitReturn(params ReadOnlySpan records) for (var i = 0; i < records.Length; i++) { if ((p[i] = records[i].Ptr) == null) throw new NullReferenceException(); + records[i].AssertEndOrCanEnd(); } - Ptr->SubmitReturn((uint)records.Length, p).TryThrow(); - foreach (var a in records) + try + { + Ptr->SubmitReturn((uint)records.Length, p).TryThrow(); + foreach (var a in records) + { + a.m_ptr = null; + a.m_data = null; + a.Reset(); + } + } + catch (Exception e) { - a.m_ptr = null; - a.m_data = null; - a.Reset(); + throw new UnrecoverableException(e); } } else @@ -226,15 +253,23 @@ public void SubmitReturn(params ReadOnlySpan records) for (var i = 0; i < records.Length; i++) { if ((arr[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); + records[i].AssertEndOrCanEnd(); } fixed (IntPtr* p = arr) { - Ptr->SubmitReturn((uint)records.Length, (FGpuRecord**)p).TryThrow(); - foreach (var a in records) + try { - a.m_ptr = null; - a.m_data = null; - a.Reset(); + Ptr->SubmitReturn((uint)records.Length, (FGpuRecord**)p).TryThrow(); + foreach (var a in records) + { + a.m_ptr = null; + a.m_data = null; + a.Reset(); + } + } + catch (Exception e) + { + throw new UnrecoverableException(e); } } } @@ -307,12 +342,12 @@ public ShaderBindGroup CreateBindGroup( { Name = new(Name, Name8, p_name, p_name8), Layout = layout.Ptr, - InitBindings = p_items, - NumInitBindings = (uint)items.Length, + Bindings = p_items, + NumBindings = (uint)items.Length, }; - FShaderBindGroup* ptr; - Device.Ptr->CreateShaderBindGroup(&f_options, &ptr).TryThrow(); - return new(ptr, Name, this, layout); + FShaderBindGroupCreateResult result; + Device.Ptr->CreateShaderBindGroup(&f_options, &result).TryThrow(); + return new(result, Name, this, layout, items); } } finally @@ -330,37 +365,36 @@ public ShaderBinding CreateBinding( string? Name = null, ReadOnlySpan Name8 = default ) { - var f_items = ArrayPool.Shared.Rent(items.Length); + if (items.Length != layout.BindGroupLayouts.Length) + throw new ArgumentException( + $"The number of binding groups provided does not meet the required number; Provided({items.Length}) != Required({layout.BindGroupLayouts.Length})" + ); + var f_items = ArrayPool.Shared.Rent(items.Length); try { for (var i = 0; i < items.Length; i++) { ref readonly var item = ref items[i]; - f_items[i] = new() - { - BindGroup = item.Group.Ptr, - Index = item.Index, - }; + f_items[i] = (IntPtr)item.Group.Ptr; } fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) - fixed (FSetBindGroupItem* p_items = f_items) + fixed (IntPtr* p_items = f_items) { FShaderBindingCreateOptions f_options = new() { Name = new(Name, Name8, p_name, p_name8), Layout = layout.Ptr, - InitBindGroups = p_items, - NumInitBindGroups = (uint)items.Length, + BindGroups = (FShaderBindGroup**)p_items, }; FShaderBinding* ptr; Device.Ptr->CreateShaderBinding(&f_options, &ptr).TryThrow(); - return new(ptr, Name, this, layout); + return new(ptr, Name, this, layout, items); } } finally { - ArrayPool.Shared.Return(f_items); + ArrayPool.Shared.Return(f_items); } } diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 43c87d9..9c8b554 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -811,8 +811,15 @@ public void SetBinding(GpuRecord self, ShaderBinding Binding) var cmd = new FCmdSetBinding { Base = { Type = FCmdType.SetBinding }, - Binding = Binding.Ptr, + Binding = (uint)self.Data.Bindings.LongLength, + Index = self.Data.NumSetBindings++, }; + self.Data.Bindings.Add( + new() + { + Binding = Binding.Ptr + } + ); self.Data.Commands.Add(new() { SetBinding = cmd }); } diff --git a/Coplt.Graphics.Core/Core/ShaderBindGroup.cs b/Coplt.Graphics.Core/Core/ShaderBindGroup.cs index b434a9a..0918f96 100644 --- a/Coplt.Graphics.Core/Core/ShaderBindGroup.cs +++ b/Coplt.Graphics.Core/Core/ShaderBindGroup.cs @@ -1,4 +1,5 @@ -using Coplt.Graphics.Native; +using Coplt.Dropping; +using Coplt.Graphics.Native; namespace Coplt.Graphics.Core; @@ -12,11 +13,22 @@ public record struct SetShaderBindItem(uint Slot, uint Index, View View) public SetShaderBindItem(uint Slot, View View) : this(Slot, 0, View) { } } -public sealed unsafe class ShaderBindGroup : IsolateChild +[Dropping(Unmanaged = true)] +public sealed unsafe partial class ShaderBindGroup : IsolateChild { + #region Fields + + internal FShaderBindGroupData* m_data; + internal View[] m_views; + + #endregion + #region Props public new FShaderBindGroup* Ptr => (FShaderBindGroup*)base.Ptr; + public ref readonly FShaderBindGroupData Data => ref *m_data; + public ReadOnlySpan Views => m_views; + public ReadOnlySpan ItemIndexes => new(m_data->ItemIndexes, (int)m_data->NumItemIndexes); public ShaderBindGroupLayout Layout { get; } #endregion @@ -24,10 +36,38 @@ public sealed unsafe class ShaderBindGroup : IsolateChild #region Ctor internal ShaderBindGroup( - FShaderBindGroup* ptr, string? name, GpuIsolate isolate, ShaderBindGroupLayout layout - ) : base((FGpuObject*)ptr, name, isolate) + FShaderBindGroupCreateResult result, string? name, GpuIsolate isolate, ShaderBindGroupLayout layout, ReadOnlySpan items + ) : base((FGpuObject*)result.BindGroup, name, isolate) { + m_data = result.Data; Layout = layout; + m_views = new View[Data.CountSlots]; + Set(items); + } + + private void Set(ReadOnlySpan items) + { + var defs = Layout.Items; + var item_indexes = ItemIndexes; + foreach (ref readonly var item in items) + { + if (item.Slot >= defs.Length) throw new IndexOutOfRangeException(); + ref readonly var def = ref defs[(int)item.Slot]; + if (item.Index >= def.Count) throw new IndexOutOfRangeException(); + ref var slot = ref m_views[item_indexes[(int)item.Slot] + item.Index]; + slot = item.View; + } + } + + #endregion + + #region Drop + + [Drop] + private void Drop() + { + m_data = null; + m_views = null!; } #endregion diff --git a/Coplt.Graphics.Core/Core/ShaderBinding.cs b/Coplt.Graphics.Core/Core/ShaderBinding.cs index 88256aa..9ab6df4 100644 --- a/Coplt.Graphics.Core/Core/ShaderBinding.cs +++ b/Coplt.Graphics.Core/Core/ShaderBinding.cs @@ -1,11 +1,19 @@ -using Coplt.Graphics.Native; +using Coplt.Dropping; +using Coplt.Graphics.Native; namespace Coplt.Graphics.Core; public record struct SetShaderBindGroupItem(uint Index, ShaderBindGroup Group); -public sealed unsafe class ShaderBinding : IsolateChild +[Dropping(Unmanaged = true)] +public sealed unsafe partial class ShaderBinding : IsolateChild { + #region Fields + + internal ShaderBindGroup[] m_groups; + + #endregion + #region Props public new FShaderBinding* Ptr => (FShaderBinding*)base.Ptr; @@ -16,10 +24,30 @@ public sealed unsafe class ShaderBinding : IsolateChild #region Ctor internal ShaderBinding( - FShaderBinding* ptr, string? name, GpuIsolate isolate, ShaderBindingLayout layout + FShaderBinding* ptr, string? name, GpuIsolate isolate, ShaderBindingLayout layout, ReadOnlySpan items ) : base((FGpuObject*)ptr, name, isolate) { Layout = layout; + m_groups = new ShaderBindGroup[layout.BindGroupLayouts.Length]; + Set(items); + } + + private void Set(ReadOnlySpan items) + { + foreach (var item in items) + { + m_groups[item.Index] = item.Group; + } + } + + #endregion + + #region Drop + + [Drop] + private void Drop() + { + m_groups = null!; } #endregion diff --git a/Coplt.Graphics.Core/Core/UnrecoverableException.cs b/Coplt.Graphics.Core/Core/UnrecoverableException.cs new file mode 100644 index 0000000..8be5a5c --- /dev/null +++ b/Coplt.Graphics.Core/Core/UnrecoverableException.cs @@ -0,0 +1,9 @@ +namespace Coplt.Graphics.Core; + +public class UnrecoverableException : Exception +{ + public UnrecoverableException() { } + public UnrecoverableException(string message) : base(message) { } + public UnrecoverableException(string message, Exception inner) : base(message, inner) { } + public UnrecoverableException(Exception inner) : base("The memory state is corrupted and continuing execution may result in undefined behavior", inner) { } +} diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index f07a3b5..2089dfa 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1325,10 +1325,10 @@ public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FSh [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, FShaderBindGroup** @out) + public FResult CreateShaderBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, [NativeTypeName("Coplt::FShaderBindGroupCreateResult *")] FShaderBindGroupCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[19]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1412,7 +1412,7 @@ public interface Interface : FGpuObject.Interface FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, [NativeTypeName("Coplt::FShaderCreateResult *")] FShaderCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, FShaderBindGroup** @out); + FResult CreateShaderBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, [NativeTypeName("Coplt::FShaderBindGroupCreateResult *")] FShaderBindGroupCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out); @@ -1720,6 +1720,8 @@ public unsafe partial struct FGpuRecordData public FList Resources; + public FList Bindings; + public FList PayloadRect; public FList PayloadViewport; @@ -1737,6 +1739,9 @@ public unsafe partial struct FGpuRecordData [NativeTypeName("FList")] public FList Blob; + [NativeTypeName("Coplt::u32")] + public uint NumSetBindings; + [NativeTypeName("Coplt::b8")] public B8 Ended; @@ -1776,7 +1781,7 @@ public enum FCmdResType : byte public unsafe partial struct FCmdRes { - [NativeTypeName("__AnonymousRecord_Cmd_L69_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L70_C9")] public _Anonymous_e__Union Anonymous; [NativeTypeName("Coplt::FCmdResType")] @@ -2160,13 +2165,22 @@ public unsafe partial struct FCmdSetPipeline public FShaderPipeline* Pipeline; } + public unsafe partial struct FCmdBinding + { + [NativeTypeName("Coplt::FShaderBinding *")] + public FShaderBinding* Binding; + } + [NativeTypeName("struct FCmdSetBinding : Coplt::FCmdBase")] - public unsafe partial struct FCmdSetBinding + public partial struct FCmdSetBinding { public FCmdBase Base; - [NativeTypeName("Coplt::FShaderBinding *")] - public FShaderBinding* Binding; + [NativeTypeName("Coplt::u32")] + public uint Binding; + + [NativeTypeName("Coplt::u32")] + public uint Index; } [NativeTypeName("struct FCmdSetViewportScissor : Coplt::FCmdBase")] @@ -2282,7 +2296,7 @@ public partial struct FCmdDispatch public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L361_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L370_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -2989,10 +3003,22 @@ public unsafe partial struct FShaderBindGroupCreateOptions public FBindGroupLayout* Layout; [NativeTypeName("Coplt::FSetBindItem *")] - public FSetBindItem* InitBindings; + public FSetBindItem* Bindings; [NativeTypeName("Coplt::u32")] - public uint NumInitBindings; + public uint NumBindings; + } + + public unsafe partial struct FShaderBindGroupData + { + [NativeTypeName("Coplt::u32 *")] + public uint* ItemIndexes; + + [NativeTypeName("Coplt::u32")] + public uint NumItemIndexes; + + [NativeTypeName("Coplt::u32")] + public uint CountSlots; } [Guid("AE54EFE5-C372-4291-B995-55298758D2B2")] @@ -3044,18 +3070,27 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderBindGroup*)Unsafe.AsPointer(ref this), &result, name); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderBindGroupData *")] + public FShaderBindGroupData* ShaderBindGroupData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderBindGroup*)Unsafe.AsPointer(ref this)); + } + public interface Interface : FGpuObject.Interface { + [return: NativeTypeName("Coplt::FShaderBindGroupData *")] + FShaderBindGroupData* ShaderBindGroupData(); } } - public unsafe partial struct FSetBindGroupItem + public unsafe partial struct FShaderBindGroupCreateResult { [NativeTypeName("Coplt::FShaderBindGroup *")] public FShaderBindGroup* BindGroup; - [NativeTypeName("Coplt::u32")] - public uint Index; + [NativeTypeName("Coplt::FShaderBindGroupData *")] + public FShaderBindGroupData* Data; } public unsafe partial struct FShaderBindingCreateOptions @@ -3066,11 +3101,7 @@ public unsafe partial struct FShaderBindingCreateOptions [NativeTypeName("Coplt::FBindingLayout *")] public FBindingLayout* Layout; - [NativeTypeName("Coplt::FSetBindGroupItem *")] - public FSetBindGroupItem* InitBindGroups; - - [NativeTypeName("Coplt::u32")] - public uint NumInitBindGroups; + public FShaderBindGroup** BindGroups; } [Guid("A3CA644A-0E02-4D25-9A18-8835D66600F7")] diff --git a/Coplt.Graphics.Native/Api/FFI/Binding.h b/Coplt.Graphics.Native/Api/FFI/Binding.h index 77daefd..796f0e8 100644 --- a/Coplt.Graphics.Native/Api/FFI/Binding.h +++ b/Coplt.Graphics.Native/Api/FFI/Binding.h @@ -20,26 +20,33 @@ namespace Coplt { FStr8or16 Name{}; FBindGroupLayout* Layout{}; - FSetBindItem* InitBindings{}; - u32 NumInitBindings{}; + FSetBindItem* Bindings{}; + u32 NumBindings{}; + }; + + struct FShaderBindGroupData + { + u32* ItemIndexes{}; + u32 NumItemIndexes{}; + u32 CountSlots{}; }; COPLT_INTERFACE_DEFINE(FShaderBindGroup, "ae54efe5-c372-4291-b995-55298758d2b2", FGpuObject) { + virtual FShaderBindGroupData* ShaderBindGroupData() noexcept = 0; }; - struct FSetBindGroupItem + struct FShaderBindGroupCreateResult { FShaderBindGroup* BindGroup{}; - u32 Index{}; + FShaderBindGroupData* Data{}; }; struct FShaderBindingCreateOptions { FStr8or16 Name{}; FBindingLayout* Layout{}; - FSetBindGroupItem* InitBindGroups{}; - u32 NumInitBindGroups{}; + FShaderBindGroup** BindGroups{}; }; COPLT_INTERFACE_DEFINE(FShaderBinding, "a3ca644a-0e02-4d25-9a18-8835d66600f7", FGpuObject) diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index c88daf8..8e8e8a1 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -268,7 +268,7 @@ namespace Coplt struct FCmdRender : FCmdBase { - // 类型为 FRenderInfo + // 类型为 FRenderInfo2 u32 InfoIndex{}; u32 CommandCount{}; }; @@ -283,11 +283,19 @@ namespace Coplt FShaderPipeline* Pipeline{}; }; - struct FCmdSetBinding : FCmdBase + struct FCmdBinding { FShaderBinding* Binding{}; }; + struct FCmdSetBinding : FCmdBase + { + // Payload 中的索引,类型为 FCmdBinding + u32 Binding{}; + // 第几个 Set + u32 Index{}; + }; + //////////////////////////////////////////////////////////////////////////////////////////////////// struct FCmdSetViewportScissor : FCmdBase diff --git a/Coplt.Graphics.Native/Api/FFI/Device.h b/Coplt.Graphics.Native/Api/FFI/Device.h index a0e3306..15300a0 100644 --- a/Coplt.Graphics.Native/Api/FFI/Device.h +++ b/Coplt.Graphics.Native/Api/FFI/Device.h @@ -91,7 +91,7 @@ namespace Coplt virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept = 0; virtual FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept = 0; - virtual FResult CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept = 0; + virtual FResult CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroupCreateResult* out) noexcept = 0; virtual FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept = 0; virtual FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept = 0; diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index d6ead62..00a5db4 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -32,6 +32,7 @@ namespace Coplt FList Commands; // 需要保证不重复,c# 部分需要使用 HashMap 去重 FList Resources; + FList Bindings; FList PayloadRect; FList PayloadViewport; FList PayloadRenderInfo; @@ -40,12 +41,13 @@ namespace Coplt FList PayloadMeshBuffers; FList PayloadVertexBufferRange; FList Blob; + u32 NumSetBindings{}; b8 Ended{}; FGpuRecordMode Mode{}; #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) - : Commands(allocator), Resources(allocator), PayloadRect(allocator), PayloadViewport(allocator), + : Commands(allocator), Resources(allocator), Bindings(allocator), PayloadRect(allocator), PayloadViewport(allocator), PayloadRenderInfo(allocator), PayloadResolveInfo(allocator), PayloadBufferCopyRange(allocator), PayloadMeshBuffers(allocator), PayloadVertexBufferRange(allocator), Blob(allocator) { @@ -55,6 +57,7 @@ namespace Coplt { Commands.Clear(); Resources.Clear(); + Bindings.Clear(); PayloadRect.Clear(); PayloadViewport.Clear(); PayloadRenderInfo.Clear(); @@ -63,6 +66,7 @@ namespace Coplt PayloadMeshBuffers.Clear(); PayloadVertexBufferRange.Clear(); Blob.Clear(); + NumSetBindings = 0; } #endif }; diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index a0be04e..c47f9d4 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -173,7 +173,11 @@ namespace Coplt::Enhanced return; } - void EnhancedBarrierAnalyzer::OnUse(FCmdResRef ResRef) + void EnhancedBarrierAnalyzer::OnUse(const View& View) + { + } + + void EnhancedBarrierAnalyzer::UpdateUse(FCmdResRef ResRef) { const auto ResIndex = ResRef.ResIndex(); auto& info = m_resources[ResIndex]; diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index af50f98..0c13c4e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -6,6 +6,7 @@ #include "../../Api/Include/Object.h" #include "../../Api/FFI/Cmd.h" #include "../Include/ResState.h" +#include "../Include/View.h" namespace Coplt { @@ -35,7 +36,8 @@ namespace Coplt virtual void EndAnalyze() = 0; virtual void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) = 0; - virtual void OnUse(FCmdResRef ResRef) = 0; + virtual void OnUse(const View& View) = 0; + virtual void UpdateUse(FCmdResRef ResRef) = 0; virtual void OnCmd() = 0; // 每个命令都需要调用一次 virtual void CmdNext() = 0; @@ -162,7 +164,8 @@ namespace Coplt void StartAnalyze(std::span resources) override; void EndAnalyze() override; void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) override; - void OnUse(FCmdResRef ResRef) override; + void OnUse(const View& View) override; + void UpdateUse(FCmdResRef ResRef) override; void OnCmd() override; void CmdNext() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index 7161c5e..b677d7f 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -17,6 +17,7 @@ D3d12ShaderBindGroup::D3d12ShaderBindGroup(Rc&& device, const FS { sum_count += std::max(1u, item.Count); } + CountSlots = sum_count; m_views = std::vector(sum_count, View{}); m_item_indexes.reserve(items.size()); for (u32 i = 0, off = 0; i < items.size(); ++i) @@ -24,7 +25,9 @@ D3d12ShaderBindGroup::D3d12ShaderBindGroup(Rc&& device, const FS m_item_indexes.push_back(off); off += std::max(1u, items[i].Count); } - Set(std::span(options.InitBindings, options.InitBindings + options.NumInitBindings)); + ItemIndexes = m_item_indexes.data(); + NumItemIndexes = static_cast(m_item_indexes.size()); + Set(std::span(options.Bindings, options.Bindings + options.NumBindings)); if (!options.Name.is_null()) { m_name = options.Name.ToString(); @@ -39,11 +42,21 @@ FResult D3d12ShaderBindGroup::SetName(const FStr8or16& name) noexcept }); } +FShaderBindGroupData* D3d12ShaderBindGroup::ShaderBindGroupData() noexcept +{ + return this; +} + const Rc& D3d12ShaderBindGroup::Layout() const noexcept { return m_layout; } +const std::span D3d12ShaderBindGroup::Views() const noexcept +{ + return m_views; +} + void D3d12ShaderBindGroup::Set(const std::span items) { const auto defs = m_layout->GetItems(); @@ -89,7 +102,7 @@ D3d12ShaderBinding::D3d12ShaderBinding(Rc&& device, const FShade m_layout = Rc::UnsafeClone(layout); const auto groups = m_layout->Groups(); m_groups = std::vector(groups.size(), Rc{}); - Set(std::span(options.InitBindGroups, options.InitBindGroups + options.NumInitBindGroups)); + Set(std::span(options.BindGroups, options.BindGroups + m_groups.size())); } FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept @@ -102,24 +115,22 @@ const Rc& D3d12ShaderBinding::Layout() const noexcept return m_layout; } -void D3d12ShaderBinding::Set(const std::span items) +const std::span> D3d12ShaderBinding::Groups() const noexcept { - const auto groups = m_layout->Groups(); - for (const auto& item : items) + return m_groups; +} + +void D3d12ShaderBinding::Set(const std::span items) +{ + for (usize i = 0; i < m_groups.size(); ++i) { - if (item.Index >= groups.size()) - COPLT_THROW("Index out of range"); - if (item.BindGroup) + const auto item = items[i]; + if (item) { - const auto bind_group = item.BindGroup->QueryInterface(); + const auto bind_group = item->QueryInterface(); if (bind_group == nullptr) COPLT_THROW("BindGroup from different backends"); - m_groups[item.Index] = Rc::UnsafeClone(bind_group); - } - else - { - m_groups[item.Index] = nullptr; + m_groups[i] = Rc::UnsafeClone(bind_group); } - m_changed_groups.Add(item.Index); } } diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index d47b4bb..b819a01 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -18,9 +18,10 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12ShaderBindGroup, "5bb948b9-ad31-4eb8-b881-98017e048259", FShaderBindGroup) { virtual const Rc& Layout() const noexcept = 0; + virtual const std::span Views() const noexcept = 0; }; - struct D3d12ShaderBindGroup final : GpuObject + struct D3d12ShaderBindGroup final : GpuObject, FShaderBindGroupData { Rc m_name{}; Rc m_device{}; @@ -31,7 +32,10 @@ namespace Coplt explicit D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; + FShaderBindGroupData* ShaderBindGroupData() noexcept override; + const Rc& Layout() const noexcept override; + const std::span Views() const noexcept override; void Set(std::span items); }; @@ -39,6 +43,7 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "5073f785-cfb7-414d-9a84-1602d3bf378d", FShaderBinding) { virtual const Rc& Layout() const noexcept = 0; + virtual const std::span> Groups() const noexcept = 0; }; struct D3d12ShaderBinding final : GpuObject @@ -46,13 +51,13 @@ namespace Coplt Rc m_device{}; Rc m_layout{}; std::vector> m_groups{}; - HashSet m_changed_groups{}; explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; const Rc& Layout() const noexcept override; + const std::span> Groups() const noexcept override; - void Set(std::span items); + void Set(std::span items); }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.cc b/Coplt.Graphics.Native/D3d12/Src/Context.cc index 8029ca8..abb11df 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Context.cc @@ -5,6 +5,7 @@ using namespace Coplt; D3d12RecordContext::D3d12RecordContext(NonNull isolate) { m_device = isolate->m_device; + m_descriptor_manager = DescriptorManager(m_device.get()); m_cmd_alloc_pool = isolate->m_cmd_alloc_pool; m_upload_buffer = FList(m_device->m_instance->m_allocator.get()); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Context.h b/Coplt.Graphics.Native/D3d12/Src/Context.h index 5657bd6..f02ea63 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.h +++ b/Coplt.Graphics.Native/D3d12/Src/Context.h @@ -20,6 +20,7 @@ namespace Coplt constexpr static u64 InitUploadBufferSize = 1024 * 1024; Rc m_device{}; + DescriptorManager m_descriptor_manager{}; Rc m_cmd_alloc_pool{}; std::vector m_recycled_command_allocators{}; std::vector m_upload_buffers{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h index cc84d1d..309a626 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h @@ -44,7 +44,7 @@ namespace Coplt struct DescriptorManager final { constexpr static u32 InitResHeapSize = 1024; - constexpr static u32 InitSmpHeapSize = 128; + constexpr static u32 InitSmpHeapSize = 64; Rc m_res{}; Rc m_smp{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 110e3be..5a1fb68 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -300,11 +300,13 @@ FResult D3d12GpuDevice::CreateShader(const FShaderCreateOptions& options, FShade }); } -FResult D3d12GpuDevice::CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept +FResult D3d12GpuDevice::CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroupCreateResult* out) noexcept { return feb([&] { - *out = new D3d12ShaderBindGroup(this->CloneThis(), options); + const auto ptr = new D3d12ShaderBindGroup(this->CloneThis(), options); + out->BindGroup = ptr; + out->Data = ptr; }); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index c0da1ed..fe4bd33 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -70,7 +70,7 @@ namespace Coplt FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept override; FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept override; - FResult CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroup** out) noexcept override; + FResult CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroupCreateResult* out) noexcept override; FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index e8f6257..3c83567 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -17,8 +17,6 @@ D3d12GpuIsolate::D3d12GpuIsolate(Rc device, const FGpuIsolateCre m_record_pool = box(); m_device = std::move(device); - m_descriptor_manager = DescriptorManager(m_device.get()); - #pragma region 创建队列 m_main_queue = new D3d12GpuQueue2(this, FGpuQueueType::Direct); diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index 1417665..6dde66c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -29,7 +29,6 @@ namespace Coplt using RecordQueue = moodycamel::ConcurrentQueue>; SRc m_config{}; - DescriptorManager m_descriptor_manager{}; Rc m_main_queue{}; Rc m_compute_queue{}; Rc m_copy_queue{}; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index bd29709..c45b1af 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -26,7 +26,7 @@ void D3d12GpuRecord::PipelineContext::Reset() void D3d12GpuRecord::PipelineContext::SetPipeline(NonNull pipeline, u32 i) { if (Pipeline && pipeline->ObjectId() == Pipeline->ObjectId()) return; - const auto dx_pipeline = pipeline->QueryInterface(); + const Ptr dx_pipeline = pipeline->QueryInterface(); if (!dx_pipeline) { COPLT_THROW_FMT( @@ -34,18 +34,18 @@ void D3d12GpuRecord::PipelineContext::SetPipeline(NonNull pipel i, static_cast(pipeline) ); } - Pipeline = Rc::UnsafeClone(dx_pipeline); + Pipeline = dx_pipeline; Layout = Pipeline->Layout(); const auto stages = pipeline->GetStages(); GPipeline = nullptr; if (HasFlags(stages, FShaderStageFlags::Pixel)) { - const auto g_pipeline = pipeline->QueryInterface(); + const Ptr g_pipeline = pipeline->QueryInterface(); if (!g_pipeline) { COPLT_THROW_FMT("[{}] Invalid pipeline: pipeline is not a graphics pipeline, but there is a pixel shader in the stages.", i); } - GPipeline = Rc::UnsafeClone(g_pipeline); + GPipeline = g_pipeline; } PipelineChanged = true; if (Binding && Binding->Layout()->ObjectId() != Layout->ObjectId()) @@ -57,7 +57,7 @@ void D3d12GpuRecord::PipelineContext::SetPipeline(NonNull pipel void D3d12GpuRecord::PipelineContext::SetBinding(NonNull binding, u32 i) { if (Binding && binding->ObjectId() == Binding->ObjectId()) return; - const auto dx_binding = binding->QueryInterface(); + const Ptr dx_binding = binding->QueryInterface(); if (!dx_binding) { COPLT_THROW_FMT( @@ -69,7 +69,7 @@ void D3d12GpuRecord::PipelineContext::SetBinding(NonNull binding { COPLT_THROW_FMT("[{}] The binding layout is not compatible with the currently set pipeline", i); } - Binding = Rc::UnsafeClone(dx_binding); + Binding = dx_binding; } D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) @@ -138,6 +138,7 @@ void D3d12GpuRecord::Recycle() m_barrier_analyzer->Clear(); m_context->Recycle(); m_resources_owner.clear(); + m_set_binding_info.clear(); m_pipeline_context.Reset(); ClearData(); Ended = false; @@ -349,8 +350,8 @@ void D3d12GpuRecord::Analyze_RenderEnd(u32 i, const FCmdRender& cmd) m_state = RecordState::Main; const auto& info = PayloadRenderInfo[cmd.InfoIndex]; const auto num_rtv = std::min(info.NumRtv, 8u); - if (info.Dsv) m_barrier_analyzer->OnUse(info.Dsv); - for (u32 n = 0; n < num_rtv; ++n) m_barrier_analyzer->OnUse(info.Rtv[n]); + if (info.Dsv) m_barrier_analyzer->UpdateUse(info.Dsv); + for (u32 n = 0; n < num_rtv; ++n) m_barrier_analyzer->UpdateUse(info.Rtv[n]); m_barrier_analyzer->OnCmd(); m_pipeline_context.Reset(); } @@ -384,8 +385,18 @@ void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) { if (m_state != RecordState::Render && m_state != RecordState::Compute) COPLT_THROW_FMT("[{}] Cannot use SetBinding in main scope", i); - // todo - SetBinding(cmd.Binding, i); + if (!SetBinding(Bindings[cmd.Binding].Binding, i)) return; + const NonNull binding = m_pipeline_context.Binding; + const auto groups = binding->Groups(); + for (const auto& group : groups) + { + const auto views = group->Views(); + for (const auto& view : views) + { + // m_barrier_analyzer->OnUse(view); + } + } + m_barrier_analyzer->OnCmd(); } void D3d12GpuRecord::Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd) @@ -798,10 +809,11 @@ void D3d12GpuRecord::SetPipeline(NonNull pipeline, u32 i) m_pipeline_context.SetPipeline(pipeline, i); } -void D3d12GpuRecord::SetBinding(NonNull binding, u32 i) +bool D3d12GpuRecord::SetBinding(NonNull binding, u32 i) { - if (m_pipeline_context.Binding && binding->ObjectId() == m_pipeline_context.Binding->ObjectId()) return; + if (m_pipeline_context.Binding && binding->ObjectId() == m_pipeline_context.Binding->ObjectId()) return false; m_pipeline_context.SetBinding(binding, i); + return true; } void D3d12GpuRecord::SetPipeline(const CmdList& list, NonNull pipeline, u32 i) diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 12baa4a..2a70554 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -78,6 +78,11 @@ namespace Coplt void SetBinding(NonNull binding, u32 i); }; + struct SetBindingInfo + { + + }; + u64 m_isolate_id{}; u64 m_record_id{}; SRc m_isolate_config{}; @@ -85,6 +90,7 @@ namespace Coplt Rc m_context{}; Rc m_barrier_analyzer{}; std::vector> m_resources_owner{}; + std::vector m_set_binding_info{}; std::vector m_queue_wait_points{}; RenderState m_cur_render{}; ComputeState m_cur_compute{}; @@ -153,7 +159,8 @@ namespace Coplt void Interpret_Dispatch(const CmdList& list, u32 i, const FCmdDispatch& cmd) const; void SetPipeline(NonNull pipeline, u32 i); - void SetBinding(NonNull binding, u32 i); + // 返回是否改变 + bool SetBinding(NonNull binding, u32 i); void SetPipeline(const CmdList& list, NonNull pipeline, u32 i); }; diff --git a/Examples/Colorful/Example.cs b/Examples/Colorful/Example.cs index a8b6c6b..9e6b1a3 100644 --- a/Examples/Colorful/Example.cs +++ b/Examples/Colorful/Example.cs @@ -63,7 +63,7 @@ protected override async Task LoadResources(GpuRecord cmd) Topology = PrimitiveTopologyType.TriangleStrip, }, BindingLayout, Name: Name ); - ArgBuffer = Device.CreateBuffer( + ArgBuffer = Isolate.CreateBuffer( new() { Purpose = ResourcePurpose.ConstantBuffer, @@ -71,8 +71,8 @@ protected override async Task LoadResources(GpuRecord cmd) }, Name: "Args" ); - BindGroup = Device.CreateBindGroup(BindGroupLayout, [new(0, ArgBuffer)]); - Binding = Device.CreateBinding(BindingLayout, [new(0, BindGroup)]); + BindGroup = Isolate.CreateBindGroup(BindGroupLayout, [new(0, ArgBuffer)]); + Binding = Isolate.CreateBinding(BindingLayout, [new(0, BindGroup)]); } protected override void Render(GpuRecord cmd, Time time) { diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index 751408c..12b9066 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -87,6 +87,7 @@ public void DoInitGraphics() catch (Exception e) { Log.Error(e, ""); + Environment.Exit(1); } } } @@ -95,6 +96,7 @@ public void DoInitGraphics() catch (Exception e) { Log.Error(e, ""); + Environment.Exit(1); } } diff --git a/Examples/HelloTriangleVertex/Example.cs b/Examples/HelloTriangleVertex/Example.cs index 21c2656..abc8d5a 100644 --- a/Examples/HelloTriangleVertex/Example.cs +++ b/Examples/HelloTriangleVertex/Example.cs @@ -52,14 +52,14 @@ protected override async Task LoadResources(GpuRecord cmd) } }, MeshLayout, Name: Name ); - PositionColorBuffer = Device.CreateBuffer( + PositionColorBuffer = Isolate.CreateBuffer( new() { Purpose = ResourcePurpose.VertexBuffer, Size = sizeof(float) * 4 * 6, }, "Position and Color" ); - UvBuffer = Device.CreateBuffer( + UvBuffer = Isolate.CreateBuffer( new() { Purpose = ResourcePurpose.VertexBuffer, diff --git a/Examples/HelloTriangleVertex/HelloTriangleVertex.md b/Examples/HelloTriangleVertex/HelloTriangleVertex.md index a128748..b147201 100644 --- a/Examples/HelloTriangleVertex/HelloTriangleVertex.md +++ b/Examples/HelloTriangleVertex/HelloTriangleVertex.md @@ -57,14 +57,14 @@ Pipeline = Device.CreateGraphicsShaderPipeline( ); // Creating vertex buffers -PositionColorBuffer = Device.CreateBuffer( +PositionColorBuffer = Isolate.CreateBuffer( new() { Purpose = ResourcePurpose.VertexBuffer, Size = sizeof(float) * 4 * 6, }, "Position and Color" ); -UvBuffer = Device.CreateBuffer( +UvBuffer = Isolate.CreateBuffer( new() { Purpose = ResourcePurpose.VertexBuffer, From da7e39815439105e8bf32747a70c4ceb9901f722 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Mon, 7 Apr 2025 22:01:12 +0800 Subject: [PATCH 35/46] save --- Coplt.Graphics.Core/Core/GpuIsolate.cs | 227 +++++++------------- Coplt.Graphics.Core/Core/ShaderBindGroup.cs | 38 ++-- Coplt.Graphics.Core/Core/ShaderBinding.cs | 32 +-- Coplt.Graphics.Core/Native/Native.cs | 15 +- Coplt.Graphics.Native/Api/FFI/Binding.h | 9 +- Coplt.Graphics.Native/Api/FFI/Types.h | 4 +- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 33 ++- Coplt.Graphics.Native/D3d12/Src/Binding.h | 16 +- Coplt.Graphics.Native/D3d12/Src/Record.cc | 2 + 9 files changed, 162 insertions(+), 214 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 50eae23..eb8e1e5 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -64,33 +64,21 @@ public GpuRecord RentRecord() public void RentRecords(Span records) { if (records.Length == 0) return; - if (records.Length < 8) - { - var p = stackalloc FGpuRecordCreateResult[records.Length]; - Ptr->RentRecords((uint)records.Length, p).TryThrow(); - for (var i = 0; i < records.Length; i++) - { - records[i] = new(p[i].Record, p[i].Data, null, this); - } - } - else + var arr = ArrayPool.Shared.Rent(records.Length); + try { - var arr = ArrayPool.Shared.Rent(records.Length); - try + fixed (FGpuRecordCreateResult* p = arr) { - fixed (FGpuRecordCreateResult* p = arr) + Ptr->RentRecords((uint)records.Length, p).TryThrow(); + for (var i = 0; i < records.Length; i++) { - Ptr->RentRecords((uint)records.Length, p).TryThrow(); - for (var i = 0; i < records.Length; i++) - { - records[i] = new(p[i].Record, p[i].Data, null, this); - } + records[i] = new(p[i].Record, p[i].Data, null, this); } } - finally - { - ArrayPool.Shared.Return(arr); - } + } + finally + { + ArrayPool.Shared.Return(arr); } } @@ -102,42 +90,27 @@ public void ReturnRecords(params ReadOnlySpan records) { if (records.Length == 0) return; bool disposed = false; - if (records.Length < 8) + var arr = ArrayPool.Shared.Rent(records.Length); + var c = 0u; + try { - var p = stackalloc FGpuRecord*[records.Length]; - var c = 0u; foreach (var t in records) { if (ExchangeUtils.ExchangePtr(ref t.m_ptr, null, out var ptr) is null) disposed = true; - else p[c++] = (FGpuRecord*)ptr; + else arr[c++] = (IntPtr)ptr; } - if (c > 0) Ptr->ReturnRecords(c, p).TryThrow(); - if (disposed) throw new ObjectDisposedException(nameof(GpuRecord)); - } - else - { - var arr = ArrayPool.Shared.Rent(records.Length); - var c = 0u; - try + if (c > 0) { - foreach (var t in records) - { - if (ExchangeUtils.ExchangePtr(ref t.m_ptr, null, out var ptr) is null) disposed = true; - else arr[c++] = (IntPtr)ptr; - } - if (c > 0) + fixed (IntPtr* p = arr) { - fixed (IntPtr* p = arr) - { - Ptr->ReturnRecords(c, (FGpuRecord**)p).TryThrow(); - } + Ptr->ReturnRecords(c, (FGpuRecord**)p).TryThrow(); } - if (disposed) throw new ObjectDisposedException(nameof(GpuRecord)); - } - finally - { - ArrayPool.Shared.Return(arr); } + if (disposed) throw new ObjectDisposedException(nameof(GpuRecord)); + } + finally + { + ArrayPool.Shared.Return(arr); } } @@ -148,70 +121,43 @@ public void ReturnRecords(params ReadOnlySpan records) public void Submit(params ReadOnlySpan records) { if (records.Length == 0) return; - if (records.Length < 8) + var arr = ArrayPool.Shared.Rent(records.Length); + var @out = ArrayPool.Shared.Rent(records.Length); + try { - var p = stackalloc FGpuRecord*[records.Length]; - var o = stackalloc FGpuRecordCreateResult[records.Length]; for (var i = 0; i < records.Length; i++) { - if ((p[i] = records[i].Ptr) == null) throw new NullReferenceException(); + if ((arr[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); records[i].AssertEndOrCanEnd(); } - try - { - Ptr->Submit((uint)records.Length, p, o).TryThrow(); - for (var i = 0; i < records.Length; i++) - { - records[i].m_ptr = (FUnknown*)o[i].Record; - records[i].m_data = o[i].Data; - records[i].Reset(); - } - } - catch (Exception e) - { - throw new UnrecoverableException(e); - } - } - else - { - var arr = ArrayPool.Shared.Rent(records.Length); - var @out = ArrayPool.Shared.Rent(records.Length); - try + fixed (IntPtr* p = arr) + fixed (FGpuRecordCreateResult* o = @out) { for (var i = 0; i < records.Length; i++) { - if ((arr[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); + if ((p[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); records[i].AssertEndOrCanEnd(); } - fixed (IntPtr* p = arr) - fixed (FGpuRecordCreateResult* o = @out) + try { + Ptr->Submit((uint)records.Length, (FGpuRecord**)p, o).TryThrow(); for (var i = 0; i < records.Length; i++) { - if ((p[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); - records[i].AssertEndOrCanEnd(); - } - try - { - Ptr->Submit((uint)records.Length, (FGpuRecord**)p, o).TryThrow(); - for (var i = 0; i < records.Length; i++) - { - records[i].m_ptr = (FUnknown*)o[i].Record; - records[i].m_data = o[i].Data; - records[i].Reset(); - } - } - catch (Exception e) - { - throw new UnrecoverableException(e); + records[i].m_ptr = (FUnknown*)o[i].Record; + records[i].m_data = o[i].Data; + records[i].Reset(); } } + catch (Exception e) + { + throw new UnrecoverableException(e); + } } - finally - { - ArrayPool.Shared.Return(arr); - ArrayPool.Shared.Return(@out); - } + } + finally + { + ArrayPool.Shared.Return(arr); + ArrayPool.Shared.Return(@out); } } @@ -222,61 +168,35 @@ public void Submit(params ReadOnlySpan records) public void SubmitReturn(params ReadOnlySpan records) { if (records.Length == 0) return; - if (records.Length < 8) + var arr = ArrayPool.Shared.Rent(records.Length); + try { - var p = stackalloc FGpuRecord*[records.Length]; for (var i = 0; i < records.Length; i++) { - if ((p[i] = records[i].Ptr) == null) throw new NullReferenceException(); + if ((arr[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); records[i].AssertEndOrCanEnd(); } - try + fixed (IntPtr* p = arr) { - Ptr->SubmitReturn((uint)records.Length, p).TryThrow(); - foreach (var a in records) + try { - a.m_ptr = null; - a.m_data = null; - a.Reset(); - } - } - catch (Exception e) - { - throw new UnrecoverableException(e); - } - } - else - { - var arr = ArrayPool.Shared.Rent(records.Length); - try - { - for (var i = 0; i < records.Length; i++) - { - if ((arr[i] = (IntPtr)records[i].Ptr) == 0) throw new NullReferenceException(); - records[i].AssertEndOrCanEnd(); - } - fixed (IntPtr* p = arr) - { - try - { - Ptr->SubmitReturn((uint)records.Length, (FGpuRecord**)p).TryThrow(); - foreach (var a in records) - { - a.m_ptr = null; - a.m_data = null; - a.Reset(); - } - } - catch (Exception e) + Ptr->SubmitReturn((uint)records.Length, (FGpuRecord**)p).TryThrow(); + foreach (var a in records) { - throw new UnrecoverableException(e); + a.m_ptr = null; + a.m_data = null; + a.Reset(); } } + catch (Exception e) + { + throw new UnrecoverableException(e); + } } - finally - { - ArrayPool.Shared.Return(arr); - } + } + finally + { + ArrayPool.Shared.Return(arr); } } @@ -321,6 +241,7 @@ public ShaderBindGroup CreateBindGroup( string? Name = null, ReadOnlySpan Name8 = default ) { + ShaderBindGroup.CheckSet(layout, items); var f_items = ArrayPool.Shared.Rent(items.Length); try { @@ -347,7 +268,7 @@ public ShaderBindGroup CreateBindGroup( }; FShaderBindGroupCreateResult result; Device.Ptr->CreateShaderBindGroup(&f_options, &result).TryThrow(); - return new(result, Name, this, layout, items); + return new(result, Name, this, layout); } } finally @@ -365,36 +286,38 @@ public ShaderBinding CreateBinding( string? Name = null, ReadOnlySpan Name8 = default ) { - if (items.Length != layout.BindGroupLayouts.Length) - throw new ArgumentException( - $"The number of binding groups provided does not meet the required number; Provided({items.Length}) != Required({layout.BindGroupLayouts.Length})" - ); - var f_items = ArrayPool.Shared.Rent(items.Length); + ShaderBinding.CheckSet(layout, items); + var f_items = ArrayPool.Shared.Rent(items.Length); try { for (var i = 0; i < items.Length; i++) { ref readonly var item = ref items[i]; - f_items[i] = (IntPtr)item.Group.Ptr; + f_items[i] = new() + { + BindGroup = item.Group.Ptr, + Index = item.Index, + }; } fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) - fixed (IntPtr* p_items = f_items) + fixed (FSetBindGroupItem* p_items = f_items) { FShaderBindingCreateOptions f_options = new() { Name = new(Name, Name8, p_name, p_name8), Layout = layout.Ptr, - BindGroups = (FShaderBindGroup**)p_items, + BindGroups = p_items, + NumBindGroups = (uint)items.Length, }; FShaderBinding* ptr; Device.Ptr->CreateShaderBinding(&f_options, &ptr).TryThrow(); - return new(ptr, Name, this, layout, items); + return new(ptr, Name, this, layout); } } finally { - ArrayPool.Shared.Return(f_items); + ArrayPool.Shared.Return(f_items); } } diff --git a/Coplt.Graphics.Core/Core/ShaderBindGroup.cs b/Coplt.Graphics.Core/Core/ShaderBindGroup.cs index 0918f96..98c9f69 100644 --- a/Coplt.Graphics.Core/Core/ShaderBindGroup.cs +++ b/Coplt.Graphics.Core/Core/ShaderBindGroup.cs @@ -19,7 +19,6 @@ public sealed unsafe partial class ShaderBindGroup : IsolateChild #region Fields internal FShaderBindGroupData* m_data; - internal View[] m_views; #endregion @@ -27,8 +26,7 @@ public sealed unsafe partial class ShaderBindGroup : IsolateChild public new FShaderBindGroup* Ptr => (FShaderBindGroup*)base.Ptr; public ref readonly FShaderBindGroupData Data => ref *m_data; - public ReadOnlySpan Views => m_views; - public ReadOnlySpan ItemIndexes => new(m_data->ItemIndexes, (int)m_data->NumItemIndexes); + public uint CountSlots => Data.CountSlots; public ShaderBindGroupLayout Layout { get; } #endregion @@ -36,27 +34,11 @@ public sealed unsafe partial class ShaderBindGroup : IsolateChild #region Ctor internal ShaderBindGroup( - FShaderBindGroupCreateResult result, string? name, GpuIsolate isolate, ShaderBindGroupLayout layout, ReadOnlySpan items + FShaderBindGroupCreateResult result, string? name, GpuIsolate isolate, ShaderBindGroupLayout layout ) : base((FGpuObject*)result.BindGroup, name, isolate) { m_data = result.Data; Layout = layout; - m_views = new View[Data.CountSlots]; - Set(items); - } - - private void Set(ReadOnlySpan items) - { - var defs = Layout.Items; - var item_indexes = ItemIndexes; - foreach (ref readonly var item in items) - { - if (item.Slot >= defs.Length) throw new IndexOutOfRangeException(); - ref readonly var def = ref defs[(int)item.Slot]; - if (item.Index >= def.Count) throw new IndexOutOfRangeException(); - ref var slot = ref m_views[item_indexes[(int)item.Slot] + item.Index]; - slot = item.View; - } } #endregion @@ -67,7 +49,21 @@ private void Set(ReadOnlySpan items) private void Drop() { m_data = null; - m_views = null!; + } + + #endregion + + #region CheckSet + + internal static void CheckSet(ShaderBindGroupLayout layout, ReadOnlySpan items) + { + var defs = layout.Items; + foreach (ref readonly var item in items) + { + if (item.Slot >= defs.Length) throw new IndexOutOfRangeException(); + ref readonly var def = ref defs[(int)item.Slot]; + if (item.Index >= def.Count) throw new IndexOutOfRangeException(); + } } #endregion diff --git a/Coplt.Graphics.Core/Core/ShaderBinding.cs b/Coplt.Graphics.Core/Core/ShaderBinding.cs index 9ab6df4..fc3532d 100644 --- a/Coplt.Graphics.Core/Core/ShaderBinding.cs +++ b/Coplt.Graphics.Core/Core/ShaderBinding.cs @@ -5,15 +5,8 @@ namespace Coplt.Graphics.Core; public record struct SetShaderBindGroupItem(uint Index, ShaderBindGroup Group); -[Dropping(Unmanaged = true)] -public sealed unsafe partial class ShaderBinding : IsolateChild +public sealed unsafe class ShaderBinding : IsolateChild { - #region Fields - - internal ShaderBindGroup[] m_groups; - - #endregion - #region Props public new FShaderBinding* Ptr => (FShaderBinding*)base.Ptr; @@ -24,30 +17,23 @@ public sealed unsafe partial class ShaderBinding : IsolateChild #region Ctor internal ShaderBinding( - FShaderBinding* ptr, string? name, GpuIsolate isolate, ShaderBindingLayout layout, ReadOnlySpan items + FShaderBinding* ptr, string? name, GpuIsolate isolate, ShaderBindingLayout layout ) : base((FGpuObject*)ptr, name, isolate) { Layout = layout; - m_groups = new ShaderBindGroup[layout.BindGroupLayouts.Length]; - Set(items); - } - - private void Set(ReadOnlySpan items) - { - foreach (var item in items) - { - m_groups[item.Index] = item.Group; - } } #endregion - #region Drop + #region CheckSet - [Drop] - private void Drop() + internal static void CheckSet(ShaderBindingLayout layout, ReadOnlySpan items) { - m_groups = null!; + var count = layout.BindGroupLayouts.Length; + foreach (ref readonly var item in items) + { + if (item.Index >= count) throw new IndexOutOfRangeException(); + } } #endregion diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 2089dfa..cc5028e 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -3093,6 +3093,15 @@ public unsafe partial struct FShaderBindGroupCreateResult public FShaderBindGroupData* Data; } + public unsafe partial struct FSetBindGroupItem + { + [NativeTypeName("Coplt::FShaderBindGroup *")] + public FShaderBindGroup* BindGroup; + + [NativeTypeName("Coplt::u32")] + public uint Index; + } + public unsafe partial struct FShaderBindingCreateOptions { [NativeTypeName("Coplt::FStr8or16")] @@ -3101,7 +3110,11 @@ public unsafe partial struct FShaderBindingCreateOptions [NativeTypeName("Coplt::FBindingLayout *")] public FBindingLayout* Layout; - public FShaderBindGroup** BindGroups; + [NativeTypeName("Coplt::FSetBindGroupItem *")] + public FSetBindGroupItem* BindGroups; + + [NativeTypeName("Coplt::u32")] + public uint NumBindGroups; } [Guid("A3CA644A-0E02-4D25-9A18-8835D66600F7")] diff --git a/Coplt.Graphics.Native/Api/FFI/Binding.h b/Coplt.Graphics.Native/Api/FFI/Binding.h index 796f0e8..8472a16 100644 --- a/Coplt.Graphics.Native/Api/FFI/Binding.h +++ b/Coplt.Graphics.Native/Api/FFI/Binding.h @@ -42,11 +42,18 @@ namespace Coplt FShaderBindGroupData* Data{}; }; + struct FSetBindGroupItem + { + FShaderBindGroup* BindGroup{}; + u32 Index{}; + }; + struct FShaderBindingCreateOptions { FStr8or16 Name{}; FBindingLayout* Layout{}; - FShaderBindGroup** BindGroups{}; + FSetBindGroupItem* BindGroups{}; + u32 NumBindGroups{}; }; COPLT_INTERFACE_DEFINE(FShaderBinding, "a3ca644a-0e02-4d25-9a18-8835d66600f7", FGpuObject) diff --git a/Coplt.Graphics.Native/Api/FFI/Types.h b/Coplt.Graphics.Native/Api/FFI/Types.h index 3528144..f27a8ad 100644 --- a/Coplt.Graphics.Native/Api/FFI/Types.h +++ b/Coplt.Graphics.Native/Api/FFI/Types.h @@ -62,8 +62,8 @@ namespace Coplt using Char16 = char16_t; using RwLock = std::shared_mutex; - using WriteLock = std::unique_lock; - using ReadLock = std::shared_lock; + using WriteGuard = std::unique_lock; + using ReadGuard = std::shared_lock; template using Ref = std::reference_wrapper; diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index b677d7f..7b051e0 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -52,11 +52,16 @@ const Rc& D3d12ShaderBindGroup::Layout() const noexcept return m_layout; } -const std::span D3d12ShaderBindGroup::Views() const noexcept +std::span D3d12ShaderBindGroup::Views() const noexcept { return m_views; } +RwLock& D3d12ShaderBindGroup::Lock() noexcept +{ + return m_lock; +} + void D3d12ShaderBindGroup::Set(const std::span items) { const auto defs = m_layout->GetItems(); @@ -102,7 +107,7 @@ D3d12ShaderBinding::D3d12ShaderBinding(Rc&& device, const FShade m_layout = Rc::UnsafeClone(layout); const auto groups = m_layout->Groups(); m_groups = std::vector(groups.size(), Rc{}); - Set(std::span(options.BindGroups, options.BindGroups + m_groups.size())); + Set(std::span(options.BindGroups, options.BindGroups + options.NumBindGroups)); } FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept @@ -115,22 +120,32 @@ const Rc& D3d12ShaderBinding::Layout() const noexcept return m_layout; } -const std::span> D3d12ShaderBinding::Groups() const noexcept +std::span> D3d12ShaderBinding::Groups() const noexcept { return m_groups; } -void D3d12ShaderBinding::Set(const std::span items) +RwLock& D3d12ShaderBinding::Lock() noexcept +{ + return m_lock; +} + +void D3d12ShaderBinding::Set(const std::span items) { - for (usize i = 0; i < m_groups.size(); ++i) + for (const auto& item : items) { - const auto item = items[i]; - if (item) + if (item.Index >= m_groups.size()) + COPLT_THROW("Index out of range"); + if (item.BindGroup) { - const auto bind_group = item->QueryInterface(); + const auto bind_group = item.BindGroup->QueryInterface(); if (bind_group == nullptr) COPLT_THROW("BindGroup from different backends"); - m_groups[i] = Rc::UnsafeClone(bind_group); + m_groups[item.Index] = Rc::UnsafeClone(bind_group); + } + else + { + m_groups[item.Index] = nullptr; } } } diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index b819a01..495d778 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -18,7 +18,8 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12ShaderBindGroup, "5bb948b9-ad31-4eb8-b881-98017e048259", FShaderBindGroup) { virtual const Rc& Layout() const noexcept = 0; - virtual const std::span Views() const noexcept = 0; + virtual std::span Views() const noexcept = 0; + virtual RwLock& Lock() noexcept = 0; }; struct D3d12ShaderBindGroup final : GpuObject, FShaderBindGroupData @@ -28,6 +29,7 @@ namespace Coplt Rc m_layout{}; std::vector m_views{}; std::vector m_item_indexes{}; + RwLock m_lock{}; explicit D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; @@ -35,7 +37,8 @@ namespace Coplt FShaderBindGroupData* ShaderBindGroupData() noexcept override; const Rc& Layout() const noexcept override; - const std::span Views() const noexcept override; + std::span Views() const noexcept override; + RwLock& Lock() noexcept override; void Set(std::span items); }; @@ -43,7 +46,8 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "5073f785-cfb7-414d-9a84-1602d3bf378d", FShaderBinding) { virtual const Rc& Layout() const noexcept = 0; - virtual const std::span> Groups() const noexcept = 0; + virtual std::span> Groups() const noexcept = 0; + virtual RwLock& Lock() noexcept = 0; }; struct D3d12ShaderBinding final : GpuObject @@ -51,13 +55,15 @@ namespace Coplt Rc m_device{}; Rc m_layout{}; std::vector> m_groups{}; + RwLock m_lock{}; explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; const Rc& Layout() const noexcept override; - const std::span> Groups() const noexcept override; + std::span> Groups() const noexcept override; + RwLock& Lock() noexcept override; - void Set(std::span items); + void Set(std::span items); }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index c45b1af..51911f2 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -387,9 +387,11 @@ void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) COPLT_THROW_FMT("[{}] Cannot use SetBinding in main scope", i); if (!SetBinding(Bindings[cmd.Binding].Binding, i)) return; const NonNull binding = m_pipeline_context.Binding; + ReadGuard binding_guard(binding->Lock()); const auto groups = binding->Groups(); for (const auto& group : groups) { + ReadGuard group_guard(group->Lock()); const auto views = group->Views(); for (const auto& view : views) { From 101aade6b18fe66b1c3b8cffa835caf2692b0e33 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 8 Apr 2025 16:16:00 +0800 Subject: [PATCH 36/46] save --- Coplt.Graphics.Core/Core/GpuIsolate.cs | 6 +- Coplt.Graphics.Core/Core/GpuRecord.cs | 3 +- Coplt.Graphics.Core/Core/ShaderBinding.cs | 25 +- Coplt.Graphics.Core/Native/Native.cs | 36 +- Coplt.Graphics.Native/Api/FFI/Binding.h | 15 +- Coplt.Graphics.Native/Api/FFI/Cmd.h | 41 +- Coplt.Graphics.Native/Api/FFI/Device.h | 2 +- Coplt.Graphics.Native/Api/FFI/Record.h | 2 +- Coplt.Graphics.Native/Api/Include/Error.h | 6 + Coplt.Graphics.Native/D3d12/Include/View.h | 11 +- Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 122 ++++-- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 30 +- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 25 +- Coplt.Graphics.Native/D3d12/Src/Binding.h | 10 +- Coplt.Graphics.Native/D3d12/Src/Device.cc | 6 +- Coplt.Graphics.Native/D3d12/Src/Device.h | 2 +- Coplt.Graphics.Native/D3d12/Src/Layout.cc | 40 +- Coplt.Graphics.Native/D3d12/Src/Layout.h | 16 + Coplt.Graphics.Native/D3d12/Src/Record.cc | 440 +++++++++++++-------- Coplt.Graphics.Native/D3d12/Src/Record.h | 55 ++- Coplt.Graphics.Native/D3d12/Src/View.cc | 32 ++ 21 files changed, 650 insertions(+), 275 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index eb8e1e5..2b55f4c 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -310,9 +310,9 @@ public ShaderBinding CreateBinding( BindGroups = p_items, NumBindGroups = (uint)items.Length, }; - FShaderBinding* ptr; - Device.Ptr->CreateShaderBinding(&f_options, &ptr).TryThrow(); - return new(ptr, Name, this, layout); + FShaderBindingCreateResult result; + Device.Ptr->CreateShaderBinding(&f_options, &result).TryThrow(); + return new(result, Name, this, layout); } } finally diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 9c8b554..bb1ab3d 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -807,7 +807,7 @@ public void SetBinding(GpuRecord self, ShaderBinding Binding) throw new InvalidOperationException("The binding layout is not compatible with the currently set pipeline"); } m_current_binding = Binding; - self.AddObject(m_current_binding); + var first = self.AddObject(m_current_binding); var cmd = new FCmdSetBinding { Base = { Type = FCmdType.SetBinding }, @@ -821,6 +821,7 @@ public void SetBinding(GpuRecord self, ShaderBinding Binding) } ); self.Data.Commands.Add(new() { SetBinding = cmd }); + if (first) self.Data.SumMaxBindSlots += Binding.Data.SumPersistentSlots + Binding.Data.SumTransientSlots; } #endregion diff --git a/Coplt.Graphics.Core/Core/ShaderBinding.cs b/Coplt.Graphics.Core/Core/ShaderBinding.cs index fc3532d..d6fb1f2 100644 --- a/Coplt.Graphics.Core/Core/ShaderBinding.cs +++ b/Coplt.Graphics.Core/Core/ShaderBinding.cs @@ -5,11 +5,19 @@ namespace Coplt.Graphics.Core; public record struct SetShaderBindGroupItem(uint Index, ShaderBindGroup Group); -public sealed unsafe class ShaderBinding : IsolateChild +[Dropping(Unmanaged = true)] +public sealed unsafe partial class ShaderBinding : IsolateChild { + #region Fields + + internal FShaderBindingData* m_data; + + #endregion + #region Props public new FShaderBinding* Ptr => (FShaderBinding*)base.Ptr; + public ref readonly FShaderBindingData Data => ref *m_data; public ShaderBindingLayout Layout { get; } #endregion @@ -17,10 +25,21 @@ public sealed unsafe class ShaderBinding : IsolateChild #region Ctor internal ShaderBinding( - FShaderBinding* ptr, string? name, GpuIsolate isolate, ShaderBindingLayout layout - ) : base((FGpuObject*)ptr, name, isolate) + FShaderBindingCreateResult result, string? name, GpuIsolate isolate, ShaderBindingLayout layout + ) : base((FGpuObject*)result.Binding, name, isolate) { Layout = layout; + m_data = result.Data; + } + + #endregion + + #region Drop + + [Drop] + private void Drop() + { + m_data = null; } #endregion diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index cc5028e..c2dc85f 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1333,10 +1333,10 @@ public FResult CreateShaderBindGroup([NativeTypeName("const FShaderBindGroupCrea [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out) + public FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, [NativeTypeName("Coplt::FShaderBindingCreateResult *")] FShaderBindingCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[20]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[20]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1415,7 +1415,7 @@ public interface Interface : FGpuObject.Interface FResult CreateShaderBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, [NativeTypeName("Coplt::FShaderBindGroupCreateResult *")] FShaderBindGroupCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] - FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, FShaderBinding** @out); + FResult CreateShaderBinding([NativeTypeName("const FShaderBindingCreateOptions &")] FShaderBindingCreateOptions* options, [NativeTypeName("Coplt::FShaderBindingCreateResult *")] FShaderBindingCreateResult* @out); [return: NativeTypeName("Coplt::FResult")] FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out); @@ -1742,6 +1742,9 @@ public unsafe partial struct FGpuRecordData [NativeTypeName("Coplt::u32")] public uint NumSetBindings; + [NativeTypeName("Coplt::u32")] + public uint SumMaxBindSlots; + [NativeTypeName("Coplt::b8")] public B8 Ended; @@ -3117,6 +3120,15 @@ public unsafe partial struct FShaderBindingCreateOptions public uint NumBindGroups; } + public partial struct FShaderBindingData + { + [NativeTypeName("Coplt::u32")] + public uint SumPersistentSlots; + + [NativeTypeName("Coplt::u32")] + public uint SumTransientSlots; + } + [Guid("A3CA644A-0E02-4D25-9A18-8835D66600F7")] [NativeTypeName("struct FShaderBinding : Coplt::FGpuObject")] public unsafe partial struct FShaderBinding : FShaderBinding.Interface, INativeGuid @@ -3166,11 +3178,29 @@ public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderBinding*)Unsafe.AsPointer(ref this), &result, name); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderBindingData *")] + public FShaderBindingData* ShaderBindingData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderBinding*)Unsafe.AsPointer(ref this)); + } + public interface Interface : FGpuObject.Interface { + [return: NativeTypeName("Coplt::FShaderBindingData *")] + FShaderBindingData* ShaderBindingData(); } } + public unsafe partial struct FShaderBindingCreateResult + { + [NativeTypeName("Coplt::FShaderBinding *")] + public FShaderBinding* Binding; + + [NativeTypeName("Coplt::FShaderBindingData *")] + public FShaderBindingData* Data; + } + public unsafe partial struct FUploadBufferBlock { [NativeTypeName("Coplt::u8 *")] diff --git a/Coplt.Graphics.Native/Api/FFI/Binding.h b/Coplt.Graphics.Native/Api/FFI/Binding.h index 8472a16..405de05 100644 --- a/Coplt.Graphics.Native/Api/FFI/Binding.h +++ b/Coplt.Graphics.Native/Api/FFI/Binding.h @@ -26,8 +26,6 @@ namespace Coplt struct FShaderBindGroupData { - u32* ItemIndexes{}; - u32 NumItemIndexes{}; u32 CountSlots{}; }; @@ -56,7 +54,20 @@ namespace Coplt u32 NumBindGroups{}; }; + struct FShaderBindingData + { + u32 SumPersistentSlots{}; + u32 SumTransientSlots{}; + }; + COPLT_INTERFACE_DEFINE(FShaderBinding, "a3ca644a-0e02-4d25-9a18-8835d66600f7", FGpuObject) { + virtual FShaderBindingData* ShaderBindingData() noexcept = 0; + }; + + struct FShaderBindingCreateResult + { + FShaderBinding* Binding{}; + FShaderBindingData* Data{}; }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index 8e8e8a1..d04ebcd 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -90,20 +90,19 @@ namespace Coplt } return nullptr; } + #endif + }; - bool IsImage() const + struct FResIndex + { + u32 Value{}; + + #ifdef FFI_SRC + explicit FResIndex(const u32 Value) : Value(Value) { - switch (Type) - { - case FCmdResType::Image: - return true; - case FCmdResType::Buffer: - return false; - case FCmdResType::Output: - return true; - } - return false; } + + operator u32() const { return Value; } #endif }; @@ -112,25 +111,9 @@ namespace Coplt u32 IndexPlusOne{}; #ifdef FFI_SRC - operator bool() const { return IndexPlusOne != 0; } + explicit operator bool() const { return IndexPlusOne != 0; } - u32 ResIndex() const { return IndexPlusOne - 1; } - - FCmdRes& Get(FList& list) const - { - const auto index = ResIndex(); - if (index > list.m_len) - COPLT_THROW("Index out of range"); - return list[index]; - } - - const FCmdRes& Get(const FList& list) const - { - const auto index = ResIndex(); - if (index > list.m_len) - COPLT_THROW("Index out of range"); - return list[index]; - } + FResIndex ResIndex() const { return FResIndex{IndexPlusOne - 1}; } #endif }; diff --git a/Coplt.Graphics.Native/Api/FFI/Device.h b/Coplt.Graphics.Native/Api/FFI/Device.h index 15300a0..4da9b41 100644 --- a/Coplt.Graphics.Native/Api/FFI/Device.h +++ b/Coplt.Graphics.Native/Api/FFI/Device.h @@ -92,7 +92,7 @@ namespace Coplt virtual FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept = 0; virtual FResult CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroupCreateResult* out) noexcept = 0; - virtual FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept = 0; + virtual FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBindingCreateResult* out) noexcept = 0; virtual FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept = 0; diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index 00a5db4..061e73b 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -30,7 +30,6 @@ namespace Coplt u64 Version{}; FRecordContext* Context{}; FList Commands; - // 需要保证不重复,c# 部分需要使用 HashMap 去重 FList Resources; FList Bindings; FList PayloadRect; @@ -42,6 +41,7 @@ namespace Coplt FList PayloadVertexBufferRange; FList Blob; u32 NumSetBindings{}; + u32 SumMaxBindSlots{}; b8 Ended{}; FGpuRecordMode Mode{}; diff --git a/Coplt.Graphics.Native/Api/Include/Error.h b/Coplt.Graphics.Native/Api/Include/Error.h index d8da7d7..53d3788 100644 --- a/Coplt.Graphics.Native/Api/Include/Error.h +++ b/Coplt.Graphics.Native/Api/Include/Error.h @@ -23,6 +23,12 @@ #define COPLT_THROW_FMT(msg, ...) throw RuntimeException(fmt::format(msg, __VA_ARGS__)) #endif +#ifdef _DEBUG +#define COPLT_DEBUG_ASSERT(x) if (!(x)) COPLT_THROW("Assertion failed: "#x) +#else +#define COPLT_DEBUG_ASSERT(x) +#endif + namespace Coplt { std::string to_string(const cpptrace::stacktrace& trace); diff --git a/Coplt.Graphics.Native/D3d12/Include/View.h b/Coplt.Graphics.Native/D3d12/Include/View.h index 14a6184..b4afe93 100644 --- a/Coplt.Graphics.Native/D3d12/Include/View.h +++ b/Coplt.Graphics.Native/D3d12/Include/View.h @@ -12,6 +12,9 @@ namespace Coplt virtual bool IsCompatible(const FBindGroupItem& def) const = 0; }; + struct ID3d12GpuBuffer; + struct ID3d12GpuImage; + struct View final { Rc m_viewable{}; @@ -30,9 +33,15 @@ namespace Coplt View(const FView& view); View& operator=(const FView& view); - operator bool() const; + explicit operator bool() const; bool IsCompatible(const FBindGroupItem& def) const; + bool IsBuffer() const; + bool IsImage() const; + bool IsSampler() const; + NonNull GetViewable() const; + Ptr TryGetBuffer() const; + Ptr TryGetImage() const; // void CreateDescriptor( // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index c47f9d4..092ab1c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -25,7 +25,7 @@ bool ID3d12EnhancedBarrierAnalyzer::Group::IsEmpty() const return m_buffer_barriers.empty() && m_texture_barriers.empty(); } -ID3d12EnhancedBarrierAnalyzer::ResInfo::ResInfo(const NonNull Res) : Res(Res) +ID3d12EnhancedBarrierAnalyzer::ResInfo::ResInfo(const u32 ResIndex) : ResIndex(ResIndex) { } @@ -95,16 +95,11 @@ namespace Coplt::Enhanced m_groups.clear(); } - void EnhancedBarrierAnalyzer::StartAnalyze(const std::span resources) + void EnhancedBarrierAnalyzer::StartAnalyze(NonNull record) { - m_use_split_barrier = m_isolate_config->UseSplitBarrier; + m_record = record; Clear(); - m_resources.reserve(resources.size()); - for (usize i = 0; i < resources.size(); ++i) - { - const auto& res = resources[i]; - m_resources.push_back(ResInfo(&res)); - } + m_use_split_barrier = m_isolate_config->UseSplitBarrier; m_groups.push_back({}); } @@ -124,11 +119,16 @@ namespace Coplt::Enhanced } m_outputs.push_back(IOResState{.ResIndex = i, .LstGroup = info.LstGroup, .State = info.State}); } + m_record = NonNull::Unchecked(nullptr); } - void EnhancedBarrierAnalyzer::OnUse(const FCmdResRef ResRef, const ResAccess Access, const ResUsage Usage, const ResLayout Layout) + void EnhancedBarrierAnalyzer::OnAddRes() + { + m_resources.push_back(ResInfo(m_resources.size())); + } + + void EnhancedBarrierAnalyzer::OnUse(const FResIndex ResIndex, const ResAccess Access, const ResUsage Usage, const ResLayout Layout) { - const auto ResIndex = ResRef.ResIndex(); auto& info = m_resources[ResIndex]; const auto new_state = ResState(Access, Usage, Layout); const auto need_split = m_use_split_barrier && m_last_cmd_count > 0; @@ -173,13 +173,65 @@ namespace Coplt::Enhanced return; } - void EnhancedBarrierAnalyzer::OnUse(const View& View) + void EnhancedBarrierAnalyzer::OnUse(const FResIndex ResIndex, const View& View, const Layout::BindItemInfo& info) { + auto access = ResAccess::Common; + auto usage = ResUsage::Common; + auto layout = ResLayout::Undefined; + for (const auto stage : IterStage(info.Stages)) + { + switch (stage) + { + case FShaderStage::Compute: + usage |= ResUsage::Compute; + break; + case FShaderStage::Pixel: + usage |= ResUsage::Pixel; + break; + case FShaderStage::Vertex: + case FShaderStage::Mesh: + case FShaderStage::Task: + usage |= ResUsage::VertexOrMesh; + break; + default: ; + } + } + switch (info.View) + { + case FShaderLayoutItemView::Cbv: + access = ResAccess::ConstantBufferRead; + break; + case FShaderLayoutItemView::Srv: + access = ResAccess::ShaderResourceRead; + if (!IsBuffer(info.Type)) layout = ResLayout::ShaderResource; + break; + case FShaderLayoutItemView::Uav: + switch (info.UavAccess) + { + case FResourceAccess::ReadOnly: + access = ResAccess::UnorderedAccessRead; + break; + case FResourceAccess::WriteOnly: + access = ResAccess::UnorderedAccessWrite; + break; + case FResourceAccess::ReadWrite: + case FResourceAccess::Unknown: + default: + access = ResAccess::UnorderedAccessRead | ResAccess::UnorderedAccessWrite; + break; + } + if (!IsBuffer(info.Type)) layout = ResLayout::UnorderedAccess; + break; + case FShaderLayoutItemView::Sampler: + case FShaderLayoutItemView::Constants: + case FShaderLayoutItemView::StaticSampler: + return; + } + OnUse(ResIndex, access, usage, layout); } - void EnhancedBarrierAnalyzer::UpdateUse(FCmdResRef ResRef) + void EnhancedBarrierAnalyzer::UpdateUse(const FResIndex ResIndex) { - const auto ResIndex = ResRef.ResIndex(); auto& info = m_resources[ResIndex]; if (info.InfoState == InfoState::Unused) COPLT_THROW("The resource is not being used and the usage location cannot be updated"); @@ -205,7 +257,7 @@ namespace Coplt::Enhanced void EnhancedBarrierAnalyzer::CreateBarrier(const ResInfo& info) { - const auto& res = *info.Res; + const auto& res = m_record->m_resource_infos[info.ResIndex]; const auto BeforeListIndex = info.PreGroup + 1; const auto AfterListIndex = info.LstGroup; const auto SyncBefore = GetBarrierSync(info.OldState.Access, info.OldState.Usage); @@ -235,7 +287,7 @@ namespace Coplt::Enhanced }; if (res.IsImage()) { - const auto img_data = GetImageData(res); + const auto img_data = res.GetImageData(); D3D12_TEXTURE_BARRIER barrier{ .SyncBefore = SyncBefore, .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, @@ -243,7 +295,7 @@ namespace Coplt::Enhanced .AccessAfter = AccessAfter, .LayoutBefore = GetBarrierLayout(info.OldState.Layout), .LayoutAfter = GetBarrierLayout(info.State.Layout), - .pResource = GetResource(res), + .pResource = res.GetResource(), .Subresources = { .IndexOrFirstMipLevel = 0, .NumMipLevels = img_data->m_mip_levels, @@ -258,13 +310,13 @@ namespace Coplt::Enhanced } else { - const auto buffer_data = GetBufferData(res); + const auto buffer_data = res.GetBufferData(); D3D12_BUFFER_BARRIER barrier{ .SyncBefore = SyncBefore, .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, .AccessBefore = AccessBefore, .AccessAfter = AccessAfter, - .pResource = GetResource(res), + .pResource = res.GetResource(), .Offset = 0, .Size = buffer_data->m_size, }; @@ -323,7 +375,7 @@ namespace Coplt::Enhanced { for (const auto& record : records) { - const NonNull data = record->Data(); + const auto resource_infos = record->ResourceInfos(); const NonNull barrier_analyzer = record->BarrierAnalyzer()->QueryInterface(); const auto& context = record->Context(); @@ -333,13 +385,14 @@ namespace Coplt::Enhanced for (const auto& input : barrier_analyzer->Inputs()) { - const auto& res = data->Resources[input.ResIndex]; + const auto& res = resource_infos[input.ResIndex]; bool exist; - auto& sr = m_submit_resources.GetOrAdd(res.GetObjectPtr()->ObjectId(), exist, [&](auto& p) + auto& sr = m_submit_resources.GetOrAdd(res.Resource->ObjectId(), exist, [&](auto& p) { p.put(ResInfo{ - .Res = res, - .State = GetState(res), + .Record = record, + .ResIndex = input.ResIndex, + .State = res.GetState(), }); }); if (!exist) @@ -349,7 +402,7 @@ namespace Coplt::Enhanced auto& group = result_list ? m_tmp_group : barrier_analyzer->Groups()[0]; if (res.IsImage()) { - const auto img_data = GetImageData(res); + const auto img_data = res.GetImageData(); const auto SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage); D3D12_TEXTURE_BARRIER barrier{ .SyncBefore = D3D12_BARRIER_SYNC_NONE, @@ -358,7 +411,7 @@ namespace Coplt::Enhanced .AccessAfter = GetBarrierAccess(input.State.Access), .LayoutBefore = GetBarrierLayout(sr.State->Layout), .LayoutAfter = GetBarrierLayout(input.State.Layout), - .pResource = GetResource(res), + .pResource = res.GetResource(), .Subresources = { .IndexOrFirstMipLevel = 0, .NumMipLevels = img_data->m_mip_levels, @@ -373,14 +426,14 @@ namespace Coplt::Enhanced } else { - const auto buffer_data = GetBufferData(res); + const auto buffer_data = res.GetBufferData(); const auto SyncAfter = GetBarrierSync(input.State.Access, input.State.Usage); D3D12_BUFFER_BARRIER barrier{ .SyncBefore = D3D12_BARRIER_SYNC_NONE, .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, .AccessAfter = GetBarrierAccess(input.State.Access), - .pResource = GetResource(res), + .pResource = res.GetResource(), .Offset = 0, .Size = buffer_data->m_size, }; @@ -405,7 +458,7 @@ namespace Coplt::Enhanced if (!m_tmp_group.IsEmpty()) { - auto allocator = context->m_cmd_alloc_pool->RentCommandAllocator(GetType(data->Mode)); + auto allocator = context->m_cmd_alloc_pool->RentCommandAllocator(GetType(record->Data()->Mode)); auto list = allocator.RentCommandList(); EnhancedBarrierAnalyzer::SubmitBarrier(list, m_tmp_group); list.Close(); @@ -421,7 +474,7 @@ namespace Coplt::Enhanced } else { - auto allocator = context->m_cmd_alloc_pool->RentCommandAllocator(GetType(data->Mode)); + auto allocator = context->m_cmd_alloc_pool->RentCommandAllocator(GetType(record->Data()->Mode)); auto list = allocator.RentCommandList(); barrier_analyzer->Interpret(list, *record); list.Close(); @@ -439,12 +492,13 @@ namespace Coplt::Enhanced for (const auto& output : barrier_analyzer->Outputs()) { - const auto& res = data->Resources[output.ResIndex]; - const auto state = GetState(res); + const auto& res = resource_infos[output.ResIndex]; + const auto state = res.GetState(); state->Layout = output.State.Layout; m_submit_resources.AddOrReplace( - res.GetObjectPtr()->ObjectId(), ResInfo{ - .Res = res, + res.Resource->ObjectId(), ResInfo{ + .Record = record, + .ResIndex = output.ResIndex, .State = state, } ); diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index 0c13c4e..87a1a1b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -3,6 +3,7 @@ #include "Context.h" #include "Device.h" #include "Isolate.h" +#include "Layout.h" #include "../../Api/Include/Object.h" #include "../../Api/FFI/Cmd.h" #include "../Include/ResState.h" @@ -19,6 +20,8 @@ namespace Coplt struct ID3d12BarrierAnalyzer; struct ID3d12BarrierCombiner; + struct D3d12GpuRecord; + struct ResourceInfo; COPLT_INTERFACE_DEFINE(ID3d12BarrierMarshal, "792f273c-376d-4027-af99-0d14d3d71302", FUnknown) { @@ -32,12 +35,13 @@ namespace Coplt virtual std::span Outputs() const = 0; virtual void Clear() = 0; - virtual void StartAnalyze(std::span resources) = 0; + virtual void StartAnalyze(NonNull record) = 0; virtual void EndAnalyze() = 0; + virtual void OnAddRes() = 0; - virtual void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) = 0; - virtual void OnUse(const View& View) = 0; - virtual void UpdateUse(FCmdResRef ResRef) = 0; + virtual void OnUse(FResIndex ResIndex, ResAccess Access, ResUsage Usage, ResLayout Layout) = 0; + virtual void OnUse(FResIndex ResIndex, const View& View, const Layout::BindItemInfo& info) = 0; + virtual void UpdateUse(FResIndex ResIndex) = 0; virtual void OnCmd() = 0; // 每个命令都需要调用一次 virtual void CmdNext() = 0; @@ -55,7 +59,8 @@ namespace Coplt { struct ResInfo { - FCmdRes Res{}; + NonNull Record; + u32 ResIndex{}; NonNull State; }; @@ -110,7 +115,7 @@ namespace Coplt struct ResInfo { - NonNull Res; + u32 ResIndex; ResState State{}; ResState OldState{}; u32 PreGroup{COPLT_U32_MAX}; @@ -118,7 +123,7 @@ namespace Coplt u32 CurGroup{COPLT_U32_MAX}; InfoState InfoState{}; - explicit ResInfo(NonNull Res); + explicit ResInfo(u32 ResIndex); void SetNewState(ResState state); }; @@ -149,6 +154,7 @@ namespace Coplt std::vector m_groups{}; u32 m_last_cmd_count{}; b8 m_use_split_barrier{}; + NonNull m_record{NonNull::Unchecked(nullptr)}; explicit EnhancedBarrierAnalyzer(const EnhancedBarrierMarshal& marshal); @@ -161,11 +167,13 @@ namespace Coplt u32 CurGroupIndex() const; void Clear() override; - void StartAnalyze(std::span resources) override; + void StartAnalyze(NonNull record) override; void EndAnalyze() override; - void OnUse(FCmdResRef ResRef, ResAccess Access, ResUsage Usage, ResLayout Layout) override; - void OnUse(const View& View) override; - void UpdateUse(FCmdResRef ResRef) override; + void OnAddRes() override; + + void OnUse(FResIndex ResIndex, ResAccess Access, ResUsage Usage, ResLayout Layout) override; + void OnUse(FResIndex ResIndex, const View& View, const Layout::BindItemInfo& info) override; + void UpdateUse(FResIndex ResIndex) override; void OnCmd() override; void CmdNext() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index 7b051e0..61f079c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -20,13 +20,17 @@ D3d12ShaderBindGroup::D3d12ShaderBindGroup(Rc&& device, const FS CountSlots = sum_count; m_views = std::vector(sum_count, View{}); m_item_indexes.reserve(items.size()); + m_define_indexes.reserve(sum_count); for (u32 i = 0, off = 0; i < items.size(); ++i) { m_item_indexes.push_back(off); - off += std::max(1u, items[i].Count); + const auto count = std::max(1u, items[i].Count); + off += count; + for (int j = 0; j < count; ++j) + { + m_define_indexes.push_back(i); + } } - ItemIndexes = m_item_indexes.data(); - NumItemIndexes = static_cast(m_item_indexes.size()); Set(std::span(options.Bindings, options.Bindings + options.NumBindings)); if (!options.Name.is_null()) { @@ -57,6 +61,16 @@ std::span D3d12ShaderBindGroup::Views() const noexcept return m_views; } +std::span D3d12ShaderBindGroup::ItemIndexes() const noexcept +{ + return m_item_indexes; +} + +std::span D3d12ShaderBindGroup::DefineIndexes() const noexcept +{ + return m_define_indexes; +} + RwLock& D3d12ShaderBindGroup::Lock() noexcept { return m_lock; @@ -115,6 +129,11 @@ FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept return FResult::None(); } +FShaderBindingData* D3d12ShaderBinding::ShaderBindingData() noexcept +{ + return this; +} + const Rc& D3d12ShaderBinding::Layout() const noexcept { return m_layout; diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index 495d778..46bb5e6 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -19,6 +19,8 @@ namespace Coplt { virtual const Rc& Layout() const noexcept = 0; virtual std::span Views() const noexcept = 0; + virtual std::span ItemIndexes() const noexcept = 0; + virtual std::span DefineIndexes() const noexcept = 0; virtual RwLock& Lock() noexcept = 0; }; @@ -28,6 +30,7 @@ namespace Coplt Rc m_device{}; Rc m_layout{}; std::vector m_views{}; + std::vector m_define_indexes{}; std::vector m_item_indexes{}; RwLock m_lock{}; @@ -38,9 +41,12 @@ namespace Coplt const Rc& Layout() const noexcept override; std::span Views() const noexcept override; + std::span ItemIndexes() const noexcept override; + std::span DefineIndexes() const noexcept override; RwLock& Lock() noexcept override; void Set(std::span items); + }; COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "5073f785-cfb7-414d-9a84-1602d3bf378d", FShaderBinding) @@ -50,7 +56,7 @@ namespace Coplt virtual RwLock& Lock() noexcept = 0; }; - struct D3d12ShaderBinding final : GpuObject + struct D3d12ShaderBinding final : GpuObject, FShaderBindingData { Rc m_device{}; Rc m_layout{}; @@ -60,6 +66,8 @@ namespace Coplt explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; + FShaderBindingData* ShaderBindingData() noexcept override; + const Rc& Layout() const noexcept override; std::span> Groups() const noexcept override; RwLock& Lock() noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 5a1fb68..1cdcccd 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -310,11 +310,13 @@ FResult D3d12GpuDevice::CreateShaderBindGroup(const FShaderBindGroupCreateOption }); } -FResult D3d12GpuDevice::CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept +FResult D3d12GpuDevice::CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBindingCreateResult* out) noexcept { return feb([&] { - *out = new D3d12ShaderBinding(this->CloneThis(), options); + const auto ptr = new D3d12ShaderBinding(this->CloneThis(), options); + out->Binding = ptr; + out->Data = ptr; }); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.h b/Coplt.Graphics.Native/D3d12/Src/Device.h index fe4bd33..4d3e0ee 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -71,7 +71,7 @@ namespace Coplt FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept override; FResult CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroupCreateResult* out) noexcept override; - FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; + FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBindingCreateResult* out) noexcept override; FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.cc b/Coplt.Graphics.Native/D3d12/Src/Layout.cc index 249675b..4c31999 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.cc @@ -114,13 +114,24 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi ); } } + m_bind_item_infos.reserve(options.NumGroups); for (u32 g = 0; g < options.NumGroups; g++) { + std::vector bind_item_infos{}; const auto& group = m_groups[g]; const auto items = group->GetItems(); + bind_item_infos.reserve(items.size()); for (u32 i = 0; i < items.size(); ++i) { - for (const auto& item = items[i]; const auto stage : IterStage(item.Stages)) + const auto& item = items[i]; + BindItemInfo bind_item_info{}; + bind_item_info.Group = g; + bind_item_info.IndexInGroup = i; + bind_item_info.Format = item.Format; + bind_item_info.Stages = item.Stages; + bind_item_info.View = item.View; + bind_item_info.UavAccess = item.UavAccess; + for (const auto stage : IterStage(item.Stages)) { BindSlot slot(item, stage); const auto info_index = m_slot_to_info.TryGet(slot); @@ -153,8 +164,30 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi } info.Group = g; info.IndexInGroup = i; + switch (def.UavAccess) + { + case FResourceAccess::ReadOnly: + if (bind_item_info.UavAccess == FResourceAccess::Unknown) + bind_item_info.UavAccess = FResourceAccess::ReadOnly; + else if (bind_item_info.UavAccess != FResourceAccess::ReadOnly) + bind_item_info.UavAccess = FResourceAccess::ReadWrite; + break; + case FResourceAccess::WriteOnly: + if (bind_item_info.UavAccess == FResourceAccess::Unknown) + bind_item_info.UavAccess = FResourceAccess::WriteOnly; + else if (bind_item_info.UavAccess != FResourceAccess::WriteOnly) + bind_item_info.UavAccess = FResourceAccess::ReadWrite; + break; + case FResourceAccess::ReadWrite: + case FResourceAccess::Unknown: + default: + bind_item_info.UavAccess = FResourceAccess::ReadWrite; + break; + } } + bind_item_infos.push_back(bind_item_info); } + m_bind_item_infos.push_back(std::move(bind_item_infos)); } std::vector root_parameters{}; @@ -367,6 +400,11 @@ std::span D3d12BindingLayout::SlotInfos() co return m_slot_infos; } +std::span> D3d12BindingLayout::BindItemInfos() const noexcept +{ + return m_bind_item_infos; +} + D3d12ShaderInputLayout::D3d12ShaderInputLayout( Rc&& device, const FShaderInputLayoutCreateOptions& options ) : m_device(std::move(device)) diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.h b/Coplt.Graphics.Native/D3d12/Src/Layout.h index be4ff96..566a769 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.h +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.h @@ -93,6 +93,7 @@ namespace Coplt struct SlotInfo final { + // Shader Layout 中的 index u32 Index{}; u32 Group{COPLT_U32_MAX}; u32 IndexInGroup{COPLT_U32_MAX}; @@ -106,6 +107,17 @@ namespace Coplt { } }; + + struct BindItemInfo + { + u32 Group{}; + u32 IndexInGroup{}; + FGraphicsFormat Format{}; + FShaderStageFlags Stages{}; + FShaderLayoutItemView View{}; + FShaderLayoutItemType Type{}; + FResourceAccess UavAccess{}; + }; } struct D3d12ShaderLayout final : GpuObject, FShaderLayoutData @@ -134,11 +146,13 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12BindingLayout, "dcebfaa2-44d9-4c3c-95e7-28189ce7d5c4", FBindingLayout) { using SlotInfo = Layout::SlotInfo; + using BindItemInfo = Layout::BindItemInfo; virtual const Rc& ShaderLayout() const noexcept = 0; virtual std::span> Groups() const noexcept = 0; virtual const ComPtr& RootSignature() const noexcept = 0; virtual std::span SlotInfos() const noexcept = 0; + virtual std::span> BindItemInfos() const noexcept = 0; }; struct D3d12BindingLayout final : GpuObject @@ -153,6 +167,7 @@ namespace Coplt std::vector m_slot_infos{}; HashMap m_slot_to_info{}; std::vector> m_tables{}; + std::vector> m_bind_item_infos{}; explicit D3d12BindingLayout(Rc&& device, const FBindingLayoutCreateOptions& options); @@ -162,6 +177,7 @@ namespace Coplt std::span> Groups() const noexcept override; const ComPtr& RootSignature() const noexcept override; std::span SlotInfos() const noexcept override; + std::span> BindItemInfos() const noexcept override; }; struct D3d12ShaderInputLayout final : GpuObject diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 51911f2..c0ee584 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -13,6 +13,187 @@ using namespace Coplt; +ResourceInfo::ResourceInfo(Rc&& resource, const FCmdRes& res, const u32 index): Resource(std::move(resource)), Index(index) +{ + Type = res.Type; + switch (res.Type) + { + case FCmdResType::Image: + { + const auto obj = res.Image->QueryInterface(); + if (obj == nullptr) + COPLT_THROW("Image from different backends"); + Image = obj; + return; + } + case FCmdResType::Buffer: + { + const auto obj = res.Image->QueryInterface(); + if (obj == nullptr) + COPLT_THROW("Buffer from different backends"); + Buffer = obj; + return; + } + case FCmdResType::Output: + { + const auto obj = res.Image->QueryInterface(); + if (obj == nullptr) + COPLT_THROW("Output from different backends"); + Output = obj; + return; + } + } + COPLT_THROW("Unreachable"); +} + +ResourceInfo::ResourceInfo(Rc&& resource, const View& view, u32 index): Resource(std::move(resource)), Index(index) +{ + switch (view.m_type) + { + case FViewType::None: + COPLT_THROW("Null view"); + case FViewType::Buffer: + Type = FCmdResType::Buffer; + Buffer = NonNull(view.TryGetBuffer()); + return; + case FViewType::Image: + Type = FCmdResType::Image; + Image = NonNull(view.TryGetImage()); + return; + case FViewType::Sampler: + COPLT_THROW("Samplers cannot be used as resources"); + } + COPLT_THROW("Unreachable"); +} + +bool ResourceInfo::IsImage() const +{ + switch (Type) + { + case FCmdResType::Image: + return true; + case FCmdResType::Buffer: + return false; + case FCmdResType::Output: + return true; + } + return false; +} + +NonNull ResourceInfo::GetResource() const +{ + switch (Type) + { + case FCmdResType::Image: + { + return Image->GetResourcePtr(); + } + case FCmdResType::Buffer: + { + return Buffer->GetResourcePtr(); + } + case FCmdResType::Output: + { + return Output->GetResourcePtr(); + } + } + COPLT_THROW("Unreachable"); +} + +NonNull ResourceInfo::GetBufferData() const +{ + switch (Type) + { + case FCmdResType::Buffer: + { + return Buffer->Data(); + } + case FCmdResType::Image: + COPLT_THROW("Image is not buffer"); + case FCmdResType::Output: + COPLT_THROW("Output is not buffer"); + } + COPLT_THROW("Unreachable"); +} + +NonNull ResourceInfo::GetImageData() const +{ + switch (Type) + { + case FCmdResType::Image: + { + return Image->Data(); + } + case FCmdResType::Output: + { + return Output->ImageData(); + } + case FCmdResType::Buffer: + COPLT_THROW("Buffer is not image"); + } + COPLT_THROW("Unreachable"); +} + +CD3DX12_CPU_DESCRIPTOR_HANDLE ResourceInfo::GetRtv() const +{ + switch (Type) + { + case FCmdResType::Image: + { + COPLT_THROW("TODO"); + } + case FCmdResType::Buffer: + { + COPLT_THROW("TODO"); + } + case FCmdResType::Output: + { + return Output->GetRtv(); + } + } + COPLT_THROW("Unreachable"); +} + +CD3DX12_CPU_DESCRIPTOR_HANDLE ResourceInfo::GetDsv() const +{ + switch (Type) + { + case FCmdResType::Image: + { + COPLT_THROW("TODO"); + } + case FCmdResType::Buffer: + { + COPLT_THROW("TODO"); + } + case FCmdResType::Output: + { + COPLT_THROW("Output dose not support Dsv"); + } + } + COPLT_THROW("Unreachable"); +} + +NonNull ResourceInfo::GetState() const +{ + switch (Type) + { + case FCmdResType::Image: + { + return Image->State(); + } + case FCmdResType::Buffer: + { + return Buffer->State(); + } + case FCmdResType::Output: + { + return Output->State(); + } + } + COPLT_THROW("Unreachable"); +} + void D3d12GpuRecord::PipelineContext::Reset() { Pipeline = nullptr; @@ -103,6 +284,11 @@ const FGpuRecordData* D3d12GpuRecord::Data() const noexcept return this; } +std::span D3d12GpuRecord::ResourceInfos() noexcept +{ + return m_resource_infos; +} + const Rc& D3d12GpuRecord::Context() const noexcept { return m_context; @@ -137,8 +323,9 @@ void D3d12GpuRecord::Recycle() m_queue_wait_points.clear(); m_barrier_analyzer->Clear(); m_context->Recycle(); - m_resources_owner.clear(); - m_set_binding_info.clear(); + m_resource_map.Clear(); + m_resource_infos.clear(); + m_set_binding_infos.clear(); m_pipeline_context.Reset(); ClearData(); Ended = false; @@ -164,8 +351,10 @@ void D3d12GpuRecord::DoEnd() COPLT_THROW("End cannot be called multiple times"); if (Resources.size() >= std::numeric_limits::max()) COPLT_THROW("Too many resources"); + m_barrier_analyzer->StartAnalyze(this); ReadyResource(); Analyze(); + m_barrier_analyzer->EndAnalyze(); if (m_isolate_config->MultiThreadRecord) { auto allocator = m_context->m_cmd_alloc_pool->RentCommandAllocator(GetType(Mode)); @@ -184,14 +373,14 @@ void D3d12GpuRecord::AfterSubmit() m_result_list = {}; } -FCmdRes& D3d12GpuRecord::GetRes(const FCmdResRef& ref) +ResourceInfo& D3d12GpuRecord::GetRes(const FCmdResRef& ref) { - return ref.Get(Resources); + return m_resource_infos[ref.ResIndex()]; } -const FCmdRes& D3d12GpuRecord::GetRes(const FCmdResRef& ref) const +const ResourceInfo& D3d12GpuRecord::GetRes(const FCmdResRef& ref) const { - return ref.Get(Resources); + return m_resource_infos[ref.ResIndex()]; } void D3d12GpuRecord::ResetState() @@ -201,20 +390,57 @@ void D3d12GpuRecord::ResetState() m_pipeline_context.Reset(); } +FResIndex D3d12GpuRecord::AddResource(const FCmdRes& res) +{ + const NonNull obj = res.GetObjectPtr(); + const auto index = m_resource_map.GetOrAdd(obj->ObjectId(), [this, obj, &res](auto& p) + { + const auto index = m_resource_infos.size(); + p.put(static_cast(index)); + m_resource_infos.push_back(ResourceInfo(Rc::UnsafeClone(obj), res, index)); + m_barrier_analyzer->OnAddRes(); + }); + return FResIndex(index); +} + +FResIndex D3d12GpuRecord::AddResource(const View& view) +{ + const auto obj = view.GetViewable(); + const auto index = m_resource_map.GetOrAdd(obj->ObjectId(), [this, obj, &view](auto& p) + { + const auto index = m_resource_infos.size(); + p.put(static_cast(index)); + m_resource_infos.push_back(ResourceInfo(Rc::UnsafeClone(obj), view, index)); + m_barrier_analyzer->OnAddRes(); + }); + return FResIndex(index); +} + void D3d12GpuRecord::ReadyResource() { - m_resources_owner.reserve(Resources.size()); + m_resource_infos.clear(); + m_resource_infos.reserve(Resources.size()); for (u32 i = 0; i < Resources.size(); ++i) { const auto& res = Resources[i]; - m_resources_owner.push_back(Rc::UnsafeClone(res.GetObjectPtr())); + const auto index = AddResource(res); + COPLT_DEBUG_ASSERT(index == i); } } +void D3d12GpuRecord::ReadyBindings() +{ + // todo +} + +void D3d12GpuRecord::ReleaseBindings() +{ + // todo +} + void D3d12GpuRecord::Analyze() { const auto commands = Commands.AsSpan(); - m_barrier_analyzer->StartAnalyze(Resources.AsSpan()); for (u32 i = 0; i < commands.size(); ++i, m_barrier_analyzer->CmdNext()) { const auto& command = commands[i]; @@ -270,7 +496,6 @@ void D3d12GpuRecord::Analyze() break; } } - m_barrier_analyzer->EndAnalyze(); } void D3d12GpuRecord::Analyze_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const @@ -279,14 +504,14 @@ void D3d12GpuRecord::Analyze_PreparePresent(u32 i, const FCmdPreparePresent& cmd COPLT_THROW_FMT("[{}] Cannot use PreparePresent in sub scope", i); if (Mode != FGpuRecordMode::Direct) COPLT_THROW_FMT("[{}] Can only present on the direct mode", i); - m_barrier_analyzer->OnUse(cmd.Output, ResAccess::None, ResUsage::Common, ResLayout::Common); + m_barrier_analyzer->OnUse(cmd.Output.ResIndex(), ResAccess::None, ResUsage::Common, ResLayout::Common); } void D3d12GpuRecord::Analyze_ClearColor(u32 i, const FCmdClearColor& cmd) const { if (m_state != RecordState::Main) COPLT_THROW_FMT("[{}] Cannot use ClearColor in sub scope", i); - m_barrier_analyzer->OnUse(cmd.Image, ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); + m_barrier_analyzer->OnUse(cmd.Image.ResIndex(), ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); m_barrier_analyzer->OnCmd(); } @@ -294,7 +519,7 @@ void D3d12GpuRecord::Analyze_ClearDepthStencil(u32 i, const FCmdClearDepthStenci { if (m_state != RecordState::Main) COPLT_THROW_FMT("[{}] Cannot use ClearDepthStencil in sub scope", i); - m_barrier_analyzer->OnUse(cmd.Image, ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); + m_barrier_analyzer->OnUse(cmd.Image.ResIndex(), ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); m_barrier_analyzer->OnCmd(); } @@ -304,13 +529,13 @@ void D3d12GpuRecord::Analyze_BufferCopy(u32 i, const FCmdBufferCopy& cmd) const COPLT_THROW_FMT("[{}] Cannot use BufferCopy in sub scope", i); if (cmd.SrcType == FBufferRefType2::Buffer && cmd.DstType == FBufferRefType2::Buffer) { - m_barrier_analyzer->OnUse(cmd.Dst.Buffer, ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); - m_barrier_analyzer->OnUse(cmd.Src.Buffer, ResAccess::CopySourceRead, ResUsage::Common, ResLayout::Common); + m_barrier_analyzer->OnUse(cmd.Dst.Buffer.ResIndex(), ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); + m_barrier_analyzer->OnUse(cmd.Src.Buffer.ResIndex(), ResAccess::CopySourceRead, ResUsage::Common, ResLayout::Common); m_barrier_analyzer->OnCmd(); } else if (cmd.SrcType == FBufferRefType2::Upload && cmd.DstType == FBufferRefType2::Buffer) { - m_barrier_analyzer->OnUse(cmd.Dst.Buffer, ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); + m_barrier_analyzer->OnUse(cmd.Dst.Buffer.ResIndex(), ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); m_barrier_analyzer->OnCmd(); } else @@ -334,11 +559,11 @@ void D3d12GpuRecord::Analyze_Render(u32 i, const FCmdRender& cmd) const auto num_rtv = std::min(info.NumRtv, 8u); if (info.Dsv) { - m_barrier_analyzer->OnUse(info.Dsv, ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); + m_barrier_analyzer->OnUse(info.Dsv.ResIndex(), ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); } for (u32 n = 0; n < num_rtv; ++n) { - m_barrier_analyzer->OnUse(info.Rtv[n], ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); + m_barrier_analyzer->OnUse(info.Rtv[n].ResIndex(), ResAccess::RenderTargetWrite, ResUsage::Common, ResLayout::RenderTarget); } m_barrier_analyzer->OnCmd(); } @@ -350,8 +575,8 @@ void D3d12GpuRecord::Analyze_RenderEnd(u32 i, const FCmdRender& cmd) m_state = RecordState::Main; const auto& info = PayloadRenderInfo[cmd.InfoIndex]; const auto num_rtv = std::min(info.NumRtv, 8u); - if (info.Dsv) m_barrier_analyzer->UpdateUse(info.Dsv); - for (u32 n = 0; n < num_rtv; ++n) m_barrier_analyzer->UpdateUse(info.Rtv[n]); + if (info.Dsv) m_barrier_analyzer->UpdateUse(info.Dsv.ResIndex()); + for (u32 n = 0; n < num_rtv; ++n) m_barrier_analyzer->UpdateUse(info.Rtv[n].ResIndex()); m_barrier_analyzer->OnCmd(); m_pipeline_context.Reset(); } @@ -387,15 +612,23 @@ void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) COPLT_THROW_FMT("[{}] Cannot use SetBinding in main scope", i); if (!SetBinding(Bindings[cmd.Binding].Binding, i)) return; const NonNull binding = m_pipeline_context.Binding; + // todo 弄个 vector 存储锁,在 end 结束后统一释放,在 end 开始时统一获取 ReadGuard binding_guard(binding->Lock()); + const auto bind_item_infos = binding->Layout()->BindItemInfos(); const auto groups = binding->Groups(); - for (const auto& group : groups) + for (u32 g = 0; g < groups.size(); ++g) { + const auto& group = groups[g]; + if (!group) continue; ReadGuard group_guard(group->Lock()); const auto views = group->Views(); - for (const auto& view : views) + for (u32 v = 0; v < views.size(); ++v) { - // m_barrier_analyzer->OnUse(view); + const auto& view = views[v]; + if (!view || view.IsSampler()) continue; + const auto& res_index = AddResource(view); + const auto& info = bind_item_infos[g][v]; + m_barrier_analyzer->OnUse(res_index, view, info); } } m_barrier_analyzer->OnCmd(); @@ -408,12 +641,12 @@ void D3d12GpuRecord::Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd const auto& buf = PayloadMeshBuffers[cmd.PayloadIndex]; if (buf.IndexBuffer.Buffer) { - m_barrier_analyzer->OnUse(buf.IndexBuffer.Buffer, ResAccess::IndexBufferRead, ResUsage::VertexOrMesh, ResLayout::Undefined); + m_barrier_analyzer->OnUse(buf.IndexBuffer.Buffer.ResIndex(), ResAccess::IndexBufferRead, ResUsage::VertexOrMesh, ResLayout::Undefined); } for (u32 c = 0; c < buf.VertexBufferCount; ++c) { const auto& item = PayloadVertexBufferRange[c]; - m_barrier_analyzer->OnUse(item.Buffer, ResAccess::VertexBufferRead, ResUsage::VertexOrMesh, ResLayout::Undefined); + m_barrier_analyzer->OnUse(item.Buffer.ResIndex(), ResAccess::VertexBufferRead, ResUsage::VertexOrMesh, ResLayout::Undefined); } m_barrier_analyzer->OnCmd(); } @@ -539,7 +772,7 @@ void D3d12GpuRecord::Interpret_ClearColor(const CmdList& list, const u32 i, cons { if (m_state != RecordState::Main) COPLT_THROW_FMT("[{}] Cannot use ClearColor in sub scope", i); - const auto rtv = GetRtv(GetRes(cmd.Image)); + const auto rtv = GetRes(cmd.Image).GetRtv(); list->g0->ClearRenderTargetView( rtv, cmd.Color, cmd.RectCount, cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) @@ -550,7 +783,7 @@ void D3d12GpuRecord::Interpret_ClearDepthStencil(const CmdList& list, const u32 { if (m_state != RecordState::Main) COPLT_THROW_FMT("[{}] Cannot use ClearDepthStencil in sub scope", i); - const auto dsv = GetDsv(GetRes(cmd.Image)); + const auto dsv = GetRes(cmd.Image).GetDsv(); D3D12_CLEAR_FLAGS flags{}; if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Depth)) flags |= D3D12_CLEAR_FLAG_DEPTH; if (HasFlags(cmd.Clear, FDepthStencilClearFlags::Stencil)) flags |= D3D12_CLEAR_FLAG_STENCIL; @@ -567,8 +800,8 @@ void D3d12GpuRecord::Interpret_BufferCopy(const CmdList& list, u32 i, const FCmd const auto& range = PayloadBufferCopyRange[cmd.RangeIndex]; if (cmd.SrcType == FBufferRefType2::Buffer && cmd.DstType == FBufferRefType2::Buffer) { - const auto dst = GetResource(GetRes(cmd.Dst.Buffer)); - const auto src = GetResource(GetRes(cmd.Src.Buffer)); + const auto dst = GetRes(cmd.Dst.Buffer).GetResource(); + const auto src = GetRes(cmd.Src.Buffer).GetResource(); if (range.Size == std::numeric_limits::max()) { list->g0->CopyResource(dst, src); @@ -580,7 +813,7 @@ void D3d12GpuRecord::Interpret_BufferCopy(const CmdList& list, u32 i, const FCmd } else if (cmd.SrcType == FBufferRefType2::Upload && cmd.DstType == FBufferRefType2::Buffer) { - const auto dst = GetResource(GetRes(cmd.Dst.Buffer)); + const auto dst = GetRes(cmd.Dst.Buffer).GetResource(); if (cmd.Src.Upload.Index >= m_context->m_upload_buffers.size()) COPLT_THROW_FMT("[{}] Index out of bounds", i); const auto& src_obj = m_context->m_upload_buffers[cmd.Src.Upload.Index]; @@ -620,7 +853,7 @@ void D3d12GpuRecord::Interpret_Render(const CmdList& list, const u32 i, const FC const auto& s_load = info.DsvLoadOp[1]; const auto& s_store = info.DsvStoreOp[1]; D3D12_RENDER_PASS_DEPTH_STENCIL_DESC desc{}; - desc.cpuDescriptor = GetDsv(dsv); + desc.cpuDescriptor = dsv.GetDsv(); desc.DepthBeginningAccess = ToDx(d_load, [&](D3D12_CLEAR_VALUE& cv) { cv.Format = ToDx(info.DsvFormat); @@ -635,8 +868,8 @@ void D3d12GpuRecord::Interpret_Render(const CmdList& list, const u32 i, const FC { const auto& res_info = PayloadResolveInfo[info.DsvResolveInfoIndex]; res.Format = ToDx(res_info.Format); - res.pSrcResource = GetResource(GetRes(res_info.Src)); - res.pDstResource = GetResource(GetRes(res_info.Dst)); + res.pSrcResource = GetRes(res_info.Src).GetResource(); + res.pDstResource = GetRes(res_info.Dst).GetResource(); res.SubresourceCount = 0; res.ResolveMode = ToDx(res_info.Mode); }); @@ -644,8 +877,8 @@ void D3d12GpuRecord::Interpret_Render(const CmdList& list, const u32 i, const FC { const auto& res_info = PayloadResolveInfo[info.DsvResolveInfoIndex]; res.Format = ToDx(res_info.Format); - res.pSrcResource = GetResource(GetRes(res_info.Src)); - res.pDstResource = GetResource(GetRes(res_info.Dst)); + res.pSrcResource = GetRes(res_info.Src).GetResource(); + res.pDstResource = GetRes(res_info.Dst).GetResource(); res.SubresourceCount = 0; res.ResolveMode = ToDx(res_info.Mode); }); @@ -657,7 +890,7 @@ void D3d12GpuRecord::Interpret_Render(const CmdList& list, const u32 i, const FC const auto& load = info.RtvLoadOp[n]; const auto& store = info.RtvStoreOp[n]; D3D12_RENDER_PASS_RENDER_TARGET_DESC desc{}; - desc.cpuDescriptor = GetRtv(rtv); + desc.cpuDescriptor = rtv.GetRtv(); desc.BeginningAccess = ToDx(load, [&](D3D12_CLEAR_VALUE& cv) { cv.Format = ToDx(info.RtvFormat[n]); @@ -670,8 +903,8 @@ void D3d12GpuRecord::Interpret_Render(const CmdList& list, const u32 i, const FC { const auto& res_info = PayloadResolveInfo[info.ResolveInfoIndex[n]]; res.Format = ToDx(res_info.Format); - res.pSrcResource = GetResource(GetRes(res_info.Src)); - res.pDstResource = GetResource(GetRes(res_info.Dst)); + res.pSrcResource = GetRes(res_info.Src).GetResource(); + res.pDstResource = GetRes(res_info.Dst).GetResource(); res.SubresourceCount = 0; res.ResolveMode = ToDx(res_info.Mode); }); @@ -750,7 +983,7 @@ void D3d12GpuRecord::Interpret_SetMeshBuffers(const CmdList& list, u32 i, const const auto vbs = std::span(PayloadVertexBufferRange.data() + buffers.VertexBuffersIndex, buffers.VertexBufferCount); if (buffers.IndexBuffer.Buffer) { - const auto resource = GetResource(GetRes(buffers.IndexBuffer.Buffer)); + const auto resource = GetRes(buffers.IndexBuffer.Buffer).GetResource(); D3D12_INDEX_BUFFER_VIEW view{}; view.BufferLocation = resource->GetGPUVirtualAddress() + buffers.IndexBuffer.Offset; view.SizeInBytes = buffers.IndexBuffer.Size; @@ -762,7 +995,7 @@ void D3d12GpuRecord::Interpret_SetMeshBuffers(const CmdList& list, u32 i, const { const auto& range = vbs[j]; const auto& def = defs[range.Index]; - const auto resource = GetResource(GetRes(range.Buffer)); + const auto resource = GetRes(range.Buffer).GetResource(); D3D12_VERTEX_BUFFER_VIEW view{}; view.BufferLocation = resource->GetGPUVirtualAddress() + range.Offset; view.SizeInBytes = range.Size; @@ -849,130 +1082,3 @@ D3D12_COMMAND_LIST_TYPE Coplt::GetType(const FGpuRecordMode Mode) } return D3D12_COMMAND_LIST_TYPE_DIRECT; } - -NonNull Coplt::GetResource(const FCmdRes& res) -{ - switch (res.Type) - { - case FCmdResType::Image: - { - const NonNull obj = res.Image->QueryInterface(); - return obj->GetResourcePtr(); - } - case FCmdResType::Buffer: - { - const NonNull obj = res.Image->QueryInterface(); - return obj->GetResourcePtr(); - } - case FCmdResType::Output: - { - const NonNull obj = res.Image->QueryInterface(); - return obj->GetResourcePtr(); - } - } - return nullptr; -} - -NonNull Coplt::GetBufferData(const FCmdRes& res) -{ - switch (res.Type) - { - case FCmdResType::Buffer: - { - const NonNull obj = res.Image->QueryInterface(); - return obj->Data(); - } - case FCmdResType::Image: - case FCmdResType::Output: - return nullptr; - } - return nullptr; -} - -NonNull Coplt::GetImageData(const FCmdRes& res) -{ - switch (res.Type) - { - case FCmdResType::Image: - { - const NonNull obj = res.Image->QueryInterface(); - return obj->Data(); - } - case FCmdResType::Output: - { - const NonNull obj = res.Image->QueryInterface(); - return obj->ImageData(); - } - case FCmdResType::Buffer: - return nullptr; - } - return nullptr; -} - -CD3DX12_CPU_DESCRIPTOR_HANDLE Coplt::GetRtv(const FCmdRes& res) -{ - switch (res.Type) - { - case FCmdResType::Image: - { - const NonNull obj = res.Image->QueryInterface(); - COPLT_THROW("TODO"); - } - case FCmdResType::Buffer: - { - const NonNull obj = res.Image->QueryInterface(); - COPLT_THROW("TODO"); - } - case FCmdResType::Output: - { - const NonNull obj = res.Image->QueryInterface(); - return obj->GetRtv(); - } - } - COPLT_THROW("Unreachable"); -} - -CD3DX12_CPU_DESCRIPTOR_HANDLE Coplt::GetDsv(const FCmdRes& res) -{ - switch (res.Type) - { - case FCmdResType::Image: - { - const NonNull obj = res.Image->QueryInterface(); - COPLT_THROW("TODO"); - } - case FCmdResType::Buffer: - { - const NonNull obj = res.Image->QueryInterface(); - COPLT_THROW("TODO"); - } - case FCmdResType::Output: - { - COPLT_THROW("Output dose not support Dsv"); - } - } - COPLT_THROW("Unreachable"); -} - -NonNull Coplt::GetState(const FCmdRes& res) -{ - switch (res.Type) - { - case FCmdResType::Image: - { - const NonNull obj = res.Image->QueryInterface(); - return obj->State(); - } - case FCmdResType::Buffer: - { - const NonNull obj = res.Image->QueryInterface(); - return obj->State(); - } - case FCmdResType::Output: - { - const NonNull obj = res.Image->QueryInterface(); - return obj->State(); - } - } - COPLT_THROW("Unreachable"); -} diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 2a70554..cd12173 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -1,22 +1,56 @@ #pragma once +#include #include #include "../../Api/Include/GpuObject.h" #include "../../Api/FFI/Record.h" #include "Barrier.h" #include "Binding.h" +#include "Buffer.h" #include "Context.h" +#include "Image.h" #include "Isolate.h" #include "Layout.h" +#include "Output.h" namespace Coplt { + struct ResourceInfo + { + Rc Resource{}; + + union + { + ID3d12GpuOutput2* Output; + ID3d12GpuBuffer* Buffer; + ID3d12GpuImage* Image; + }; + + FCmdResType Type{}; + u32 Index{}; + + ResourceInfo() = default; + explicit ResourceInfo(Rc&& resource, const FCmdRes& res, u32 index); + explicit ResourceInfo(Rc&& resource, const View& view, u32 index); + + bool IsImage() const; + + NonNull GetResource() const; + NonNull GetBufferData() const; + NonNull GetImageData() const; + CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv() const; + CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv() const; + NonNull GetState() const; + }; + COPLT_INTERFACE_DEFINE(ID3d12GpuRecord, "57a9c7f9-1ec0-4d78-89b9-e547667c50b3", FGpuRecord) { virtual FGpuRecordData* Data() noexcept = 0; virtual const FGpuRecordData* Data() const noexcept = 0; + virtual std::span ResourceInfos() noexcept = 0; + virtual const Rc& Context() const noexcept = 0; // 可空 @@ -80,7 +114,6 @@ namespace Coplt struct SetBindingInfo { - }; u64 m_isolate_id{}; @@ -89,8 +122,9 @@ namespace Coplt Rc m_device{}; Rc m_context{}; Rc m_barrier_analyzer{}; - std::vector> m_resources_owner{}; - std::vector m_set_binding_info{}; + HashMap m_resource_map{}; // id -> index + std::vector m_resource_infos{}; + std::vector m_set_binding_infos{}; std::vector m_queue_wait_points{}; RenderState m_cur_render{}; ComputeState m_cur_compute{}; @@ -104,6 +138,7 @@ namespace Coplt FGpuRecordData* GpuFGpuRecordData() noexcept override; FGpuRecordData* Data() noexcept override; const FGpuRecordData* Data() const noexcept override; + std::span ResourceInfos() noexcept override; const Rc& Context() const noexcept override; const D3d12RentedCommandList& ResultList() const noexcept override; @@ -119,12 +154,16 @@ namespace Coplt void AfterSubmit() override; - FCmdRes& GetRes(const FCmdResRef& ref); - const FCmdRes& GetRes(const FCmdResRef& ref) const; + ResourceInfo& GetRes(const FCmdResRef& ref); + const ResourceInfo& GetRes(const FCmdResRef& ref) const; void ResetState(); + FResIndex AddResource(const FCmdRes& res); + FResIndex AddResource(const View& view); void ReadyResource(); + void ReadyBindings(); + void ReleaseBindings(); void Analyze(); void Analyze_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const; @@ -165,10 +204,4 @@ namespace Coplt }; D3D12_COMMAND_LIST_TYPE GetType(FGpuRecordMode Mode); - NonNull GetResource(const FCmdRes& res); - NonNull GetBufferData(const FCmdRes& res); - NonNull GetImageData(const FCmdRes& res); - CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv(const FCmdRes& res); - CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv(const FCmdRes& res); - NonNull GetState(const FCmdRes& res); } diff --git a/Coplt.Graphics.Native/D3d12/Src/View.cc b/Coplt.Graphics.Native/D3d12/Src/View.cc index 1e1e080..62a566d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/View.cc +++ b/Coplt.Graphics.Native/D3d12/Src/View.cc @@ -1,5 +1,7 @@ #include "../Include/View.h" #include "../Include/GraphicsFormat.h" +#include "Buffer.h" +#include "Image.h" using namespace Coplt; @@ -46,6 +48,36 @@ bool View::IsCompatible(const FBindGroupItem& def) const return true; } +bool View::IsBuffer() const +{ + return m_type == FViewType::Buffer; +} + +bool View::IsImage() const +{ + return m_type == FViewType::Image; +} + +bool View::IsSampler() const +{ + return m_type == FViewType::Sampler; +} + +NonNull View::GetViewable() const +{ + return m_viewable; +} + +Ptr View::TryGetBuffer() const +{ + return m_viewable->QueryInterface(); +} + +Ptr View::TryGetImage() const +{ + return m_viewable->QueryInterface(); +} + // void View::CreateDescriptor( // NonNull device, const FShaderLayoutItemDefine& def, const CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView type // ) const From 556784322aca32ff2f5cbf2567fece2a158a0d16 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Tue, 8 Apr 2025 17:18:23 +0800 Subject: [PATCH 37/46] save --- Coplt.Graphics.Core/Core/GpuIsolate.cs | 59 +++++++++++++++++++- Coplt.Graphics.Core/Core/GpuOutput.cs | 2 + Coplt.Graphics.Core/Native/Native.cs | 48 +++++++++++++--- Coplt.Graphics.Native/Api/FFI/Isolate.h | 4 ++ Coplt.Graphics.Native/Api/FFI/Output.h | 3 + Coplt.Graphics.Native/D3d12/Src/Isolate.cc | 22 +++++++- Coplt.Graphics.Native/D3d12/Src/Isolate.h | 2 + Coplt.Graphics.Native/D3d12/Src/SwapChain.cc | 49 ++++++++++++---- Coplt.Graphics.Native/D3d12/Src/SwapChain.h | 22 +++++--- 9 files changed, 181 insertions(+), 30 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs index 2b55f4c..626ab00 100644 --- a/Coplt.Graphics.Core/Core/GpuIsolate.cs +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -202,12 +202,21 @@ public void SubmitReturn(params ReadOnlySpan records) #endregion - #region CreateSwapChainForHwnd + #region CreateSwapChainOnWindows + + private enum SwapChainFor + { + Composition, + CoreWindow, + Hwnd, + } /// /// Will fail on non Windows systems /// - public GpuSwapChain CreateSwapChainForHwnd(IntPtr Hwnd, in GpuSwapChainCreateOptions Options, string? Name = null, ReadOnlySpan Name8 = default) + private GpuSwapChain CreateSwapChainOnWindows( + IntPtr Handle, SwapChainFor For, in GpuSwapChainCreateOptions Options, string? Name = null, ReadOnlySpan Name8 = default + ) { fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) @@ -227,13 +236,57 @@ public GpuSwapChain CreateSwapChainForHwnd(IntPtr Hwnd, in GpuSwapChainCreateOpt VSync = Options.VSync, }; FGpuSwapChainCreateResult r; - Ptr->CreateSwapChainForHwnd(&f_options, (void*)Hwnd, &r).TryThrow(); + switch (For) + { + case SwapChainFor.Composition: + Ptr->CreateSwapChainForComposition(&f_options, &r).TryThrow(); + break; + case SwapChainFor.CoreWindow: + Ptr->CreateSwapChainForCoreWindow(&f_options, (void*)Handle, &r).TryThrow(); + break; + case SwapChainFor.Hwnd: + Ptr->CreateSwapChainForHwnd(&f_options, (void*)Handle, &r).TryThrow(); + break; + default: + throw new ArgumentOutOfRangeException(nameof(For), For, null); + } return new(r.SwapChain, r.Data, Name, this); } } #endregion + #region CreateSwapChainForComposition + + /// + /// Will fail on non Windows systems + /// + public GpuSwapChain CreateSwapChainForComposition(in GpuSwapChainCreateOptions Options, string? Name = null, ReadOnlySpan Name8 = default) + => CreateSwapChainOnWindows(0, SwapChainFor.Composition, in Options, Name, Name8); + + #endregion + + #region CreateSwapChainForCoreWindow + + /// + /// Will fail on non Windows systems + /// + public GpuSwapChain CreateSwapChainForCoreWindow( + IntPtr Window, in GpuSwapChainCreateOptions Options, string? Name = null, ReadOnlySpan Name8 = default + ) => CreateSwapChainOnWindows(Window, SwapChainFor.CoreWindow, in Options, Name, Name8); + + #endregion + + #region CreateSwapChainForHwnd + + /// + /// Will fail on non Windows systems + /// + public GpuSwapChain CreateSwapChainForHwnd(IntPtr Hwnd, in GpuSwapChainCreateOptions Options, string? Name = null, ReadOnlySpan Name8 = default) + => CreateSwapChainOnWindows(Hwnd, SwapChainFor.Hwnd, in Options, Name, Name8); + + #endregion + #region CreateBindGroup public ShaderBindGroup CreateBindGroup( diff --git a/Coplt.Graphics.Core/Core/GpuOutput.cs b/Coplt.Graphics.Core/Core/GpuOutput.cs index 7dbc002..667f70e 100644 --- a/Coplt.Graphics.Core/Core/GpuOutput.cs +++ b/Coplt.Graphics.Core/Core/GpuOutput.cs @@ -168,6 +168,8 @@ internal GpuSwapChain(FGpuSwapChain* ptr, FGpuSwapChainData* data, string? name, #region Methods public void SetVSync(bool Enable) => Ptr->SetVSync(Enable).TryThrow(); + + public void GetRawPtr() => Ptr->GetRawPtr(); #endregion } diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index c2dc85f..2b75fa3 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1651,12 +1651,28 @@ public FResult CreateSwapChainFromExists([NativeTypeName("const FGpuSwapChainFro return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateSwapChainForComposition([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] public FResult CreateSwapChainForHwnd([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, void* hwnd, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, hwnd, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, hwnd, @out); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateSwapChainForCoreWindow([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, void* w, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, w, @out); } public interface Interface : FGpuObject.Interface @@ -1679,8 +1695,14 @@ public interface Interface : FGpuObject.Interface [return: NativeTypeName("Coplt::FResult")] FResult CreateSwapChainFromExists([NativeTypeName("const FGpuSwapChainFromExistsCreateOptions &")] FGpuSwapChainFromExistsCreateOptions* options, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out); + [return: NativeTypeName("Coplt::FResult")] + FResult CreateSwapChainForComposition([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out); + [return: NativeTypeName("Coplt::FResult")] FResult CreateSwapChainForHwnd([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, void* hwnd, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateSwapChainForCoreWindow([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, void* w, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out); } } @@ -1837,6 +1859,12 @@ public unsafe partial struct _Anonymous_e__Union } } + public partial struct FResIndex + { + [NativeTypeName("Coplt::u32")] + public uint Value; + } + public partial struct FCmdResRef { [NativeTypeName("Coplt::u32")] @@ -2299,7 +2327,7 @@ public partial struct FCmdDispatch public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L370_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L353_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -3012,14 +3040,8 @@ public unsafe partial struct FShaderBindGroupCreateOptions public uint NumBindings; } - public unsafe partial struct FShaderBindGroupData + public partial struct FShaderBindGroupData { - [NativeTypeName("Coplt::u32 *")] - public uint* ItemIndexes; - - [NativeTypeName("Coplt::u32")] - public uint NumItemIndexes; - [NativeTypeName("Coplt::u32")] public uint CountSlots; } @@ -4344,6 +4366,12 @@ public FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable) return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result, Enable); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* GetRawPtr() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); + } + public interface Interface : FGpuOutput2.Interface { [return: NativeTypeName("const FGpuSwapChainData *")] @@ -4354,6 +4382,8 @@ public interface Interface : FGpuOutput2.Interface [return: NativeTypeName("Coplt::FResult")] FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable); + + void* GetRawPtr(); } } diff --git a/Coplt.Graphics.Native/Api/FFI/Isolate.h b/Coplt.Graphics.Native/Api/FFI/Isolate.h index 77963aa..2149aad 100644 --- a/Coplt.Graphics.Native/Api/FFI/Isolate.h +++ b/Coplt.Graphics.Native/Api/FFI/Isolate.h @@ -56,7 +56,11 @@ namespace Coplt virtual FResult CreateSwapChainFromExists(const FGpuSwapChainFromExistsCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept = 0; // 在非 windows 系统上会报错 + virtual FResult CreateSwapChainForComposition(const FGpuSwapChainCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept = 0; + // 在非 windows 系统上会报错 virtual FResult CreateSwapChainForHwnd(const FGpuSwapChainCreateOptions& options, void* hwnd, FGpuSwapChainCreateResult& out) noexcept = 0; + // 在非 windows 系统上会报错 + virtual FResult CreateSwapChainForCoreWindow(const FGpuSwapChainCreateOptions& options, void* w, FGpuSwapChainCreateResult& out) noexcept = 0; }; struct FGpuIsolateCreateResult diff --git a/Coplt.Graphics.Native/Api/FFI/Output.h b/Coplt.Graphics.Native/Api/FFI/Output.h index e9e9414..fb0177a 100644 --- a/Coplt.Graphics.Native/Api/FFI/Output.h +++ b/Coplt.Graphics.Native/Api/FFI/Output.h @@ -92,6 +92,9 @@ namespace Coplt // 设置垂直同步,实现可以选择忽略 virtual FResult SetVSync(b8 Enable) noexcept = 0; + + // dx 后端是 IDXGISwapChain3* + virtual void* GetRawPtr() const noexcept = 0; }; struct FGpuSwapChainCreateResult diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc index 3c83567..06cb968 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -137,11 +137,31 @@ FResult D3d12GpuIsolate::CreateSwapChainFromExists(const FGpuSwapChainFromExists }); } +FResult D3d12GpuIsolate::CreateSwapChainForComposition(const FGpuSwapChainCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept +{ + return feb([&] + { + const auto ptr = new D3d12GpuSwapChain(this, options, nullptr, SwapChainFor::Composition); + out.SwapChain = ptr; + out.Data = ptr; + }); +} + +FResult D3d12GpuIsolate::CreateSwapChainForCoreWindow(const FGpuSwapChainCreateOptions& options, void* win, FGpuSwapChainCreateResult& out) noexcept +{ + return feb([&] + { + const auto ptr = new D3d12GpuSwapChain(this, options, win, SwapChainFor::CoreWindow); + out.SwapChain = ptr; + out.Data = ptr; + }); +} + FResult D3d12GpuIsolate::CreateSwapChainForHwnd(const FGpuSwapChainCreateOptions& options, void* hwnd, FGpuSwapChainCreateResult& out) noexcept { return feb([&] { - const auto ptr = new D3d12GpuSwapChain(this, options, static_cast(hwnd)); + const auto ptr = new D3d12GpuSwapChain(this, options, hwnd, SwapChainFor::Hwnd); out.SwapChain = ptr; out.Data = ptr; }); diff --git a/Coplt.Graphics.Native/D3d12/Src/Isolate.h b/Coplt.Graphics.Native/D3d12/Src/Isolate.h index 6dde66c..879760b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Isolate.h +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -58,6 +58,8 @@ namespace Coplt FResult SubmitReturn(u32 NumRecords, FGpuRecord** Records) noexcept override; FResult CreateSwapChainFromExists(const FGpuSwapChainFromExistsCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept override; + FResult CreateSwapChainForComposition(const FGpuSwapChainCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept override; + FResult CreateSwapChainForCoreWindow(const FGpuSwapChainCreateOptions& options, void* win, FGpuSwapChainCreateResult& out) noexcept override; FResult CreateSwapChainForHwnd(const FGpuSwapChainCreateOptions& options, void* hwnd, FGpuSwapChainCreateResult& out) noexcept override; void RentRecords(std::span out); diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc index fb1e9c3..eff1622 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -72,8 +72,9 @@ D3d12GpuSwapChain::D3d12GpuSwapChain(const NonNull isolate, con Initialize(); } -D3d12GpuSwapChain::D3d12GpuSwapChain(const NonNull isolate, const FGpuSwapChainCreateOptions& options, HWND hwnd) - : D3d12GpuSwapChain(isolate, options, options.AlphaMode, options.VSync) +D3d12GpuSwapChain::D3d12GpuSwapChain( + const NonNull isolate, const FGpuSwapChainCreateOptions& options, void* handle, SwapChainFor For +) : D3d12GpuSwapChain(isolate, options, options.AlphaMode, options.VSync) { bool is_hdr = false; this->Format = SelectFormat(options, is_hdr); @@ -113,14 +114,37 @@ D3d12GpuSwapChain::D3d12GpuSwapChain(const NonNull isolate, con } ComPtr swap_chain; - chr | m_isolate->m_device->m_instance->m_factory->CreateSwapChainForHwnd( - m_queue.Get(), - hwnd, - &desc, - nullptr, - nullptr, - &swap_chain - ); + + if (For == SwapChainFor::Composition) + { + chr | m_isolate->m_device->m_instance->m_factory->CreateSwapChainForComposition( + m_queue.Get(), + &desc, + nullptr, + &swap_chain + ); + } + else if (For == SwapChainFor::CoreWindow) + { + chr | m_isolate->m_device->m_instance->m_factory->CreateSwapChainForCoreWindow( + m_queue.Get(), + static_cast(handle), + &desc, + nullptr, + &swap_chain + ); + } + else + { + chr | m_isolate->m_device->m_instance->m_factory->CreateSwapChainForHwnd( + m_queue.Get(), + static_cast(handle), + &desc, + nullptr, + nullptr, + &swap_chain + ); + } chr | swap_chain.As(&m_swap_chain); @@ -372,3 +396,8 @@ void D3d12GpuSwapChain::WaitFenceValueNoLock(const u64 fence_value) const { m_isolate->m_main_queue->WaitFenceValue(fence_value, m_event); } + +void* D3d12GpuSwapChain::GetRawPtr() const noexcept +{ + return m_swap_chain.Get(); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.h b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h index 95788e0..2f735be 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.h +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h @@ -10,7 +10,17 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12GpuSwapChain, "d726caf3-41c4-4d60-895e-61c68a4dff98", FGpuSwapChain) { constexpr static UINT MaxBufferCount = 3; + }; + + enum class SwapChainFor + { + Hwnd, + CoreWindow, + Composition, + }; + struct D3d12GpuSwapChain final : GpuObject, FGpuSwapChainData + { Rc m_isolate{}; // 可空 Rc m_name{}; @@ -19,6 +29,8 @@ namespace Coplt ComPtr m_swap_chain{}; ComPtr m_rtv_heap{}; ComPtr m_buffers[MaxBufferCount]; + FGpuImageData m_image_data{}; + LayoutState m_layout_state{}; std::mutex m_resize_mutex{}; std::mutex m_present_mutex{}; HANDLE m_event{}; @@ -31,12 +43,6 @@ namespace Coplt std::atomic_bool m_waiting{}; std::atomic_bool m_need_resize{}; b8 m_debug_enabled{}; - }; - - struct D3d12GpuSwapChain final : GpuObject, FGpuSwapChainData - { - FGpuImageData m_image_data{}; - LayoutState m_layout_state{}; private: explicit D3d12GpuSwapChain( @@ -47,7 +53,7 @@ namespace Coplt public: explicit D3d12GpuSwapChain(NonNull isolate, const FGpuSwapChainFromExistsCreateOptions& options); - explicit D3d12GpuSwapChain(NonNull isolate, const FGpuSwapChainCreateOptions& options, HWND hwnd); + explicit D3d12GpuSwapChain(NonNull isolate, const FGpuSwapChainCreateOptions& options, void* handle, SwapChainFor For); static FGraphicsFormat SelectFormat(const FGpuSwapChainCreateOptions& options, bool& is_hdr); @@ -85,5 +91,7 @@ namespace Coplt void WaitAllNoLock() const; void WaitFenceValueNoLock(u64 fence_value) const; + + void* GetRawPtr() const noexcept override; }; } From 5f06aadbe802aada3a446ba8c8d1c067d85a2016 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Wed, 9 Apr 2025 14:23:07 +0800 Subject: [PATCH 38/46] save --- Coplt.Graphics.Core/Core/GpuRecord.cs | 7 +----- Coplt.Graphics.Native/Api/Include/Finally.h | 2 +- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 24 +++++++++++++++--- Coplt.Graphics.Native/D3d12/Src/Binding.h | 28 +++++++++++++++------ Coplt.Graphics.Native/D3d12/Src/Layout.cc | 12 +++++++++ Coplt.Graphics.Native/D3d12/Src/Layout.h | 24 ++++++++++++++++-- Coplt.Graphics.Native/D3d12/Src/Record.cc | 22 ++++++++-------- Coplt.Graphics.Native/D3d12/Src/Record.h | 5 +++- 8 files changed, 93 insertions(+), 31 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index bb1ab3d..1b1b2ee 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -814,12 +814,7 @@ public void SetBinding(GpuRecord self, ShaderBinding Binding) Binding = (uint)self.Data.Bindings.LongLength, Index = self.Data.NumSetBindings++, }; - self.Data.Bindings.Add( - new() - { - Binding = Binding.Ptr - } - ); + self.Data.Bindings.Add(new() { Binding = Binding.Ptr }); self.Data.Commands.Add(new() { SetBinding = cmd }); if (first) self.Data.SumMaxBindSlots += Binding.Data.SumPersistentSlots + Binding.Data.SumTransientSlots; } diff --git a/Coplt.Graphics.Native/Api/Include/Finally.h b/Coplt.Graphics.Native/Api/Include/Finally.h index 6ddf10d..cdc5f17 100644 --- a/Coplt.Graphics.Native/Api/Include/Finally.h +++ b/Coplt.Graphics.Native/Api/Include/Finally.h @@ -18,7 +18,7 @@ namespace Coplt { } - ~Finally() + ~Finally() noexcept(false) { f(); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index 61f079c..d6cddf8 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -71,13 +71,14 @@ std::span D3d12ShaderBindGroup::DefineIndexes() const noexcept return m_define_indexes; } -RwLock& D3d12ShaderBindGroup::Lock() noexcept +RwLock& D3d12ShaderBindGroup::SelfLock() noexcept { - return m_lock; + return m_self_lock; } void D3d12ShaderBindGroup::Set(const std::span items) { + if (items.empty()) return; const auto defs = m_layout->GetItems(); for (const auto& item : items) { @@ -111,6 +112,16 @@ void D3d12ShaderBindGroup::Set(const std::span items) } m_views[index] = std::move(view); } + m_changed = true; +} + +void D3d12ShaderBindGroup::EnsureAvailable(ID3d12ShaderBinding& binding, u32 group_index) +{ + if (!m_changed) return; + std::lock_guard guard(binding.DescLock()); + if (!m_changed) return; + // todo + m_changed = false; } D3d12ShaderBinding::D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options) : m_device(std::move(device)) @@ -144,9 +155,14 @@ std::span> D3d12ShaderBinding::Groups() const no return m_groups; } -RwLock& D3d12ShaderBinding::Lock() noexcept +RwLock& D3d12ShaderBinding::SelfLock() noexcept +{ + return m_self_lock; +} + +std::mutex& D3d12ShaderBinding::DescLock() noexcept { - return m_lock; + return m_desc_lock; } void D3d12ShaderBinding::Set(const std::span items) diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index 46bb5e6..2ca4b86 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -12,7 +12,7 @@ namespace Coplt { struct DescriptorHeap; - struct D3d12GpuQueue; + struct ID3d12ShaderBinding; struct DescriptorAllocation; COPLT_INTERFACE_DEFINE(ID3d12ShaderBindGroup, "5bb948b9-ad31-4eb8-b881-98017e048259", FShaderBindGroup) @@ -21,7 +21,8 @@ namespace Coplt virtual std::span Views() const noexcept = 0; virtual std::span ItemIndexes() const noexcept = 0; virtual std::span DefineIndexes() const noexcept = 0; - virtual RwLock& Lock() noexcept = 0; + virtual RwLock& SelfLock() noexcept = 0; + virtual void EnsureAvailable(ID3d12ShaderBinding& binding, u32 group_index) = 0; }; struct D3d12ShaderBindGroup final : GpuObject, FShaderBindGroupData @@ -32,7 +33,9 @@ namespace Coplt std::vector m_views{}; std::vector m_define_indexes{}; std::vector m_item_indexes{}; - RwLock m_lock{}; + // 绑定修改锁 + RwLock m_self_lock{}; + volatile bool m_changed{}; explicit D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; @@ -43,17 +46,21 @@ namespace Coplt std::span Views() const noexcept override; std::span ItemIndexes() const noexcept override; std::span DefineIndexes() const noexcept override; - RwLock& Lock() noexcept override; + RwLock& SelfLock() noexcept override; + // 需要外部锁 m_self_lock 必须是 Write 锁定状态 void Set(std::span items); + // 需要外部锁 m_self_lock 和 binding 的 m_self_lock 必须是 Read 锁定状态 + void EnsureAvailable(ID3d12ShaderBinding& binding, u32 group_index) override; }; COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "5073f785-cfb7-414d-9a84-1602d3bf378d", FShaderBinding) { virtual const Rc& Layout() const noexcept = 0; virtual std::span> Groups() const noexcept = 0; - virtual RwLock& Lock() noexcept = 0; + virtual RwLock& SelfLock() noexcept = 0; + virtual std::mutex& DescLock() noexcept = 0; }; struct D3d12ShaderBinding final : GpuObject, FShaderBindingData @@ -61,7 +68,12 @@ namespace Coplt Rc m_device{}; Rc m_layout{}; std::vector> m_groups{}; - RwLock m_lock{}; + ComPtr m_resource_heap{}; + ComPtr m_sampler_heap{}; + // 绑定修改锁 + RwLock m_self_lock{}; + // 标识符创建锁,必须在 m_self_lock Read 锁定状态使用 + std::mutex m_desc_lock{}; explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; @@ -70,8 +82,10 @@ namespace Coplt const Rc& Layout() const noexcept override; std::span> Groups() const noexcept override; - RwLock& Lock() noexcept override; + RwLock& SelfLock() noexcept override; + std::mutex& DescLock() noexcept override; + // 需要外部锁 m_self_lock 必须是 Write 锁定状态 void Set(std::span items); }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.cc b/Coplt.Graphics.Native/D3d12/Src/Layout.cc index 4c31999..d311405 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.cc @@ -328,6 +328,8 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi param.DescriptorTable.pDescriptorRanges = Ranges.data(); root_parameters.push_back(param); infos.push_back(Info); + if (Info.Type == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER) SumTableSamplerSlots += Info.Size; + else SumTableResourceSlots += Info.Size; } m_tables.push_back(std::move(infos)); } @@ -380,6 +382,11 @@ FResult D3d12BindingLayout::SetName(const FStr8or16& name) noexcept }); } +const D3d12BindingLayoutData& D3d12BindingLayout::Data() const noexcept +{ + return *this; +} + const Rc& D3d12BindingLayout::ShaderLayout() const noexcept { return m_shader_layout; @@ -400,6 +407,11 @@ std::span D3d12BindingLayout::SlotInfos() co return m_slot_infos; } +std::span> D3d12BindingLayout::TableInfos() const noexcept +{ + return m_tables; +} + std::span> D3d12BindingLayout::BindItemInfos() const noexcept { return m_bind_item_infos; diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.h b/Coplt.Graphics.Native/D3d12/Src/Layout.h index 566a769..bc4a832 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.h +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.h @@ -23,6 +23,14 @@ namespace Coplt D3D12_DESCRIPTOR_RANGE_TYPE Type{}; }; + struct GroupInfo final + { + std::vector Tables{}; + // 第一个资源描述符表在 cpu 暂存描述符堆中的偏移 + u32 ResourceTableOffset{}; + u32 SamplerTableOffset{}; + }; + struct TableDefine final { std::vector Ranges{}; @@ -143,22 +151,30 @@ namespace Coplt FBindGroupLayoutData* BindGroupLayoutData() noexcept override; }; + struct D3d12BindingLayoutData + { + u32 SumTableResourceSlots{}; + u32 SumTableSamplerSlots{}; + }; + COPLT_INTERFACE_DEFINE(ID3d12BindingLayout, "dcebfaa2-44d9-4c3c-95e7-28189ce7d5c4", FBindingLayout) { using SlotInfo = Layout::SlotInfo; using BindItemInfo = Layout::BindItemInfo; + using TableInfo = Layout::TableInfo; + virtual const D3d12BindingLayoutData& Data() const noexcept = 0; virtual const Rc& ShaderLayout() const noexcept = 0; virtual std::span> Groups() const noexcept = 0; virtual const ComPtr& RootSignature() const noexcept = 0; virtual std::span SlotInfos() const noexcept = 0; + virtual std::span> TableInfos() const noexcept = 0; virtual std::span> BindItemInfos() const noexcept = 0; }; - struct D3d12BindingLayout final : GpuObject + struct D3d12BindingLayout final : GpuObject, D3d12BindingLayoutData { using BindSlot = Layout::BindSlot; - using TableInfo = Layout::TableInfo; Rc m_device{}; ComPtr m_root_signature{}; @@ -166,17 +182,21 @@ namespace Coplt std::vector> m_groups{}; std::vector m_slot_infos{}; HashMap m_slot_to_info{}; + // 第一层索引是 Group index std::vector> m_tables{}; + // 第一层索引是 Group index std::vector> m_bind_item_infos{}; explicit D3d12BindingLayout(Rc&& device, const FBindingLayoutCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; + const D3d12BindingLayoutData& Data() const noexcept override; const Rc& ShaderLayout() const noexcept override; std::span> Groups() const noexcept override; const ComPtr& RootSignature() const noexcept override; std::span SlotInfos() const noexcept override; + std::span> TableInfos() const noexcept override; std::span> BindItemInfos() const noexcept override; }; diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index c0ee584..99e1686 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -10,6 +10,7 @@ #include "Buffer.h" #include "Pipeline.h" #include "GraphicsPipeline.h" +#include "../../Api/Include/Finally.h" using namespace Coplt; @@ -353,6 +354,7 @@ void D3d12GpuRecord::DoEnd() COPLT_THROW("Too many resources"); m_barrier_analyzer->StartAnalyze(this); ReadyResource(); + ReadyBindings(); Analyze(); m_barrier_analyzer->EndAnalyze(); if (m_isolate_config->MultiThreadRecord) @@ -430,12 +432,12 @@ void D3d12GpuRecord::ReadyResource() void D3d12GpuRecord::ReadyBindings() { - // todo -} - -void D3d12GpuRecord::ReleaseBindings() -{ - // todo + m_set_binding_infos.clear(); + m_set_binding_infos.reserve(NumSetBindings); + for (u32 i = 0; i < NumSetBindings; ++i) + { + m_set_binding_infos.push_back(SetBindingInfo()); + } } void D3d12GpuRecord::Analyze() @@ -485,7 +487,7 @@ void D3d12GpuRecord::Analyze() break; case FCmdType::SetViewportScissor: if (Mode != FGpuRecordMode::Direct) - COPLT_THROW_FMT("[{}] Can only Draw on the direct mode", i); + COPLT_THROW_FMT("[{}] Can only SetViewportScissor on the direct mode", i); break; case FCmdType::Draw: if (Mode != FGpuRecordMode::Direct) @@ -612,15 +614,14 @@ void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) COPLT_THROW_FMT("[{}] Cannot use SetBinding in main scope", i); if (!SetBinding(Bindings[cmd.Binding].Binding, i)) return; const NonNull binding = m_pipeline_context.Binding; - // todo 弄个 vector 存储锁,在 end 结束后统一释放,在 end 开始时统一获取 - ReadGuard binding_guard(binding->Lock()); + ReadGuard binding_guard(binding->SelfLock()); const auto bind_item_infos = binding->Layout()->BindItemInfos(); const auto groups = binding->Groups(); for (u32 g = 0; g < groups.size(); ++g) { const auto& group = groups[g]; if (!group) continue; - ReadGuard group_guard(group->Lock()); + ReadGuard group_guard(group->SelfLock()); const auto views = group->Views(); for (u32 v = 0; v < views.size(); ++v) { @@ -630,6 +631,7 @@ void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) const auto& info = bind_item_infos[g][v]; m_barrier_analyzer->OnUse(res_index, view, info); } + group->EnsureAvailable(*binding, g); } m_barrier_analyzer->OnCmd(); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index cd12173..8747529 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -112,6 +112,10 @@ namespace Coplt void SetBinding(NonNull binding, u32 i); }; + struct BindingInfo + { + }; + struct SetBindingInfo { }; @@ -163,7 +167,6 @@ namespace Coplt FResIndex AddResource(const View& view); void ReadyResource(); void ReadyBindings(); - void ReleaseBindings(); void Analyze(); void Analyze_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const; From e843d3a0f22bf477a4fb3353062ecd250514dee0 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Wed, 9 Apr 2025 15:41:24 +0800 Subject: [PATCH 39/46] save --- Coplt.Graphics.Core/Core/GpuRecord.cs | 2 +- Coplt.Graphics.Native/Api/FFI/Layout.h | 1 + Coplt.Graphics.Native/D3d12/Src/Layout.cc | 66 +++++++++++++++++++---- Coplt.Graphics.Native/D3d12/Src/Layout.h | 50 ++++++++++++----- 4 files changed, 95 insertions(+), 24 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 1b1b2ee..30e2120 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -816,7 +816,7 @@ public void SetBinding(GpuRecord self, ShaderBinding Binding) }; self.Data.Bindings.Add(new() { Binding = Binding.Ptr }); self.Data.Commands.Add(new() { SetBinding = cmd }); - if (first) self.Data.SumMaxBindSlots += Binding.Data.SumPersistentSlots + Binding.Data.SumTransientSlots; + if (first) self.Data.SumMaxBindSlots += Binding.Data.SumPersistentSlots + Binding.Data.SumTransientSlots; // todo 这个计算移到 c艹 } #endregion diff --git a/Coplt.Graphics.Native/Api/FFI/Layout.h b/Coplt.Graphics.Native/Api/FFI/Layout.h index da87653..8bc2541 100644 --- a/Coplt.Graphics.Native/Api/FFI/Layout.h +++ b/Coplt.Graphics.Native/Api/FFI/Layout.h @@ -200,6 +200,7 @@ namespace Coplt // 一般组 Common = 0, // 提示组的使用是频繁更改的,d3d12 将会尽可能使用根描述符 + // 只有缓冲区可以使用根描述符,且建议小缓冲区(几个 32 位值)尽量使用根常量 Dynamic = 1, }; diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.cc b/Coplt.Graphics.Native/D3d12/Src/Layout.cc index d311405..92952dd 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.cc @@ -74,6 +74,39 @@ D3d12BindGroupLayout::D3d12BindGroupLayout(const FBindGroupLayoutCreateOptions& NumItems = m_items.size(); NumStaticSamplers = m_static_samplers.size(); Usage = options.Usage; + + m_slots.reserve(m_items.size()); + for (u32 i = 0; i < m_items.size(); ++i) + { + BindSlotInfo info{}; + const auto& item = m_items[i]; + const auto count = std::max(1u, item.Count); + switch (item.View) + { + case FShaderLayoutItemView::Cbv: + case FShaderLayoutItemView::Srv: + case FShaderLayoutItemView::Uav: + if (Usage == FBindGroupUsage::Dynamic && item.Count <= 1 && IsBuffer(item.Type)) + { + info.Place = BindSlotPlace::NonTable; + break; + } + info.OffsetInTable = ResourceTableSize; + info.Place = BindSlotPlace::ResourceTable; + ResourceTableSize += count; + break; + case FShaderLayoutItemView::Sampler: + info.OffsetInTable = SamplerTableSize; + info.Place = BindSlotPlace::SamplerTable; + SamplerTableSize += count; + break; + case FShaderLayoutItemView::Constants: + case FShaderLayoutItemView::StaticSampler: + info.Place = BindSlotPlace::NonTable; + break; + } + m_slots.push_back(info); + } } FResult D3d12BindGroupLayout::SetName(const FStr8or16& name) noexcept @@ -86,6 +119,16 @@ FBindGroupLayoutData* D3d12BindGroupLayout::BindGroupLayoutData() noexcept return this; } +const D3d12BindGroupLayoutData& D3d12BindGroupLayout::Data() const noexcept +{ + return *this; +} + +std::span D3d12BindGroupLayout::Slots() const noexcept +{ + return m_slots; +} + D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindingLayoutCreateOptions& options) : m_device(device) { @@ -93,7 +136,10 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi m_groups.reserve(options.NumGroups); for (u32 i = 0; i < options.NumGroups; i++) { - m_groups.push_back(Rc::UnsafeClone(options.Groups[i])); + const auto group = NonNull(options.Groups[i])->QueryInterface(); + if (group == nullptr) + COPLT_THROW_FMT("Group [{}] from different backends", i); + m_groups.push_back(Rc::UnsafeClone(group)); } const auto defines = m_shader_layout->GetItems(); @@ -119,6 +165,9 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi { std::vector bind_item_infos{}; const auto& group = m_groups[g]; + const auto& group_data = group->Data(); + SumTableSamplerSlots += group_data.ResourceTableSize; + SumTableResourceSlots += group_data.SamplerTableSize; const auto items = group->GetItems(); bind_item_infos.reserve(items.size()); for (u32 i = 0; i < items.size(); ++i) @@ -229,7 +278,8 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi if (item.View == FShaderLayoutItemView::Sampler) goto DefineDescriptorTable; - if (group->Data().Usage == FBindGroupUsage::Dynamic) + const auto usage = group->Data().Usage; + if (usage == FBindGroupUsage::Dynamic) { if (item.Count > 1 || !IsBuffer(item.Type)) { @@ -256,8 +306,9 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi DefineDescriptorTable: { - const auto group_items = group->GetItems(); - const auto& group_item = group_items[info.IndexInGroup]; + const auto slots = group->Slots(); + const auto& slot = slots[info.IndexInGroup]; + COPLT_DEBUG_ASSERT(slot.Place != BindSlotPlace::NonTable); D3D12_DESCRIPTOR_RANGE1 range{}; const auto range_type = ToTableType(item.View); range.RangeType = range_type; @@ -274,11 +325,10 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi range.NumDescriptors = std::max(1u, item.Count); range.BaseShaderRegister = item.Slot; range.RegisterSpace = item.Space; - range.OffsetInDescriptorsFromTableStart = table.Info.Size; + range.OffsetInDescriptorsFromTableStart = slot.OffsetInTable; info.SigIndex = static_cast(table.Ranges.size()); info.SigPlace = SigPlace::Grouped; table.Ranges.push_back(range); - table.Info.Size += group_item.Count; continue; } DefineDescriptor: @@ -328,8 +378,6 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi param.DescriptorTable.pDescriptorRanges = Ranges.data(); root_parameters.push_back(param); infos.push_back(Info); - if (Info.Type == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER) SumTableSamplerSlots += Info.Size; - else SumTableResourceSlots += Info.Size; } m_tables.push_back(std::move(infos)); } @@ -392,7 +440,7 @@ const Rc& D3d12BindingLayout::ShaderLayout() const noexcept return m_shader_layout; } -std::span> D3d12BindingLayout::Groups() const noexcept +std::span> D3d12BindingLayout::Groups() const noexcept { return m_groups; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.h b/Coplt.Graphics.Native/D3d12/Src/Layout.h index bc4a832..6a15eb0 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.h +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.h @@ -14,23 +14,27 @@ namespace Coplt { D3D12_DESCRIPTOR_RANGE_TYPE ToTableType(FShaderLayoutItemView view); + enum class BindSlotPlace : u8 + { + NonTable, + ResourceTable, + SamplerTable, + }; + + struct BindSlotInfo + { + u32 OffsetInTable{}; + BindSlotPlace Place{}; + }; + struct TableInfo final { - u32 Size{}; u32 Group{}; u32 RootIndex{}; FShaderStage Stage{}; D3D12_DESCRIPTOR_RANGE_TYPE Type{}; }; - struct GroupInfo final - { - std::vector Tables{}; - // 第一个资源描述符表在 cpu 暂存描述符堆中的偏移 - u32 ResourceTableOffset{}; - u32 SamplerTableOffset{}; - }; - struct TableDefine final { std::vector Ranges{}; @@ -139,16 +143,32 @@ namespace Coplt FShaderLayoutData* ShaderLayoutData() noexcept override; }; - struct D3d12BindGroupLayout final : GpuObject, FBindGroupLayoutData + struct D3d12BindGroupLayoutData : FBindGroupLayoutData + { + u32 ResourceTableSize{}; + u32 SamplerTableSize{}; + }; + + COPLT_INTERFACE_DEFINE(ID3d12BindGroupLayout, "2e440ba8-f47a-4f98-a434-31125406e55c", FBindGroupLayout) + { + using BindSlotInfo = Layout::BindSlotInfo; + virtual const D3d12BindGroupLayoutData& Data() const noexcept = 0; + virtual std::span Slots() const noexcept = 0; + }; + + struct D3d12BindGroupLayout final : GpuObject, D3d12BindGroupLayoutData { std::vector m_items{}; std::vector m_static_samplers{}; + std::vector m_slots{}; explicit D3d12BindGroupLayout(const FBindGroupLayoutCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; FBindGroupLayoutData* BindGroupLayoutData() noexcept override; + const D3d12BindGroupLayoutData& Data() const noexcept override; + std::span Slots() const noexcept override; }; struct D3d12BindingLayoutData @@ -157,7 +177,7 @@ namespace Coplt u32 SumTableSamplerSlots{}; }; - COPLT_INTERFACE_DEFINE(ID3d12BindingLayout, "dcebfaa2-44d9-4c3c-95e7-28189ce7d5c4", FBindingLayout) + COPLT_INTERFACE_DEFINE(ID3d12BindingLayout, "7271c0de-ec05-44be-9d1b-4b54894e297e", FBindingLayout) { using SlotInfo = Layout::SlotInfo; using BindItemInfo = Layout::BindItemInfo; @@ -165,10 +185,12 @@ namespace Coplt virtual const D3d12BindingLayoutData& Data() const noexcept = 0; virtual const Rc& ShaderLayout() const noexcept = 0; - virtual std::span> Groups() const noexcept = 0; + virtual std::span> Groups() const noexcept = 0; virtual const ComPtr& RootSignature() const noexcept = 0; virtual std::span SlotInfos() const noexcept = 0; + // 第一层索引是 Group index virtual std::span> TableInfos() const noexcept = 0; + // 第一层索引是 Group index virtual std::span> BindItemInfos() const noexcept = 0; }; @@ -179,7 +201,7 @@ namespace Coplt Rc m_device{}; ComPtr m_root_signature{}; Rc m_shader_layout{}; - std::vector> m_groups{}; + std::vector> m_groups{}; std::vector m_slot_infos{}; HashMap m_slot_to_info{}; // 第一层索引是 Group index @@ -193,7 +215,7 @@ namespace Coplt const D3d12BindingLayoutData& Data() const noexcept override; const Rc& ShaderLayout() const noexcept override; - std::span> Groups() const noexcept override; + std::span> Groups() const noexcept override; const ComPtr& RootSignature() const noexcept override; std::span SlotInfos() const noexcept override; std::span> TableInfos() const noexcept override; From 7963f2be038a81b2905e82f26186244f70c30e4a Mon Sep 17 00:00:00 2001 From: U2A5F Date: Wed, 9 Apr 2025 16:31:18 +0800 Subject: [PATCH 40/46] save --- Coplt.Graphics.Native/D3d12/Include/View.h | 25 +- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 133 ++- Coplt.Graphics.Native/D3d12/Src/Binding.h | 29 +- Coplt.Graphics.Native/D3d12/Src/Record.cc | 2 +- Coplt.Graphics.Native/D3d12/Src/View.cc | 1140 ++++++++++---------- 5 files changed, 704 insertions(+), 625 deletions(-) diff --git a/Coplt.Graphics.Native/D3d12/Include/View.h b/Coplt.Graphics.Native/D3d12/Include/View.h index b4afe93..e8be9c8 100644 --- a/Coplt.Graphics.Native/D3d12/Include/View.h +++ b/Coplt.Graphics.Native/D3d12/Include/View.h @@ -2,6 +2,9 @@ #include +#include +#include + #include "../../Api/FFI/Resource.h" #include "../../Api/FFI/Binding.h" @@ -14,6 +17,7 @@ namespace Coplt struct ID3d12GpuBuffer; struct ID3d12GpuImage; + struct ID3d12GpuSampler; struct View final { @@ -42,21 +46,12 @@ namespace Coplt NonNull GetViewable() const; Ptr TryGetBuffer() const; Ptr TryGetImage() const; + Ptr TryGetSampler() const; - // void CreateDescriptor( - // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type - // ) const; - // static void CreateNullDescriptor( - // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView view - // ); - // void CreateBufferDescriptor( - // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type - // ) const; - // void CreateImageDescriptor( - // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type - // ) const; - // void CreateSamplerDescriptor( - // NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type - // ) const; + void CreateDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const; + static void CreateNullDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle); + void CreateBufferDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const; + void CreateImageDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const; + void CreateSamplerDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index d6cddf8..ffa90fa 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -10,7 +10,10 @@ using namespace Coplt; D3d12ShaderBindGroup::D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options) : m_device(std::move(device)) { - m_layout = Rc::UnsafeClone(NonNull(options.Layout)); + const auto layout = NonNull(options.Layout)->QueryInterface(); + if (layout == nullptr) + COPLT_THROW("Layout from different backends"); + m_layout = Rc::UnsafeClone(layout); const auto items = m_layout->GetItems(); usize sum_count = 0; for (const auto& item : items) @@ -19,6 +22,7 @@ D3d12ShaderBindGroup::D3d12ShaderBindGroup(Rc&& device, const FS } CountSlots = sum_count; m_views = std::vector(sum_count, View{}); + m_changed_marks = std::vector(sum_count, false); m_item_indexes.reserve(items.size()); m_define_indexes.reserve(sum_count); for (u32 i = 0, off = 0; i < items.size(); ++i) @@ -31,11 +35,29 @@ D3d12ShaderBindGroup::D3d12ShaderBindGroup(Rc&& device, const FS m_define_indexes.push_back(i); } } - Set(std::span(options.Bindings, options.Bindings + options.NumBindings)); + const auto& layout_data = m_layout->Data(); + m_resource_heap_inc = m_device->m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + m_sampler_heap_inc = m_device->m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + if (layout_data.ResourceTableSize > 0) + { + D3D12_DESCRIPTOR_HEAP_DESC desc{}; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + desc.NumDescriptors = layout_data.ResourceTableSize; + chr | m_device->m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_resource_heap)); + } + if (layout_data.SamplerTableSize > 0) + { + D3D12_DESCRIPTOR_HEAP_DESC desc{}; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; + desc.NumDescriptors = layout_data.SamplerTableSize; + chr | m_device->m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_sampler_heap)); + } if (!options.Name.is_null()) { m_name = options.Name.ToString(); + DoSetName(m_name->GetStr()); } + Set(std::span(options.Bindings, options.Bindings + options.NumBindings)); } FResult D3d12ShaderBindGroup::SetName(const FStr8or16& name) noexcept @@ -43,15 +65,53 @@ FResult D3d12ShaderBindGroup::SetName(const FStr8or16& name) noexcept return feb([&] { m_name = name.ToString(); + DoSetName(name); }); } +void D3d12ShaderBindGroup::DoSetName(const FStr8or16& name) const +{ + if (name.is_null()) return; + if (m_resource_heap) + { + if (name.is8()) + { + const auto str = fmt::format("[{}]::ResourceDescriptorHeap", name.str8); + chr | m_resource_heap >> SetNameEx(FStr8or16(str)); + } + else + { + const auto str = fmt::format( + L"[{}]::ResourceDescriptorHeap", + reinterpret_cast(name.str16) + ); + chr | m_resource_heap >> SetNameEx(FStr8or16(str)); + } + } + if (m_sampler_heap) + { + if (name.is8()) + { + const auto str = fmt::format("[{}]::SamplerDescriptorHeap", name.str8); + chr | m_resource_heap >> SetNameEx(FStr8or16(str)); + } + else + { + const auto str = fmt::format( + L"[{}]::SamplerDescriptorHeap", + reinterpret_cast(name.str16) + ); + chr | m_resource_heap >> SetNameEx(FStr8or16(str)); + } + } +} + FShaderBindGroupData* D3d12ShaderBindGroup::ShaderBindGroupData() noexcept { return this; } -const Rc& D3d12ShaderBindGroup::Layout() const noexcept +const Rc& D3d12ShaderBindGroup::Layout() const noexcept { return m_layout; } @@ -80,6 +140,7 @@ void D3d12ShaderBindGroup::Set(const std::span items) { if (items.empty()) return; const auto defs = m_layout->GetItems(); + const auto slots = m_layout->Slots(); for (const auto& item : items) { if (item.Slot >= defs.size()) @@ -89,38 +150,59 @@ void D3d12ShaderBindGroup::Set(const std::span items) COPLT_THROW("Index out of range"); const auto index = m_item_indexes[item.Slot] + item.Index; View view(item.View); - if (!view.IsCompatible(def)) + if (view) { - const auto id = ObjectId(); - if (m_device->Debug() && m_device->Logger().IsEnable(FLogLevel::Error)) + if (!view.IsCompatible(def)) { - const auto name = m_name->GetStr(); - if (name.is_null()) - m_device->Logger().Log(FLogLevel::Error, fmt::format("Incompatible bindings in BindGroup({})", id)); - else if (name.is8()) - m_device->Logger().Log(FLogLevel::Error, fmt::format("Incompatible bindings in BindGroup({}, \"{}\")", id, name.str8)); - else - m_device->Logger().LogW( - FLogLevel::Error, - fmt::format( - L"Incompatible bindings in BindGroup({}, \"{}\")", id, - reinterpret_cast(name.str16) - ) - ); + const auto id = ObjectId(); + if (m_device->Debug() && m_device->Logger().IsEnable(FLogLevel::Error)) + { + const auto name = m_name->GetStr(); + if (name.is_null()) + m_device->Logger().Log(FLogLevel::Error, fmt::format("Incompatible bindings in BindGroup({})", id)); + else if (name.is8()) + m_device->Logger().Log(FLogLevel::Error, fmt::format("Incompatible bindings in BindGroup({}, \"{}\")", id, name.str8)); + else + m_device->Logger().LogW( + FLogLevel::Error, + fmt::format( + L"Incompatible bindings in BindGroup({}, \"{}\")", id, + reinterpret_cast(name.str16) + ) + ); + } + COPLT_THROW_FMT("Incompatible bindings [{},{}] in BindGroup({})", item.Slot, item.Index, id); } - COPLT_THROW_FMT("Incompatible bindings [{},{}] in BindGroup({})", item.Slot, item.Index, id); } m_views[index] = std::move(view); + const auto& slot = slots[item.Slot]; + if (slot.Place == Layout::BindSlotPlace::NonTable) continue; + m_changed_marks[index] = true; } m_changed = true; } -void D3d12ShaderBindGroup::EnsureAvailable(ID3d12ShaderBinding& binding, u32 group_index) +void D3d12ShaderBindGroup::EnsureAvailable() { if (!m_changed) return; - std::lock_guard guard(binding.DescLock()); + std::lock_guard guard(m_desc_lock); if (!m_changed) return; - // todo + const auto defs = m_layout->GetItems(); + const auto slots = m_layout->Slots(); + for (usize i = 0; i < m_views.size(); ++i) + { + const auto def_index = m_define_indexes[i]; + const auto& slot = slots[def_index]; + if (slot.Place == Layout::BindSlotPlace::NonTable) continue; + if (const auto& mark = m_changed_marks[i]) continue; + else mark = false; + const auto& view = m_views[i]; + const auto& def = defs[def_index]; + const auto& heap = slot.Place == Layout::BindSlotPlace::ResourceTable ? m_resource_heap : m_sampler_heap; + COPLT_DEBUG_ASSERT(heap != nullptr); + CD3DX12_CPU_DESCRIPTOR_HANDLE handle(heap->GetCPUDescriptorHandleForHeapStart(), slot.OffsetInTable, m_resource_heap_inc); + view.CreateDescriptor(m_device->m_device.Get(), def, handle); + } m_changed = false; } @@ -160,11 +242,6 @@ RwLock& D3d12ShaderBinding::SelfLock() noexcept return m_self_lock; } -std::mutex& D3d12ShaderBinding::DescLock() noexcept -{ - return m_desc_lock; -} - void D3d12ShaderBinding::Set(const std::span items) { for (const auto& item : items) diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index 2ca4b86..eb564fd 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -17,32 +17,43 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12ShaderBindGroup, "5bb948b9-ad31-4eb8-b881-98017e048259", FShaderBindGroup) { - virtual const Rc& Layout() const noexcept = 0; + virtual const Rc& Layout() const noexcept = 0; virtual std::span Views() const noexcept = 0; virtual std::span ItemIndexes() const noexcept = 0; virtual std::span DefineIndexes() const noexcept = 0; virtual RwLock& SelfLock() noexcept = 0; - virtual void EnsureAvailable(ID3d12ShaderBinding& binding, u32 group_index) = 0; + virtual void EnsureAvailable() = 0; }; struct D3d12ShaderBindGroup final : GpuObject, FShaderBindGroupData { Rc m_name{}; Rc m_device{}; - Rc m_layout{}; + Rc m_layout{}; + ComPtr m_resource_heap{}; + ComPtr m_sampler_heap{}; + u32 m_resource_heap_inc{}; + u32 m_sampler_heap_inc{}; std::vector m_views{}; + // 这里就是 vector 当 bitset 用 + std::vector m_changed_marks{}; + // view index => 布局 item index std::vector m_define_indexes{}; + // 布局 item index => view index std::vector m_item_indexes{}; // 绑定修改锁 RwLock m_self_lock{}; + // 标识符创建锁,必须在 m_self_lock Read 锁定状态使用 + std::mutex m_desc_lock{}; volatile bool m_changed{}; explicit D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; + void DoSetName(const FStr8or16& name) const; FShaderBindGroupData* ShaderBindGroupData() noexcept override; - const Rc& Layout() const noexcept override; + const Rc& Layout() const noexcept override; std::span Views() const noexcept override; std::span ItemIndexes() const noexcept override; std::span DefineIndexes() const noexcept override; @@ -51,8 +62,8 @@ namespace Coplt // 需要外部锁 m_self_lock 必须是 Write 锁定状态 void Set(std::span items); - // 需要外部锁 m_self_lock 和 binding 的 m_self_lock 必须是 Read 锁定状态 - void EnsureAvailable(ID3d12ShaderBinding& binding, u32 group_index) override; + // 需要外部锁 m_self_lock 必须是 Read 锁定状态 + void EnsureAvailable() override; }; COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "5073f785-cfb7-414d-9a84-1602d3bf378d", FShaderBinding) @@ -60,7 +71,6 @@ namespace Coplt virtual const Rc& Layout() const noexcept = 0; virtual std::span> Groups() const noexcept = 0; virtual RwLock& SelfLock() noexcept = 0; - virtual std::mutex& DescLock() noexcept = 0; }; struct D3d12ShaderBinding final : GpuObject, FShaderBindingData @@ -68,12 +78,8 @@ namespace Coplt Rc m_device{}; Rc m_layout{}; std::vector> m_groups{}; - ComPtr m_resource_heap{}; - ComPtr m_sampler_heap{}; // 绑定修改锁 RwLock m_self_lock{}; - // 标识符创建锁,必须在 m_self_lock Read 锁定状态使用 - std::mutex m_desc_lock{}; explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; @@ -83,7 +89,6 @@ namespace Coplt const Rc& Layout() const noexcept override; std::span> Groups() const noexcept override; RwLock& SelfLock() noexcept override; - std::mutex& DescLock() noexcept override; // 需要外部锁 m_self_lock 必须是 Write 锁定状态 void Set(std::span items); diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 99e1686..db8d205 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -631,7 +631,7 @@ void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) const auto& info = bind_item_infos[g][v]; m_barrier_analyzer->OnUse(res_index, view, info); } - group->EnsureAvailable(*binding, g); + group->EnsureAvailable(); } m_barrier_analyzer->OnCmd(); } diff --git a/Coplt.Graphics.Native/D3d12/Src/View.cc b/Coplt.Graphics.Native/D3d12/Src/View.cc index 62a566d..ffae667 100644 --- a/Coplt.Graphics.Native/D3d12/Src/View.cc +++ b/Coplt.Graphics.Native/D3d12/Src/View.cc @@ -2,6 +2,7 @@ #include "../Include/GraphicsFormat.h" #include "Buffer.h" #include "Image.h" +#include "Sampler.h" using namespace Coplt; @@ -78,572 +79,573 @@ Ptr View::TryGetImage() const return m_viewable->QueryInterface(); } -// void View::CreateDescriptor( -// NonNull device, const FShaderLayoutItemDefine& def, const CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView type -// ) const -// { -// switch (Type()) -// { -// case Type::None: -// CreateNullDescriptor(device, def, handle, type); -// break; -// case Type::Buffer: -// CreateBufferDescriptor(device, def, handle, type); -// break; -// case Type::Image: -// CreateImageDescriptor(device, def, handle, type); -// break; -// case Type::Sampler: -// CreateSamplerDescriptor(device, def, handle, type); -// break; -// } -// } -// -// void View::CreateNullDescriptor( -// NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView view -// ) -// { -// switch (view) -// { -// case FShaderLayoutGroupView::Cbv: -// { -// device->CreateConstantBufferView(nullptr, handle); -// break; -// } -// case FShaderLayoutGroupView::Srv: -// { -// D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; -// desc.Format = ToDx(def.Format); -// desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; -// switch (def.Type) -// { -// case FShaderLayoutItemType::ConstantBuffer: -// COPLT_THROW("Srv does not support ConstantBuffer"); -// case FShaderLayoutItemType::Buffer: -// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; -// break; -// case FShaderLayoutItemType::RawBuffer: -// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; -// desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; -// break; -// case FShaderLayoutItemType::StructureBuffer: -// case FShaderLayoutItemType::StructureBufferWithCounter: -// desc.Format = DXGI_FORMAT_UNKNOWN; -// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; -// desc.Buffer.FirstElement = 0; -// desc.Buffer.NumElements = 1; -// desc.Buffer.StructureByteStride = 1; -// break; -// case FShaderLayoutItemType::Texture1D: -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; -// desc.Texture1D.MostDetailedMip = 0; -// desc.Texture1D.MipLevels = 1; -// desc.Texture1D.ResourceMinLODClamp = 0; -// break; -// case FShaderLayoutItemType::Texture1DArray: -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; -// desc.Texture1DArray.MostDetailedMip = 0; -// desc.Texture1DArray.MipLevels = 1; -// desc.Texture1DArray.FirstArraySlice = 0; -// desc.Texture1DArray.ArraySize = 1; -// desc.Texture1DArray.ResourceMinLODClamp = 0; -// break; -// case FShaderLayoutItemType::Texture2D: -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; -// desc.Texture2D.MostDetailedMip = 0; -// desc.Texture2D.MipLevels = 1; -// desc.Texture2D.PlaneSlice = 0; -// desc.Texture2D.ResourceMinLODClamp = 0; -// break; -// case FShaderLayoutItemType::Texture2DArray: -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; -// desc.Texture2DArray.MostDetailedMip = 0; -// desc.Texture2DArray.MipLevels = 1; -// desc.Texture2DArray.FirstArraySlice = 0; -// desc.Texture2DArray.ArraySize = 1; -// desc.Texture2DArray.PlaneSlice = 0; -// desc.Texture2DArray.ResourceMinLODClamp = 0; -// break; -// case FShaderLayoutItemType::Texture2DMultisample: -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; -// break; -// case FShaderLayoutItemType::Texture2DArrayMultisample: -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; -// desc.Texture2DMSArray.FirstArraySlice = 0; -// desc.Texture2DMSArray.ArraySize = 1; -// break; -// case FShaderLayoutItemType::Texture3D: -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; -// desc.Texture3D.MostDetailedMip = 0; -// desc.Texture3D.MipLevels = 1; -// desc.Texture3D.ResourceMinLODClamp = 0; -// break; -// case FShaderLayoutItemType::TextureCube: -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; -// desc.TextureCube.MostDetailedMip = 0; -// desc.TextureCube.MipLevels = 1; -// desc.TextureCube.ResourceMinLODClamp = 0; -// break; -// case FShaderLayoutItemType::TextureCubeArray: -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; -// desc.TextureCubeArray.MostDetailedMip = 0; -// desc.TextureCubeArray.MipLevels = 1; -// desc.TextureCubeArray.First2DArrayFace = 0; -// desc.TextureCubeArray.NumCubes = 1; -// desc.TextureCubeArray.ResourceMinLODClamp = 0; -// break; -// case FShaderLayoutItemType::Sampler: -// COPLT_THROW("Srv does does not support sampler"); -// case FShaderLayoutItemType::RayTracingAccelerationStructure: -// desc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; -// break; -// } -// device->CreateShaderResourceView(nullptr, &desc, handle); -// break; -// } -// case FShaderLayoutGroupView::Uav: -// { -// D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; -// desc.Format = ToDx(def.Format); -// switch (def.Type) -// { -// case FShaderLayoutItemType::ConstantBuffer: -// COPLT_THROW("Uav does not support ConstantBuffer"); -// case FShaderLayoutItemType::Buffer: -// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; -// break; -// case FShaderLayoutItemType::RawBuffer: -// desc.Format = DXGI_FORMAT_R32_TYPELESS; -// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; -// desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; -// break; -// case FShaderLayoutItemType::StructureBuffer: -// case FShaderLayoutItemType::StructureBufferWithCounter: -// desc.Format = DXGI_FORMAT_UNKNOWN; -// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; -// desc.Buffer.FirstElement = 0; -// desc.Buffer.NumElements = 1; -// desc.Buffer.StructureByteStride = 1; -// desc.Buffer.CounterOffsetInBytes = 0; -// break; -// case FShaderLayoutItemType::Texture1D: -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D; -// desc.Texture1D.MipSlice = 0; -// break; -// case FShaderLayoutItemType::Texture1DArray: -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY; -// desc.Texture1DArray.MipSlice = 0; -// desc.Texture1DArray.FirstArraySlice = 0; -// desc.Texture1DArray.ArraySize = 1; -// break; -// case FShaderLayoutItemType::Texture2D: -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; -// desc.Texture2D.MipSlice = 0; -// desc.Texture2D.PlaneSlice = 0; -// break; -// case FShaderLayoutItemType::Texture2DArray: -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY; -// desc.Texture2DArray.MipSlice = 0; -// desc.Texture2DArray.FirstArraySlice = 0; -// desc.Texture2DArray.ArraySize = 1; -// desc.Texture2DArray.PlaneSlice = 0; -// break; -// case FShaderLayoutItemType::Texture2DMultisample: -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMS; -// break; -// case FShaderLayoutItemType::Texture2DArrayMultisample: -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY; -// desc.Texture2DMSArray.FirstArraySlice = 0; -// desc.Texture2DMSArray.ArraySize = 1; -// break; -// case FShaderLayoutItemType::Texture3D: -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D; -// desc.Texture3D.MipSlice = 0; -// desc.Texture3D.FirstWSlice = 0; -// desc.Texture3D.WSize = 1; -// break; -// case FShaderLayoutItemType::TextureCube: -// COPLT_THROW("Uav does not support TextureCube"); -// case FShaderLayoutItemType::TextureCubeArray: -// COPLT_THROW("Uav does not support TextureCubeArray"); -// case FShaderLayoutItemType::Sampler: -// COPLT_THROW("Uav does not support Sampler"); -// case FShaderLayoutItemType::RayTracingAccelerationStructure: -// COPLT_THROW("Uav does not support RayTracingAccelerationStructure"); -// } -// device->CreateUnorderedAccessView(nullptr, nullptr, &desc, handle); -// break; -// } -// case FShaderLayoutGroupView::Sampler: -// { -// D3D12_SAMPLER_DESC desc{}; -// desc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; -// desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; -// desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; -// desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; -// desc.MaxLOD = FLT_MAX; -// device->CreateSampler(&desc, handle); -// break; -// } -// default: -// std::unreachable(); -// } -// } -// -// void View::CreateBufferDescriptor( -// NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type -// ) const -// { -// const auto buffer = Buffer().get(); -// const auto resource = buffer->GetResourcePtr(); -// const auto data = buffer->GpuBufferData(); -// switch (type) -// { -// case FShaderLayoutGroupView::Cbv: -// { -// D3D12_CONSTANT_BUFFER_VIEW_DESC desc{}; -// desc.BufferLocation = resource->GetGPUVirtualAddress(); -// desc.SizeInBytes = data->m_size; -// device->CreateConstantBufferView(&desc, handle); -// break; -// } -// case FShaderLayoutGroupView::Srv: -// { -// D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; -// desc.Format = ToDx(def.Format); -// desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; -// switch (def.Type) -// { -// case FShaderLayoutItemType::ConstantBuffer: -// COPLT_THROW("Srv does not support ConstantBuffer"); -// case FShaderLayoutItemType::Buffer: -// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; -// break; -// case FShaderLayoutItemType::RawBuffer: -// if (data->m_usage != FBufferUsage::Raw) -// COPLT_THROW("Buffer not a Raw Buffer"); -// desc.Format = DXGI_FORMAT_R32_TYPELESS; -// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; -// desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; -// break; -// case FShaderLayoutItemType::StructureBuffer: -// case FShaderLayoutItemType::StructureBufferWithCounter: -// if (data->m_usage != FBufferUsage::Structured) -// COPLT_THROW("Buffer not a Structured Buffer"); -// desc.Format = DXGI_FORMAT_UNKNOWN; -// desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; -// desc.Buffer.FirstElement = 0; -// desc.Buffer.NumElements = data->m_count; -// desc.Buffer.StructureByteStride = data->m_stride; -// 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: -// COPLT_THROW("Buffer Srv does not support Texture"); -// case FShaderLayoutItemType::Sampler: -// COPLT_THROW("Buffer Srv does not support Sampler"); -// case FShaderLayoutItemType::RayTracingAccelerationStructure: -// desc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; -// desc.RaytracingAccelerationStructure.Location = resource->GetGPUVirtualAddress(); -// break; -// } -// device->CreateShaderResourceView(resource, &desc, handle); -// break; -// } -// case FShaderLayoutGroupView::Uav: -// { -// D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; -// desc.Format = ToDx(def.Format); -// switch (def.Type) -// { -// case FShaderLayoutItemType::ConstantBuffer: -// COPLT_THROW("Uav does not support ConstantBuffer"); -// case FShaderLayoutItemType::Buffer: -// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; -// break; -// case FShaderLayoutItemType::RawBuffer: -// if (data->m_usage != FBufferUsage::Raw) -// COPLT_THROW("Buffer not a Raw Buffer"); -// desc.Format = DXGI_FORMAT_R32_TYPELESS; -// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; -// desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; -// break; -// case FShaderLayoutItemType::StructureBuffer: -// case FShaderLayoutItemType::StructureBufferWithCounter: -// if (data->m_usage != FBufferUsage::Structured) -// COPLT_THROW("Buffer not a Structured Buffer"); -// desc.Format = DXGI_FORMAT_UNKNOWN; -// desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; -// desc.Buffer.FirstElement = 0; -// desc.Buffer.NumElements = data->m_count; -// desc.Buffer.StructureByteStride = data->m_stride; -// desc.Buffer.CounterOffsetInBytes = 0; -// 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: -// COPLT_THROW("Buffer Uav does not support Texture"); -// case FShaderLayoutItemType::Sampler: -// COPLT_THROW("Buffer Uav does not support Sampler"); -// case FShaderLayoutItemType::RayTracingAccelerationStructure: -// COPLT_THROW("Buffer Uav does not support RayTracingAccelerationStructure"); -// } -// device->CreateUnorderedAccessView(resource, nullptr, &desc, handle); -// break; -// } -// case FShaderLayoutGroupView::Sampler: -// COPLT_THROW("Buffer cannot be used as a sampler"); -// } -// } -// -// void View::CreateImageDescriptor( -// NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type -// ) const -// { -// const auto image = Image().get(); -// const auto resource = image->GetResourcePtr(); -// const auto data = image->GpuImageData(); -// switch (type) -// { -// case FShaderLayoutGroupView::Cbv: -// COPLT_THROW("Image cannot be used as a Cbv"); -// case FShaderLayoutGroupView::Srv: -// { -// D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; -// desc.Format = ToDx(data->m_format); -// desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; -// switch (def.Type) -// { -// case FShaderLayoutItemType::ConstantBuffer: -// COPLT_THROW("Srv does not support ConstantBuffer"); -// case FShaderLayoutItemType::Buffer: -// case FShaderLayoutItemType::RawBuffer: -// case FShaderLayoutItemType::StructureBuffer: -// case FShaderLayoutItemType::StructureBufferWithCounter: -// COPLT_THROW("Image Srv does not support Buffer"); -// case FShaderLayoutItemType::Texture1D: -// { -// if (data->m_dimension != FImageDimension::One) -// COPLT_THROW("Bind required Texture1D, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; -// desc.Texture1D.MostDetailedMip = 0; -// desc.Texture1D.MipLevels = data->m_mip_levels; -// desc.Texture1D.ResourceMinLODClamp = 0; -// break; -// } -// case FShaderLayoutItemType::Texture1DArray: -// { -// if (data->m_dimension != FImageDimension::One) -// COPLT_THROW("Bind required Texture1DArray, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; -// desc.Texture1DArray.MostDetailedMip = 0; -// desc.Texture1DArray.MipLevels = data->m_mip_levels; -// desc.Texture1DArray.FirstArraySlice = 0; -// desc.Texture1DArray.ArraySize = data->m_depth_or_length; -// desc.Texture1DArray.ResourceMinLODClamp = 0; -// break; -// } -// case FShaderLayoutItemType::Texture2D: -// { -// if (data->m_dimension != FImageDimension::Two) -// COPLT_THROW("Bind required Texture2D, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; -// desc.Texture2D.MostDetailedMip = 0; -// desc.Texture2D.MipLevels = data->m_mip_levels; -// desc.Texture2D.PlaneSlice = 0; -// desc.Texture2D.ResourceMinLODClamp = 0; -// break; -// } -// case FShaderLayoutItemType::Texture2DArray: -// { -// if (data->m_dimension != FImageDimension::Two) -// COPLT_THROW("Bind required Texture2DArray, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; -// desc.Texture2DArray.MostDetailedMip = 0; -// desc.Texture2DArray.MipLevels = data->m_mip_levels; -// desc.Texture2DArray.FirstArraySlice = 0; -// desc.Texture2DArray.ArraySize = data->m_depth_or_length; -// desc.Texture2DArray.PlaneSlice = 0; -// desc.Texture2DArray.ResourceMinLODClamp = 0; -// break; -// } -// case FShaderLayoutItemType::Texture2DMultisample: -// { -// if (data->m_dimension != FImageDimension::Two) -// COPLT_THROW("Bind required Texture2DMultisample, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; -// break; -// } -// case FShaderLayoutItemType::Texture2DArrayMultisample: -// { -// if (data->m_dimension != FImageDimension::Two) -// COPLT_THROW("Bind required Texture2DArrayMultisample, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; -// desc.Texture2DMSArray.FirstArraySlice = 0; -// desc.Texture2DMSArray.ArraySize = data->m_depth_or_length; -// break; -// } -// case FShaderLayoutItemType::Texture3D: -// { -// if (data->m_dimension != FImageDimension::Three) -// COPLT_THROW("Bind required Texture3D, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; -// desc.Texture3D.MostDetailedMip = 0; -// desc.Texture3D.MipLevels = data->m_mip_levels; -// desc.Texture3D.ResourceMinLODClamp = 0; -// break; -// } -// case FShaderLayoutItemType::TextureCube: -// { -// if (data->m_dimension != FImageDimension::Cube) -// COPLT_THROW("Bind required TextureCube, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; -// desc.TextureCube.MostDetailedMip = 0; -// desc.TextureCube.MipLevels = data->m_mip_levels; -// desc.TextureCube.ResourceMinLODClamp = 0; -// break; -// } -// case FShaderLayoutItemType::TextureCubeArray: -// { -// if (data->m_dimension != FImageDimension::Cube) -// COPLT_THROW("Bind required TextureCubeArray, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; -// desc.TextureCubeArray.MostDetailedMip = 0; -// desc.TextureCubeArray.MipLevels = data->m_mip_levels; -// desc.TextureCubeArray.First2DArrayFace = 0; -// desc.TextureCubeArray.NumCubes = (data->m_depth_or_length + 5) / 6; -// desc.TextureCubeArray.ResourceMinLODClamp = 0; -// break; -// } -// case FShaderLayoutItemType::Sampler: -// COPLT_THROW("Srv does not support sampler"); -// case FShaderLayoutItemType::RayTracingAccelerationStructure: -// COPLT_THROW("Image Srv does not support RayTracingAccelerationStructure"); -// } -// device->CreateShaderResourceView(resource, &desc, handle); -// break; -// } -// case FShaderLayoutGroupView::Uav: -// { -// D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; -// desc.Format = ToDx(data->m_format); -// switch (def.Type) -// { -// case FShaderLayoutItemType::ConstantBuffer: -// COPLT_THROW("Uav not support ConstantBuffer"); -// -// case FShaderLayoutItemType::Buffer: -// case FShaderLayoutItemType::RawBuffer: -// case FShaderLayoutItemType::StructureBuffer: -// case FShaderLayoutItemType::StructureBufferWithCounter: -// COPLT_THROW("Image Srv does not support Buffer"); -// case FShaderLayoutItemType::Texture1D: -// { -// if (data->m_dimension != FImageDimension::One) -// COPLT_THROW("Bind required Texture1D, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D; -// desc.Texture1D.MipSlice = 0; -// break; -// } -// case FShaderLayoutItemType::Texture1DArray: -// { -// if (data->m_dimension != FImageDimension::One) -// COPLT_THROW("Bind required Texture1DArray, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY; -// desc.Texture1DArray.MipSlice = 0; -// desc.Texture1DArray.FirstArraySlice = 0; -// desc.Texture1DArray.ArraySize = data->m_depth_or_length; -// break; -// } -// case FShaderLayoutItemType::Texture2D: -// { -// if (data->m_dimension != FImageDimension::Two) -// COPLT_THROW("Bind required Texture2D, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; -// desc.Texture2D.MipSlice = 0; -// desc.Texture2D.PlaneSlice = 0; -// break; -// } -// case FShaderLayoutItemType::Texture2DArray: -// { -// if (data->m_dimension != FImageDimension::Two) -// COPLT_THROW("Bind required Texture2DArray, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY; -// desc.Texture2DArray.MipSlice = 0; -// desc.Texture2DArray.FirstArraySlice = 0; -// desc.Texture2DArray.ArraySize = data->m_depth_or_length; -// desc.Texture2DArray.PlaneSlice = 0; -// break; -// } -// case FShaderLayoutItemType::Texture2DMultisample: -// { -// if (data->m_dimension != FImageDimension::Two) -// COPLT_THROW("Bind required Texture2DMultisample, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMS; -// break; -// } -// case FShaderLayoutItemType::Texture2DArrayMultisample: -// { -// if (data->m_dimension != FImageDimension::Two) -// COPLT_THROW("Bind required Texture2DArrayMultisample, but the actual resources provided are not"); -// desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY; -// desc.Texture2DMSArray.FirstArraySlice = 0; -// desc.Texture2DMSArray.ArraySize = data->m_depth_or_length; -// break; -// } -// case FShaderLayoutItemType::Texture3D: -// { -// if (data->m_dimension != FImageDimension::Three) -// COPLT_THROW("Bind required Texture3D, but the actual resources provided are not"); -// desc.Texture3D.MipSlice = 0; -// desc.Texture3D.FirstWSlice = 0; -// desc.Texture3D.WSize = data->m_depth_or_length; -// break; -// } -// case FShaderLayoutItemType::TextureCube: -// COPLT_THROW("Uav not support TextureCube"); -// case FShaderLayoutItemType::TextureCubeArray: -// COPLT_THROW("Uav not support TextureCubeArray"); -// case FShaderLayoutItemType::Sampler: -// COPLT_THROW("Uav not support Sampler"); -// case FShaderLayoutItemType::RayTracingAccelerationStructure: -// COPLT_THROW("Uav not support RayTracingAccelerationStructure"); -// } -// device->CreateUnorderedAccessView(resource, nullptr, &desc, handle); -// break; -// } -// case FShaderLayoutGroupView::Sampler: -// COPLT_THROW("Image cannot be used as a sampler"); -// } -// } -// -// void View::CreateSamplerDescriptor( -// NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type -// ) const -// { -// const auto sampler = Sampler().get(); -// switch (type) -// { -// case FShaderLayoutGroupView::Cbv: -// COPLT_THROW("Sampler cannot be used as a Cbv"); -// case FShaderLayoutGroupView::Srv: -// COPLT_THROW("Sampler cannot be used as a Srv"); -// case FShaderLayoutGroupView::Uav: -// COPLT_THROW("Sampler cannot be used as a Uav"); -// case FShaderLayoutGroupView::Sampler: -// device->CreateSampler(sampler->Desc(), handle); -// break; -// } -// } +Ptr View::TryGetSampler() const +{ + return m_viewable->QueryInterface(); +} + +void View::CreateDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const +{ + switch (m_type) + { + case FViewType::None: + CreateNullDescriptor(device, def, handle); + break; + case FViewType::Buffer: + // CreateBufferDescriptor(device, def, handle); + break; + case FViewType::Image: + // CreateImageDescriptor(device, def, handle); + break; + case FViewType::Sampler: + // CreateSamplerDescriptor(device, def, handle); + break; + } +} + +void View::CreateNullDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) +{ + switch (def.View) + { + case FShaderLayoutItemView::Cbv: + { + device->CreateConstantBufferView(nullptr, handle); + break; + } + case FShaderLayoutItemView::Srv: + { + D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; + desc.Format = ToDx(def.Format); + desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + switch (def.Type) + { + case FShaderLayoutItemType::ConstantBuffer: + COPLT_THROW("Srv does not support ConstantBuffer"); + case FShaderLayoutItemType::Buffer: + desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + break; + case FShaderLayoutItemType::RawBuffer: + desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; + break; + case FShaderLayoutItemType::StructureBuffer: + case FShaderLayoutItemType::StructureBufferWithCounter: + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + desc.Buffer.FirstElement = 0; + desc.Buffer.NumElements = 1; + desc.Buffer.StructureByteStride = 1; + break; + case FShaderLayoutItemType::Texture1D: + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; + desc.Texture1D.MostDetailedMip = 0; + desc.Texture1D.MipLevels = 1; + desc.Texture1D.ResourceMinLODClamp = 0; + break; + case FShaderLayoutItemType::Texture1DArray: + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; + desc.Texture1DArray.MostDetailedMip = 0; + desc.Texture1DArray.MipLevels = 1; + desc.Texture1DArray.FirstArraySlice = 0; + desc.Texture1DArray.ArraySize = 1; + desc.Texture1DArray.ResourceMinLODClamp = 0; + break; + case FShaderLayoutItemType::Texture2D: + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + desc.Texture2D.MostDetailedMip = 0; + desc.Texture2D.MipLevels = 1; + desc.Texture2D.PlaneSlice = 0; + desc.Texture2D.ResourceMinLODClamp = 0; + break; + case FShaderLayoutItemType::Texture2DArray: + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; + desc.Texture2DArray.MostDetailedMip = 0; + desc.Texture2DArray.MipLevels = 1; + desc.Texture2DArray.FirstArraySlice = 0; + desc.Texture2DArray.ArraySize = 1; + desc.Texture2DArray.PlaneSlice = 0; + desc.Texture2DArray.ResourceMinLODClamp = 0; + break; + case FShaderLayoutItemType::Texture2DMultisample: + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; + break; + case FShaderLayoutItemType::Texture2DArrayMultisample: + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; + desc.Texture2DMSArray.FirstArraySlice = 0; + desc.Texture2DMSArray.ArraySize = 1; + break; + case FShaderLayoutItemType::Texture3D: + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; + desc.Texture3D.MostDetailedMip = 0; + desc.Texture3D.MipLevels = 1; + desc.Texture3D.ResourceMinLODClamp = 0; + break; + case FShaderLayoutItemType::TextureCube: + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; + desc.TextureCube.MostDetailedMip = 0; + desc.TextureCube.MipLevels = 1; + desc.TextureCube.ResourceMinLODClamp = 0; + break; + case FShaderLayoutItemType::TextureCubeArray: + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; + desc.TextureCubeArray.MostDetailedMip = 0; + desc.TextureCubeArray.MipLevels = 1; + desc.TextureCubeArray.First2DArrayFace = 0; + desc.TextureCubeArray.NumCubes = 1; + desc.TextureCubeArray.ResourceMinLODClamp = 0; + break; + case FShaderLayoutItemType::Sampler: + COPLT_THROW("Srv does does not support sampler"); + case FShaderLayoutItemType::RayTracingAccelerationStructure: + desc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; + break; + } + device->CreateShaderResourceView(nullptr, &desc, handle); + break; + } + case FShaderLayoutItemView::Uav: + { + D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; + desc.Format = ToDx(def.Format); + switch (def.Type) + { + case FShaderLayoutItemType::ConstantBuffer: + COPLT_THROW("Uav does not support ConstantBuffer"); + case FShaderLayoutItemType::Buffer: + desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + break; + case FShaderLayoutItemType::RawBuffer: + desc.Format = DXGI_FORMAT_R32_TYPELESS; + desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; + break; + case FShaderLayoutItemType::StructureBuffer: + case FShaderLayoutItemType::StructureBufferWithCounter: + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + desc.Buffer.FirstElement = 0; + desc.Buffer.NumElements = 1; + desc.Buffer.StructureByteStride = 1; + desc.Buffer.CounterOffsetInBytes = 0; + break; + case FShaderLayoutItemType::Texture1D: + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D; + desc.Texture1D.MipSlice = 0; + break; + case FShaderLayoutItemType::Texture1DArray: + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY; + desc.Texture1DArray.MipSlice = 0; + desc.Texture1DArray.FirstArraySlice = 0; + desc.Texture1DArray.ArraySize = 1; + break; + case FShaderLayoutItemType::Texture2D: + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipSlice = 0; + desc.Texture2D.PlaneSlice = 0; + break; + case FShaderLayoutItemType::Texture2DArray: + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY; + desc.Texture2DArray.MipSlice = 0; + desc.Texture2DArray.FirstArraySlice = 0; + desc.Texture2DArray.ArraySize = 1; + desc.Texture2DArray.PlaneSlice = 0; + break; + case FShaderLayoutItemType::Texture2DMultisample: + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMS; + break; + case FShaderLayoutItemType::Texture2DArrayMultisample: + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY; + desc.Texture2DMSArray.FirstArraySlice = 0; + desc.Texture2DMSArray.ArraySize = 1; + break; + case FShaderLayoutItemType::Texture3D: + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D; + desc.Texture3D.MipSlice = 0; + desc.Texture3D.FirstWSlice = 0; + desc.Texture3D.WSize = 1; + break; + case FShaderLayoutItemType::TextureCube: + COPLT_THROW("Uav does not support TextureCube"); + case FShaderLayoutItemType::TextureCubeArray: + COPLT_THROW("Uav does not support TextureCubeArray"); + case FShaderLayoutItemType::Sampler: + COPLT_THROW("Uav does not support Sampler"); + case FShaderLayoutItemType::RayTracingAccelerationStructure: + COPLT_THROW("Uav does not support RayTracingAccelerationStructure"); + } + device->CreateUnorderedAccessView(nullptr, nullptr, &desc, handle); + break; + } + case FShaderLayoutItemView::Sampler: + { + D3D12_SAMPLER_DESC desc{}; + desc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; + desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + desc.MaxLOD = FLT_MAX; + device->CreateSampler(&desc, handle); + break; + } + default: + std::unreachable(); + } +} + +void View::CreateBufferDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const +{ + const NonNull buffer = TryGetBuffer(); + const auto resource = buffer->GetResourcePtr(); + const auto data = buffer->GpuBufferData(); + switch (def.View) + { + case FShaderLayoutItemView::Cbv: + { + D3D12_CONSTANT_BUFFER_VIEW_DESC desc{}; + desc.BufferLocation = resource->GetGPUVirtualAddress(); + desc.SizeInBytes = data->m_size; + device->CreateConstantBufferView(&desc, handle); + break; + } + case FShaderLayoutItemView::Srv: + { + D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; + desc.Format = ToDx(def.Format); + desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + switch (def.Type) + { + case FShaderLayoutItemType::ConstantBuffer: + COPLT_THROW("Srv does not support ConstantBuffer"); + case FShaderLayoutItemType::Buffer: + desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + break; + case FShaderLayoutItemType::RawBuffer: + if (data->m_usage != FBufferUsage::Raw) + COPLT_THROW("Buffer not a Raw Buffer"); + desc.Format = DXGI_FORMAT_R32_TYPELESS; + desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; + break; + case FShaderLayoutItemType::StructureBuffer: + case FShaderLayoutItemType::StructureBufferWithCounter: + if (data->m_usage != FBufferUsage::Structured) + COPLT_THROW("Buffer not a Structured Buffer"); + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; + desc.Buffer.FirstElement = 0; + desc.Buffer.NumElements = data->m_count; + desc.Buffer.StructureByteStride = data->m_stride; + 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: + COPLT_THROW("Buffer Srv does not support Texture"); + case FShaderLayoutItemType::Sampler: + COPLT_THROW("Buffer Srv does not support Sampler"); + case FShaderLayoutItemType::RayTracingAccelerationStructure: + desc.ViewDimension = D3D12_SRV_DIMENSION_RAYTRACING_ACCELERATION_STRUCTURE; + desc.RaytracingAccelerationStructure.Location = resource->GetGPUVirtualAddress(); + break; + } + device->CreateShaderResourceView(resource, &desc, handle); + break; + } + case FShaderLayoutItemView::Uav: + { + D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; + desc.Format = ToDx(def.Format); + switch (def.Type) + { + case FShaderLayoutItemType::ConstantBuffer: + COPLT_THROW("Uav does not support ConstantBuffer"); + case FShaderLayoutItemType::Buffer: + desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + break; + case FShaderLayoutItemType::RawBuffer: + if (data->m_usage != FBufferUsage::Raw) + COPLT_THROW("Buffer not a Raw Buffer"); + desc.Format = DXGI_FORMAT_R32_TYPELESS; + desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW; + break; + case FShaderLayoutItemType::StructureBuffer: + case FShaderLayoutItemType::StructureBufferWithCounter: + if (data->m_usage != FBufferUsage::Structured) + COPLT_THROW("Buffer not a Structured Buffer"); + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; + desc.Buffer.FirstElement = 0; + desc.Buffer.NumElements = data->m_count; + desc.Buffer.StructureByteStride = data->m_stride; + desc.Buffer.CounterOffsetInBytes = 0; + 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: + COPLT_THROW("Buffer Uav does not support Texture"); + case FShaderLayoutItemType::Sampler: + COPLT_THROW("Buffer Uav does not support Sampler"); + case FShaderLayoutItemType::RayTracingAccelerationStructure: + COPLT_THROW("Buffer Uav does not support RayTracingAccelerationStructure"); + } + device->CreateUnorderedAccessView(resource, nullptr, &desc, handle); + break; + } + case FShaderLayoutItemView::Sampler: + COPLT_THROW("Buffer cannot be used as a sampler"); + default: + std::unreachable(); + } +} + +void View::CreateImageDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const +{ + const NonNull image = TryGetImage(); + const auto resource = image->GetResourcePtr(); + const auto data = image->GpuImageData(); + switch (def.View) + { + case FShaderLayoutItemView::Cbv: + COPLT_THROW("Image cannot be used as a Cbv"); + case FShaderLayoutItemView::Srv: + { + D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; + desc.Format = ToDx(data->m_format); + desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + switch (def.Type) + { + case FShaderLayoutItemType::ConstantBuffer: + COPLT_THROW("Srv does not support ConstantBuffer"); + case FShaderLayoutItemType::Buffer: + case FShaderLayoutItemType::RawBuffer: + case FShaderLayoutItemType::StructureBuffer: + case FShaderLayoutItemType::StructureBufferWithCounter: + COPLT_THROW("Image Srv does not support Buffer"); + case FShaderLayoutItemType::Texture1D: + { + if (data->m_dimension != FImageDimension::One) + COPLT_THROW("Bind required Texture1D, but the actual resources provided are not"); + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D; + desc.Texture1D.MostDetailedMip = 0; + desc.Texture1D.MipLevels = data->m_mip_levels; + desc.Texture1D.ResourceMinLODClamp = 0; + break; + } + case FShaderLayoutItemType::Texture1DArray: + { + if (data->m_dimension != FImageDimension::One) + COPLT_THROW("Bind required Texture1DArray, but the actual resources provided are not"); + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; + desc.Texture1DArray.MostDetailedMip = 0; + desc.Texture1DArray.MipLevels = data->m_mip_levels; + desc.Texture1DArray.FirstArraySlice = 0; + desc.Texture1DArray.ArraySize = data->m_depth_or_length; + desc.Texture1DArray.ResourceMinLODClamp = 0; + break; + } + case FShaderLayoutItemType::Texture2D: + { + if (data->m_dimension != FImageDimension::Two) + COPLT_THROW("Bind required Texture2D, but the actual resources provided are not"); + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + desc.Texture2D.MostDetailedMip = 0; + desc.Texture2D.MipLevels = data->m_mip_levels; + desc.Texture2D.PlaneSlice = 0; + desc.Texture2D.ResourceMinLODClamp = 0; + break; + } + case FShaderLayoutItemType::Texture2DArray: + { + if (data->m_dimension != FImageDimension::Two) + COPLT_THROW("Bind required Texture2DArray, but the actual resources provided are not"); + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; + desc.Texture2DArray.MostDetailedMip = 0; + desc.Texture2DArray.MipLevels = data->m_mip_levels; + desc.Texture2DArray.FirstArraySlice = 0; + desc.Texture2DArray.ArraySize = data->m_depth_or_length; + desc.Texture2DArray.PlaneSlice = 0; + desc.Texture2DArray.ResourceMinLODClamp = 0; + break; + } + case FShaderLayoutItemType::Texture2DMultisample: + { + if (data->m_dimension != FImageDimension::Two) + COPLT_THROW("Bind required Texture2DMultisample, but the actual resources provided are not"); + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMS; + break; + } + case FShaderLayoutItemType::Texture2DArrayMultisample: + { + if (data->m_dimension != FImageDimension::Two) + COPLT_THROW("Bind required Texture2DArrayMultisample, but the actual resources provided are not"); + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY; + desc.Texture2DMSArray.FirstArraySlice = 0; + desc.Texture2DMSArray.ArraySize = data->m_depth_or_length; + break; + } + case FShaderLayoutItemType::Texture3D: + { + if (data->m_dimension != FImageDimension::Three) + COPLT_THROW("Bind required Texture3D, but the actual resources provided are not"); + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; + desc.Texture3D.MostDetailedMip = 0; + desc.Texture3D.MipLevels = data->m_mip_levels; + desc.Texture3D.ResourceMinLODClamp = 0; + break; + } + case FShaderLayoutItemType::TextureCube: + { + if (data->m_dimension != FImageDimension::Cube) + COPLT_THROW("Bind required TextureCube, but the actual resources provided are not"); + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE; + desc.TextureCube.MostDetailedMip = 0; + desc.TextureCube.MipLevels = data->m_mip_levels; + desc.TextureCube.ResourceMinLODClamp = 0; + break; + } + case FShaderLayoutItemType::TextureCubeArray: + { + if (data->m_dimension != FImageDimension::Cube) + COPLT_THROW("Bind required TextureCubeArray, but the actual resources provided are not"); + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY; + desc.TextureCubeArray.MostDetailedMip = 0; + desc.TextureCubeArray.MipLevels = data->m_mip_levels; + desc.TextureCubeArray.First2DArrayFace = 0; + desc.TextureCubeArray.NumCubes = (data->m_depth_or_length + 5) / 6; + desc.TextureCubeArray.ResourceMinLODClamp = 0; + break; + } + case FShaderLayoutItemType::Sampler: + COPLT_THROW("Srv does not support sampler"); + case FShaderLayoutItemType::RayTracingAccelerationStructure: + COPLT_THROW("Image Srv does not support RayTracingAccelerationStructure"); + } + device->CreateShaderResourceView(resource, &desc, handle); + break; + } + case FShaderLayoutItemView::Uav: + { + D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; + desc.Format = ToDx(data->m_format); + switch (def.Type) + { + case FShaderLayoutItemType::ConstantBuffer: + COPLT_THROW("Uav not support ConstantBuffer"); + + case FShaderLayoutItemType::Buffer: + case FShaderLayoutItemType::RawBuffer: + case FShaderLayoutItemType::StructureBuffer: + case FShaderLayoutItemType::StructureBufferWithCounter: + COPLT_THROW("Image Srv does not support Buffer"); + case FShaderLayoutItemType::Texture1D: + { + if (data->m_dimension != FImageDimension::One) + COPLT_THROW("Bind required Texture1D, but the actual resources provided are not"); + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1D; + desc.Texture1D.MipSlice = 0; + break; + } + case FShaderLayoutItemType::Texture1DArray: + { + if (data->m_dimension != FImageDimension::One) + COPLT_THROW("Bind required Texture1DArray, but the actual resources provided are not"); + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE1DARRAY; + desc.Texture1DArray.MipSlice = 0; + desc.Texture1DArray.FirstArraySlice = 0; + desc.Texture1DArray.ArraySize = data->m_depth_or_length; + break; + } + case FShaderLayoutItemType::Texture2D: + { + if (data->m_dimension != FImageDimension::Two) + COPLT_THROW("Bind required Texture2D, but the actual resources provided are not"); + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipSlice = 0; + desc.Texture2D.PlaneSlice = 0; + break; + } + case FShaderLayoutItemType::Texture2DArray: + { + if (data->m_dimension != FImageDimension::Two) + COPLT_THROW("Bind required Texture2DArray, but the actual resources provided are not"); + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY; + desc.Texture2DArray.MipSlice = 0; + desc.Texture2DArray.FirstArraySlice = 0; + desc.Texture2DArray.ArraySize = data->m_depth_or_length; + desc.Texture2DArray.PlaneSlice = 0; + break; + } + case FShaderLayoutItemType::Texture2DMultisample: + { + if (data->m_dimension != FImageDimension::Two) + COPLT_THROW("Bind required Texture2DMultisample, but the actual resources provided are not"); + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMS; + break; + } + case FShaderLayoutItemType::Texture2DArrayMultisample: + { + if (data->m_dimension != FImageDimension::Two) + COPLT_THROW("Bind required Texture2DArrayMultisample, but the actual resources provided are not"); + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DMSARRAY; + desc.Texture2DMSArray.FirstArraySlice = 0; + desc.Texture2DMSArray.ArraySize = data->m_depth_or_length; + break; + } + case FShaderLayoutItemType::Texture3D: + { + if (data->m_dimension != FImageDimension::Three) + COPLT_THROW("Bind required Texture3D, but the actual resources provided are not"); + desc.Texture3D.MipSlice = 0; + desc.Texture3D.FirstWSlice = 0; + desc.Texture3D.WSize = data->m_depth_or_length; + break; + } + case FShaderLayoutItemType::TextureCube: + COPLT_THROW("Uav not support TextureCube"); + case FShaderLayoutItemType::TextureCubeArray: + COPLT_THROW("Uav not support TextureCubeArray"); + case FShaderLayoutItemType::Sampler: + COPLT_THROW("Uav not support Sampler"); + case FShaderLayoutItemType::RayTracingAccelerationStructure: + COPLT_THROW("Uav not support RayTracingAccelerationStructure"); + } + device->CreateUnorderedAccessView(resource, nullptr, &desc, handle); + break; + } + case FShaderLayoutItemView::Sampler: + COPLT_THROW("Image cannot be used as a sampler"); + default: + std::unreachable(); + } +} + +void View::CreateSamplerDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const +{ + const NonNull sampler = TryGetSampler(); + switch (def.View) + { + case FShaderLayoutItemView::Cbv: + COPLT_THROW("Sampler cannot be used as a Cbv"); + case FShaderLayoutItemView::Srv: + COPLT_THROW("Sampler cannot be used as a Srv"); + case FShaderLayoutItemView::Uav: + COPLT_THROW("Sampler cannot be used as a Uav"); + case FShaderLayoutItemView::Sampler: + device->CreateSampler(sampler->Desc(), handle); + break; + default: + std::unreachable(); + } +} From 01be70458cf37c0b864160ee25f95d84aaa5c838 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 10 Apr 2025 14:59:14 +0800 Subject: [PATCH 41/46] srgb linear --- Coplt.Graphics.Core/Core/Color.cs | 75 ++++++- Coplt.Graphics.Core/Core/GpuOutput.cs | 7 +- Coplt.Graphics.Core/Core/GpuRecord.cs | 2 +- Coplt.Graphics.Core/Native/Native.cs | 5 - Coplt.Graphics.Core/Utils/Utils.cs | 211 ++++++++++++++++++ Coplt.Graphics.Native/Api/FFI/Binding.h | 2 - .../Api/FFI/GraphicsFormat.h | 57 +++++ .../D3d12/Include/GraphicsFormat.h | 11 + Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 2 + .../D3d12/Src/DescriptorManager.h | 2 + Coplt.Graphics.Native/D3d12/Src/Record.cc | 16 +- Coplt.Graphics.Native/D3d12/Src/Record.h | 4 + Coplt.Graphics.Native/D3d12/Src/SwapChain.cc | 7 +- Examples/ExampleBase/ExampleBase.cs | 4 +- Examples/HelloTriangleVertex/Example.cs | 1 + 15 files changed, 385 insertions(+), 21 deletions(-) diff --git a/Coplt.Graphics.Core/Core/Color.cs b/Coplt.Graphics.Core/Core/Color.cs index fd2c52d..1d02588 100644 --- a/Coplt.Graphics.Core/Core/Color.cs +++ b/Coplt.Graphics.Core/Core/Color.cs @@ -1,10 +1,17 @@ -using System.Runtime.CompilerServices; +using System.Numerics; +using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; using Coplt.Graphics.Utilities; namespace Coplt.Graphics; -public struct Color : IEquatable, IComparable, IComparable +public struct Color + : IEquatable, IComparable, IComparable, + IAdditionOperators, + ISubtractionOperators, + IMultiplyOperators, + IDivisionOperators, + IModulusOperators { #region Fields @@ -109,6 +116,8 @@ public float A public static Color operator *(Color a, Color b) => new(a.Vector * b.Vector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Color operator /(Color a, Color b) => new(a.Vector / b.Vector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Color operator %(Color a, Color b) => new(Utils.Rem(a.Vector, b.Vector)); #endregion @@ -290,9 +299,47 @@ public ColorHsl Hsl } #endregion + + #region Linear + + public readonly Color ToLinear + { + [MethodImpl(256 | 512)] + get + { + var vector = m_vector; + var c = Vector128.LessThanOrEqual(vector, Vector128.Create(0.04045f)); + var low = vector * Vector128.Create(1f / 12.92f); + var high = Utils.Pow((vector + Vector128.Create(0.055f)) * Vector128.Create(1f / 1.055f), Vector128.Create(2.4f)); + var r = Vector128.ConditionalSelect(c, low, high); + return new Color(Vector128.ConditionalSelect(Vector128.Create(-1, -1, -1, 0).AsSingle(), r, vector)); + } + } + + public readonly Color ToSrgb + { + [MethodImpl(256 | 512)] + get + { + var vector = m_vector; + var c = Vector128.LessThanOrEqual(vector, Vector128.Create(0.0031308f)); + var low = vector * Vector128.Create(12.92f); + var high = Utils.Fma(Vector128.Create(1.055f), Utils.Pow(vector, Vector128.Create(1f / 2.4f)), Vector128.Create(-0.055f)); + var r = Vector128.ConditionalSelect(c, low, high); + return new Color(Vector128.ConditionalSelect(Vector128.Create(-1, -1, -1, 0).AsSingle(), r, vector)); + } + } + + #endregion } -public struct Color255 : IEquatable, IComparable, IComparable +public struct Color255 + : IEquatable, IComparable, IComparable, + IAdditionOperators, + ISubtractionOperators, + IMultiplyOperators, + IDivisionOperators, + IModulusOperators { #region Fields @@ -392,6 +439,8 @@ public float A public static Color255 operator *(Color255 a, Color255 b) => new(a.Vector * b.Vector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Color255 operator /(Color255 a, Color255 b) => new(a.Vector / b.Vector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Color255 operator %(Color255 a, Color255 b) => new(Utils.Rem(a.Vector, b.Vector)); #endregion @@ -490,7 +539,13 @@ public ColorHsl Hsl #endregion } -public struct ColorHsv : IEquatable, IComparable, IComparable +public struct ColorHsv + : IEquatable, IComparable, IComparable, + IAdditionOperators, + ISubtractionOperators, + IMultiplyOperators, + IDivisionOperators, + IModulusOperators { #region Fields @@ -581,6 +636,8 @@ public float A public static ColorHsv operator *(ColorHsv a, ColorHsv b) => new(a.Vector * b.Vector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorHsv operator /(ColorHsv a, ColorHsv b) => new(a.Vector / b.Vector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ColorHsv operator %(ColorHsv a, ColorHsv b) => new(Utils.Rem(a.Vector, b.Vector)); #endregion @@ -714,7 +771,13 @@ public ColorHsl Hsl #endregion } -public struct ColorHsl : IEquatable, IComparable, IComparable +public struct ColorHsl + : IEquatable, IComparable, IComparable, + IAdditionOperators, + ISubtractionOperators, + IMultiplyOperators, + IDivisionOperators, + IModulusOperators { #region Fields @@ -805,6 +868,8 @@ public float A public static ColorHsl operator *(ColorHsl a, ColorHsl b) => new(a.Vector * b.Vector); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ColorHsl operator /(ColorHsl a, ColorHsl b) => new(a.Vector / b.Vector); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ColorHsl operator %(ColorHsl a, ColorHsl b) => new(Utils.Rem(a.Vector, b.Vector)); #endregion diff --git a/Coplt.Graphics.Core/Core/GpuOutput.cs b/Coplt.Graphics.Core/Core/GpuOutput.cs index 667f70e..88fcc81 100644 --- a/Coplt.Graphics.Core/Core/GpuOutput.cs +++ b/Coplt.Graphics.Core/Core/GpuOutput.cs @@ -130,9 +130,12 @@ public record struct GpuSwapChainCreateOptions() public required uint Width; public required uint Height; /// - /// 是否使用 srgb,实现可以选择忽略 + /// 是否使用 sRGB,实现可以选择忽略 + /// 是指整个渲染管线是不是使用 sRGB,而不是交换链是不是使用,具体交换链格式请使用 获取 + /// 设置为 false 时需要注意保证顶点缓冲区和 cbuffer 中传入的颜色是线性的,以及使用 sRGB 视图转换纹理到线性 + /// true 时将原样传输像素数据进行呈现,false 将在呈现时对输出执行 线性 -> sRGB 转换 /// - public bool Srgb; + public bool Srgb = true; /// /// 是否使用 hdr,实现可以选择忽略 /// diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 30e2120..8b5e144 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -816,7 +816,7 @@ public void SetBinding(GpuRecord self, ShaderBinding Binding) }; self.Data.Bindings.Add(new() { Binding = Binding.Ptr }); self.Data.Commands.Add(new() { SetBinding = cmd }); - if (first) self.Data.SumMaxBindSlots += Binding.Data.SumPersistentSlots + Binding.Data.SumTransientSlots; // todo 这个计算移到 c艹 + // if (first) self.Data.SumMaxBindSlots += Binding.Data.SumPersistentSlots + Binding.Data.SumTransientSlots; // todo 这个计算移到 c艹 } #endregion diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 2b75fa3..e6935eb 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -3144,11 +3144,6 @@ public unsafe partial struct FShaderBindingCreateOptions public partial struct FShaderBindingData { - [NativeTypeName("Coplt::u32")] - public uint SumPersistentSlots; - - [NativeTypeName("Coplt::u32")] - public uint SumTransientSlots; } [Guid("A3CA644A-0E02-4D25-9A18-8835D66600F7")] diff --git a/Coplt.Graphics.Core/Utils/Utils.cs b/Coplt.Graphics.Core/Utils/Utils.cs index cce4bfc..53d42ce 100644 --- a/Coplt.Graphics.Core/Utils/Utils.cs +++ b/Coplt.Graphics.Core/Utils/Utils.cs @@ -138,6 +138,130 @@ private struct AlignOfHelper where T : unmanaged #region Simd Math + [MethodImpl(256 | 512)] + public static Vector128 Ne(Vector128 a, Vector128 b) + { + if (Sse.IsSupported) + { + return Sse.CompareNotEqual(a, b); + } + if (PackedSimd.IsSupported) + { + return PackedSimd.CompareNotEqual(a, b); + } + return ~Vector128.Equals(a, b); + } + + [MethodImpl(256 | 512)] + public static Vector128 Rem(Vector128 x, Vector128 y) + { + var div = x / y; + var flr = RoundToZero(div); + return Fnma(flr, y, x); + } + + [MethodImpl(256 | 512)] + private static Vector64 Round(Vector64 x) + { + if (Sse41.IsSupported) + { + return Sse41.RoundToNearestInteger(x.ToVector128()).GetLower(); + } + if (AdvSimd.IsSupported) + { + return AdvSimd.RoundToNearest(x); + } + if (PackedSimd.IsSupported) + { + return PackedSimd.RoundToNearest(x.ToVector128()).GetLower(); + } + return Vector64.Create( + MathF.Round(x.GetElement(0)), + MathF.Round(x.GetElement(1)) + ); + } + + [MethodImpl(256 | 512)] + public static Vector128 Round(Vector128 x) + { + if (Sse41.IsSupported) + { + return Sse41.RoundToNearestInteger(x); + } + if (AdvSimd.IsSupported) + { + return AdvSimd.RoundToNearest(x); + } + if (PackedSimd.IsSupported) + { + return PackedSimd.RoundToNearest(x); + } + if (Vector64.IsHardwareAccelerated) + { + return Vector128.Create( + Round(x.GetLower()), + Round(x.GetUpper()) + ); + } + return Vector128.Create( + MathF.Round(x.GetElement(0)), + MathF.Round(x.GetElement(1)), + MathF.Round(x.GetElement(2)), + MathF.Round(x.GetElement(3)) + ); + } + + [MethodImpl(256 | 512)] + private static Vector64 RoundToZero(Vector64 x) + { + if (Sse41.IsSupported) + { + return Sse41.RoundToZero(x.ToVector128()).GetLower(); + } + if (AdvSimd.IsSupported) + { + return AdvSimd.RoundToZero(x); + } + if (PackedSimd.IsSupported) + { + return PackedSimd.Truncate(x.ToVector128()).GetLower(); + } + return Vector64.Create( + MathF.Round(x.GetElement(0), MidpointRounding.ToZero), + MathF.Round(x.GetElement(1), MidpointRounding.ToZero) + ); + } + + [MethodImpl(256 | 512)] + public static Vector128 RoundToZero(Vector128 x) + { + if (Sse41.IsSupported) + { + return Sse41.RoundToZero(x); + } + if (AdvSimd.IsSupported) + { + return AdvSimd.RoundToZero(x); + } + if (PackedSimd.IsSupported) + { + return PackedSimd.Truncate(x); + } + if (Vector64.IsHardwareAccelerated) + { + return Vector128.Create( + RoundToZero(x.GetLower()), + RoundToZero(x.GetUpper()) + ); + } + return Vector128.Create( + MathF.Round(x.GetElement(0), MidpointRounding.ToZero), + MathF.Round(x.GetElement(1), MidpointRounding.ToZero), + MathF.Round(x.GetElement(2), MidpointRounding.ToZero), + MathF.Round(x.GetElement(3), MidpointRounding.ToZero) + ); + } + /// a * b + c [MethodImpl(256 | 512)] public static Vector128 Fma(Vector128 a, Vector128 b, Vector128 c) @@ -175,5 +299,92 @@ public static Vector128 Lerp(Vector128 start, Vector128 end [MethodImpl(256 | 512)] public static Vector128 Frac(Vector128 a) => a - Vector128.Floor(a); + [MethodImpl(256 | 512)] + public static Vector128 Log2(Vector128 a) + { + var xl = Vector128.Max(a, Vector128.Zero).AsInt32(); + var mantissa = (xl >>> 23) - Vector128.Create(0x7F); + var r = Vector128.ConvertToSingle(mantissa); + + xl = (xl & Vector128.Create(0x7FFFFF)) | Vector128.Create(0x7F << 23); + + var d = (xl.AsSingle() | Vector128.One) * Vector128.Create(2.0f / 3.0f); + + #region Approx + + // A Taylor Series approximation of ln(x) that relies on the identity that ln(x) = 2*atan((x-1)/(x+1)). + d = (d - Vector128.One) / (d + Vector128.One); + var sq = d * d; + + var rx = Fma(sq, Vector128.Create(0.2371599674224853515625f), Vector128.Create(0.285279005765914916992188f)); + rx = Fma(rx, sq, Vector128.Create(0.400005519390106201171875f)); + rx = Fma(rx, sq, Vector128.Create(0.666666567325592041015625f)); + rx = Fma(rx, sq, Vector128.Create(2.0f)); + + d *= rx; + + #endregion + + r += Fma(d, Vector128.Create(1.4426950408889634f), Vector128.Create(0.58496250072115619f)); + + r = Vector128.ConditionalSelect( + Vector128.GreaterThan(a, Vector128.Zero), + r, Vector128.Create(float.NaN) + ); + r = Vector128.ConditionalSelect( + Vector128.Equals(a, Vector128.Create(float.PositiveInfinity)), + Vector128.Create(float.PositiveInfinity), r + ); + r = Vector128.ConditionalSelect( + Vector128.Equals(a, Vector128.Zero), + Vector128.Create(float.NegativeInfinity), r + ); + + return r; + } + + [MethodImpl(256 | 512)] + public static Vector128 Exp2(Vector128 x) + { + // 1 / log(2) + const float F_1_Div_Log2 = 1.4426950408889634073599246810018921374266459541529859341354494069f; + + var e = Vector128.GreaterThanOrEqual(x, Vector128.Create(89f)) & Vector128.Create(float.PositiveInfinity); + e += Ne(x, x); + + var xx = Vector128.Max( + Vector128.Min(x, Vector128.Create(81.0f * F_1_Div_Log2)), + Vector128.Create(-81.0f * F_1_Div_Log2) + ); + + var fx = Round(xx); + + xx -= fx; + var r = Fma(xx, Vector128.Create(1.530610536076361E-05f), Vector128.Create(0.000154631026827329f)); + r = Fma(r, xx, Vector128.Create(0.0013333465742372899f)); + r = Fma(r, xx, Vector128.Create(0.00961804886829518f)); + r = Fma(r, xx, Vector128.Create(0.05550410925060949f)); + r = Fma(r, xx, Vector128.Create(0.240226509999339f)); + r = Fma(r, xx, Vector128.Create(0.6931471805500692f)); + r = Fma(r, xx, Vector128.Create(1.0f)); + + fx = ((Vector128.ConvertToInt32(fx) + Vector128.Create(127)) << 23).AsSingle(); + + r = Fma(r, fx, e); + r = Vector128.AndNot(r, Vector128.Equals(x, Vector128.Create(float.NegativeInfinity))); + + return r; + } + + [MethodImpl(256 | 512)] + public static Vector128 Pow(Vector128 a, Vector128 b) + { + var sig = Vector128.LessThan(a, default) + & Ne(Rem(b, Vector128.Create(2.0f)), default) + & Vector128.Create(0x8000_0000).AsSingle(); + var r = Exp2(Log2(Vector128.Abs(a)) * b); + return r | sig; + } + #endregion } diff --git a/Coplt.Graphics.Native/Api/FFI/Binding.h b/Coplt.Graphics.Native/Api/FFI/Binding.h index 405de05..7aa8e57 100644 --- a/Coplt.Graphics.Native/Api/FFI/Binding.h +++ b/Coplt.Graphics.Native/Api/FFI/Binding.h @@ -56,8 +56,6 @@ namespace Coplt struct FShaderBindingData { - u32 SumPersistentSlots{}; - u32 SumTransientSlots{}; }; COPLT_INTERFACE_DEFINE(FShaderBinding, "a3ca644a-0e02-4d25-9a18-8835d66600f7", FGpuObject) diff --git a/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h b/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h index bfb5b9f..f032a00 100644 --- a/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h +++ b/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h @@ -682,6 +682,63 @@ namespace Coplt } } + inline FGraphicsFormat ToLinear(const FGraphicsFormat value) + { + switch (value) + { + case FGraphicsFormat::BC1_UNorm_sRGB: + return FGraphicsFormat::BC1_UNorm; + case FGraphicsFormat::BC2_UNorm_sRGB: + return FGraphicsFormat::BC2_UNorm; + case FGraphicsFormat::BC3_UNorm_sRGB: + return FGraphicsFormat::BC3_UNorm; + case FGraphicsFormat::BC7_UNorm_sRGB: + return FGraphicsFormat::BC7_UNorm; + case FGraphicsFormat::B8G8R8A8_UNorm_sRGB: + return FGraphicsFormat::B8G8R8A8_UNorm; + case FGraphicsFormat::B8G8R8X8_UNorm_sRGB: + return FGraphicsFormat::B8G8R8X8_UNorm; + case FGraphicsFormat::R8G8B8A8_UNorm_sRGB: + return FGraphicsFormat::R8G8B8A8_UNorm; + case FGraphicsFormat::Etc2_R8G8B8_sRGB: + return FGraphicsFormat::Etc2_R8G8B8_UNorm; + case FGraphicsFormat::Etc2_R8G8B8A1_sRGB: + return FGraphicsFormat::Etc2_R8G8B8A1_UNorm; + case FGraphicsFormat::Etc2_R8G8B8A8_sRGB: + return FGraphicsFormat::Etc2_R8G8B8A8_UNorm; + case FGraphicsFormat::Astc_4x4_sRGB: + return FGraphicsFormat::Astc_4x4_UNorm; + case FGraphicsFormat::Astc_5x4_sRGB: + return FGraphicsFormat::Astc_5x4_UNorm; + case FGraphicsFormat::Astc_5x5_sRGB: + return FGraphicsFormat::Astc_5x5_UNorm; + case FGraphicsFormat::Astc_6x5_sRGB: + return FGraphicsFormat::Astc_6x5_UNorm; + case FGraphicsFormat::Astc_6x6_sRGB: + return FGraphicsFormat::Astc_6x6_UNorm; + case FGraphicsFormat::Astc_8x5_sRGB: + return FGraphicsFormat::Astc_8x5_UNorm; + case FGraphicsFormat::Astc_8x6_sRGB: + return FGraphicsFormat::Astc_8x6_UNorm; + case FGraphicsFormat::Astc_8x8_sRGB: + return FGraphicsFormat::Astc_8x8_UNorm; + case FGraphicsFormat::Astc_10x5_sRGB: + return FGraphicsFormat::Astc_10x5_UNorm; + case FGraphicsFormat::Astc_10x6_sRGB: + return FGraphicsFormat::Astc_10x6_UNorm; + case FGraphicsFormat::Astc_10x8_sRGB: + return FGraphicsFormat::Astc_10x8_UNorm; + case FGraphicsFormat::Astc_10x10_sRGB: + return FGraphicsFormat::Astc_10x10_UNorm; + case FGraphicsFormat::Astc_12x10_sRGB: + return FGraphicsFormat::Astc_12x10_UNorm; + case FGraphicsFormat::Astc_12x12_sRGB: + return FGraphicsFormat::Astc_12x12_UNorm; + default: + return value; + } + } + inline bool IsDepthStencil(const FGraphicsFormat value) { switch (value) diff --git a/Coplt.Graphics.Native/D3d12/Include/GraphicsFormat.h b/Coplt.Graphics.Native/D3d12/Include/GraphicsFormat.h index afeb6bd..91cfe46 100644 --- a/Coplt.Graphics.Native/D3d12/Include/GraphicsFormat.h +++ b/Coplt.Graphics.Native/D3d12/Include/GraphicsFormat.h @@ -163,8 +163,19 @@ namespace Coplt case FGraphicsFormat::Astc_12x10_sRGB: case FGraphicsFormat::Astc_12x12_UNorm: case FGraphicsFormat::Astc_12x12_sRGB: + case FGraphicsFormat::Etc2_R8G8B8_UNorm: + case FGraphicsFormat::Etc2_R8G8B8_sRGB: + case FGraphicsFormat::Etc2_R8G8B8A1_UNorm: + case FGraphicsFormat::Etc2_R8G8B8A1_sRGB: + case FGraphicsFormat::Etc2_R8G8B8A8_UNorm: + case FGraphicsFormat::Etc2_R8G8B8A8_sRGB: + case FGraphicsFormat::Eac_R11_UNorm: + case FGraphicsFormat::Eac_R11_SNorm: + case FGraphicsFormat::Eac_R11G11_UNorm: + case FGraphicsFormat::Eac_R11G11_SNorm: return DXGI_FORMAT_UNKNOWN; } + return static_cast(value); } diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index 092ab1c..e75f18b 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -326,11 +326,13 @@ namespace Coplt::Enhanced void EnhancedBarrierAnalyzer::Interpret(const D3d12RentedCommandList& list, ID3d12GpuRecord& record) { + record.BeforeInterpret(list); for (auto& group : m_groups) { SubmitBarrier(list, group); record.Interpret(list, group.m_cmd_index, group.m_cmd_count); } + record.AfterInterpret(list); } void EnhancedBarrierAnalyzer::SubmitBarrier(const D3d12RentedCommandList& list, Group& group) diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h index 309a626..3edf6aa 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h @@ -52,5 +52,7 @@ namespace Coplt DescriptorManager() = default; explicit DescriptorManager(NonNull device); + + void EnsureCapacity(); }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index db8d205..fc3ba0e 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -442,6 +442,7 @@ void D3d12GpuRecord::ReadyBindings() void D3d12GpuRecord::Analyze() { + // m_context->m_descriptor_manager const auto commands = Commands.AsSpan(); for (u32 i = 0; i < commands.size(); ++i, m_barrier_analyzer->CmdNext()) { @@ -668,7 +669,20 @@ void D3d12GpuRecord::Analyze_Dispatch(u32 i, const FCmdDispatch& cmd) const } } -void D3d12GpuRecord::Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) +void D3d12GpuRecord::BeforeInterpret(const D3d12RentedCommandList& list) +{ + if (const auto& g0 = list->g0) + { + ID3D12DescriptorHeap* heaps[2]{m_context->m_descriptor_manager.m_res->m_heap.Get(), m_context->m_descriptor_manager.m_smp->m_heap.Get()}; + g0->SetDescriptorHeaps(2, heaps); + } +} + +void D3d12GpuRecord::AfterInterpret(const D3d12RentedCommandList& list) +{ +} + +void D3d12GpuRecord::Interpret(const D3d12RentedCommandList& list, const u32 offset, const u32 count) { const auto commands = Commands.AsSpan(); for (u32 c = 0; c < count; ++c) diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 8747529..7b1557d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -64,7 +64,9 @@ namespace Coplt virtual const Rc& BarrierAnalyzer() = 0; + virtual void BeforeInterpret(const D3d12RentedCommandList& list) = 0; virtual void Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) = 0; + virtual void AfterInterpret(const D3d12RentedCommandList& list) = 0; virtual void AfterSubmit() = 0; }; @@ -182,6 +184,8 @@ namespace Coplt void Analyze_SetMeshBuffers(u32 i, const FCmdSetMeshBuffers& cmd); void Analyze_Dispatch(u32 i, const FCmdDispatch& cmd) const; + void BeforeInterpret(const D3d12RentedCommandList& list) override; + void AfterInterpret(const D3d12RentedCommandList& list) override; void Interpret(const D3d12RentedCommandList& list, u32 offset, u32 count) override; void Interpret_Label(const CmdList& list, u32 i, const FCmdLabel& cmd) const; void Interpret_BeginScope(const CmdList& list, u32 i, const FCmdBeginScope& cmd) const; diff --git a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc index eff1622..e04e9ed 100644 --- a/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -77,12 +77,13 @@ D3d12GpuSwapChain::D3d12GpuSwapChain( ) : D3d12GpuSwapChain(isolate, options, options.AlphaMode, options.VSync) { bool is_hdr = false; - this->Format = SelectFormat(options, is_hdr); + const auto format = SelectFormat(options, is_hdr); + this->Format = this->Srgb ? format : ToSrgb(format); DXGI_SWAP_CHAIN_DESC1 desc{}; desc.Width = this->Width = options.Width; desc.Height = this->Height = options.Height; - desc.Format = ToDx(this->Format); + desc.Format = ToDx(format); desc.SampleDesc.Count = 1; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; @@ -194,7 +195,7 @@ void D3d12GpuSwapChain::CreateRts() { chr | m_swap_chain->GetBuffer(i, IID_PPV_ARGS(&m_buffers[i])); D3D12_RENDER_TARGET_VIEW_DESC desc{}; - desc.Format = ToDx(this->Srgb ? ToSrgb(this->Format) : this->Format); + desc.Format = ToDx(this->Format); desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; desc.Texture2D.MipSlice = 0; desc.Texture2D.PlaneSlice = 0; diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index 12b9066..88350d5 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -52,8 +52,8 @@ public void DoInitGraphics() { Width = Width, Height = Height, - // VSync = true, - // Srgb = true, + VSync = true, + // Srgb = false, } ); Record = Isolate.RentRecord(); diff --git a/Examples/HelloTriangleVertex/Example.cs b/Examples/HelloTriangleVertex/Example.cs index abc8d5a..38643b0 100644 --- a/Examples/HelloTriangleVertex/Example.cs +++ b/Examples/HelloTriangleVertex/Example.cs @@ -1,6 +1,7 @@ using Coplt.Graphics; using Coplt.Graphics.Core; using Coplt.Graphics.States; +using Serilog; namespace Examples; From e0b621dba22bfb0a133e110a1e3a7c03038fe136 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 10 Apr 2025 15:14:28 +0800 Subject: [PATCH 42/46] Shuffle --- Coplt.Graphics.Core/Core/Color.cs | 124 +++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) diff --git a/Coplt.Graphics.Core/Core/Color.cs b/Coplt.Graphics.Core/Core/Color.cs index 1d02588..4de0748 100644 --- a/Coplt.Graphics.Core/Core/Color.cs +++ b/Coplt.Graphics.Core/Core/Color.cs @@ -300,6 +300,66 @@ public ColorHsl Hsl #endregion + #region Shuffle + + public Color RgbaToBgra + { + [MethodImpl(256 | 512)] + get + { + var vector = m_vector; + var r = Vector128.Shuffle(vector, Vector128.Create(2, 1, 0, 3)); + return new(r); + } + } + + public Color BgraToRgba + { + [MethodImpl(256 | 512)] + get => RgbaToBgra; + } + + public Color RgbaToArgb + { + [MethodImpl(256 | 512)] + get + { + var vector = m_vector; + var r = Vector128.Shuffle(vector, Vector128.Create(3, 0, 1, 2)); + return new(r); + } + } + + public Color ArgbToRgba + { + [MethodImpl(256 | 512)] + get + { + var vector = m_vector; + var r = Vector128.Shuffle(vector, Vector128.Create(1, 2, 3, 0)); + return new(r); + } + } + + public Color RgbaToAbgr + { + [MethodImpl(256 | 512)] + get + { + var vector = m_vector; + var r = Vector128.Shuffle(vector, Vector128.Create(3, 2, 1, 0)); + return new(r); + } + } + + public Color AbgrToRgba + { + [MethodImpl(256 | 512)] + get => RgbaToAbgr; + } + + #endregion + #region Linear public readonly Color ToLinear @@ -312,7 +372,7 @@ public readonly Color ToLinear var low = vector * Vector128.Create(1f / 12.92f); var high = Utils.Pow((vector + Vector128.Create(0.055f)) * Vector128.Create(1f / 1.055f), Vector128.Create(2.4f)); var r = Vector128.ConditionalSelect(c, low, high); - return new Color(Vector128.ConditionalSelect(Vector128.Create(-1, -1, -1, 0).AsSingle(), r, vector)); + return new(Vector128.ConditionalSelect(Vector128.Create(-1, -1, -1, 0).AsSingle(), r, vector)); } } @@ -326,7 +386,7 @@ public readonly Color ToSrgb var low = vector * Vector128.Create(12.92f); var high = Utils.Fma(Vector128.Create(1.055f), Utils.Pow(vector, Vector128.Create(1f / 2.4f)), Vector128.Create(-0.055f)); var r = Vector128.ConditionalSelect(c, low, high); - return new Color(Vector128.ConditionalSelect(Vector128.Create(-1, -1, -1, 0).AsSingle(), r, vector)); + return new(Vector128.ConditionalSelect(Vector128.Create(-1, -1, -1, 0).AsSingle(), r, vector)); } } @@ -537,6 +597,66 @@ public ColorHsl Hsl } #endregion + + #region Shuffle + + public Color255 RgbaToBgra + { + [MethodImpl(256 | 512)] + get + { + var vector = m_vector; + var r = Vector128.Shuffle(vector, Vector128.Create(2, 1, 0, 3)); + return new(r); + } + } + + public Color255 BgraToRgba + { + [MethodImpl(256 | 512)] + get => RgbaToBgra; + } + + public Color255 RgbaToArgb + { + [MethodImpl(256 | 512)] + get + { + var vector = m_vector; + var r = Vector128.Shuffle(vector, Vector128.Create(3, 0, 1, 2)); + return new(r); + } + } + + public Color255 ArgbToRgba + { + [MethodImpl(256 | 512)] + get + { + var vector = m_vector; + var r = Vector128.Shuffle(vector, Vector128.Create(1, 2, 3, 0)); + return new(r); + } + } + + public Color255 RgbaToAbgr + { + [MethodImpl(256 | 512)] + get + { + var vector = m_vector; + var r = Vector128.Shuffle(vector, Vector128.Create(3, 2, 1, 0)); + return new(r); + } + } + + public Color255 AbgrToRgba + { + [MethodImpl(256 | 512)] + get => RgbaToAbgr; + } + + #endregion } public struct ColorHsv From 24805d3458a6084db15f7cecc7a6e52501646d9c Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 10 Apr 2025 16:23:01 +0800 Subject: [PATCH 43/46] save --- Coplt.Graphics.Core/Core/GpuRecord.cs | 10 +- Coplt.Graphics.Core/Native/Native.cs | 13 ++- Coplt.Graphics.Native/Api/FFI/Cmd.h | 6 + Coplt.Graphics.Native/Api/FFI/Record.h | 9 +- .../D3d12/Src/DescriptorManager.cc | 104 +++++++++++++----- .../D3d12/Src/DescriptorManager.h | 30 ++++- Coplt.Graphics.Native/D3d12/Src/Record.cc | 18 ++- Coplt.Graphics.Native/D3d12/Src/Record.h | 3 +- 8 files changed, 148 insertions(+), 45 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 8b5e144..18fd672 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -807,16 +807,20 @@ public void SetBinding(GpuRecord self, ShaderBinding Binding) throw new InvalidOperationException("The binding layout is not compatible with the currently set pipeline"); } m_current_binding = Binding; + var binding_index = (uint)self.Data.Bindings.LongLength; + self.Data.Bindings.Add(new() { Binding = Binding.Ptr }); var first = self.AddObject(m_current_binding); + if (first) + { + self.Data.BindingChange.Add(new() { Binding = binding_index, }); + } var cmd = new FCmdSetBinding { Base = { Type = FCmdType.SetBinding }, - Binding = (uint)self.Data.Bindings.LongLength, + Binding = binding_index, Index = self.Data.NumSetBindings++, }; - self.Data.Bindings.Add(new() { Binding = Binding.Ptr }); self.Data.Commands.Add(new() { SetBinding = cmd }); - // if (first) self.Data.SumMaxBindSlots += Binding.Data.SumPersistentSlots + Binding.Data.SumTransientSlots; // todo 这个计算移到 c艹 } #endregion diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index e6935eb..92202c3 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1744,6 +1744,8 @@ public unsafe partial struct FGpuRecordData public FList Bindings; + public FList BindingChange; + public FList PayloadRect; public FList PayloadViewport; @@ -1764,9 +1766,6 @@ public unsafe partial struct FGpuRecordData [NativeTypeName("Coplt::u32")] public uint NumSetBindings; - [NativeTypeName("Coplt::u32")] - public uint SumMaxBindSlots; - [NativeTypeName("Coplt::b8")] public B8 Ended; @@ -2202,6 +2201,12 @@ public unsafe partial struct FCmdBinding public FShaderBinding* Binding; } + public partial struct FBindingChange + { + [NativeTypeName("Coplt::u32")] + public uint Binding; + } + [NativeTypeName("struct FCmdSetBinding : Coplt::FCmdBase")] public partial struct FCmdSetBinding { @@ -2327,7 +2332,7 @@ public partial struct FCmdDispatch public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L353_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L359_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index d04ebcd..a53edaf 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -271,6 +271,12 @@ namespace Coplt FShaderBinding* Binding{}; }; + struct FBindingChange + { + // Payload 中的索引,类型为 FCmdBinding + u32 Binding{}; + }; + struct FCmdSetBinding : FCmdBase { // Payload 中的索引,类型为 FCmdBinding diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index 061e73b..9b58413 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -32,6 +32,7 @@ namespace Coplt FList Commands; FList Resources; FList Bindings; + FList BindingChange; FList PayloadRect; FList PayloadViewport; FList PayloadRenderInfo; @@ -41,15 +42,14 @@ namespace Coplt FList PayloadVertexBufferRange; FList Blob; u32 NumSetBindings{}; - u32 SumMaxBindSlots{}; b8 Ended{}; FGpuRecordMode Mode{}; #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) - : Commands(allocator), Resources(allocator), Bindings(allocator), PayloadRect(allocator), PayloadViewport(allocator), - PayloadRenderInfo(allocator), PayloadResolveInfo(allocator), PayloadBufferCopyRange(allocator), - PayloadMeshBuffers(allocator), PayloadVertexBufferRange(allocator), Blob(allocator) + : Commands(allocator), Resources(allocator), Bindings(allocator), BindingChange(allocator), + PayloadRect(allocator), PayloadViewport(allocator), PayloadRenderInfo(allocator), PayloadResolveInfo(allocator), + PayloadBufferCopyRange(allocator), PayloadMeshBuffers(allocator), PayloadVertexBufferRange(allocator), Blob(allocator) { } @@ -58,6 +58,7 @@ namespace Coplt Commands.Clear(); Resources.Clear(); Bindings.Clear(); + BindingChange.Clear(); PayloadRect.Clear(); PayloadViewport.Clear(); PayloadRenderInfo.Clear(); diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc index a6ff74c..b6dc8ae 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc @@ -4,40 +4,28 @@ using namespace Coplt; -DescriptorAllocation::DescriptorAllocation(DescriptorHeap& heap, const D3D12MA::VirtualAllocation allocation, const u64 offset) - : m_heap(heap.CloneThis()), m_version(heap.m_version), m_allocation(allocation), m_offset(offset) +DescriptorAllocation::DescriptorAllocation(DescriptorHeap& heap, const u64 offset) + : m_heap(heap.CloneThis()), m_offset(offset) { } -DescriptorAllocation::~DescriptorAllocation() -{ - if (!m_heap) return; - if (m_heap->m_version != m_version) return; - m_heap->m_virtual_block->FreeAllocation(m_allocation); - m_heap = {}; -} - CD3DX12_CPU_DESCRIPTOR_HANDLE DescriptorAllocation::GetCpuHandle() const { - if (m_heap->m_version != m_version) - COPLT_THROW("This allocation has expired"); return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_heap->m_heap->GetCPUDescriptorHandleForHeapStart(), m_offset, m_heap->m_inc); } CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorAllocation::GetGpuHandle() const { - if (m_heap->m_version != m_version) - COPLT_THROW("This allocation has expired"); return CD3DX12_GPU_DESCRIPTOR_HANDLE(m_heap->m_heap->GetGPUDescriptorHandleForHeapStart(), m_offset, m_heap->m_inc); } DescriptorHeap::DescriptorHeap(NonNull device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 init_size) - : m_device(device->m_device), m_type(type) + : m_device(device->m_device), m_half_size(init_size), m_type(type) { { D3D12_DESCRIPTOR_HEAP_DESC desc{}; desc.Type = type; - desc.NumDescriptors = init_size; + desc.NumDescriptors = m_half_size * 2; desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; chr | m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_heap)); @@ -49,21 +37,81 @@ DescriptorHeap::DescriptorHeap(NonNull device, D3D12_DESCRIPTOR_ D3D12MA::ALLOCATION_CALLBACKS allocation_callbacks{}; allocation_callbacks.pAllocate = [](auto size, auto align, auto data) { return mi_malloc_aligned(size, align); }; allocation_callbacks.pFree = [](auto ptr, auto data) { return mi_free(ptr); }; - desc.Size = init_size; + desc.Size = m_half_size; + desc.pAllocationCallbacks = &allocation_callbacks; + chr | CreateVirtualBlock(&desc, &m_virtual_block); + } +} + +void DescriptorHeap::ReadyFrame(const u32 cap) +{ + m_tmp_offset = 0; + EnsureCapacity(cap); +} + +void DescriptorHeap::EnsureCapacity(u32 cap) +{ + cap = std::bit_ceil(cap); + if (m_need_grow) cap = std::max(cap, m_half_size * 2); + else if (cap <= m_half_size) return; + + m_half_size = cap; + m_version++; + m_virtual_block->Clear(); + m_allocations.Clear(); + + { + D3D12_DESCRIPTOR_HEAP_DESC desc{}; + desc.Type = m_type; + desc.NumDescriptors = m_half_size * 2; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + chr | m_device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&m_heap)); + } + + { + D3D12MA::VIRTUAL_BLOCK_DESC desc{}; + D3D12MA::ALLOCATION_CALLBACKS allocation_callbacks{}; + allocation_callbacks.pAllocate = [](auto size, auto align, auto data) { return mi_malloc_aligned(size, align); }; + allocation_callbacks.pFree = [](auto ptr, auto data) { return mi_free(ptr); }; + desc.Size = m_half_size; desc.pAllocationCallbacks = &allocation_callbacks; chr | CreateVirtualBlock(&desc, &m_virtual_block); } } -DescriptorAllocation DescriptorHeap::Allocate(const u32 size) +DescriptorAllocation DescriptorHeap::Allocate(const u64 ObjectId, const u32 Size, bool& IsOld) +{ + const auto& allocation = m_allocations.GetOrAdd(ObjectId, IsOld, [this, Size](auto& p) + { + D3D12MA::VIRTUAL_ALLOCATION_DESC desc{}; + desc.Alignment = 1; + desc.Size = Size; + D3D12MA::VirtualAllocation allocation{}; + u64 offset{}; + const auto r = m_virtual_block->Allocate(&desc, &allocation, &offset); + if (r == E_OUTOFMEMORY) + { + const auto a = AllocateTmp(Size); + m_need_grow = true; + p.put(Allocation{{}, a.m_offset}); + } + else + { + chr | r; + p.put(Allocation{allocation, offset}); + } + }); + return DescriptorAllocation(*this, allocation.m_offset); +} + +DescriptorAllocation DescriptorHeap::AllocateTmp(const u32 Size) { - D3D12MA::VIRTUAL_ALLOCATION_DESC desc{}; - desc.Alignment = 1; - desc.Size = size; - D3D12MA::VirtualAllocation allocation{}; - u64 offset{}; - chr | m_virtual_block->Allocate(&desc, &allocation, &offset); - return DescriptorAllocation(*this, allocation, offset); + const auto offset = m_tmp_offset; + m_tmp_offset += Size; + if (m_tmp_offset > m_half_size) + COPLT_THROW("Out of descriptor heap"); + const auto inv_offset = m_half_size * 2 - offset - Size; + return DescriptorAllocation(*this, inv_offset); } DescriptorManager::DescriptorManager(NonNull device) @@ -71,3 +119,9 @@ DescriptorManager::DescriptorManager(NonNull device) m_res = new DescriptorHeap(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, InitResHeapSize); m_smp = new DescriptorHeap(device, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, InitSmpHeapSize); } + +void DescriptorManager::ReadyFrame(const u32 res_cap, const u32 smp_cap) const +{ + m_res->ReadyFrame(res_cap); + m_smp->ReadyFrame(smp_cap); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h index 3edf6aa..3686cef 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h @@ -3,6 +3,7 @@ #include #include #include "D3D12MemAlloc.h" +#include "../../Api/Include/HashMap.h" #include "../../Api/Include/Ptr.h" #include "../../Api/Include/Utils.h" @@ -13,15 +14,13 @@ namespace Coplt struct D3d12GpuDevice; struct DescriptorHeap; + // 分配只能在帧内使用 struct DescriptorAllocation { Rc m_heap{}; - u64 m_version{}; - D3D12MA::VirtualAllocation m_allocation{}; u64 m_offset{}; - explicit DescriptorAllocation(DescriptorHeap& heap, D3D12MA::VirtualAllocation allocation, u64 offset); - ~DescriptorAllocation(); + explicit DescriptorAllocation(DescriptorHeap& heap, u64 offset); CD3DX12_CPU_DESCRIPTOR_HANDLE GetCpuHandle() const; CD3DX12_GPU_DESCRIPTOR_HANDLE GetGpuHandle() const; @@ -29,16 +28,35 @@ namespace Coplt struct DescriptorHeap final : Object { + struct Allocation + { + D3D12MA::VirtualAllocation m_allocation{}; + u64 m_offset{}; + }; + + // 堆版本,每次扩容增加版本,每次扩容所有持久分配都会失效 u64 m_version{}; ComPtr m_device{}; ComPtr m_heap{}; ComPtr m_virtual_block{}; + HashMap m_allocations{}; // todo 释放绑组时排队到隔离,释放分配 + // 描述符半容量,永远保证一半容量可以完整容纳每帧需求 + u32 m_half_size{}; + // 临时分配的偏移 + u32 m_tmp_offset{}; + // heap 类型的描述符增量 u32 m_inc{}; D3D12_DESCRIPTOR_HEAP_TYPE m_type{}; + // 下帧是否需要扩容,即使半容量足够 + bool m_need_grow{}; explicit DescriptorHeap(NonNull device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 init_size); - DescriptorAllocation Allocate(u32 size); + void ReadyFrame(u32 cap); + void EnsureCapacity(u32 cap); + + DescriptorAllocation Allocate(u64 ObjectId, u32 Size, bool& IsOld); + DescriptorAllocation AllocateTmp(u32 Size); }; struct DescriptorManager final @@ -53,6 +71,6 @@ namespace Coplt explicit DescriptorManager(NonNull device); - void EnsureCapacity(); + void ReadyFrame(u32 res_cap, u32 smp_cap) const; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index fc3ba0e..0cc1541 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -354,7 +354,9 @@ void D3d12GpuRecord::DoEnd() COPLT_THROW("Too many resources"); m_barrier_analyzer->StartAnalyze(this); ReadyResource(); - ReadyBindings(); + u32 MinResHeapSize{}, MinSmpHeapSize{}; + ReadyBindings(MinResHeapSize, MinSmpHeapSize); + m_context->m_descriptor_manager.ReadyFrame(MinResHeapSize, MinSmpHeapSize); Analyze(); m_barrier_analyzer->EndAnalyze(); if (m_isolate_config->MultiThreadRecord) @@ -430,14 +432,26 @@ void D3d12GpuRecord::ReadyResource() } } -void D3d12GpuRecord::ReadyBindings() +void D3d12GpuRecord::ReadyBindings(u32& MinResHeapSize, u32& MinSmpHeapSize) { + MinResHeapSize = 0; + MinSmpHeapSize = 0; m_set_binding_infos.clear(); m_set_binding_infos.reserve(NumSetBindings); for (u32 i = 0; i < NumSetBindings; ++i) { m_set_binding_infos.push_back(SetBindingInfo()); } + for (u32 i = 0; i < BindingChange.size(); ++i) + { + const auto& item = BindingChange[i]; + const auto binding = NonNull(Bindings[item.Binding].Binding)->QueryInterface(); + if (binding == nullptr) + COPLT_THROW_FMT("Binding [{}] comes from different backends", item.Binding); + const auto& data = binding->Layout()->Data(); + MinResHeapSize += data.SumTableResourceSlots; + MinSmpHeapSize += data.SumTableSamplerSlots; + } } void D3d12GpuRecord::Analyze() diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 7b1557d..876e75d 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -168,7 +168,8 @@ namespace Coplt FResIndex AddResource(const FCmdRes& res); FResIndex AddResource(const View& view); void ReadyResource(); - void ReadyBindings(); + // 返回帧所需的最小描述符堆大小 + void ReadyBindings(u32& MinResHeapSize, u32& MinSmpHeapSize); void Analyze(); void Analyze_PreparePresent(u32 i, const FCmdPreparePresent& cmd) const; From b720cca027deb1e8edbdd3e6e34c079145e5aa56 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 10 Apr 2025 18:23:14 +0800 Subject: [PATCH 44/46] save --- Coplt.Graphics.Native/D3d12/Src/Barrier.cc | 2 +- Coplt.Graphics.Native/D3d12/Src/Barrier.h | 4 +- Coplt.Graphics.Native/D3d12/Src/Binding.cc | 34 ++++- Coplt.Graphics.Native/D3d12/Src/Binding.h | 17 ++- .../D3d12/Src/DescriptorManager.cc | 15 ++- .../D3d12/Src/DescriptorManager.h | 7 +- Coplt.Graphics.Native/D3d12/Src/Layout.cc | 42 ++++-- Coplt.Graphics.Native/D3d12/Src/Layout.h | 30 ++++- Coplt.Graphics.Native/D3d12/Src/Record.cc | 122 ++++++++++++++++-- Coplt.Graphics.Native/D3d12/Src/Record.h | 23 +++- Coplt.Graphics.Native/D3d12/Src/View.cc | 6 +- 11 files changed, 257 insertions(+), 45 deletions(-) diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc index e75f18b..bba3d8a 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -173,7 +173,7 @@ namespace Coplt::Enhanced return; } - void EnhancedBarrierAnalyzer::OnUse(const FResIndex ResIndex, const View& View, const Layout::BindItemInfo& info) + void EnhancedBarrierAnalyzer::OnUse(const FResIndex ResIndex, const View& View, const Layout::GroupItemInfo& info) { auto access = ResAccess::Common; auto usage = ResUsage::Common; diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h index 87a1a1b..8d427ab 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Barrier.h +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -40,7 +40,7 @@ namespace Coplt virtual void OnAddRes() = 0; virtual void OnUse(FResIndex ResIndex, ResAccess Access, ResUsage Usage, ResLayout Layout) = 0; - virtual void OnUse(FResIndex ResIndex, const View& View, const Layout::BindItemInfo& info) = 0; + virtual void OnUse(FResIndex ResIndex, const View& View, const Layout::GroupItemInfo& info) = 0; virtual void UpdateUse(FResIndex ResIndex) = 0; virtual void OnCmd() = 0; // 每个命令都需要调用一次 @@ -172,7 +172,7 @@ namespace Coplt void OnAddRes() override; void OnUse(FResIndex ResIndex, ResAccess Access, ResUsage Usage, ResLayout Layout) override; - void OnUse(FResIndex ResIndex, const View& View, const Layout::BindItemInfo& info) override; + void OnUse(FResIndex ResIndex, const View& View, const Layout::GroupItemInfo& info) override; void UpdateUse(FResIndex ResIndex) override; void OnCmd() override; void CmdNext() override; diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index ffa90fa..6788291 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -111,6 +111,11 @@ FShaderBindGroupData* D3d12ShaderBindGroup::ShaderBindGroupData() noexcept return this; } +u64 D3d12ShaderBindGroup::Version() const noexcept +{ + return m_version; +} + const Rc& D3d12ShaderBindGroup::Layout() const noexcept { return m_layout; @@ -180,13 +185,14 @@ void D3d12ShaderBindGroup::Set(const std::span items) m_changed_marks[index] = true; } m_changed = true; + m_version++; } -void D3d12ShaderBindGroup::EnsureAvailable() +bool D3d12ShaderBindGroup::EnsureAvailable() { - if (!m_changed) return; + if (!m_changed) return false; std::lock_guard guard(m_desc_lock); - if (!m_changed) return; + if (!m_changed) return false; const auto defs = m_layout->GetItems(); const auto slots = m_layout->Slots(); for (usize i = 0; i < m_views.size(); ++i) @@ -194,8 +200,8 @@ void D3d12ShaderBindGroup::EnsureAvailable() const auto def_index = m_define_indexes[i]; const auto& slot = slots[def_index]; if (slot.Place == Layout::BindSlotPlace::NonTable) continue; - if (const auto& mark = m_changed_marks[i]) continue; - else mark = false; + if (const auto& mark = m_changed_marks[i]) mark = false; + else continue; const auto& view = m_views[i]; const auto& def = defs[def_index]; const auto& heap = slot.Place == Layout::BindSlotPlace::ResourceTable ? m_resource_heap : m_sampler_heap; @@ -204,6 +210,17 @@ void D3d12ShaderBindGroup::EnsureAvailable() view.CreateDescriptor(m_device->m_device.Get(), def, handle); } m_changed = false; + return true; +} + +const ComPtr& D3d12ShaderBindGroup::ResourceHeap() noexcept +{ + return m_resource_heap; +} + +const ComPtr& D3d12ShaderBindGroup::SamplerHeap() noexcept +{ + return m_sampler_heap; } D3d12ShaderBinding::D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options) : m_device(std::move(device)) @@ -227,6 +244,11 @@ FShaderBindingData* D3d12ShaderBinding::ShaderBindingData() noexcept return this; } +u64 D3d12ShaderBinding::Version() const noexcept +{ + return m_version; +} + const Rc& D3d12ShaderBinding::Layout() const noexcept { return m_layout; @@ -244,6 +266,7 @@ RwLock& D3d12ShaderBinding::SelfLock() noexcept void D3d12ShaderBinding::Set(const std::span items) { + if (items.size() == 0) return; for (const auto& item : items) { if (item.Index >= m_groups.size()) @@ -260,4 +283,5 @@ void D3d12ShaderBinding::Set(const std::span items) m_groups[item.Index] = nullptr; } } + m_version++; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index eb564fd..0c58245 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -17,16 +17,22 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12ShaderBindGroup, "5bb948b9-ad31-4eb8-b881-98017e048259", FShaderBindGroup) { + virtual u64 Version() const noexcept = 0; virtual const Rc& Layout() const noexcept = 0; virtual std::span Views() const noexcept = 0; virtual std::span ItemIndexes() const noexcept = 0; virtual std::span DefineIndexes() const noexcept = 0; virtual RwLock& SelfLock() noexcept = 0; - virtual void EnsureAvailable() = 0; + // 返回是否有改变 + virtual bool EnsureAvailable() = 0; + + virtual const ComPtr& ResourceHeap() noexcept = 0; + virtual const ComPtr& SamplerHeap() noexcept = 0; }; struct D3d12ShaderBindGroup final : GpuObject, FShaderBindGroupData { + volatile u64 m_version{}; Rc m_name{}; Rc m_device{}; Rc m_layout{}; @@ -53,6 +59,7 @@ namespace Coplt FShaderBindGroupData* ShaderBindGroupData() noexcept override; + u64 Version() const noexcept override; const Rc& Layout() const noexcept override; std::span Views() const noexcept override; std::span ItemIndexes() const noexcept override; @@ -63,11 +70,15 @@ namespace Coplt void Set(std::span items); // 需要外部锁 m_self_lock 必须是 Read 锁定状态 - void EnsureAvailable() override; + bool EnsureAvailable() override; + + const ComPtr& ResourceHeap() noexcept override; + const ComPtr& SamplerHeap() noexcept override; }; COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "5073f785-cfb7-414d-9a84-1602d3bf378d", FShaderBinding) { + virtual u64 Version() const noexcept = 0; virtual const Rc& Layout() const noexcept = 0; virtual std::span> Groups() const noexcept = 0; virtual RwLock& SelfLock() noexcept = 0; @@ -75,6 +86,7 @@ namespace Coplt struct D3d12ShaderBinding final : GpuObject, FShaderBindingData { + volatile u64 m_version{}; Rc m_device{}; Rc m_layout{}; std::vector> m_groups{}; @@ -86,6 +98,7 @@ namespace Coplt FShaderBindingData* ShaderBindingData() noexcept override; + u64 Version() const noexcept override; const Rc& Layout() const noexcept override; std::span> Groups() const noexcept override; RwLock& SelfLock() noexcept override; diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc index b6dc8ae..c44d2ef 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc @@ -4,21 +4,28 @@ using namespace Coplt; -DescriptorAllocation::DescriptorAllocation(DescriptorHeap& heap, const u64 offset) - : m_heap(heap.CloneThis()), m_offset(offset) +DescriptorAllocation::DescriptorAllocation(DescriptorHeap* heap, const u64 offset) + : m_heap(heap), m_offset(offset) { } CD3DX12_CPU_DESCRIPTOR_HANDLE DescriptorAllocation::GetCpuHandle() const { + if (!m_heap) return {}; return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_heap->m_heap->GetCPUDescriptorHandleForHeapStart(), m_offset, m_heap->m_inc); } CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorAllocation::GetGpuHandle() const { + if (!m_heap) return {}; return CD3DX12_GPU_DESCRIPTOR_HANDLE(m_heap->m_heap->GetGPUDescriptorHandleForHeapStart(), m_offset, m_heap->m_inc); } +DescriptorAllocation::operator bool() const +{ + return m_heap != nullptr; +} + DescriptorHeap::DescriptorHeap(NonNull device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 init_size) : m_device(device->m_device), m_half_size(init_size), m_type(type) { @@ -101,7 +108,7 @@ DescriptorAllocation DescriptorHeap::Allocate(const u64 ObjectId, const u32 Size p.put(Allocation{allocation, offset}); } }); - return DescriptorAllocation(*this, allocation.m_offset); + return DescriptorAllocation(this, allocation.m_offset); } DescriptorAllocation DescriptorHeap::AllocateTmp(const u32 Size) @@ -111,7 +118,7 @@ DescriptorAllocation DescriptorHeap::AllocateTmp(const u32 Size) if (m_tmp_offset > m_half_size) COPLT_THROW("Out of descriptor heap"); const auto inv_offset = m_half_size * 2 - offset - Size; - return DescriptorAllocation(*this, inv_offset); + return DescriptorAllocation(this, inv_offset); } DescriptorManager::DescriptorManager(NonNull device) diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h index 3686cef..7074cb3 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h @@ -17,13 +17,16 @@ namespace Coplt // 分配只能在帧内使用 struct DescriptorAllocation { - Rc m_heap{}; + DescriptorHeap* m_heap; u64 m_offset{}; - explicit DescriptorAllocation(DescriptorHeap& heap, u64 offset); + DescriptorAllocation() = default; + explicit DescriptorAllocation(DescriptorHeap* heap, u64 offset); CD3DX12_CPU_DESCRIPTOR_HANDLE GetCpuHandle() const; CD3DX12_GPU_DESCRIPTOR_HANDLE GetGpuHandle() const; + + explicit operator bool() const; }; struct DescriptorHeap final : Object diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.cc b/Coplt.Graphics.Native/D3d12/Src/Layout.cc index 92952dd..11cd9da 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.cc @@ -160,20 +160,20 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi ); } } - m_bind_item_infos.reserve(options.NumGroups); + m_group_item_infos.reserve(options.NumGroups); for (u32 g = 0; g < options.NumGroups; g++) { - std::vector bind_item_infos{}; + std::vector group_item_infos{}; const auto& group = m_groups[g]; const auto& group_data = group->Data(); SumTableSamplerSlots += group_data.ResourceTableSize; SumTableResourceSlots += group_data.SamplerTableSize; const auto items = group->GetItems(); - bind_item_infos.reserve(items.size()); + group_item_infos.reserve(items.size()); for (u32 i = 0; i < items.size(); ++i) { const auto& item = items[i]; - BindItemInfo bind_item_info{}; + GroupItemInfo bind_item_info{}; bind_item_info.Group = g; bind_item_info.IndexInGroup = i; bind_item_info.Format = item.Format; @@ -234,9 +234,9 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi break; } } - bind_item_infos.push_back(bind_item_info); + group_item_infos.push_back(bind_item_info); } - m_bind_item_infos.push_back(std::move(bind_item_infos)); + m_group_item_infos.push_back(std::move(group_item_infos)); } std::vector root_parameters{}; @@ -263,6 +263,13 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi info.SigIndex = static_cast(root_parameters.size()); info.SigPlace = SigPlace::Const; root_parameters.push_back(param); + + BindItemInfo item_info{}; + item_info.Group = info.Group; + item_info.IndexInGroup = info.Index; + item_info.RootIndex = info.SigIndex; + item_info.Place = BindItemPlace::Const; + m_bind_item_infos.push_back(item_info); continue; } @@ -342,6 +349,13 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi info.SigIndex = static_cast(root_parameters.size()); info.SigPlace = SigPlace::Direct; root_parameters.push_back(param); + + BindItemInfo item_info{}; + item_info.Group = info.Group; + item_info.IndexInGroup = info.Index; + item_info.RootIndex = info.SigIndex; + item_info.Place = BindItemPlace::Direct; + m_bind_item_infos.push_back(item_info); continue; } DefineStaticSampler: @@ -378,6 +392,13 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi param.DescriptorTable.pDescriptorRanges = Ranges.data(); root_parameters.push_back(param); infos.push_back(Info); + + BindItemInfo item_info{}; + item_info.Group = Info.Group; + item_info.IndexInGroup = 0; + item_info.RootIndex = Info.RootIndex; + item_info.Place = BindItemPlace::Table; + m_bind_item_infos.push_back(item_info); } m_tables.push_back(std::move(infos)); } @@ -455,14 +476,19 @@ std::span D3d12BindingLayout::SlotInfos() co return m_slot_infos; } +std::span D3d12BindingLayout::BindItemInfos() const noexcept +{ + return m_bind_item_infos; +} + std::span> D3d12BindingLayout::TableInfos() const noexcept { return m_tables; } -std::span> D3d12BindingLayout::BindItemInfos() const noexcept +std::span> D3d12BindingLayout::GroupItemInfos() const noexcept { - return m_bind_item_infos; + return m_group_item_infos; } D3d12ShaderInputLayout::D3d12ShaderInputLayout( diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.h b/Coplt.Graphics.Native/D3d12/Src/Layout.h index 6a15eb0..3c8039a 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.h +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.h @@ -120,7 +120,7 @@ namespace Coplt } }; - struct BindItemInfo + struct GroupItemInfo { u32 Group{}; u32 IndexInGroup{}; @@ -130,6 +130,22 @@ namespace Coplt FShaderLayoutItemType Type{}; FResourceAccess UavAccess{}; }; + + enum class BindItemPlace : u8 + { + Table, + Direct, + Const, + }; + + struct BindItemInfo + { + u32 Group{}; + // Place 为 Table 时永远为 0 + u32 IndexInGroup{}; + u32 RootIndex{}; + BindItemPlace Place{}; + }; } struct D3d12ShaderLayout final : GpuObject, FShaderLayoutData @@ -180,18 +196,20 @@ namespace Coplt COPLT_INTERFACE_DEFINE(ID3d12BindingLayout, "7271c0de-ec05-44be-9d1b-4b54894e297e", FBindingLayout) { using SlotInfo = Layout::SlotInfo; - using BindItemInfo = Layout::BindItemInfo; + using GroupItemInfo = Layout::GroupItemInfo; using TableInfo = Layout::TableInfo; + using BindItemInfo = Layout::BindItemInfo; virtual const D3d12BindingLayoutData& Data() const noexcept = 0; virtual const Rc& ShaderLayout() const noexcept = 0; virtual std::span> Groups() const noexcept = 0; virtual const ComPtr& RootSignature() const noexcept = 0; virtual std::span SlotInfos() const noexcept = 0; + virtual std::span BindItemInfos() const noexcept = 0; // 第一层索引是 Group index virtual std::span> TableInfos() const noexcept = 0; // 第一层索引是 Group index - virtual std::span> BindItemInfos() const noexcept = 0; + virtual std::span> GroupItemInfos() const noexcept = 0; }; struct D3d12BindingLayout final : GpuObject, D3d12BindingLayoutData @@ -203,11 +221,12 @@ namespace Coplt Rc m_shader_layout{}; std::vector> m_groups{}; std::vector m_slot_infos{}; + std::vector m_bind_item_infos{}; HashMap m_slot_to_info{}; // 第一层索引是 Group index std::vector> m_tables{}; // 第一层索引是 Group index - std::vector> m_bind_item_infos{}; + std::vector> m_group_item_infos{}; explicit D3d12BindingLayout(Rc&& device, const FBindingLayoutCreateOptions& options); @@ -218,8 +237,9 @@ namespace Coplt std::span> Groups() const noexcept override; const ComPtr& RootSignature() const noexcept override; std::span SlotInfos() const noexcept override; + std::span BindItemInfos() const noexcept override; std::span> TableInfos() const noexcept override; - std::span> BindItemInfos() const noexcept override; + std::span> GroupItemInfos() const noexcept override; }; struct D3d12ShaderInputLayout final : GpuObject diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index 0cc1541..e756ab8 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -236,7 +236,7 @@ void D3d12GpuRecord::PipelineContext::SetPipeline(NonNull pipel } } -void D3d12GpuRecord::PipelineContext::SetBinding(NonNull binding, u32 i) +void D3d12GpuRecord::PipelineContext::SetBinding(NonNull binding, u32 i, const FCmdSetBinding& cmd) { if (Binding && binding->ObjectId() == Binding->ObjectId()) return; const Ptr dx_binding = binding->QueryInterface(); @@ -252,6 +252,7 @@ void D3d12GpuRecord::PipelineContext::SetBinding(NonNull binding COPLT_THROW_FMT("[{}] The binding layout is not compatible with the currently set pipeline", i); } Binding = dx_binding; + SetBindingIndex = cmd.Index; } D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) @@ -326,7 +327,10 @@ void D3d12GpuRecord::Recycle() m_context->Recycle(); m_resource_map.Clear(); m_resource_infos.clear(); + m_binding_infos.clear(); m_set_binding_infos.clear(); + m_allocations.clear(); + m_bind_items.clear(); m_pipeline_context.Reset(); ClearData(); Ended = false; @@ -436,6 +440,12 @@ void D3d12GpuRecord::ReadyBindings(u32& MinResHeapSize, u32& MinSmpHeapSize) { MinResHeapSize = 0; MinSmpHeapSize = 0; + m_binding_infos.clear(); + m_binding_infos.reserve(Bindings.size()); + for (u32 i = 0; i < Bindings.size(); ++i) + { + m_binding_infos.push_back({}); + } m_set_binding_infos.clear(); m_set_binding_infos.reserve(NumSetBindings); for (u32 i = 0; i < NumSetBindings; ++i) @@ -456,7 +466,6 @@ void D3d12GpuRecord::ReadyBindings(u32& MinResHeapSize, u32& MinSmpHeapSize) void D3d12GpuRecord::Analyze() { - // m_context->m_descriptor_manager const auto commands = Commands.AsSpan(); for (u32 i = 0; i < commands.size(); ++i, m_barrier_analyzer->CmdNext()) { @@ -627,27 +636,86 @@ void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) { if (m_state != RecordState::Render && m_state != RecordState::Compute) COPLT_THROW_FMT("[{}] Cannot use SetBinding in main scope", i); - if (!SetBinding(Bindings[cmd.Binding].Binding, i)) return; + if (!SetBinding(Bindings[cmd.Binding].Binding, i, cmd)) return; const NonNull binding = m_pipeline_context.Binding; ReadGuard binding_guard(binding->SelfLock()); - const auto bind_item_infos = binding->Layout()->BindItemInfos(); + Finally clear_lock([&] { m_tmp_locks.clear(); }); // todo 锁移到整个 render pass 范围,不允许在 render pass 中修改绑定内容 const auto groups = binding->Groups(); for (u32 g = 0; g < groups.size(); ++g) { const auto& group = groups[g]; if (!group) continue; - ReadGuard group_guard(group->SelfLock()); + m_tmp_locks.push_back(ReadGuard{group->SelfLock()}); + } + const auto& binding_layout = binding->Layout(); + const auto group_item_infos = binding_layout->GroupItemInfos(); + const auto bind_item_infos = binding_layout->BindItemInfos(); + bool any_changed = false; + for (u32 g = 0; g < groups.size(); ++g) + { + const auto& group = groups[g]; + if (!group) continue; const auto views = group->Views(); for (u32 v = 0; v < views.size(); ++v) { const auto& view = views[v]; if (!view || view.IsSampler()) continue; const auto& res_index = AddResource(view); - const auto& info = bind_item_infos[g][v]; - m_barrier_analyzer->OnUse(res_index, view, info); + const auto& info = group_item_infos[g][v]; + m_barrier_analyzer->OnUse(res_index, view, info); // todo 屏障移动到每次 draw + } + if (group->EnsureAvailable()) any_changed = true; + } + auto& binding_info = m_binding_infos[cmd.Binding]; + auto& set_binding_info = m_set_binding_infos[cmd.Index]; + const auto binding_version = binding->Version(); + if (binding_info.AllocationIndex == COPLT_U32_MAX || binding_info.BindingVersion != binding_version || any_changed) + { + binding_info.BindingVersion = binding_version; + binding_info.AllocationIndex = m_allocations.size(); + binding_info.BindItemIndex = m_bind_items.size(); + for (u32 g = 0; g < groups.size(); ++g) + { + const auto& group = groups[g]; + if (!group) + { + m_allocations.push_back({}); + continue; + } + const auto object_id = group->ObjectId(); + const auto& data = group->Layout()->Data(); + // todo 确定是最后一次修改 + const auto f = [&](const u32 size, const Rc& heap, const ComPtr& dh, const bool last) + { + if (size == 0) return; + DescriptorAllocation allocation; + if (data.Usage == FBindGroupUsage::Dynamic && !last) + { + allocation = heap->AllocateTmp(size); + m_allocations.push_back(allocation); + } + else + { + bool exists = false; + allocation = heap->Allocate(object_id, size, exists); + m_allocations.push_back(allocation); + if (exists) return; + } + m_device->m_device->CopyDescriptorsSimple(size, allocation.GetCpuHandle(), dh->GetCPUDescriptorHandleForHeapStart(), heap->m_type); + }; + f(data.ResourceTableSize, m_context->m_descriptor_manager.m_res, group->ResourceHeap(), true); + f(data.SamplerTableSize, m_context->m_descriptor_manager.m_smp, group->SamplerHeap(), true); + } + for (const auto& bind_item_info : bind_item_infos) + { + BindItem item{}; + // todo 直接资源和常量 + m_bind_items.push_back(item); } - group->EnsureAvailable(); } + set_binding_info.Layout = binding_layout.get(); + set_binding_info.AllocationIndex = binding_info.AllocationIndex; + set_binding_info.BindItemIndex = binding_info.BindItemIndex; m_barrier_analyzer->OnCmd(); } @@ -993,7 +1061,39 @@ void D3d12GpuRecord::Interpret_SetPipeline(const CmdList& list, const u32 i, con void D3d12GpuRecord::Interpret_SetBinding(const CmdList& list, u32 i, const FCmdSetBinding& cmd) { - // todo + if (m_state != RecordState::Render && m_state != RecordState::Compute) + COPLT_THROW_FMT("[{}] Cannot use SetBinding in main scope", i); + if (!SetBinding(Bindings[cmd.Binding].Binding, i, cmd)) return; + const auto& set_binding_info = m_set_binding_infos[m_pipeline_context.SetBindingIndex]; + const auto bind_item_infos = set_binding_info.Layout->BindItemInfos(); + for (usize n = 0; n < bind_item_infos.size(); ++n) + { + const auto& bind_item_info = bind_item_infos[n]; + const auto& bind_item = m_bind_items[set_binding_info.BindItemIndex + n]; + // todo 直接资源和常量 + switch (bind_item_info.Place) + { + case Layout::BindItemPlace::Table: + { + const auto& allocation = m_allocations[set_binding_info.AllocationIndex + bind_item_info.Group]; + if (m_state == RecordState::Render) + { + list->g0->SetGraphicsRootDescriptorTable(bind_item_info.RootIndex, allocation.GetGpuHandle()); + } + else + { + list->g0->SetComputeRootDescriptorTable(bind_item_info.RootIndex, allocation.GetGpuHandle()); + } + break; + } + case Layout::BindItemPlace::Direct: + // todo + break; + case Layout::BindItemPlace::Const: + // todo + break; + } + } } void D3d12GpuRecord::Interpret_SetViewportScissor(const CmdList& list, u32 i, const FCmdSetViewportScissor& cmd) const @@ -1074,10 +1174,10 @@ void D3d12GpuRecord::SetPipeline(NonNull pipeline, u32 i) m_pipeline_context.SetPipeline(pipeline, i); } -bool D3d12GpuRecord::SetBinding(NonNull binding, u32 i) +bool D3d12GpuRecord::SetBinding(NonNull binding, u32 i, const FCmdSetBinding& cmd) { if (m_pipeline_context.Binding && binding->ObjectId() == m_pipeline_context.Binding->ObjectId()) return false; - m_pipeline_context.SetBinding(binding, i); + m_pipeline_context.SetBinding(binding, i, cmd); return true; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index 876e75d..b0dcec4 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -105,21 +105,36 @@ namespace Coplt Ptr GPipeline{}; Ptr Binding{}; + u32 SetBindingIndex{}; bool PipelineChanged{}; bool BindingChanged{}; void Reset(); void SetPipeline(NonNull pipeline, u32 i); - void SetBinding(NonNull binding, u32 i); + void SetBinding(NonNull binding, u32 i, const FCmdSetBinding& cmd); }; struct BindingInfo { + u64 BindingVersion{}; + u32 AllocationIndex{COPLT_U32_MAX}; + u32 BindItemIndex{COPLT_U32_MAX}; }; struct SetBindingInfo { + ID3d12BindingLayout* Layout{}; + u32 AllocationIndex{COPLT_U32_MAX}; + u32 BindItemIndex{COPLT_U32_MAX}; + }; + + struct BindItem + { + union + { + // todo 直接资源和常量 + }; }; u64 m_isolate_id{}; @@ -130,8 +145,12 @@ namespace Coplt Rc m_barrier_analyzer{}; HashMap m_resource_map{}; // id -> index std::vector m_resource_infos{}; + std::vector m_binding_infos{}; std::vector m_set_binding_infos{}; + std::vector m_allocations{}; + std::vector m_bind_items{}; std::vector m_queue_wait_points{}; + std::vector m_tmp_locks{}; RenderState m_cur_render{}; ComputeState m_cur_compute{}; PipelineContext m_pipeline_context{}; @@ -207,7 +226,7 @@ namespace Coplt void SetPipeline(NonNull pipeline, u32 i); // 返回是否改变 - bool SetBinding(NonNull binding, u32 i); + bool SetBinding(NonNull binding, u32 i, const FCmdSetBinding& cmd); void SetPipeline(const CmdList& list, NonNull pipeline, u32 i); }; diff --git a/Coplt.Graphics.Native/D3d12/Src/View.cc b/Coplt.Graphics.Native/D3d12/Src/View.cc index ffae667..72892fe 100644 --- a/Coplt.Graphics.Native/D3d12/Src/View.cc +++ b/Coplt.Graphics.Native/D3d12/Src/View.cc @@ -92,13 +92,13 @@ void View::CreateDescriptor(NonNull device, const FBindGroupItem& CreateNullDescriptor(device, def, handle); break; case FViewType::Buffer: - // CreateBufferDescriptor(device, def, handle); + CreateBufferDescriptor(device, def, handle); break; case FViewType::Image: - // CreateImageDescriptor(device, def, handle); + CreateImageDescriptor(device, def, handle); break; case FViewType::Sampler: - // CreateSamplerDescriptor(device, def, handle); + CreateSamplerDescriptor(device, def, handle); break; } } From 119174e88260f7556c485e6a99c875e385475bf0 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 10 Apr 2025 22:13:06 +0800 Subject: [PATCH 45/46] save --- Coplt.Graphics.Core/Core/GpuRecord.cs | 100 +++++++++- .../Core/ImageUploadBufferMemory.cs | 20 -- Coplt.Graphics.Core/Core/UploadLoc.cs | 3 +- Coplt.Graphics.Core/Native/FUploadLoc.cs | 6 - Coplt.Graphics.Core/Native/Native.cs | 25 ++- Coplt.Graphics.Native/Api/FFI/Cmd.h | 4 +- Coplt.Graphics.Native/Api/FFI/Record.h | 8 +- Coplt.Graphics.Native/D3d12/Src/Layout.cc | 38 ++-- Coplt.Graphics.Native/D3d12/Src/Layout.h | 7 + Coplt.Graphics.Native/D3d12/Src/Record.cc | 172 +++++++++++++++++- Coplt.Graphics.Native/D3d12/Src/Record.h | 10 +- Coplt.Graphics.Native/D3d12/Src/Resource.cc | 1 + Examples/ExampleBase/ExampleBase.cs | 2 +- Examples/Image/Example.cs | 165 ++++++++++------- 14 files changed, 418 insertions(+), 143 deletions(-) diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs index 18fd672..8baaefa 100644 --- a/Coplt.Graphics.Core/Core/GpuRecord.cs +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -102,7 +102,7 @@ internal void AssertEndOrCanEnd() /// /// 返回的 Span 只能写入 /// - public FSlice AllocUploadMemory(uint Size, out UploadLoc2 loc, uint Align = 4) + public FSlice AllocUploadMemory(uint Size, out UploadLoc loc, uint Align = 4) { if (Align > 1) Size += Align - 1; ref var upload_buffers = ref Data.Context->m_upload_buffer; @@ -113,7 +113,7 @@ public FSlice AllocUploadMemory(uint Size, out UploadLoc2 loc, uint Align { var offset = block.cur_offset.Aligned(Align); var r = new FSlice(block.mapped_ptr, (nuint)block.size).Slice((nuint)offset); - loc = new UploadLoc2(Data.Id, Data.Version, i, offset, Size); + loc = new UploadLoc(Data.Id, Data.Version, i, offset, Size); block.cur_offset += Size; return r; } @@ -126,13 +126,13 @@ public FSlice AllocUploadMemory(uint Size, out UploadLoc2 loc, uint Align if (block.cur_offset + Size >= block.size) throw new OutOfMemoryException(); var offset = block.cur_offset.Aligned(Align); var r = new FSlice(block.mapped_ptr, (nuint)block.size).Slice((nuint)offset); - loc = new UploadLoc2(Data.Id, Data.Version, i, offset, Size); + loc = new UploadLoc(Data.Id, Data.Version, i, offset, Size); block.cur_offset += Size; return r; } } - public UploadLoc2 WriteToUpload(ReadOnlySpan Data, uint Align = 4) + public UploadLoc WriteToUpload(ReadOnlySpan Data, uint Align = 4) { Data.CopyTo(AllocUploadMemory((uint)Data.Length, out var loc, Align)); return loc; @@ -141,20 +141,20 @@ public UploadLoc2 WriteToUpload(ReadOnlySpan Data, uint Align = 4) /// /// 分配用于上传纹理的 256 对齐的内存 /// - public ImageUploadBufferMemory2 AllocImageUploadMemory2D(uint PixelSize, uint Width, uint Height, uint Length = 1) => + public ImageUploadBufferMemory AllocImageUploadMemory2D(uint PixelSize, uint Width, uint Height, uint Length = 1) => AllocImageUploadMemory2D(PixelSize, Width, Height, Length, out _); /// /// 分配用于上传纹理的 256 对齐的内存 /// - public ImageUploadBufferMemory2 AllocImageUploadMemory2D(uint PixelSize, uint Width, uint Height, uint Length, out UploadLoc2 loc) + public ImageUploadBufferMemory AllocImageUploadMemory2D(uint PixelSize, uint Width, uint Height, uint Length, out UploadLoc loc) { if (PixelSize < 1 || Width < 1 || Height < 1 || Length < 1) throw new ArgumentOutOfRangeException(); var row_stride = (PixelSize * Width).Aligned(256); var row_count = Height * Length; var buffer_size = row_stride * row_count + 256u; var slice = AllocUploadMemory(buffer_size, out loc, 256u); - return new ImageUploadBufferMemory2(slice, row_stride, row_count, Length, Height, loc); + return new ImageUploadBufferMemory(slice, row_stride, row_count, Length, Height, loc); } #endregion @@ -462,7 +462,7 @@ public void Upload( public void Upload( GpuBuffer Dst, - UploadLoc2 Loc, + UploadLoc Loc, ulong DstOffset = 0 ) { @@ -493,6 +493,90 @@ public void Upload( Data.Commands.Add(new() { BufferCopy = cmd }); } + #endregion + + #region ImageUpload + + public void Upload( + GpuImage Dst, + ImageUploadBufferMemory Memory, + uint MipLevel = 0, + uint ImageIndex = 0, + uint ImageCount = 1, + ImagePlane Plane = ImagePlane.All + ) => Upload( + Dst, Memory.Loc, Memory.RowStride, Memory.RowsPerImage, + MipLevel, ImageIndex, ImageCount, Plane + ); + + public void Upload( + GpuImage Dst, + UploadLoc Loc, + uint BytesPerRow, + uint RowsPerImage, + uint MipLevel = 0, + uint ImageIndex = 0, + uint ImageCount = 1, + ImagePlane Plane = ImagePlane.All + ) => Upload( + Dst, Loc, + 0, 0, 0, + Dst.Width, Dst.Height, Dst.DepthOrLength, + BytesPerRow, RowsPerImage, + MipLevel, ImageIndex, ImageCount, Plane + ); + + public void Upload( + GpuImage Dst, + UploadLoc Loc, + uint DstX, + uint DstY, + uint DstZ, + uint DstWidth, + uint DstHeight, + uint DstDepth, + uint BytesPerRow, + uint RowsPerImage, + uint MipLevel = 0, + uint ImageIndex = 0, + uint ImageCount = 1, + ImagePlane Plane = ImagePlane.All + ) + { + Dst.AssertSameIsolate(Isolate); + if (Loc.RecordId != Data.Id) + throw new ArgumentException("An attempt was made to use an expired upload location"); + if (Loc.RecordVersion != Data.Version) + throw new ArgumentException("An attempt was made to use an expired upload location"); + var cmd = new FCmdBufferImageCopy + { + Base = { Type = FCmdType.BufferImageCopy }, + RangeIndex = (uint)Data.PayloadBufferImageCopyRange.LongLength, + Image = AddResource(Dst), + Buffer = { Upload = Loc }, + BufferType = FBufferRefType2.Upload, + ImageToBuffer = false, + }; + var range = new FBufferImageCopyRange + { + BufferOffset = Loc.Offset, + BytesPerRow = BytesPerRow, + RowsPerImage = RowsPerImage, + ImageIndex = ImageIndex, + ImageCount = ImageCount, + MipLevel = (ushort)MipLevel, + Plane = Plane.ToFFI(), + }; + range.ImageOffset[0] = DstX; + range.ImageOffset[1] = DstY; + range.ImageOffset[2] = DstZ; + range.ImageExtent[0] = DstWidth; + range.ImageExtent[1] = DstHeight; + range.ImageExtent[2] = DstDepth; + Data.PayloadBufferImageCopyRange.Add(range); + Data.Commands.Add(new() { BufferImageCopy = cmd }); + } + #endregion #region Render diff --git a/Coplt.Graphics.Core/Core/ImageUploadBufferMemory.cs b/Coplt.Graphics.Core/Core/ImageUploadBufferMemory.cs index f704811..06ddbdf 100644 --- a/Coplt.Graphics.Core/Core/ImageUploadBufferMemory.cs +++ b/Coplt.Graphics.Core/Core/ImageUploadBufferMemory.cs @@ -21,23 +21,3 @@ public FSlice this[uint index] } } } - -public readonly struct ImageUploadBufferMemory2(FSlice Slice, uint RowStride, uint RowCount, uint ImageCount, uint RowsPerImage, UploadLoc2 Loc) -{ - public readonly FSlice Slice = Slice; - public readonly uint RowStride = RowStride; - public readonly uint RowCount = RowCount; - public readonly uint ImageCount = ImageCount; - public readonly uint RowsPerImage = RowsPerImage; - public readonly UploadLoc2 Loc = Loc; - - public FSlice this[uint index] - { - get - { - if (index >= RowCount) throw new IndexOutOfRangeException(); - var offset = RowStride * index; - return Slice.Slice(offset, RowStride); - } - } -} diff --git a/Coplt.Graphics.Core/Core/UploadLoc.cs b/Coplt.Graphics.Core/Core/UploadLoc.cs index c9e3bfb..1b4ec8c 100644 --- a/Coplt.Graphics.Core/Core/UploadLoc.cs +++ b/Coplt.Graphics.Core/Core/UploadLoc.cs @@ -1,4 +1,3 @@ namespace Coplt.Graphics.Core; -public record struct UploadLoc(nuint Index, ulong Offset, uint Size, SubmitId SubmitId); -public record struct UploadLoc2(ulong RecordId, ulong RecordVersion, nuint Index, ulong Offset, uint Size); +public record struct UploadLoc(ulong RecordId, ulong RecordVersion, nuint Index, ulong Offset, uint Size); diff --git a/Coplt.Graphics.Core/Native/FUploadLoc.cs b/Coplt.Graphics.Core/Native/FUploadLoc.cs index 321deaf..04c29f9 100644 --- a/Coplt.Graphics.Core/Native/FUploadLoc.cs +++ b/Coplt.Graphics.Core/Native/FUploadLoc.cs @@ -8,12 +8,6 @@ public FUploadLoc(in UploadLoc loc) { Index = (uint)loc.Index; } - - public FUploadLoc(in UploadLoc2 loc) - { - Index = (uint)loc.Index; - } public static implicit operator FUploadLoc(in UploadLoc loc) => new(loc); - public static implicit operator FUploadLoc(in UploadLoc2 loc) => new(loc); } diff --git a/Coplt.Graphics.Core/Native/Native.cs b/Coplt.Graphics.Core/Native/Native.cs index 92202c3..c0f2f20 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -1756,6 +1756,8 @@ public unsafe partial struct FGpuRecordData public FList PayloadBufferCopyRange; + public FList PayloadBufferImageCopyRange; + public FList PayloadMeshBuffers; public FList PayloadVertexBufferRange; @@ -1785,6 +1787,7 @@ public enum FCmdType : uint ClearColor, ClearDepthStencil, BufferCopy, + BufferImageCopy, Render, Compute, SetPipeline, @@ -1805,7 +1808,7 @@ public enum FCmdResType : byte public unsafe partial struct FCmdRes { - [NativeTypeName("__AnonymousRecord_Cmd_L70_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L71_C9")] public _Anonymous_e__Union Anonymous; [NativeTypeName("Coplt::FCmdResType")] @@ -2144,8 +2147,8 @@ public partial struct FCmdBufferCopy public FBufferRefType2 SrcType; } - [NativeTypeName("struct FCndBufferImageCopy : Coplt::FCmdBase")] - public partial struct FCndBufferImageCopy + [NativeTypeName("struct FCmdBufferImageCopy : Coplt::FCmdBase")] + public partial struct FCmdBufferImageCopy { public FCmdBase Base; @@ -2332,7 +2335,7 @@ public partial struct FCmdDispatch public partial struct FCmdItem { - [NativeTypeName("__AnonymousRecord_Cmd_L359_C9")] + [NativeTypeName("__AnonymousRecord_Cmd_L360_C9")] public _Anonymous_e__Union Anonymous; [UnscopedRef] @@ -2415,6 +2418,16 @@ public ref FCmdBufferCopy BufferCopy } } + [UnscopedRef] + public ref FCmdBufferImageCopy BufferImageCopy + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.BufferImageCopy; + } + } + [UnscopedRef] public ref FCmdRender Render { @@ -2540,6 +2553,10 @@ public partial struct _Anonymous_e__Union [NativeTypeName("Coplt::FCmdBufferCopy")] public FCmdBufferCopy BufferCopy; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdBufferImageCopy")] + public FCmdBufferImageCopy BufferImageCopy; + [FieldOffset(0)] [NativeTypeName("Coplt::FCmdRender")] public FCmdRender Render; diff --git a/Coplt.Graphics.Native/Api/FFI/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h index a53edaf..267dea8 100644 --- a/Coplt.Graphics.Native/Api/FFI/Cmd.h +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -23,6 +23,7 @@ namespace Coplt ClearDepthStencil, BufferCopy, + BufferImageCopy, Render, Compute, @@ -236,7 +237,7 @@ namespace Coplt FBufferRefType2 SrcType{}; }; - struct FCndBufferImageCopy : FCmdBase + struct FCmdBufferImageCopy : FCmdBase { // 类型为 FBufferImageCopyRange u32 RangeIndex{}; @@ -370,6 +371,7 @@ namespace Coplt FCmdClearDepthStencil ClearDepthStencil; FCmdBufferCopy BufferCopy; + FCmdBufferImageCopy BufferImageCopy; FCmdRender Render; FCmdCompute Compute; diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h index 9b58413..1d7f9ba 100644 --- a/Coplt.Graphics.Native/Api/FFI/Record.h +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -38,6 +38,7 @@ namespace Coplt FList PayloadRenderInfo; FList PayloadResolveInfo; FList PayloadBufferCopyRange; + FList PayloadBufferImageCopyRange; FList PayloadMeshBuffers; FList PayloadVertexBufferRange; FList Blob; @@ -47,9 +48,9 @@ namespace Coplt #ifdef FFI_SRC explicit FGpuRecordData(FAllocator* allocator) - : Commands(allocator), Resources(allocator), Bindings(allocator), BindingChange(allocator), - PayloadRect(allocator), PayloadViewport(allocator), PayloadRenderInfo(allocator), PayloadResolveInfo(allocator), - PayloadBufferCopyRange(allocator), PayloadMeshBuffers(allocator), PayloadVertexBufferRange(allocator), Blob(allocator) + : Commands(allocator), Resources(allocator), Bindings(allocator), BindingChange(allocator), PayloadRect(allocator), + PayloadViewport(allocator), PayloadRenderInfo(allocator), PayloadResolveInfo(allocator), PayloadBufferCopyRange(allocator), + PayloadBufferImageCopyRange(allocator), PayloadMeshBuffers(allocator), PayloadVertexBufferRange(allocator), Blob(allocator) { } @@ -64,6 +65,7 @@ namespace Coplt PayloadRenderInfo.Clear(); PayloadResolveInfo.Clear(); PayloadBufferCopyRange.Clear(); + PayloadBufferImageCopyRange.Clear(); PayloadMeshBuffers.Clear(); PayloadVertexBufferRange.Clear(); Blob.Clear(); diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.cc b/Coplt.Graphics.Native/D3d12/Src/Layout.cc index 11cd9da..febe186 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.cc @@ -173,13 +173,14 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi for (u32 i = 0; i < items.size(); ++i) { const auto& item = items[i]; - GroupItemInfo bind_item_info{}; - bind_item_info.Group = g; - bind_item_info.IndexInGroup = i; - bind_item_info.Format = item.Format; - bind_item_info.Stages = item.Stages; - bind_item_info.View = item.View; - bind_item_info.UavAccess = item.UavAccess; + GroupItemInfo group_item_info{}; + group_item_info.Group = g; + group_item_info.IndexInGroup = i; + group_item_info.Format = item.Format; + group_item_info.Stages = item.Stages; + group_item_info.View = item.View; + group_item_info.Type = item.Type; + group_item_info.UavAccess = item.UavAccess; for (const auto stage : IterStage(item.Stages)) { BindSlot slot(item, stage); @@ -216,25 +217,25 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi switch (def.UavAccess) { case FResourceAccess::ReadOnly: - if (bind_item_info.UavAccess == FResourceAccess::Unknown) - bind_item_info.UavAccess = FResourceAccess::ReadOnly; - else if (bind_item_info.UavAccess != FResourceAccess::ReadOnly) - bind_item_info.UavAccess = FResourceAccess::ReadWrite; + if (group_item_info.UavAccess == FResourceAccess::Unknown) + group_item_info.UavAccess = FResourceAccess::ReadOnly; + else if (group_item_info.UavAccess != FResourceAccess::ReadOnly) + group_item_info.UavAccess = FResourceAccess::ReadWrite; break; case FResourceAccess::WriteOnly: - if (bind_item_info.UavAccess == FResourceAccess::Unknown) - bind_item_info.UavAccess = FResourceAccess::WriteOnly; - else if (bind_item_info.UavAccess != FResourceAccess::WriteOnly) - bind_item_info.UavAccess = FResourceAccess::ReadWrite; + if (group_item_info.UavAccess == FResourceAccess::Unknown) + group_item_info.UavAccess = FResourceAccess::WriteOnly; + else if (group_item_info.UavAccess != FResourceAccess::WriteOnly) + group_item_info.UavAccess = FResourceAccess::ReadWrite; break; case FResourceAccess::ReadWrite: case FResourceAccess::Unknown: default: - bind_item_info.UavAccess = FResourceAccess::ReadWrite; + group_item_info.UavAccess = FResourceAccess::ReadWrite; break; } } - group_item_infos.push_back(bind_item_info); + group_item_infos.push_back(group_item_info); } m_group_item_infos.push_back(std::move(group_item_infos)); } @@ -269,6 +270,7 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi item_info.IndexInGroup = info.Index; item_info.RootIndex = info.SigIndex; item_info.Place = BindItemPlace::Const; + item_info.Type = BindItemType::Resource; m_bind_item_infos.push_back(item_info); continue; } @@ -355,6 +357,7 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi item_info.IndexInGroup = info.Index; item_info.RootIndex = info.SigIndex; item_info.Place = BindItemPlace::Direct; + item_info.Type = BindItemType::Resource; m_bind_item_infos.push_back(item_info); continue; } @@ -398,6 +401,7 @@ D3d12BindingLayout::D3d12BindingLayout(Rc&& device, const FBindi item_info.IndexInGroup = 0; item_info.RootIndex = Info.RootIndex; item_info.Place = BindItemPlace::Table; + item_info.Type = Info.Type == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER ? BindItemType::Sampler : BindItemType::Resource; m_bind_item_infos.push_back(item_info); } m_tables.push_back(std::move(infos)); diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.h b/Coplt.Graphics.Native/D3d12/Src/Layout.h index 3c8039a..abf58e1 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.h +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.h @@ -138,6 +138,12 @@ namespace Coplt Const, }; + enum class BindItemType : u8 + { + Resource, + Sampler, + }; + struct BindItemInfo { u32 Group{}; @@ -145,6 +151,7 @@ namespace Coplt u32 IndexInGroup{}; u32 RootIndex{}; BindItemPlace Place{}; + BindItemType Type{}; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.cc b/Coplt.Graphics.Native/D3d12/Src/Record.cc index e756ab8..3e194b0 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -495,6 +495,9 @@ void D3d12GpuRecord::Analyze() case FCmdType::BufferCopy: Analyze_BufferCopy(i, command.BufferCopy); break; + case FCmdType::BufferImageCopy: + Analyze_BufferImageCopy(i, command.BufferImageCopy); + break; case FCmdType::Render: Analyze_Render(i, command.Render); break; @@ -573,6 +576,29 @@ void D3d12GpuRecord::Analyze_BufferCopy(u32 i, const FCmdBufferCopy& cmd) const } } +void D3d12GpuRecord::Analyze_BufferImageCopy(u32 i, const FCmdBufferImageCopy& cmd) const +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use BufferImageCopy in sub scope", i); + if (cmd.ImageToBuffer) + { + m_barrier_analyzer->OnUse(cmd.Image.ResIndex(), ResAccess::CopySourceRead, ResUsage::Common, ResLayout::CopySource); + if (cmd.BufferType == FBufferRefType2::Buffer) + { + m_barrier_analyzer->OnUse(cmd.Buffer.Buffer.ResIndex(), ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::Common); + } + } + else + { + m_barrier_analyzer->OnUse(cmd.Image.ResIndex(), ResAccess::CopyDestWrite, ResUsage::Common, ResLayout::CopyDest); + if (cmd.BufferType == FBufferRefType2::Buffer) + { + m_barrier_analyzer->OnUse(cmd.Buffer.Buffer.ResIndex(), ResAccess::CopySourceRead, ResUsage::Common, ResLayout::Common); + } + } + m_barrier_analyzer->OnCmd(); +} + void D3d12GpuRecord::Analyze_Render(u32 i, const FCmdRender& cmd) { if (m_state != RecordState::Main) @@ -639,7 +665,7 @@ void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) if (!SetBinding(Bindings[cmd.Binding].Binding, i, cmd)) return; const NonNull binding = m_pipeline_context.Binding; ReadGuard binding_guard(binding->SelfLock()); - Finally clear_lock([&] { m_tmp_locks.clear(); }); // todo 锁移到整个 render pass 范围,不允许在 render pass 中修改绑定内容 + Finally clear_lock([&] { m_tmp_locks.clear(); }); const auto groups = binding->Groups(); for (u32 g = 0; g < groups.size(); ++g) { @@ -662,7 +688,7 @@ void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) if (!view || view.IsSampler()) continue; const auto& res_index = AddResource(view); const auto& info = group_item_infos[g][v]; - m_barrier_analyzer->OnUse(res_index, view, info); // todo 屏障移动到每次 draw + m_barrier_analyzer->OnUse(res_index, view, info); } if (group->EnsureAvailable()) any_changed = true; } @@ -684,27 +710,30 @@ void D3d12GpuRecord::Analyze_SetBinding(u32 i, const FCmdSetBinding& cmd) } const auto object_id = group->ObjectId(); const auto& data = group->Layout()->Data(); + DescriptorAllocation resource_allocation{}; + DescriptorAllocation sampler_allocation{}; // todo 确定是最后一次修改 - const auto f = [&](const u32 size, const Rc& heap, const ComPtr& dh, const bool last) + const auto f = [&]( + const bool last, const u32 size, const Rc& heap, + const ComPtr& dh, DescriptorAllocation& allocation + ) { if (size == 0) return; - DescriptorAllocation allocation; if (data.Usage == FBindGroupUsage::Dynamic && !last) { allocation = heap->AllocateTmp(size); - m_allocations.push_back(allocation); } else { bool exists = false; allocation = heap->Allocate(object_id, size, exists); - m_allocations.push_back(allocation); if (exists) return; } m_device->m_device->CopyDescriptorsSimple(size, allocation.GetCpuHandle(), dh->GetCPUDescriptorHandleForHeapStart(), heap->m_type); }; - f(data.ResourceTableSize, m_context->m_descriptor_manager.m_res, group->ResourceHeap(), true); - f(data.SamplerTableSize, m_context->m_descriptor_manager.m_smp, group->SamplerHeap(), true); + f(true, data.ResourceTableSize, m_context->m_descriptor_manager.m_res, group->ResourceHeap(), resource_allocation); + f(true, data.SamplerTableSize, m_context->m_descriptor_manager.m_smp, group->SamplerHeap(), sampler_allocation); + m_allocations.push_back({resource_allocation, sampler_allocation}); } for (const auto& bind_item_info : bind_item_infos) { @@ -800,6 +829,9 @@ void D3d12GpuRecord::Interpret(const D3d12RentedCommandList& list, const u32 off case FCmdType::BufferCopy: Interpret_BufferCopy(list, i, command.BufferCopy); break; + case FCmdType::BufferImageCopy: + Interpret_BufferImageCopy(list, i, command.BufferImageCopy); + break; case FCmdType::Render: Interpret_Render(list, i, command.Render); break; @@ -929,6 +961,125 @@ void D3d12GpuRecord::Interpret_BufferCopy(const CmdList& list, u32 i, const FCmd } } +void D3d12GpuRecord::Interpret_BufferImageCopy(const CmdList& list, u32 i, const FCmdBufferImageCopy& cmd) +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use BufferImageCopy in sub scope", i); + const auto& range = PayloadBufferImageCopyRange[cmd.RangeIndex]; + const auto& image_info = GetRes(cmd.Image); + const auto image_data = image_info.GetImageData(); + const auto IsDsOrYCbCr = IsDepthStencil(image_data->m_format) || IsYCbCr(image_data->m_format); + auto bytes_per_row = range.BytesPerRow; + auto rows_per_image = range.RowsPerImage; + if (bytes_per_row == 0) + { + const auto [block_width, _] = GetBlockDimensions(image_data->m_format); + const auto block_size = GetBlockCopySize(image_data->m_format, IsDsOrYCbCr ? Some(range.Plane) : nullptr); + bytes_per_row = (range.ImageExtent[0] / block_width) * block_size; + bytes_per_row = Aligned256(bytes_per_row); + } + else + { + if (!IsAligned256(bytes_per_row)) + COPLT_THROW_FMT("BytesPerRow must must be a multiple of 256 at command {}", i); + } + if (rows_per_image == 0) + { + if (image_data->m_dimension == FImageDimension::Three) + { + rows_per_image = range.ImageExtent[1] * range.ImageExtent[2]; + } + else + { + rows_per_image = range.ImageExtent[1]; + } + } + if (image_data->m_dimension == FImageDimension::Three) + { + if (range.ImageIndex != 0 || range.ImageCount != 1) + COPLT_THROW_FMT("Image index or count out of range at command {}", i); + } + else + { + if (range.ImageCount < 1 || range.ImageIndex + range.ImageCount > image_data->m_depth_or_length) + COPLT_THROW_FMT("Image index or count out of range at command {}", i); + } + if (IsDepthStencil(image_data->m_format) || IsYCbCr(image_data->m_format)) + { + if (static_cast(range.Plane) >= 2) + COPLT_THROW_FMT("Plane index or count out of range at command {}", i); + } + else + { + if (range.Plane != FImagePlane::All) + COPLT_THROW_FMT("Plane index or count out of range at command {}", i); + } + const auto image = image_info.GetResource(); + auto buffer = NonNull::Unchecked(nullptr); + if (cmd.BufferType == FBufferRefType2::Buffer) + { + buffer = GetRes(cmd.Buffer.Buffer).GetResource(); + } + else if (cmd.BufferType == FBufferRefType2::Upload) + { + const auto& obj = m_context->m_upload_buffers[cmd.Buffer.Upload.Index]; + buffer = obj.m_resource.m_resource.Get(); + } + else + { + COPLT_THROW_FMT("Unknown Buffer Type {} at command {}", static_cast(cmd.BufferType), i); + } + D3D12_TEXTURE_COPY_LOCATION buffer_loc{}; + buffer_loc.pResource = buffer; + buffer_loc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + buffer_loc.PlacedFootprint.Footprint.Format = GetBufferImageCopyFormat(image_data->m_format, range.Plane, IsDsOrYCbCr); + buffer_loc.PlacedFootprint.Footprint.Width = range.ImageExtent[0]; + buffer_loc.PlacedFootprint.Footprint.Height = range.ImageExtent[1]; + buffer_loc.PlacedFootprint.Footprint.Depth = range.ImageExtent[2]; + buffer_loc.PlacedFootprint.Footprint.RowPitch = bytes_per_row; + D3D12_TEXTURE_COPY_LOCATION image_loc{}; + image_loc.pResource = image; + image_loc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + const auto image_stride = bytes_per_row * rows_per_image; + for (auto ai = 0u; ai < range.ImageCount; ++ai) + { + buffer_loc.PlacedFootprint.Offset = range.BufferOffset + ai * image_stride; + image_loc.SubresourceIndex = D3D12CalcSubresource( + range.MipLevel, range.ImageIndex + ai, static_cast(range.Plane), + image_data->m_mip_levels, image_data->m_depth_or_length + ); + if (cmd.ImageToBuffer) + { + D3D12_BOX box{}; + box.left = range.ImageOffset[0]; + box.top = range.ImageOffset[1]; + box.front = range.ImageOffset[2]; + box.right = range.ImageOffset[0] + range.ImageExtent[0]; + box.bottom = range.ImageOffset[1] + range.ImageExtent[1]; + box.back = range.ImageOffset[2] + range.ImageExtent[2]; + list->g0->CopyTextureRegion( + &buffer_loc, + 0, + 0, + 0, + &image_loc, + &box + ); + } + else + { + list->g0->CopyTextureRegion( + &image_loc, + range.ImageOffset[0], + range.ImageOffset[1], + range.ImageOffset[2], + &buffer_loc, + nullptr + ); + } + } +} + void D3d12GpuRecord::Interpret_Render(const CmdList& list, const u32 i, const FCmdRender& cmd) { if (m_state != RecordState::Main) @@ -1076,13 +1227,14 @@ void D3d12GpuRecord::Interpret_SetBinding(const CmdList& list, u32 i, const FCmd case Layout::BindItemPlace::Table: { const auto& allocation = m_allocations[set_binding_info.AllocationIndex + bind_item_info.Group]; + const auto& al = bind_item_info.Type == Layout::BindItemType::Resource ? allocation.Resource : allocation.Sampler; if (m_state == RecordState::Render) { - list->g0->SetGraphicsRootDescriptorTable(bind_item_info.RootIndex, allocation.GetGpuHandle()); + list->g0->SetGraphicsRootDescriptorTable(bind_item_info.RootIndex, al.GetGpuHandle()); } else { - list->g0->SetComputeRootDescriptorTable(bind_item_info.RootIndex, allocation.GetGpuHandle()); + list->g0->SetComputeRootDescriptorTable(bind_item_info.RootIndex, al.GetGpuHandle()); } break; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h index b0dcec4..ca8ae87 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Record.h +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -137,6 +137,12 @@ namespace Coplt }; }; + struct AllocationPoint + { + DescriptorAllocation Resource{}; + DescriptorAllocation Sampler{}; + }; + u64 m_isolate_id{}; u64 m_record_id{}; SRc m_isolate_config{}; @@ -147,7 +153,7 @@ namespace Coplt std::vector m_resource_infos{}; std::vector m_binding_infos{}; std::vector m_set_binding_infos{}; - std::vector m_allocations{}; + std::vector m_allocations{}; std::vector m_bind_items{}; std::vector m_queue_wait_points{}; std::vector m_tmp_locks{}; @@ -195,6 +201,7 @@ namespace Coplt void Analyze_ClearColor(u32 i, const FCmdClearColor& cmd) const; void Analyze_ClearDepthStencil(u32 i, const FCmdClearDepthStencil& cmd) const; void Analyze_BufferCopy(u32 i, const FCmdBufferCopy& cmd) const; + void Analyze_BufferImageCopy(u32 i, const FCmdBufferImageCopy& cmd) const; void Analyze_Render(u32 i, const FCmdRender& cmd); void Analyze_RenderEnd(u32 i, const FCmdRender& cmd); void Analyze_Compute(u32 i, const FCmdCompute& cmd); @@ -213,6 +220,7 @@ namespace Coplt void Interpret_ClearColor(const CmdList& list, u32 i, const FCmdClearColor& cmd); void Interpret_ClearDepthStencil(const CmdList& list, u32 i, const FCmdClearDepthStencil& cmd); void Interpret_BufferCopy(const CmdList& list, u32 i, const FCmdBufferCopy& cmd); + void Interpret_BufferImageCopy(const CmdList& list, u32 i, const FCmdBufferImageCopy& cmd); void Interpret_Render(const CmdList& list, u32 i, const FCmdRender& cmd); void Interpret_RenderEnd(const CmdList& list, u32 i, const FCmdRender& cmd); void Interpret_Compute(const CmdList& list, u32 i, const FCmdCompute& cmd); diff --git a/Coplt.Graphics.Native/D3d12/Src/Resource.cc b/Coplt.Graphics.Native/D3d12/Src/Resource.cc index 53fe97d..8ee3f15 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Resource.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Resource.cc @@ -29,6 +29,7 @@ ResourcePack::ResourcePack( break; } + layout = ResLayout::Undefined; D3D12_BARRIER_LAYOUT init_layout = D3D12_BARRIER_LAYOUT_UNDEFINED; D3D12_RESOURCE_STATES init_state{}; switch (cpu_access) diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index 88350d5..6b704b1 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -52,7 +52,7 @@ public void DoInitGraphics() { Width = Width, Height = Height, - VSync = true, + // VSync = true, // Srgb = false, } ); diff --git a/Examples/Image/Example.cs b/Examples/Image/Example.cs index 04dfbc2..941dd47 100644 --- a/Examples/Image/Example.cs +++ b/Examples/Image/Example.cs @@ -8,79 +8,104 @@ namespace Examples; public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handle, Width, Height) { - private ShaderLayout Layout = null!; + private ShaderLayout ShaderLayout = null!; + private ShaderBindGroupLayout BindGroupLayout = null!; + private ShaderBindingLayout BindingLayout = null!; private Shader Shader = null!; private Sampler Sampler = null!; private GraphicsShaderPipeline Pipeline = null!; - private ShaderBinding ShaderBinding = null!; + private ShaderBindGroup BindGroup = null!; + private ShaderBinding Binding = null!; public override string Name => "Image"; - // protected override async Task LoadResources(CommandList cmd) - // { - // var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); - // Layout = Device.CreateShaderLayout( - // [ - // new() - // { - // Slot = 0, - // Stage = ShaderStage.Pixel, - // View = ShaderLayoutItemView.Srv, - // Type = ShaderLayoutItemType.Texture2D, - // Usage = ShaderLayoutItemUsage.Persist, - // }, - // new() - // { - // Slot = 0, - // Stage = ShaderStage.Pixel, - // View = ShaderLayoutItemView.Sampler, - // Type = ShaderLayoutItemType.Sampler, - // Usage = ShaderLayoutItemUsage.Persist, - // } - // ], - // Name: Name - // ); - // Shader = Device.CreateShader(modules, Layout); - // ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); - // Pipeline = Device.CreateGraphicsShaderPipeline( - // Shader, new() - // { - // DsvFormat = GraphicsFormat.Unknown, - // BlendState = - // { - // Rt0 = - // { - // Src = BlendType.SrcAlpha, - // Dst = BlendType.InvSrcAlpha, - // Op = BlendOp.Add, - // } - // }, - // Topology = PrimitiveTopologyType.TriangleStrip, - // }, Name: Name - // ); - // Sampler = Device.CreateSampler(SamplerInfo.LinearRepeat); - // using var image_data = await LoadImage("./Image.png"); - // var upload_memory = Device.MainQueue.AllocImageUploadMemory2D(4, (uint)image_data.Width, (uint)image_data.Height); - // for (var row = 0u; row < upload_memory.RowCount; row++) - // { - // var row_span = image_data.Frames[0].PixelBuffer.DangerousGetRowSpan((int)row); - // MemoryMarshal.AsBytes(row_span).CopyTo(upload_memory[row]); - // } - // var test_image = Device.CreateImage( - // new() - // { - // Purpose = ResourcePurpose.ShaderResource, - // Format = GraphicsFormat.R8G8B8A8_UNorm, - // Width = (uint)image_data.Width, - // Height = (uint)image_data.Height, - // }, - // Name: "Test Image" - // ); - // cmd.Upload(test_image, upload_memory); - // cmd.Bind(ShaderBinding, [new(0, test_image), new(1, Sampler)]); - // } - // protected override void Render(CommandList cmd, Time time) - // { - // using var render = cmd.Render([new(Output, LoadOp.Discard)]); - // render.Draw(Pipeline, 4, Binding: ShaderBinding); - // } + protected override async Task LoadResources(GpuRecord cmd) + { + var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); + ShaderLayout = Device.CreateShaderLayout( + [ + new() + { + Id = 0, + Slot = 0, + Stage = ShaderStage.Pixel, + View = ShaderLayoutItemView.Srv, + Type = ShaderLayoutItemType.Texture2D, + }, + new() + { + Id = 1, + Slot = 0, + Stage = ShaderStage.Pixel, + View = ShaderLayoutItemView.Sampler, + Type = ShaderLayoutItemType.Sampler, + } + ], + Name: Name + ); + BindingLayout = Device.CreateBindingLayout( + ShaderLayout, [ + BindGroupLayout = Device.CreateBindGroupLayout( + [ + new() + { + Id = 0, + Stages = ShaderStageFlags.Pixel, + View = ShaderLayoutItemView.Srv, + Type = ShaderLayoutItemType.Texture2D, + }, + new() + { + Id = 1, + Stages = ShaderStageFlags.Pixel, + View = ShaderLayoutItemView.Sampler, + Type = ShaderLayoutItemType.Sampler, + } + ] + ) + ], Name: Name + ); + Shader = Device.CreateShader(modules, ShaderLayout); + Pipeline = Device.CreateGraphicsShaderPipeline( + Shader, new() + { + DsvFormat = GraphicsFormat.Unknown, + BlendState = + { + Rt0 = + { + Src = BlendType.SrcAlpha, + Dst = BlendType.InvSrcAlpha, + Op = BlendOp.Add, + } + }, + Topology = PrimitiveTopologyType.TriangleStrip, + }, BindingLayout, Name: Name + ); + Sampler = Device.CreateSampler(SamplerInfo.LinearRepeat); + using var image_data = await LoadImage("./Image.png"); + var upload_memory = cmd.AllocImageUploadMemory2D(4, (uint)image_data.Width, (uint)image_data.Height); + for (var row = 0u; row < upload_memory.RowCount; row++) + { + var row_span = image_data.Frames[0].PixelBuffer.DangerousGetRowSpan((int)row); + MemoryMarshal.AsBytes(row_span).CopyTo(upload_memory[row]); + } + var test_image = Isolate.CreateImage( + new() + { + Purpose = ResourcePurpose.ShaderResource, + Format = GraphicsFormat.R8G8B8A8_UNorm, + Width = (uint)image_data.Width, + Height = (uint)image_data.Height, + }, + Name: "Test Image" + ); + cmd.Upload(test_image, upload_memory); + BindGroup = Isolate.CreateBindGroup(BindGroupLayout, [new(0, test_image), new(1, Sampler)]); + Binding = Isolate.CreateBinding(BindingLayout, [new(0, BindGroup)]); + } + protected override void Render(GpuRecord cmd, Time time) + { + using var render = cmd.Render([new(Output, LoadOp.Discard)]); + render.Draw(Pipeline, 4, Binding: Binding); + } } From d7e4b341ce236121a490a23ba81f600db6187ab5 Mon Sep 17 00:00:00 2001 From: U2A5F Date: Thu, 10 Apr 2025 22:36:41 +0800 Subject: [PATCH 46/46] save --- Examples/Colorful/Colorful.md | 57 ++++++++++++++++++++++++----------- Examples/Image/Image.md | 45 ++++++++++++++++++++------- 2 files changed, 73 insertions(+), 29 deletions(-) diff --git a/Examples/Colorful/Colorful.md b/Examples/Colorful/Colorful.md index 5337328..1f5e95c 100644 --- a/Examples/Colorful/Colorful.md +++ b/Examples/Colorful/Colorful.md @@ -25,31 +25,50 @@ var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage // Defines the shader layout. // This rhi does not provide shader compilation and reflection related features, and needs to be provided by the user. -Layout = Device.CreateShaderLayout( +ShaderLayout = Device.CreateShaderLayout( [ new() { + Id = 0, // The ID of the binding point. different stages and scopes can be repeated. + Scope = 0, // The Id Scope Slot = 0, // Dx: hlsl register; Vk: binding or push const offset when View is Constants + Space = 0, // Dx: hlsl space; Vk: binding set + Count = 1, // The size of the array, must >= 1, or == 1 when View is StaticSampler, or num of 32 bit value when view is Constants + Format = GraphicsFormat.Unknown, // The format Stage = ShaderStage.Pixel, // Can only be bound to a single shader stage View = ShaderLayoutItemView.Cbv, // View type, Cbv Srv Uav Sampler Constants Type = ShaderLayoutItemType.ConstantBuffer, // Resource type, use hlsl style, ConstantBuffer StructureBuffer Texture2D etc - Usage = ShaderLayoutItemUsage.Persist, // Resource binding change frequency - // Dynamic: may change every frame - // Persist:rarely changes, such as material parameters - // Instant:only buffer and sampler, when buffer mean may change every draw, when sampler it is static sampler - // View type is Constants will ignore Usage - UavAccess: ResourceAccess.Unknown, // Unknown ReadOnly WriteOnly ReadWrite - // Not necessary, can optimize automatic barriers + UavAccess = ResourceAccess.Unknown, // Used to distinguish read and write behaviors during uav access } - ], - Name: Name + ] +); +// Define the bind group layout and binding layout +BindingLayout = Device.CreateBindingLayout( + ShaderLayout, [ + // A binding layout has multiple binding group layouts, and a binding group can be shared among multiple bindings. + // A typical usage is to extract shared binding groups for bindings shared by all materials, + // and separate binding groups for bindings unique to each material, and split static and dynamic bindings into different binding groups. + BindGroupLayout = Device.CreateBindGroupLayout( + [ + new() + { + Id = 0, // Same to Id in ShaderLayout + Scope = 0, // Same to Scope in ShaderLayout + Count = 1, // Must be >= Count in ShaderLayout + StaticSamplerIndex = 0, // Index if View is StaticSampler + Format = GraphicsFormat.Unknown, // Must same to Format in ShaderLayout + Stages = ShaderStageFlags.Pixel, // Allow multiple stages + View = ShaderLayoutItemView.Cbv, // Must same to View in ShaderLayout + Type = ShaderLayoutItemType.ConstantBuffer, // Must same to Type in ShaderLayout + UavAccess = ResourceAccess.Unknown, // If in shader layout is ResourceAccess.Unknown, then use this + } + ] + ) + ], Name: Name ); -Shader = Device.CreateShader(modules, Layout); -Pipeline = Device.CreateGraphicsShaderPipeline(... Omitted here); - -// Shader Binding instance, maybe it's similar to webgpu's bindgroup, but allows dynamic changes -ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); +Shader = Device.CreateShader(modules, ShaderLayout); +Pipeline = Device.CreateGraphicsShaderPipeline(Shader, new() { .. Omitted here }, BindingLayout, Name: Name); // Create argument buffer ArgBuffer = Device.CreateBuffer( @@ -60,8 +79,10 @@ ArgBuffer = Device.CreateBuffer( }, Name: "Args" ); -// Bind it -cmd.Bind(ShaderBinding, [new(0, ArgBuffer)]); + +// Create Binding +BindGroup = Isolate.CreateBindGroup(BindGroupLayout, [new(0, ArgBuffer)]); +Binding = Isolate.CreateBinding(BindingLayout, [new(0, BindGroup)]); ``` ## 3 Render @@ -69,5 +90,5 @@ cmd.Bind(ShaderBinding, [new(0, ArgBuffer)]); // Write time data cmd.Upload(ArgBuffer, [(float)time.Total.TotalSeconds]); using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f, 1f))]); -render.Draw(Pipeline, 4, Binding: ShaderBinding); +render.Draw(Pipeline, 4, Binding: Binding); ``` diff --git a/Examples/Image/Image.md b/Examples/Image/Image.md index 30597f0..2fd12d0 100644 --- a/Examples/Image/Image.md +++ b/Examples/Image/Image.md @@ -8,30 +8,52 @@ Demonstrates the use of image load, upload and sampler ```cs var modules = await LoadShaderModules("Shader", [ShaderStage.Vertex, ShaderStage.Pixel]); -Layout = Device.CreateShaderLayout( +ShaderLayout = Device.CreateShaderLayout( [ new() { + Id = 0, Slot = 0, Stage = ShaderStage.Pixel, View = ShaderLayoutItemView.Srv, Type = ShaderLayoutItemType.Texture2D, - Usage = ShaderLayoutItemUsage.Persist, }, new() { + Id = 1, Slot = 0, Stage = ShaderStage.Pixel, View = ShaderLayoutItemView.Sampler, Type = ShaderLayoutItemType.Sampler, - Usage = ShaderLayoutItemUsage.Persist, } - ] + ], + Name: Name +); +BindingLayout = Device.CreateBindingLayout( + ShaderLayout, [ + BindGroupLayout = Device.CreateBindGroupLayout( + [ + new() + { + Id = 0, + Stages = ShaderStageFlags.Pixel, + View = ShaderLayoutItemView.Srv, + Type = ShaderLayoutItemType.Texture2D, + }, + new() + { + Id = 1, + Stages = ShaderStageFlags.Pixel, + View = ShaderLayoutItemView.Sampler, + Type = ShaderLayoutItemType.Sampler, + } + ] + ) + ], Name: Name ); -Shader = Device.CreateShader(modules, Layout); -Pipeline = Device.CreateGraphicsShaderPipeline(... Omitted here); -ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); +Shader = Device.CreateShader(modules, ShaderLayout); +Pipeline = Device.CreateGraphicsShaderPipeline(.. Omitted here); Sampler = Device.CreateSampler(SamplerInfo.LinearRepeat); // or @@ -48,14 +70,14 @@ using var image_data = await LoadImage("./Image.png"); // Allocate memory for image upload. Due to the 256 row alignment requirement, // the memory cannot be simply calculated and cannot be used as a whole block of memory. // This rhi does not provide a high-level abstraction for uploading images, as any image loading library can be used -var upload_memory = Device.MainQueue.AllocImageUploadMemory2D(4, (uint)image_data.Width, (uint)image_data.Height); +var upload_memory = cmd.AllocImageUploadMemory2D(4, (uint)image_data.Width, (uint)image_data.Height); for (var row = 0u; row < upload_memory.RowCount; row++) { var row_span = image_data.Frames[0].PixelBuffer.DangerousGetRowSpan((int)row); MemoryMarshal.AsBytes(row_span).CopyTo(upload_memory[row]); } -var test_image = Device.CreateImage( +var test_image = Isolate.CreateImage( new() { Purpose = ResourcePurpose.ShaderResource, @@ -67,11 +89,12 @@ var test_image = Device.CreateImage( ); cmd.Upload(test_image, upload_memory); -cmd.Bind(ShaderBinding, [new(0, test_image), new(1, Sampler)]); +BindGroup = Isolate.CreateBindGroup(BindGroupLayout, [new(0, test_image), new(1, Sampler)]); +Binding = Isolate.CreateBinding(BindingLayout, [new(0, BindGroup)]); ``` ## 3 Render ```cs using var render = cmd.Render([new(Output, LoadOp.Discard)]); -render.Draw(Pipeline, 4, Binding: ShaderBinding); +render.Draw(Pipeline, 4, Binding: Binding); ```