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/Color.cs b/Coplt.Graphics.Core/Core/Color.cs index fd2c52d..4de0748 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,107 @@ 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 + { + [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(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(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 +499,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 @@ -488,9 +597,75 @@ 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 : IEquatable, IComparable, IComparable +public struct ColorHsv + : IEquatable, IComparable, IComparable, + IAdditionOperators, + ISubtractionOperators, + IMultiplyOperators, + IDivisionOperators, + IModulusOperators { #region Fields @@ -581,6 +756,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 +891,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 +988,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/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/DeviceChild.cs b/Coplt.Graphics.Core/Core/DeviceChild.cs deleted file mode 100644 index 9ef473f..0000000 --- a/Coplt.Graphics.Core/Core/DeviceChild.cs +++ /dev/null @@ -1,21 +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 -} 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/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/GpuAdapter.cs b/Coplt.Graphics.Core/Core/GpuAdapter.cs index 12a6d97..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 @@ -70,11 +69,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) { @@ -82,9 +76,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, QueueName: QueueName, QueueName8: QueueName8); + FGpuDeviceCreateResult result; + m_ptr->CreateDevice(&f_options, &result).TryThrow(); + return new(result, Instance, this, Name); } } diff --git a/Coplt.Graphics.Core/Core/GpuBuffer.cs b/Coplt.Graphics.Core/Core/GpuBuffer.cs index 317aea9..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 @@ -64,6 +59,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); diff --git a/Coplt.Graphics.Core/Core/GpuDevice.cs b/Coplt.Graphics.Core/Core/GpuDevice.cs index e18ed1e..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; @@ -11,93 +9,49 @@ 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; + internal readonly GpuIsolate? m_main_isolate; + [Drop] + internal readonly GpuIsolate? m_copy_isolate; #endregion #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; - public CommandList MainCommandList => MainQueue.CommandList; + 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, string? QueueName = null, ReadOnlySpan QueueName8 = default - ) + internal GpuDevice(FGpuDeviceCreateResult result, GraphicsInstance instance, GpuAdapter? adapter, string? name) : base((FGpuObject*)result.Device, name) { m_instance = instance; m_name = name; - m_ptr = ptr; - m_adapter = adapter ?? m_instance.m_ptr_to_adapters[(nuint)m_ptr->GetAdapter()]; - m_main_queue = CreateMainQueue(Name: QueueName, Name8: QueueName8); - } - - #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) + 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) { - 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(); + m_copy_isolate = new GpuIsolate(result.CopyIsolate.Isolate, result.CopyIsolate.Data, null, this); } } #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(); + public void* GetRawDevice() => Ptr->GetRawDevice(); #endregion @@ -107,96 +61,135 @@ m_name is null #endregion - #region CreateMainQueue + #region CreateIsolate - public GpuQueue CreateMainQueue(string? Name = null, ReadOnlySpan Name8 = default) + public GpuIsolate CreateIsolate(string? Name = null, ReadOnlySpan Name8 = default) { fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) { - FMainQueueCreateOptions f_options = new() + FGpuIsolateCreateOptions f_options = new() { Name = new(Name, Name8, p_name, p_name8), }; - FGpuQueue* ptr; - m_ptr->CreateMainQueue(&f_options, &ptr).TryThrow(); - return new(ptr, Name, this); + FGpuIsolateCreateResult f_result; + Ptr->CreateIsolate(&f_options, &f_result).TryThrow(); + return new GpuIsolate(f_result.Isolate, f_result.Data, null, this); } } #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, }; - FShaderModule* ptr; - m_ptr->CreateShaderModule(&f_options, &ptr).TryThrow(); - return new(ptr, Name, EntryPoint); + 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 ShaderBindGroupLayout 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, - }; - FShaderLayout* ptr; - m_ptr->CreateShaderLayout(&f_options, &ptr).TryThrow(); - return new(ptr, Name); - } + 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 ShaderBindingLayout 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, }; - FShaderLayout* ptr; - self.m_ptr->GetEmptyShaderLayout(&f_options, &ptr).TryThrow(); - return new(ptr, $"Empty Shader Layout ({flags})"); - }, this - ); + FBindingLayout* ptr; + Ptr->CreateBindingLayout(&f_options, &ptr).TryThrow(); + return new(ptr, Name, this, ShaderLayout, GroupLayouts.ToArray()); + } + } + finally + { + ArrayPool.Shared.Return(groups); + } + } #endregion @@ -247,8 +240,8 @@ public ShaderInputLayout CreateShaderInputLayout( Count = (uint)Elements.Length, }; FShaderInputLayout* ptr; - m_ptr->CreateShaderInputLayout(&f_options, &ptr).TryThrow(); - return new(ptr, meta, Name); + Ptr->CreateShaderInputLayout(&f_options, &ptr).TryThrow(); + return new(ptr, meta, Name, this); } } @@ -258,78 +251,98 @@ public ShaderInputLayout CreateShaderInputLayout( #endregion - #region CreateShader + #region CreateMeshLayout - public Shader CreateShader( - ReadOnlySpan Modules, ShaderLayout? Layout, ShaderInputLayout? InputLayout = null, + public MeshLayout CreateMeshLayout( + ReadOnlySpan Buffers, + ReadOnlySpan Elements, string? Name = null, ReadOnlySpan Name8 = default ) { - if (Modules.Length == 0) throw new ArgumentException("No modules provided"); - if (Modules.Length > FShader.MaxShaderModuleCount) - throw new ArgumentException( - $"Too many shader modules, there can be a maximum of {FShader.MaxShaderModuleCount}" - ); - Shader.ShaderModuleArray arr = new(); - var p_modules = stackalloc FShaderModule*[Modules.Length]; - for (var i = 0; i < Modules.Length; i++) - { - var module = Modules[i]; - arr[i] = module; - p_modules[i] = module.m_ptr; - } + fixed (MeshBufferDefine* p_buffers = Buffers) + fixed (MeshBufferElement* p_elements = Elements) fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) { - FShaderCreateOptions f_options = new() + FMeshLayoutCreateOptions 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, - Modules = p_modules, - Count = (byte)Modules.Length, + Buffers = (FMeshBufferDefine*)p_buffers, + Elements = (FMeshBufferElement*)p_elements, + BufferCount = (uint)Buffers.Length, + ElementCount = (uint)Elements.Length, }; - FShader* ptr; - m_ptr->CreateShader(&f_options, &ptr).TryThrow(); - return new(ptr, arr, Layout, InputLayout, Name); + FMeshLayout* ptr; + Ptr->CreateMeshLayout(&f_options, &ptr).TryThrow(); + return new(ptr, Name, this); } } #endregion - #region CreateShaderBinding + #region CreateShaderModule - public ShaderBinding CreateShaderBinding( - ShaderLayout Layout, + public ShaderModule CreateShaderModule( + ShaderStage Stage, ReadOnlySpan Blob, + String8? EntryPoint = null, string? Name = null, ReadOnlySpan Name8 = default - ) => MainQueue.CreateShaderBinding(Layout, Name, Name8); + ) + { + 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 CreateMeshLayout + #region CreateShader - public MeshLayout CreateMeshLayout( - ReadOnlySpan Buffers, - ReadOnlySpan Elements, + public Shader CreateShader( + ReadOnlySpan Modules, ShaderLayout? Layout, ShaderInputLayout? InputLayout = null, string? Name = null, ReadOnlySpan Name8 = default ) { - fixed (MeshBufferDefine* p_buffers = Buffers) - fixed (MeshBufferElement* p_elements = Elements) + if (Modules.Length == 0) throw new ArgumentException("No modules provided"); + if (Modules.Length > FShader.MaxShaderModuleCount) + 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++) + { + var module = Modules[i]; + arr[i] = module; + p_modules[i] = module.Ptr; + } fixed (char* p_name = Name) fixed (byte* p_name8 = Name8) { - FMeshLayoutCreateOptions f_options = new() + FShaderCreateOptions 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, + Layout = Layout.Ptr, + InputLayout = InputLayout == null ? null : InputLayout.Ptr, + Modules = p_modules, + Count = (byte)Modules.Length, }; - FMeshLayout* ptr; - m_ptr->CreateMeshLayout(&f_options, &ptr).TryThrow(); - return new(ptr, Name); + FShaderCreateResult result; + Ptr->CreateShader(&f_options, &result).TryThrow(); + return new(result, arr, Layout, InputLayout, Name, this); } } @@ -340,6 +353,11 @@ public MeshLayout CreateMeshLayout( 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, ShaderBindingLayout BindingLayout, MeshLayout? MeshLayout = null, + string? Name = null, ReadOnlySpan Name8 = default ) { fixed (char* p_name = Name) @@ -350,37 +368,20 @@ public GraphicsShaderPipeline CreateGraphicsShaderPipeline( Base = new() { Name = new(Name, Name8, p_name, p_name8), - Shader = Shader.m_ptr, + Shader = Shader.Ptr, + Layout = BindingLayout.Ptr, }, - MeshLayout = MeshLayout == null ? null : MeshLayout.m_ptr, + MeshLayout = MeshLayout == null ? null : MeshLayout.Ptr, GraphicsState = PipelineState.ToFFI(), }; FGraphicsShaderPipeline* ptr; - m_ptr->CreateGraphicsPipeline(&f_options, &ptr).TryThrow(); - return new(ptr, Name, Shader, PipelineState, MeshLayout); + Ptr->CreateGraphicsPipeline(&f_options, &ptr).TryThrow(); + return new(ptr, Name, Shader, PipelineState, BindingLayout, MeshLayout); } } #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 public Sampler CreateSampler( @@ -397,7 +398,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/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 644cf48..fd2406e 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 @@ -131,6 +126,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); diff --git a/Coplt.Graphics.Core/Core/GpuIsolate.cs b/Coplt.Graphics.Core/Core/GpuIsolate.cs new file mode 100644 index 0000000..626ab00 --- /dev/null +++ b/Coplt.Graphics.Core/Core/GpuIsolate.cs @@ -0,0 +1,463 @@ +using System.Buffers; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using Coplt.Dropping; +using Coplt.Graphics.Native; +using Coplt.Graphics.States; + +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 +{ + #region Fields + + internal FGpuIsolateData* m_data; + + #endregion + + #region Props + + public new FGpuIsolate* Ptr => (FGpuIsolate*)m_ptr; + public ref readonly FGpuIsolateData Data => ref *m_data; + public GpuIsolateConfig Config => new(ref *Data.Config); + public FrameId FrameId => new(Data.FrameId); + + #endregion + + #region Ctor + + internal GpuIsolate(FGpuIsolate* ptr, FGpuIsolateData* data, string? name, GpuDevice device) + : base((FGpuObject*)ptr, name, device) + { + m_data = data; + } + + #endregion + + #region Drop + + [Drop] + private void Drop() + { + m_data = null; + } + + #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; + 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(params ReadOnlySpan records) + { + if (records.Length == 0) return; + bool disposed = false; + 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 + + #region Submit + + public void Submit(params ReadOnlySpan records) + { + if (records.Length == 0) return; + 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(); + records[i].AssertEndOrCanEnd(); + } + fixed (IntPtr* p = arr) + fixed (FGpuRecordCreateResult* o = @out) + { + 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); + } + } + } + finally + { + ArrayPool.Shared.Return(arr); + ArrayPool.Shared.Return(@out); + } + } + + #endregion + + #region Submit Return + + public void SubmitReturn(params ReadOnlySpan records) + { + if (records.Length == 0) return; + 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) + { + throw new UnrecoverableException(e); + } + } + } + finally + { + ArrayPool.Shared.Return(arr); + } + } + + #endregion + + #region CreateSwapChainOnWindows + + private enum SwapChainFor + { + Composition, + CoreWindow, + Hwnd, + } + + /// + /// Will fail on non Windows systems + /// + 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) + { + FGpuSwapChainCreateOptions f_options = new() + { + Base = new() + { + 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, + AlphaMode = (FOutputAlphaMode)Options.AlphaMode, + VSync = Options.VSync, + }; + FGpuSwapChainCreateResult r; + 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( + ShaderBindGroupLayout layout, ReadOnlySpan items, + string? Name = null, ReadOnlySpan Name8 = default + ) + { + ShaderBindGroup.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] = 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, + Bindings = p_items, + NumBindings = (uint)items.Length, + }; + FShaderBindGroupCreateResult result; + Device.Ptr->CreateShaderBindGroup(&f_options, &result).TryThrow(); + return new(result, 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 + ) + { + 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] = 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, + BindGroups = p_items, + NumBindGroups = (uint)items.Length, + }; + FShaderBindingCreateResult result; + Device.Ptr->CreateShaderBinding(&f_options, &result).TryThrow(); + return new(result, Name, this, layout); + } + } + finally + { + ArrayPool.Shared.Return(f_items); + } + } + + #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 = + { + 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 = + { + 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/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/GpuOutput.cs b/Coplt.Graphics.Core/Core/GpuOutput.cs index 2415676..88fcc81 100644 --- a/Coplt.Graphics.Core/Core/GpuOutput.cs +++ b/Coplt.Graphics.Core/Core/GpuOutput.cs @@ -31,82 +31,58 @@ 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 [Dropping(Unmanaged = true)] -public sealed unsafe partial class GpuOutput : GpuExecutor, IQueueOwned, IGpuResource, IRtv, ISrv +public abstract unsafe partial class GpuOutput2 : IsolateChild, IGpuResource, IRtv, ISrv { #region Fields - internal new FGpuOutput* m_ptr; + internal FGpuOutputData* m_data; #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; + public new FGpuOutput2* Ptr => (FGpuOutput2*)m_ptr; + internal ref readonly FGpuOutputData Data => ref *m_data; GpuResourceType IGpuResource.Type => GpuResourceType.Image; IGpuResource IGpuView.Resource => this; - FResourceMeta IGpuResource.GetMeta() => new() - { - Type = FResourceRefType.Output, - Output = m_ptr, - }; + 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 #region Ctor - internal GpuOutput(FGpuOutput* ptr, string? name, GpuQueue queue) : base((FGpuExecutor*)ptr, name, queue) + internal GpuOutput2(FGpuOutput2* ptr, FGpuOutputData* data, string? name, GpuIsolate isolate) : base((FGpuObject*)ptr, name, isolate) { - m_ptr = ptr; + m_data = data; } #endregion @@ -116,36 +92,87 @@ internal GpuOutput(FGpuOutput* ptr, string? name, GpuQueue queue) : base((FGpuEx [Drop] private void Drop() { - m_ptr = null; + m_data = null; } #endregion - #region ToString + #region Cmd - public override string ToString() => - m_name is null - ? $"{nameof(GpuOutput)}(0x{(nuint)m_ptr:X})" - : $"{nameof(GpuOutput)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; + FCmdRes IGpuResource.IntoCmd() => new() + { + Type = FCmdResType.Output, + Output = Ptr, + }; #endregion - #region Present + #region Views - public void Present(bool NoWait = false) => Queue.Submit(this, NoWait); + public bool TrySrv() => true; + public bool TryRtv() => true; #endregion - #region Views + #region Methods - public bool TrySrv() => true; - public bool TryRtv() => true; + 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; + /// + /// 是否使用 sRGB,实现可以选择忽略 + /// 是指整个渲染管线是不是使用 sRGB,而不是交换链是不是使用,具体交换链格式请使用 获取 + /// 设置为 false 时需要注意保证顶点缓冲区和 cbuffer 中传入的颜色是线性的,以及使用 sRGB 视图转换纹理到线性 + /// true 时将原样传输像素数据进行呈现,false 将在呈现时对输出执行 线性 -> sRGB 转换 + /// + public bool Srgb = true; + /// + /// 是否使用 hdr,实现可以选择忽略 + /// + public HdrType Hdr; + public PresentMode PresentMode = PresentMode.TripleBuffer; + public OutputAlphaMode AlphaMode = OutputAlphaMode.Opaque; + public bool VSync = false; +} + +public sealed unsafe class GpuSwapChain : GpuOutput2 +{ + #region Props + + public new FGpuSwapChain* Ptr => (FGpuSwapChain*)m_ptr; + 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 + + #region Ctor + + internal GpuSwapChain(FGpuSwapChain* ptr, FGpuSwapChainData* data, string? name, GpuIsolate isolate) + : base((FGpuOutput2*)ptr, (FGpuOutputData*)data, name, isolate) { } #endregion - #region Resize + #region Methods - public void Resize(uint width, uint height) => m_ptr->Resize(width, height).TryThrow(); + public void SetVSync(bool Enable) => Ptr->SetVSync(Enable).TryThrow(); + + public void GetRawPtr() => Ptr->GetRawPtr(); #endregion } diff --git a/Coplt.Graphics.Core/Core/GpuQueue.cs b/Coplt.Graphics.Core/Core/GpuQueue.cs index 6a3d1e4..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 @@ -19,331 +22,15 @@ public static partial class GraphicsExtensions public static FGpuQueueType ToFFI(this GpuQueueType value) => (FGpuQueueType)value; public static GpuQueueType FromFFI(this FGpuQueueType value) => (GpuQueueType)value; -} - -[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, - Format = Options.Format.ToFFI(), - 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(); - return new(ptr, Name, this); - } - } - #endregion - - #region CreateShaderBinding - - public ShaderBinding CreateShaderBinding( - ShaderLayout Layout, - string? Name = null, ReadOnlySpan Name8 = default - ) + public static ReadOnlySpan ToUtf8String(this GpuQueueType value) => value switch { - 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.m_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.m_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.m_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 + 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) + }; } diff --git a/Coplt.Graphics.Core/Core/GpuRecord.cs b/Coplt.Graphics.Core/Core/GpuRecord.cs new file mode 100644 index 0000000..8baaefa --- /dev/null +++ b/Coplt.Graphics.Core/Core/GpuRecord.cs @@ -0,0 +1,1435 @@ +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Coplt.Graphics.Native; +using Coplt.Graphics.Utilities; +using Coplt.Union; + +namespace Coplt.Graphics.Core; + +/// +/// 命令录制对象,非线程安全,需要外部同步 +/// +public sealed unsafe class GpuRecord : IsolateChild +{ + #region Fields + + internal FGpuRecordData* m_data; + internal readonly Dictionary m_resources = new(); + internal readonly HashSet m_objects = new(); + internal uint m_debug_scope_count; + internal bool m_in_render_or_compute_scope; + + #endregion + + #region Props + + public new FGpuRecord* Ptr => (FGpuRecord*)m_ptr; + internal ref FGpuRecordData Data => ref *m_data; + public bool DebugEnabled { get; } + + #endregion + + #region Ctor + + internal GpuRecord(FGpuRecord* ptr, FGpuRecordData* data, string? name, GpuIsolate isolate) : base((FGpuObject*)ptr, name, isolate) + { + m_data = data; + DebugEnabled = Isolate.Device.Instance.DebugEnabled; + } + + #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 + + #region Reset + + internal void Reset() + { + m_resources.Clear(); + m_objects.Clear(); + } + + #endregion + + #region End + + public void AssertNotEnded() + { + if (Data.Ended) throw new InvalidOperationException("Gpu record is already ended"); + } + + 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." + ); + 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 + + #region Alloc Upload + + /// + /// 返回的 Span 只能写入 + /// + 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; + 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(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 UploadLoc(Data.Id, Data.Version, i, offset, Size); + 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 + + #region Payload + + #region AddResource + + internal FCmdResRef AddResource(IGpuResource resource) + { + ref var slot = ref CollectionsMarshal.GetValueRefOrAddDefault(m_resources, resource, 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; + Data.Resources.Add(resource.IntoCmd()); + } + return new() { IndexPlusOne = slot + 1 }; + } + + #endregion + + #region AddObject + + /// + /// 返回是否首次 + /// + internal bool AddObject(object obj) => m_objects.Add(obj); + + #endregion + + #region AddRects + + 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); + Data.PayloadRect.AddRange(MemoryMarshal.Cast(Rects)); + return (uint)len; + } + + #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) + { + 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) + { + AssertNotEnded(); + if (!DebugEnabled) return; + var cmd = new FCmdLabel + { + 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; + } + Data.Commands.Add(new() { Label = cmd }); + } + + public void Label(ReadOnlySpan Label, Color? Color = null) + { + AssertNotEnded(); + 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) + { + AssertNotEnded(); + 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) + { + AssertNotEnded(); + 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) + { + 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) => + 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 + + #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); + 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, + UploadLoc Loc, + ulong DstOffset = 0 + ) + { + AssertNotEnded(); + Dst.AssertSameIsolate(Isolate); + 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 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 + + 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 + ) + { + 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 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 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 + +public struct DebugScope2(GpuRecord self) : IDisposable +{ + private bool m_disposed; + public void Dispose() + { + if (m_disposed) throw new ObjectDisposedException(nameof(DebugScope2)); + 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 + +#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; + 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 = binding_index, + Index = self.Data.NumSetBindings++, + }; + self.Data.Commands.Add(new() { SetBinding = cmd }); + } + + #endregion +} + +#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 + + PipelineContext m_pipeline_context; + internal bool m_disposed; + + #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(RenderScope2)); + 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_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_pipeline_context.SetPipeline(self, Pipeline); + } + + #endregion + + #region SetBinding + + public void SetBinding(ShaderBinding Binding) + { + self.AssertNotEnded(); + m_pipeline_context.SetBinding(self, Binding); + } + + #endregion + + #region SetViewportScissor + + public void SetViewportScissor( + ReadOnlySpan Viewports, + ReadOnlySpan Scissors + ) + { + self.AssertNotEnded(); + 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.AssertNotEnded(); + 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.Ptr, + VertexBufferCount = (uint)VertexBuffers.Length, + }; + if (IndexBuffer is { } index_buffer) + { + index_buffer.Buffer.AssertSameIsolate(self.Isolate); + 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); + 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 + + 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 + ) + { + self.AssertNotEnded(); + if (Pipeline != null) + { + if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Vertex)) + throw new ArgumentException("Only Vertex shaders can use Draw"); + SetPipeline(Pipeline); + } + else + { + 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); + 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 }); + } + + #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 + ) + { + self.AssertNotEnded(); + if (Pipeline != null) + { + if (!Pipeline.Shader.Stages.HasFlags(ShaderStageFlags.Mesh)) + throw new ArgumentException("Only Mesh shaders can use DispatchMesh"); + SetPipeline(Pipeline); + } + else + { + 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); + var cmd = new FCmdDispatch + { + Base = { Type = FCmdType.Dispatch }, + GroupCountX = GroupCountX, + GroupCountY = GroupCountY, + GroupCountZ = GroupCountZ, + Type = FDispatchType.Mesh, + }; + self.Data.Commands.Add(new() { Dispatch = cmd }); + } + + #endregion +} + +#endregion + +#region ComputeScope + +public unsafe struct ComputeScope2( + GpuRecord self, + uint cmd_index, + bool debug_scope, + uint debug_scope_count +) : IDisposable +{ + #region Fields + + PipelineContext m_pipeline_context; + 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_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_pipeline_context.SetPipeline(self, Pipeline); + } + + #endregion + + #region SetBinding + + public void SetBinding(ShaderBinding Binding) + { + self.AssertNotEnded(); + m_pipeline_context.SetBinding(self, Binding); + } + + #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_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); + 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 +} + +#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..5ed2299 100644 --- a/Coplt.Graphics.Core/Core/GpuResource.cs +++ b/Coplt.Graphics.Core/Core/GpuResource.cs @@ -5,35 +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; - 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 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, GpuQueue queue) - : base((FGpuViewable*)ptr, (FGpuViewableData*)data, name, queue) { } + 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 8f317e7..e3f9f49 100644 --- a/Coplt.Graphics.Core/Core/GpuViewable.cs +++ b/Coplt.Graphics.Core/Core/GpuViewable.cs @@ -4,81 +4,17 @@ namespace Coplt.Graphics.Core; -[Dropping(Unmanaged = true)] -public abstract unsafe partial class GpuViewable : IQueueOwned +public abstract unsafe class GpuViewable : DeviceChild { - #region Fields - - internal FGpuViewable* m_ptr; - internal readonly FGpuViewableData* m_data; - internal string? m_name; - internal readonly GpuQueue m_queue; - - #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; #endregion #region Ctor - internal GpuViewable(FGpuViewable* ptr, FGpuViewableData* data, string? name, GpuQueue queue) - { - m_ptr = ptr; - m_data = data; - m_name = name; - m_queue = queue; - } - - #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(GpuViewable)}(0x{(nuint)m_ptr:X})" - : $"{nameof(GpuViewable)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; + internal GpuViewable(FGpuViewable* ptr, string? name, GpuDevice device) : base((FGpuObject*)ptr, name, device) { } #endregion } diff --git a/Coplt.Graphics.Core/Core/GraphicsInstance.cs b/Coplt.Graphics.Core/Core/GraphicsInstance.cs index 5789ee2..c02b28a 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) { @@ -340,9 +337,9 @@ public GpuDevice CreateDevice( }, }, }; - FGpuDevice* ptr; - m_ptr->CreateDevice(&f_options, &ptr).TryThrow(); - return new(ptr, this, null, Name, QueueName: QueueName, QueueName8: QueueName8); + 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..f05c240 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; @@ -27,29 +24,12 @@ 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) + Shader shader, GraphicsPipelineState pipeline_state, ShaderBindingLayout binding_layout, MeshLayout? mesh_layout + ) : base((FShaderPipeline*)ptr, name, shader, binding_layout) { - 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/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/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/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/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/Shader.cs b/Coplt.Graphics.Core/Core/Shader.cs index 7980f1f..09cec6e 100644 --- a/Coplt.Graphics.Core/Core/Shader.cs +++ b/Coplt.Graphics.Core/Core/Shader.cs @@ -5,13 +5,12 @@ 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 readonly ShaderLayout? m_layout; + 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 ShaderLayout? Layout => m_layout; + 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/ShaderBindGroup.cs b/Coplt.Graphics.Core/Core/ShaderBindGroup.cs new file mode 100644 index 0000000..98c9f69 --- /dev/null +++ b/Coplt.Graphics.Core/Core/ShaderBindGroup.cs @@ -0,0 +1,70 @@ +using Coplt.Dropping; +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) { } +} + +[Dropping(Unmanaged = true)] +public sealed unsafe partial class ShaderBindGroup : IsolateChild +{ + #region Fields + + internal FShaderBindGroupData* m_data; + + #endregion + + #region Props + + public new FShaderBindGroup* Ptr => (FShaderBindGroup*)base.Ptr; + public ref readonly FShaderBindGroupData Data => ref *m_data; + public uint CountSlots => Data.CountSlots; + public ShaderBindGroupLayout Layout { get; } + + #endregion + + #region Ctor + + internal ShaderBindGroup( + FShaderBindGroupCreateResult result, string? name, GpuIsolate isolate, ShaderBindGroupLayout layout + ) : base((FGpuObject*)result.BindGroup, name, isolate) + { + m_data = result.Data; + Layout = layout; + } + + #endregion + + #region Drop + + [Drop] + private void Drop() + { + m_data = 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/ShaderBindGroupLayout.cs b/Coplt.Graphics.Core/Core/ShaderBindGroupLayout.cs new file mode 100644 index 0000000..1825b79 --- /dev/null +++ b/Coplt.Graphics.Core/Core/ShaderBindGroupLayout.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 ShaderBindGroupLayout : 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 ShaderBindGroupLayout(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/ShaderBinding.cs b/Coplt.Graphics.Core/Core/ShaderBinding.cs index 10d1e30..d6fb1f2 100644 --- a/Coplt.Graphics.Core/Core/ShaderBinding.cs +++ b/Coplt.Graphics.Core/Core/ShaderBinding.cs @@ -1,50 +1,35 @@ -using System.Buffers; -using Coplt.Dropping; +using Coplt.Dropping; 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 : IQueueOwned +public sealed unsafe partial class ShaderBinding : IsolateChild { #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(); + internal FShaderBindingData* m_data; #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; + public new FShaderBinding* Ptr => (FShaderBinding*)base.Ptr; + public ref readonly FShaderBindingData Data => ref *m_data; + public ShaderBindingLayout Layout { get; } #endregion #region Ctor - internal ShaderBinding(FShaderBinding* ptr, string? name, GpuDevice device, GpuQueue queue, ShaderLayout layout) + internal ShaderBinding( + FShaderBindingCreateResult result, string? name, GpuIsolate isolate, ShaderBindingLayout layout + ) : base((FGpuObject*)result.Binding, name, isolate) { - 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]; + Layout = layout; + m_data = result.Data; } #endregion @@ -54,80 +39,21 @@ internal ShaderBinding(FShaderBinding* ptr, string? name, GpuDevice device, GpuQ [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(); - } + m_data = null; } #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 + #region CheckSet - internal void Set(ReadOnlySpan Items, Span dst) + internal static void CheckSet(ShaderBindingLayout layout, ReadOnlySpan items) { - var defines = Layout.NativeDefines; - var infos = Layout.NativeItemInfos; - var views = MutViews; - for (var i = 0; i < Items.Length; i++) + var count = layout.BindGroupLayouts.Length; + foreach (ref readonly var item in items) { - 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)); - } + if (item.Index >= count) throw new IndexOutOfRangeException(); } } #endregion - - #region ApplyChange - - internal void ApplyChange() - { - m_changed_groups.Clear(); - } - - #endregion } diff --git a/Coplt.Graphics.Core/Core/ShaderBindingLayout.cs b/Coplt.Graphics.Core/Core/ShaderBindingLayout.cs new file mode 100644 index 0000000..5a111d3 --- /dev/null +++ b/Coplt.Graphics.Core/Core/ShaderBindingLayout.cs @@ -0,0 +1,36 @@ +using System.Runtime.InteropServices; +using Coplt.Dropping; +using Coplt.Graphics.Native; + +namespace Coplt.Graphics.Core; + +public sealed unsafe class ShaderBindingLayout : DeviceChild +{ + #region Fields + + internal readonly ShaderLayout m_shader_layout; + internal readonly ShaderBindGroupLayout[] 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 ShaderBindingLayout( + FBindingLayout* ptr, string? name, GpuDevice device, + ShaderLayout shader_layout, ShaderBindGroupLayout[] 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/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..6d8baf9 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)); } } @@ -106,51 +100,30 @@ public enum ShaderLayoutFlags : byte } [Dropping(Unmanaged = true)] -public sealed unsafe partial class ShaderLayout +public sealed unsafe partial 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; + internal FShaderLayoutData* m_data; + internal ShaderBindingLayout? m_empty_binding_layout; #endregion #region Props - public FShaderLayout* Ptr => m_ptr; - public ReadOnlySpan NativeDefines => m_native_defines.Span; - public ReadOnlySpan NativeItemInfos => m_native_item_infos.Span; - public ReadOnlySpan NativeGroupClasses => m_native_group_classes.Span; + public new FShaderLayout* Ptr => (FShaderLayout*)m_ptr; + public ref readonly FShaderLayoutData Data => ref *m_data; + public ReadOnlySpan NativeItems => new(Data.Items, (int)Data.NumItems); + public ShaderLayoutFlags Flags => (ShaderLayoutFlags)Data.Flags; #endregion #region Ctor - internal ShaderLayout(FShaderLayout* ptr, string? name) + internal ShaderLayout(FShaderLayoutCreateResult result, string? name, GpuDevice device) : base((FGpuObject*)result.Layout, name, device) { - m_ptr = ptr; - m_name = name; - if (m_ptr != null) - { - { - uint count = 0; - var defines = m_ptr->GetItemDefines(&count); - m_native_defines = new(defines, count); - } - { - uint count = 0; - var defines = m_ptr->GetItemInfos(&count); - m_native_item_infos = new(defines, count); - } - { - uint count = 0; - var defines = m_ptr->GetGroupClasses(&count); - m_native_group_classes = new(defines, count); - } - } + if (Ptr == null) return; + m_data = result.Data; } #endregion @@ -160,42 +133,14 @@ internal ShaderLayout(FShaderLayout* ptr, string? name) [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(); - } + m_data = null; } #endregion - #region ToString + #region GetEmptyBindingLayout - public override string ToString() => - m_name is null - ? $"{nameof(ShaderLayout)}(0x{(nuint)m_ptr:X})" - : $"{nameof(ShaderLayout)}(0x{(nuint)m_ptr:X} \"{m_name}\")"; + public ShaderBindingLayout GetEmptyBindingLayout() => m_empty_binding_layout ??= Device.CreateBindingLayout(this, [], $"Empty Binding Layout of [{this}]"); #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..0840ed9 100644 --- a/Coplt.Graphics.Core/Core/ShaderPipeline.cs +++ b/Coplt.Graphics.Core/Core/ShaderPipeline.cs @@ -1,78 +1,31 @@ -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; + internal readonly ShaderBindingLayout m_binding_layout; #endregion #region Props - public FShaderPipeline* Ptr => m_ptr; + public new FShaderPipeline* Ptr => (FShaderPipeline*)m_ptr; public Shader Shader => m_shader; + public ShaderBindingLayout BindingLayout => m_binding_layout; #endregion #region Ctor - internal ShaderPipeline(FShaderPipeline* ptr, string? name, Shader shader) + internal ShaderPipeline(FShaderPipeline* ptr, string? name, Shader shader, ShaderBindingLayout binding_layout) : base((FGpuObject*)ptr, name, shader.Device) { - m_ptr = ptr; - m_name = name; m_shader = shader; + m_binding_layout = binding_layout; } #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/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/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/Core/UploadLoc.cs b/Coplt.Graphics.Core/Core/UploadLoc.cs index 31aac91..1b4ec8c 100644 --- a/Coplt.Graphics.Core/Core/UploadLoc.cs +++ b/Coplt.Graphics.Core/Core/UploadLoc.cs @@ -1,3 +1,3 @@ namespace Coplt.Graphics.Core; -public record struct UploadLoc(nuint Index, ulong Offset, uint Size, SubmitId SubmitId); +public record struct UploadLoc(ulong RecordId, ulong RecordVersion, nuint Index, ulong Offset, uint Size); 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/Core/Views.cs b/Coplt.Graphics.Core/Core/Views.cs index dad0780..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 +public interface IGpuView : IIsolateChild { /// /// 视图所属资源 @@ -64,11 +64,7 @@ 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(); } 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/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/FList.cs b/Coplt.Graphics.Core/Native/FList.cs index 25c7568..ef8de13 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; @@ -108,6 +109,26 @@ private void Grow() #endregion + #region EnsureCap + + public void EnsureCap(nuint cap) + { + cap = BitOperations.RoundUpToPowerOf2(cap); + if (cap < m_cap) return; + 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() @@ -125,6 +146,21 @@ public void Add(T item) #endregion + #region AddRange + + public Span UnsafeAddRange(int size) + { + var new_len = m_len + (nuint)size; + if (new_len >= m_cap) EnsureCap(new_len); + 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 public void RemoveAt(int index) 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/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 037a7ec..c0f2f20 100644 --- a/Coplt.Graphics.Core/Native/Native.cs +++ b/Coplt.Graphics.Core/Native/Native.cs @@ -6,6 +6,156 @@ 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; + } + + [NativeTypeName("Coplt::u8")] + public enum FDepthStencilClearFlags : byte + { + None = 0, + Depth = 1, + 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 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; + } + + [NativeTypeName("Coplt::u8")] + public enum FDispatchType : byte + { + Compute, + Mesh, + } + public unsafe partial struct FObject : FObject.Interface { public void** lpVtbl; @@ -714,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 @@ -726,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); } } @@ -747,333 +897,142 @@ 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)); + [NativeTypeName("Coplt::FGpuDevice *")] + public FGpuDevice* Device; + + [NativeTypeName("Coplt::FGpuIsolateCreateResult")] + public FGpuIsolateCreateResult MainIsolate; + + [NativeTypeName("Coplt::FGpuIsolateCreateResult")] + public FGpuIsolateCreateResult CopyIsolate; + } + + public partial struct FInstanceCreateOptions + { + [NativeTypeName("Coplt::b8")] + public B8 Debug; + + [NativeTypeName("Coplt::b8")] + public B8 GpuBasedValidation; + } + + [Guid("CC2894BA-57C7-474A-B777-1A3E3A7C922C")] + [NativeTypeName("struct FInstance : Coplt::FUnknown")] + public unsafe partial struct FInstance : FInstance.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FInstance)); public void** lpVtbl; + [NativeTypeName("Coplt::FAllocator *")] + public FAllocator* m_allocator; + + [NativeTypeName("Coplt::b8")] + public B8 m_debug_enabled; + + [NativeTypeName("Coplt::b8")] + public B8 m_gpu_based_validation_enabled; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuDevice*)Unsafe.AsPointer(ref this)); + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FInstance*)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)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FInstance*)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)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FInstance*)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)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FInstance*)Unsafe.AsPointer(ref this), id); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + public FResult SetLogger([NativeTypeName("const FLogger &")] FLogger* logger) { 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)); + return *((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FInstance*)Unsafe.AsPointer(ref this), &result, logger); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateMainQueue([NativeTypeName("const FMainQueueCreateOptions &")] FMainQueueCreateOptions* options, FGpuQueue** @out) + public FResult CreateString8([NativeTypeName("const Char8 *")] byte* data, [NativeTypeName("Coplt::usize")] nuint size, FString8** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FInstance*)Unsafe.AsPointer(ref this), &result, data, size, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, FShaderModule** @out) + public FResult CreateString16([NativeTypeName("const Char16 *")] char* data, [NativeTypeName("Coplt::usize")] nuint size, FString16** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FInstance*)Unsafe.AsPointer(ref this), &result, data, size, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, FShaderLayout** @out) + public FResult CreateBlob([NativeTypeName("Coplt::usize")] nuint size, FBlob** @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FInstance*)Unsafe.AsPointer(ref this), &result, size, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, FShaderLayout** @out) + [return: NativeTypeName("FGpuAdapter *const *")] + public FGpuAdapter** GetAdapters([NativeTypeName("Coplt::u32 *")] uint* out_count) { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FInstance*)Unsafe.AsPointer(ref this), out_count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out) + public FResult CreateDevice([NativeTypeName("const FGpuAutoSelectDeviceCreateOptions &")] FGpuAutoSelectDeviceCreateOptions* options, [NativeTypeName("Coplt::FGpuDeviceCreateResult *")] FGpuDeviceCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FInstance*)Unsafe.AsPointer(ref this), &result, options, @out); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateShader([NativeTypeName("const FShaderCreateOptions &")] FShaderCreateOptions* options, FShader** @out) + public interface Interface : FUnknown.Interface { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); - } + [return: NativeTypeName("Coplt::FResult")] + FResult SetLogger([NativeTypeName("const FLogger &")] FLogger* logger); - [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); - } + [return: NativeTypeName("Coplt::FResult")] + FResult CreateString8([NativeTypeName("const Char8 *")] byte* data, [NativeTypeName("Coplt::usize")] nuint size, FString8** @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); - } + [return: NativeTypeName("Coplt::FResult")] + FResult CreateString16([NativeTypeName("const Char16 *")] char* data, [NativeTypeName("Coplt::usize")] nuint size, FString16** @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); + [return: NativeTypeName("Coplt::FResult")] + FResult CreateBlob([NativeTypeName("Coplt::usize")] nuint size, FBlob** @out); + + [return: NativeTypeName("FGpuAdapter *const *")] + FGpuAdapter** GetAdapters([NativeTypeName("Coplt::u32 *")] uint* out_count); + + [return: NativeTypeName("Coplt::FResult")] + FResult CreateDevice([NativeTypeName("const FGpuAutoSelectDeviceCreateOptions &")] FGpuAutoSelectDeviceCreateOptions* options, [NativeTypeName("Coplt::FGpuDeviceCreateResult *")] FGpuDeviceCreateResult* @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 CreateMainQueue([NativeTypeName("const FMainQueueCreateOptions &")] FMainQueueCreateOptions* options, FGpuQueue** @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); - } - } - - public partial struct FInstanceCreateOptions - { - [NativeTypeName("Coplt::b8")] - public B8 Debug; - - [NativeTypeName("Coplt::b8")] - public B8 GpuBasedValidation; - } - - [Guid("CC2894BA-57C7-474A-B777-1A3E3A7C922C")] - [NativeTypeName("struct FInstance : Coplt::FUnknown")] - public unsafe partial struct FInstance : FInstance.Interface, INativeGuid - { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FInstance)); - - public void** lpVtbl; - - [NativeTypeName("Coplt::FAllocator *")] - public FAllocator* m_allocator; - - [NativeTypeName("Coplt::b8")] - public B8 m_debug_enabled; - - [NativeTypeName("Coplt::b8")] - public B8 m_gpu_based_validation_enabled; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FInstance*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FInstance*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FInstance*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FInstance*)Unsafe.AsPointer(ref this), id); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetLogger([NativeTypeName("const FLogger &")] FLogger* logger) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FInstance*)Unsafe.AsPointer(ref this), &result, logger); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateString8([NativeTypeName("const Char8 *")] byte* data, [NativeTypeName("Coplt::usize")] nuint size, FString8** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FInstance*)Unsafe.AsPointer(ref this), &result, data, size, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateString16([NativeTypeName("const Char16 *")] char* data, [NativeTypeName("Coplt::usize")] nuint size, FString16** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FInstance*)Unsafe.AsPointer(ref this), &result, data, size, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateBlob([NativeTypeName("Coplt::usize")] nuint size, FBlob** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FInstance*)Unsafe.AsPointer(ref this), &result, size, @out); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("FGpuAdapter *const *")] - public FGpuAdapter** GetAdapters([NativeTypeName("Coplt::u32 *")] uint* out_count) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FInstance*)Unsafe.AsPointer(ref this), out_count); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult CreateDevice([NativeTypeName("const FGpuAutoSelectDeviceCreateOptions &")] FGpuAutoSelectDeviceCreateOptions* options, FGpuDevice** @out) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FInstance*)Unsafe.AsPointer(ref this), &result, options, @out); - } - - public interface Interface : FUnknown.Interface - { - [return: NativeTypeName("Coplt::FResult")] - FResult SetLogger([NativeTypeName("const FLogger &")] FLogger* logger); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateString8([NativeTypeName("const Char8 *")] byte* data, [NativeTypeName("Coplt::usize")] nuint size, FString8** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateString16([NativeTypeName("const Char16 *")] char* data, [NativeTypeName("Coplt::usize")] nuint size, FString16** @out); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateBlob([NativeTypeName("Coplt::usize")] nuint size, FBlob** @out); - - [return: NativeTypeName("FGpuAdapter *const *")] - FGpuAdapter** GetAdapters([NativeTypeName("Coplt::u32 *")] uint* out_count); - - [return: NativeTypeName("Coplt::FResult")] - FResult CreateDevice([NativeTypeName("const FGpuAutoSelectDeviceCreateOptions &")] FGpuAutoSelectDeviceCreateOptions* options, FGpuDevice** @out); - } - } + } [NativeTypeName("Coplt::u32")] public enum FShaderModelLevel : uint @@ -1144,6 +1103,15 @@ public partial struct FDeviceFeatures [NativeTypeName("Coplt::b8")] public B8 DynBindlessOnly; + + [NativeTypeName("Coplt::b8")] + public B8 ExtraIsolate; + + [NativeTypeName("Coplt::b8")] + public B8 UMA; + + [NativeTypeName("Coplt::b8")] + public B8 CacheCoherentUMA; } [NativeTypeName("Coplt::i32")] @@ -1205,92 +1173,45 @@ public partial struct FGpuDeviceCreateOptions public FStr8or16 Name; } - [NativeTypeName("Coplt::u8")] - public enum FShaderStage : byte - { - Compute = 0, - Pixel = 1, - Vertex = 2, - Mesh = 3, - Task = 4, - } - - [NativeTypeName("Coplt::u32")] - public enum FShaderStageFlags : uint - { - None = 0, - Compute = 1 << 0, - Pixel = 1 << 1, - Vertex = 1 << 2, - Mesh = 1 << 3, - Task = 1 << 4, - } - - public unsafe partial struct FShaderModuleCreateOptions - { - [NativeTypeName("Coplt::FStr8or16")] - public FStr8or16 Name; - - [NativeTypeName("Coplt::FString8 *")] - public FString8* EntryPoint; - - public void* Data; - - [NativeTypeName("Coplt::usize")] - public nuint Size; - - [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 + [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_FShaderModule)); + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuDevice)); public void** lpVtbl; - [NativeTypeName("Coplt::u8 *")] - public byte* Data; - - [NativeTypeName("Coplt::usize")] - public nuint Size; - - [NativeTypeName("Coplt::FShaderStage")] - public FShaderStage Stage; - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShaderModule*)Unsafe.AsPointer(ref this)); + ((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]))((FShaderModule*)Unsafe.AsPointer(ref this)); + 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]))((FShaderModule*)Unsafe.AsPointer(ref this)); + 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]))((FShaderModule*)Unsafe.AsPointer(ref this), 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]))((FShaderModule*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuDevice*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1298,156 +1219,261 @@ public ulong ObjectId() public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderModule*)Unsafe.AsPointer(ref this), &result, name); + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, name); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FString8 *")] - public FString8* GetEntryPoint() + [return: NativeTypeName("Coplt::FGpuAdapter *")] + public FGpuAdapter* GetAdapter() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderModule*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuDevice*)Unsafe.AsPointer(ref this)); } - public interface Interface : FGpuObject.Interface + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* GetRawDevice() { - [return: NativeTypeName("Coplt::FString8 *")] - FString8* GetEntryPoint(); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuDevice*)Unsafe.AsPointer(ref this)); } - } - public partial struct FShaderLayout - { - } + [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); + } - [Guid("552A498E-8F3A-47FF-A335-7AF2DE0901E8")] - [NativeTypeName("struct FShaderLayout : Coplt::FGpuObject")] - public unsafe partial struct FShaderLayout : FShaderLayout.Interface, INativeGuid - { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShaderLayout)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + 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); + } - public void** lpVtbl; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + 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); + } - [NativeTypeName("Coplt::FShaderLayoutFlags")] - public FShaderLayoutFlags Flags; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateBindingLayout([NativeTypeName("const FBindingLayoutCreateOptions &")] FBindingLayoutCreateOptions* options, FBindingLayout** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() + [return: NativeTypeName("Coplt::FResult")] + public FResult GetEmptyShaderLayout([NativeTypeName("const FGetEmptyShaderLayoutOptions &")] FGetEmptyShaderLayoutOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out) { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShaderLayout*)Unsafe.AsPointer(ref this)); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() + [return: NativeTypeName("Coplt::FResult")] + public FResult GetEmptyBindGroupLayout([NativeTypeName("Coplt::FBindGroupLayoutCreateResult *")] FBindGroupLayoutCreateResult* @out) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FShaderLayout*)Unsafe.AsPointer(ref this)); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() + [return: NativeTypeName("Coplt::FResult")] + public FResult GetEmptyBindingLayout([NativeTypeName("const FGetEmptyBindingLayoutOptions &")] FGetEmptyBindingLayoutOptions* options, FBindingLayout** @out) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FShaderLayout*)Unsafe.AsPointer(ref this)); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateShaderInputLayout([NativeTypeName("const FShaderInputLayoutCreateOptions &")] FShaderInputLayoutCreateOptions* options, FShaderInputLayout** @out) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FShaderLayout*)Unsafe.AsPointer(ref this), id); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateMeshLayout([NativeTypeName("const FMeshLayoutCreateOptions &")] FMeshLayoutCreateOptions* options, FMeshLayout** @out) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FShaderLayout*)Unsafe.AsPointer(ref this)); + 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 SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + public FResult CreateShaderModule([NativeTypeName("const FShaderModuleCreateOptions &")] FShaderModuleCreateOptions* options, [NativeTypeName("Coplt::FShaderModuleCreateResult *")] FShaderModuleCreateResult* @out) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderLayout*)Unsafe.AsPointer(ref this), &result, name); + return *((delegate* unmanaged[Thiscall])(lpVtbl[17]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("const FShaderLayoutItemDefine *")] - public FShaderLayoutItemDefine* GetItemDefines([NativeTypeName("Coplt::u32 *")] uint* out_count) + [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 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); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + 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); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateGraphicsPipeline([NativeTypeName("const FGraphicsShaderPipelineCreateOptions &")] FGraphicsShaderPipelineCreateOptions* options, FGraphicsShaderPipeline** @out) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[21]))((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) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[22]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("const FShaderLayoutItemInfo *")] - public FShaderLayoutItemInfo* GetItemInfos([NativeTypeName("Coplt::u32 *")] uint* out_count) + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateImage([NativeTypeName("const FGpuImageCreateOptions &")] FGpuImageCreateOptions* options, FGpuImage** @out) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[23]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("const FShaderLayoutGroupClass *")] - public FShaderLayoutGroupClass* GetGroupClasses([NativeTypeName("Coplt::u32 *")] uint* out_count) + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateSampler([NativeTypeName("const FGpuSamplerCreateOptions &")] FGpuSamplerCreateOptions* options, FGpuSampler** @out) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FShaderLayout*)Unsafe.AsPointer(ref this), out_count); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[24]))((FGpuDevice*)Unsafe.AsPointer(ref this), &result, options, @out); } public interface Interface : FGpuObject.Interface { - [return: NativeTypeName("const FShaderLayoutItemDefine *")] - FShaderLayoutItemDefine* GetItemDefines([NativeTypeName("Coplt::u32 *")] uint* out_count); + [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 CreateShaderLayout([NativeTypeName("const FShaderLayoutCreateOptions &")] FShaderLayoutCreateOptions* options, [NativeTypeName("Coplt::FShaderLayoutCreateResult *")] FShaderLayoutCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + 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 GetEmptyBindGroupLayout([NativeTypeName("Coplt::FBindGroupLayoutCreateResult *")] FBindGroupLayoutCreateResult* @out); + + [return: NativeTypeName("Coplt::FResult")] + FResult GetEmptyBindingLayout([NativeTypeName("const FGetEmptyBindingLayoutOptions &")] FGetEmptyBindingLayoutOptions* options, FBindingLayout** @out); + + [return: NativeTypeName("Coplt::FResult")] + 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 CreateShaderBindGroup([NativeTypeName("const FShaderBindGroupCreateOptions &")] FShaderBindGroupCreateOptions* options, [NativeTypeName("Coplt::FShaderBindGroupCreateResult *")] FShaderBindGroupCreateResult* @out); - [return: NativeTypeName("const FShaderLayoutItemInfo *")] - FShaderLayoutItemInfo* GetItemInfos([NativeTypeName("Coplt::u32 *")] uint* out_count); + [return: NativeTypeName("Coplt::FResult")] + 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); + + [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("const FShaderLayoutGroupClass *")] - FShaderLayoutGroupClass* GetGroupClasses([NativeTypeName("Coplt::u32 *")] uint* out_count); + [return: NativeTypeName("Coplt::FResult")] + FResult CreateSampler([NativeTypeName("const FGpuSamplerCreateOptions &")] FGpuSamplerCreateOptions* options, FGpuSampler** @out); } } - public partial struct FShaderInputLayout + public partial struct FGpuRecord { } - [Guid("70229C9A-FB3D-46B4-B534-72FDB167D807")] - [NativeTypeName("struct FShaderInputLayout : Coplt::FGpuObject")] - public unsafe partial struct FShaderInputLayout : FShaderInputLayout.Interface, INativeGuid + [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_FShaderInputLayout)); + 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]))((FShaderInputLayout*)Unsafe.AsPointer(ref this)); + ((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]))((FShaderInputLayout*)Unsafe.AsPointer(ref this)); + 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]))((FShaderInputLayout*)Unsafe.AsPointer(ref this)); + 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]))((FShaderInputLayout*)Unsafe.AsPointer(ref this), 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]))((FShaderInputLayout*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuRecord*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1455,85 +1481,119 @@ public ulong ObjectId() public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderInputLayout*)Unsafe.AsPointer(ref this), &result, name); + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuRecord*)Unsafe.AsPointer(ref this), &result, name); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("const FShaderInputLayoutElement *")] - public FShaderInputLayoutElement* GetElements([NativeTypeName("Coplt::u32 *")] uint* out_count) + [return: NativeTypeName("Coplt::FGpuRecordData *")] + public FGpuRecordData* GpuFGpuRecordData() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderInputLayout*)Unsafe.AsPointer(ref this), out_count); + 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("const FShaderInputLayoutElement *")] - FShaderInputLayoutElement* GetElements([NativeTypeName("Coplt::u32 *")] uint* out_count); + [return: NativeTypeName("Coplt::FGpuRecordData *")] + FGpuRecordData* GpuFGpuRecordData(); + + [return: NativeTypeName("Coplt::FResult")] + FResult End(); } } - public unsafe partial struct FShaderCreateOptions + public partial struct FGpuRecordCreateResult + { + } + + public unsafe partial struct FGpuRecordCreateResult + { + [NativeTypeName("Coplt::FGpuRecord *")] + public FGpuRecord* Record; + + [NativeTypeName("Coplt::FGpuRecordData *")] + public FGpuRecordData* Data; + } + + public enum FGpuIsolateType + { + Main, + Copy, + } + + public partial struct FGpuIsolateCreateOptions { [NativeTypeName("Coplt::FStr8or16")] public FStr8or16 Name; - [NativeTypeName("Coplt::FShaderLayout *")] - public FShaderLayout* Layout; - - [NativeTypeName("Coplt::FShaderInputLayout *")] - public FShaderInputLayout* InputLayout; + [NativeTypeName("Coplt::FGpuIsolateType")] + public FGpuIsolateType Type; + } - public FShaderModule** Modules; + public partial struct FGpuIsolateConfig + { + [NativeTypeName("Coplt::b8")] + public B8 MultiThreadRecord; - [NativeTypeName("Coplt::u8")] - public byte Count; + [NativeTypeName("Coplt::b8")] + public B8 UseSplitBarrier; } - [Guid("DE1352D5-023D-42B0-BEAC-122B3B296C9C")] - [NativeTypeName("struct FShader : Coplt::FGpuObject")] - public unsafe partial struct FShader : FShader.Interface, INativeGuid + public unsafe partial struct FGpuIsolateData { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShader)); + [NativeTypeName("Coplt::u64")] + public ulong FrameId; - public void** lpVtbl; + [NativeTypeName("Coplt::FGpuIsolateConfig *")] + public FGpuIsolateConfig* Config; + } - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags Stages; + [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)); - [NativeTypeName("const u32")] - public const uint MaxShaderModuleCount = 3; + public void** lpVtbl; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShader*)Unsafe.AsPointer(ref this)); + ((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]))((FShader*)Unsafe.AsPointer(ref this)); + 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]))((FShader*)Unsafe.AsPointer(ref this)); + 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]))((FShader*)Unsafe.AsPointer(ref this), 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]))((FShader*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuIsolate*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1541,837 +1601,920 @@ public ulong ObjectId() public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShader*)Unsafe.AsPointer(ref this), &result, name); + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, name); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FShaderLayout *")] - public FShaderLayout* Layout() + [return: NativeTypeName("Coplt::FGpuIsolateData *")] + public FGpuIsolateData* GpuIsolateData() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShader*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuIsolate*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FShaderInputLayout *")] - public FShaderInputLayout* InputLayout() + [return: NativeTypeName("Coplt::FResult")] + public FResult RentRecords([NativeTypeName("Coplt::u32")] uint NumRecords, [NativeTypeName("Coplt::FGpuRecordCreateResult *")] FGpuRecordCreateResult* OutRecords) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FShader*)Unsafe.AsPointer(ref this)); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, OutRecords); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FShaderModule *")] - public FShaderModule* Compute() + [return: NativeTypeName("Coplt::FResult")] + public FResult ReturnRecords([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FShader*)Unsafe.AsPointer(ref this)); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FShaderModule *")] - public FShaderModule* Pixel() + [return: NativeTypeName("Coplt::FResult")] + public FResult Submit([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records, [NativeTypeName("Coplt::FGpuRecordCreateResult *")] FGpuRecordCreateResult* OutRecords) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FShader*)Unsafe.AsPointer(ref this)); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records, OutRecords); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FShaderModule *")] - public FShaderModule* Vertex() + [return: NativeTypeName("Coplt::FResult")] + public FResult SubmitReturn([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FShader*)Unsafe.AsPointer(ref this)); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, NumRecords, Records); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FShaderModule *")] - public FShaderModule* Mesh() + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateSwapChainFromExists([NativeTypeName("const FGpuSwapChainFromExistsCreateOptions &")] FGpuSwapChainFromExistsCreateOptions* options, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FShader*)Unsafe.AsPointer(ref this)); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FShaderModule *")] - public FShaderModule* Task() + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateSwapChainForComposition([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FShader*)Unsafe.AsPointer(ref this)); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, @out); } - public interface Interface : FGpuObject.Interface + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult CreateSwapChainForHwnd([NativeTypeName("const FGpuSwapChainCreateOptions &")] FGpuSwapChainCreateOptions* options, void* hwnd, [NativeTypeName("Coplt::FGpuSwapChainCreateResult &")] FGpuSwapChainCreateResult* @out) { - [return: NativeTypeName("Coplt::FShaderLayout *")] - FShaderLayout* Layout(); + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuIsolate*)Unsafe.AsPointer(ref this), &result, options, hwnd, @out); + } - [return: NativeTypeName("Coplt::FShaderInputLayout *")] - FShaderInputLayout* InputLayout(); + [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); + } - [return: NativeTypeName("Coplt::FShaderModule *")] - FShaderModule* Compute(); + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FGpuIsolateData *")] + FGpuIsolateData* GpuIsolateData(); - [return: NativeTypeName("Coplt::FShaderModule *")] - FShaderModule* Pixel(); + [return: NativeTypeName("Coplt::FResult")] + FResult RentRecords([NativeTypeName("Coplt::u32")] uint NumRecords, [NativeTypeName("Coplt::FGpuRecordCreateResult *")] FGpuRecordCreateResult* OutRecords); - [return: NativeTypeName("Coplt::FShaderModule *")] - FShaderModule* Vertex(); + [return: NativeTypeName("Coplt::FResult")] + FResult ReturnRecords([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records); - [return: NativeTypeName("Coplt::FShaderModule *")] - FShaderModule* Mesh(); + [return: NativeTypeName("Coplt::FResult")] + FResult Submit([NativeTypeName("Coplt::u32")] uint NumRecords, FGpuRecord** Records, [NativeTypeName("Coplt::FGpuRecordCreateResult *")] FGpuRecordCreateResult* OutRecords); - [return: NativeTypeName("Coplt::FShaderModule *")] - FShaderModule* Task(); + [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); + + [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); } } - public unsafe partial struct FShaderBindingCreateOptions + public partial struct FGpuIsolate { - [NativeTypeName("Coplt::FStr8or16")] - public FStr8or16 Name; + } - [NativeTypeName("Coplt::FShaderLayout *")] - public FShaderLayout* Layout; + public unsafe partial struct FGpuIsolateCreateResult + { + [NativeTypeName("Coplt::FGpuIsolate *")] + public FGpuIsolate* Isolate; + + [NativeTypeName("Coplt::FGpuIsolateData *")] + public FGpuIsolateData* Data; } - public partial struct FBindItem + [NativeTypeName("Coplt::u8")] + public enum FGpuRecordMode : byte { - [NativeTypeName("Coplt::FView")] - public FView View; + Direct = 0, + Compute = 1, + Copy = 2, + } + + public unsafe partial struct FGpuRecordData + { + [NativeTypeName("Coplt::u64")] + public ulong Id; + + [NativeTypeName("Coplt::u64")] + public ulong Version; + + [NativeTypeName("Coplt::FRecordContext *")] + public FRecordContext* Context; + + public FList Commands; + + public FList Resources; + + public FList Bindings; + + public FList BindingChange; + + public FList PayloadRect; + + public FList PayloadViewport; + + public FList PayloadRenderInfo; + + public FList PayloadResolveInfo; + + public FList PayloadBufferCopyRange; + + public FList PayloadBufferImageCopyRange; + + public FList PayloadMeshBuffers; + + public FList PayloadVertexBufferRange; + + [NativeTypeName("FList")] + public FList Blob; [NativeTypeName("Coplt::u32")] - public uint Index; + public uint NumSetBindings; + + [NativeTypeName("Coplt::b8")] + public B8 Ended; + + [NativeTypeName("Coplt::FGpuRecordMode")] + public FGpuRecordMode Mode; } - [Guid("A3CA644A-0E02-4D25-9A18-8835D66600F7")] - [NativeTypeName("struct FShaderBinding : Coplt::FGpuObject")] - public unsafe partial struct FShaderBinding : FShaderBinding.Interface, INativeGuid + [NativeTypeName("Coplt::u32")] + public enum FCmdType : uint { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShaderBinding)); + None = 0, + End = 1, + Label, + BeginScope, + EndScope, + PreparePresent, + ClearColor, + ClearDepthStencil, + BufferCopy, + BufferImageCopy, + Render, + Compute, + SetPipeline, + SetBinding, + SetViewportScissor, + SetMeshBuffers, + Draw, + Dispatch, + } - public void** lpVtbl; + [NativeTypeName("Coplt::u8")] + public enum FCmdResType : byte + { + Image, + Buffer, + Output, + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShaderBinding*)Unsafe.AsPointer(ref this)); - } + public unsafe partial struct FCmdRes + { + [NativeTypeName("__AnonymousRecord_Cmd_L71_C9")] + public _Anonymous_e__Union Anonymous; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FShaderBinding*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::FCmdResType")] + public FCmdResType Type; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() + [UnscopedRef] + public ref FGpuOutput2* Output { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FShaderBinding*)Unsafe.AsPointer(ref this)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Output; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + [UnscopedRef] + public ref FGpuBuffer* Buffer { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FShaderBinding*)Unsafe.AsPointer(ref this), id); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Buffer; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() + [UnscopedRef] + public ref FGpuImage* Image { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FShaderBinding*)Unsafe.AsPointer(ref this)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Image; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + [StructLayout(LayoutKind.Explicit)] + public unsafe partial struct _Anonymous_e__Union { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderBinding*)Unsafe.AsPointer(ref this), &result, name); - } + [FieldOffset(0)] + [NativeTypeName("Coplt::FGpuOutput2 *")] + public FGpuOutput2* Output; - public interface Interface : FGpuObject.Interface - { + [FieldOffset(0)] + [NativeTypeName("Coplt::FGpuBuffer *")] + public FGpuBuffer* Buffer; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FGpuImage *")] + public FGpuImage* Image; } } - public unsafe partial struct FUploadBufferBlock + public partial struct FResIndex { - [NativeTypeName("Coplt::u8 *")] - public byte* mapped_ptr; + [NativeTypeName("Coplt::u32")] + public uint Value; + } - [NativeTypeName("Coplt::u64")] - public ulong cur_offset; + public partial struct FCmdResRef + { + [NativeTypeName("Coplt::u32")] + public uint IndexPlusOne; + } - [NativeTypeName("Coplt::u64")] - public ulong size; + 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; } - [Guid("3A22DE68-8377-4E57-A167-3EFDB97C102A")] - [NativeTypeName("struct FFrameContext : Coplt::FGpuObject")] - public unsafe partial struct FFrameContext : FFrameContext.Interface, INativeGuid + public partial struct FRenderInfo2 { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FFrameContext)); + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Dsv; - public void** lpVtbl; + [NativeTypeName("Coplt::u32")] + public uint NumRtv; - public FList m_upload_buffer; + [NativeTypeName("FCmdResRef[8]")] + public _Rtv_e__FixedBuffer Rtv; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() + [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 { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FFrameContext*)Unsafe.AsPointer(ref this)); + public FCmdResRef e0; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() + [InlineArray(8)] + public partial struct _ResolveInfoIndex_e__FixedBuffer { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FFrameContext*)Unsafe.AsPointer(ref this)); + public uint e0; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() + [InlineArray(8)] + public partial struct _RtvFormat_e__FixedBuffer { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FFrameContext*)Unsafe.AsPointer(ref this)); + public FGraphicsFormat e0; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + [InlineArray(32)] + public partial struct _Color_e__FixedBuffer { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FFrameContext*)Unsafe.AsPointer(ref this), id); + public float e0; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() + [InlineArray(2)] + public partial struct _DsvLoadOp_e__FixedBuffer { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FFrameContext*)Unsafe.AsPointer(ref this)); + public FLoadOp e0; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + [InlineArray(2)] + public partial struct _DsvStoreOp_e__FixedBuffer { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FFrameContext*)Unsafe.AsPointer(ref this), &result, name); + public FStoreOp e0; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult GrowUploadBuffer([NativeTypeName("Coplt::u64")] ulong min_required_size) + [InlineArray(8)] + public partial struct _RtvLoadOp_e__FixedBuffer { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FFrameContext*)Unsafe.AsPointer(ref this), &result, min_required_size); + public FLoadOp e0; } - public interface Interface : FGpuObject.Interface + [InlineArray(8)] + public partial struct _RtvStoreOp_e__FixedBuffer { - [return: NativeTypeName("Coplt::FResult")] - FResult GrowUploadBuffer([NativeTypeName("Coplt::u64")] ulong min_required_size); + public FStoreOp e0; } } - public partial struct FMainQueueCreateOptions + [StructLayout(LayoutKind.Explicit)] + public partial struct FBufferRef2 { - [NativeTypeName("Coplt::FStr8or16")] - public FStr8or16 Name; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Buffer; + + [FieldOffset(0)] + [NativeTypeName("Coplt::FUploadLoc")] + public FUploadLoc Upload; } [NativeTypeName("Coplt::u8")] - public enum FGpuQueueType : byte + public enum FBufferRefType2 : byte { - Direct, - Compute, - Copy, - Video, + Buffer = 0, + Upload, } - [Guid("95E60E28-E387-4055-9B33-2D23AF901F8A")] - [NativeTypeName("struct FGpuQueue : Coplt::FGpuObject")] - public unsafe partial struct FGpuQueue : FGpuQueue.Interface, INativeGuid + public partial struct FCmdBase { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuQueue)); + [NativeTypeName("Coplt::FCmdType")] + public FCmdType Type; + } - public void** lpVtbl; + [NativeTypeName("struct FCmdLabel : Coplt::FCmdBase")] + public partial struct FCmdLabel + { + public FCmdBase Base; - [NativeTypeName("Coplt::FFrameContext *")] - public FFrameContext* m_context; + [NativeTypeName("Coplt::u32")] + public uint StringLength; - [NativeTypeName("Coplt::u64")] - public ulong m_submit_id; + [NativeTypeName("Coplt::usize")] + public nuint StringIndex; - [NativeTypeName("Coplt::FGpuQueueType")] - public FGpuQueueType m_queue_type; + [NativeTypeName("Coplt::FStrType")] + public FStrType StrType; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuQueue*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("u8[3]")] + public _Color_e__FixedBuffer Color; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuQueue*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::b8")] + public B8 HasColor; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() + [InlineArray(3)] + public partial struct _Color_e__FixedBuffer { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuQueue*)Unsafe.AsPointer(ref this)); + public byte e0; } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuQueue*)Unsafe.AsPointer(ref this), id); - } + [NativeTypeName("struct FCmdBeginScope : Coplt::FCmdBase")] + public partial struct FCmdBeginScope + { + public FCmdBase Base; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuQueue*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::u32")] + public uint StringLength; - [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); - } + [NativeTypeName("Coplt::usize")] + public nuint StringIndex; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* GetRawQueue() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuQueue*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::FStrType")] + public FStrType StrType; - [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); - } + [NativeTypeName("u8[3]")] + public _Color_e__FixedBuffer Color; - [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); - } + [NativeTypeName("Coplt::b8")] + public B8 HasColor; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Submit([NativeTypeName("Coplt::FGpuExecutor *")] FGpuExecutor* Executor, [NativeTypeName("const FCommandSubmit *")] FCommandSubmit* submit) + [InlineArray(3)] + public partial struct _Color_e__FixedBuffer { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuQueue*)Unsafe.AsPointer(ref this), &result, Executor, submit); + public byte e0; } + } - [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); - } + [NativeTypeName("struct FCmdEndScope : Coplt::FCmdBase")] + public partial struct FCmdEndScope + { + public FCmdBase Base; + } - public interface Interface : FGpuObject.Interface - { - void* GetRawQueue(); + [NativeTypeName("struct FCmdPreparePresent : Coplt::FCmdBase")] + public partial struct FCmdPreparePresent + { + public FCmdBase Base; - [return: NativeTypeName("Coplt::FResult")] - FResult CreateOutputFromRawSwapchain([NativeTypeName("const FGpuOutputFromSwapChainCreateOptions &")] FGpuOutputFromSwapChainCreateOptions* options, void* swapchain, FGpuOutput** @out); + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Output; + } - [return: NativeTypeName("Coplt::FResult")] - FResult CreateOutputForHwnd([NativeTypeName("const FGpuOutputCreateOptions &")] FGpuOutputCreateOptions* options, void* hwnd, FGpuOutput** @out); + [NativeTypeName("struct FCmdClearColor : Coplt::FCmdBase")] + public partial struct FCmdClearColor + { + public FCmdBase Base; - [return: NativeTypeName("Coplt::FResult")] - FResult Submit([NativeTypeName("Coplt::FGpuExecutor *")] FGpuExecutor* Executor, [NativeTypeName("const FCommandSubmit *")] FCommandSubmit* submit); + [NativeTypeName("Coplt::u32")] + public uint RectCount; - [return: NativeTypeName("Coplt::FResult")] - FResult SubmitNoWait([NativeTypeName("Coplt::FGpuExecutor *")] FGpuExecutor* Executor, [NativeTypeName("const FCommandSubmit *")] FCommandSubmit* submit); - } - } + [NativeTypeName("Coplt::u32")] + public uint RectIndex; - [Guid("EDAB0989-E0C2-4B1E-826F-C73380088FC6")] - [NativeTypeName("struct FGpuExecutor : Coplt::FGpuObject")] - public unsafe partial struct FGpuExecutor : FGpuExecutor.Interface, INativeGuid - { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuExecutor)); + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Image; - public void** lpVtbl; + [NativeTypeName("f32[4]")] + public _Color_e__FixedBuffer Color; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() + [InlineArray(4)] + public partial struct _Color_e__FixedBuffer { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuExecutor*)Unsafe.AsPointer(ref this)); + public float e0; } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuExecutor*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("struct FCmdClearDepthStencil : Coplt::FCmdBase")] + public partial struct FCmdClearDepthStencil + { + public FCmdBase Base; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuExecutor*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::u32")] + public uint RectCount; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuExecutor*)Unsafe.AsPointer(ref this), id); - } + [NativeTypeName("Coplt::u32")] + public uint RectIndex; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuExecutor*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Image; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuExecutor*)Unsafe.AsPointer(ref this), &result, name); - } + [NativeTypeName("Coplt::f32")] + public float Depth; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Wait() - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuExecutor*)Unsafe.AsPointer(ref this), &result); - } + [NativeTypeName("Coplt::u8")] + public byte Stencil; - public interface Interface : FGpuObject.Interface - { - [return: NativeTypeName("Coplt::FResult")] - FResult Wait(); - } + [NativeTypeName("Coplt::FDepthStencilClearFlags")] + public FDepthStencilClearFlags Clear; } - [NativeTypeName("Coplt::u8")] - public enum ResourceType : byte + [NativeTypeName("struct FCmdBufferCopy : Coplt::FCmdBase")] + public partial struct FCmdBufferCopy { - Unknown = 0, - Buffer = 1, - Image = 2, + 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("Coplt::u8")] - public enum FResourceViewType : byte + [NativeTypeName("struct FCmdBufferImageCopy : Coplt::FCmdBase")] + public partial struct FCmdBufferImageCopy { - None = 0, - ConstantBuffer, - ShaderResource, - UnorderedAccess, - RenderTarget, - DepthStencil, - IndexBuffer, - VertexBuffer, - StreamOutput, + 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("Coplt::u32")] - public enum FResourcePurpose : uint + [NativeTypeName("struct FCmdRender : Coplt::FCmdBase")] + public partial struct FCmdRender { - 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 FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint InfoIndex; + + [NativeTypeName("Coplt::u32")] + public uint CommandCount; } - [NativeTypeName("Coplt::u8")] - public enum FCpuAccess : byte + [NativeTypeName("struct FCmdCompute : Coplt::FCmdBase")] + public partial struct FCmdCompute { - None = 0, - Write = 1, - Read = 2, + public FCmdBase Base; + + [NativeTypeName("Coplt::u32")] + public uint CommandCount; } - [NativeTypeName("Coplt::u8")] - public enum FBufferUsage : byte + [NativeTypeName("struct FCmdSetPipeline : Coplt::FCmdBase")] + public unsafe partial struct FCmdSetPipeline { - Undefined, - Structured, - Raw, + public FCmdBase Base; + + [NativeTypeName("Coplt::FShaderPipeline *")] + public FShaderPipeline* Pipeline; } - public partial struct FGpuViewCreateOptions + public unsafe partial struct FCmdBinding { - [NativeTypeName("Coplt::FStr8or16")] - public FStr8or16 Name; - - [NativeTypeName("Coplt::FResourcePurpose")] - public FResourcePurpose Purpose; + [NativeTypeName("Coplt::FShaderBinding *")] + public FShaderBinding* Binding; } - public partial struct FGpuViewableData + public partial struct FBindingChange { - [NativeTypeName("Coplt::FResourcePurpose")] - public FResourcePurpose m_purpose; + [NativeTypeName("Coplt::u32")] + public uint Binding; } - [Guid("B3AEB8A5-1FA6-4866-97EF-1A5FA401E18F")] - [NativeTypeName("struct FGpuViewable : Coplt::FGpuObject")] - public unsafe partial struct FGpuViewable : FGpuViewable.Interface, INativeGuid + [NativeTypeName("struct FCmdSetBinding : Coplt::FCmdBase")] + public partial struct FCmdSetBinding { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuViewable)); + public FCmdBase Base; - public void** lpVtbl; + [NativeTypeName("Coplt::u32")] + public uint Binding; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuViewable*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuViewable*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuViewable*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::u32")] + public uint Index; + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuViewable*)Unsafe.AsPointer(ref this), id); - } + [NativeTypeName("struct FCmdSetViewportScissor : Coplt::FCmdBase")] + public partial struct FCmdSetViewportScissor + { + public FCmdBase Base; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuViewable*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::u32")] + public uint ViewportCount; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuViewable*)Unsafe.AsPointer(ref this), &result, name); - } + [NativeTypeName("Coplt::u32")] + public uint ViewportIndex; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuViewableData *")] - public FGpuViewableData* GpuViewableData() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuViewable*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::u32")] + public uint ScissorRectCount; - public interface Interface : FGpuObject.Interface - { - [return: NativeTypeName("Coplt::FGpuViewableData *")] - FGpuViewableData* GpuViewableData(); - } + [NativeTypeName("Coplt::u32")] + public uint ScissorRectIndex; } - [NativeTypeName("struct FGpuResourceCreateOptions : Coplt::FGpuViewCreateOptions")] - public partial struct FGpuResourceCreateOptions + public partial struct FBufferRange2 { - public FGpuViewCreateOptions Base; + [NativeTypeName("Coplt::FCmdResRef")] + public FCmdResRef Buffer; - [NativeTypeName("Coplt::FCpuAccess")] - public FCpuAccess CpuAccess; + [NativeTypeName("Coplt::u32")] + public uint Offset; + + [NativeTypeName("Coplt::u32")] + public uint Size; } - [NativeTypeName("struct FGpuResourceData : Coplt::FGpuViewableData")] - public partial struct FGpuResourceData + [NativeTypeName("struct FVertexBufferRange2 : Coplt::FBufferRange2")] + public partial struct FVertexBufferRange2 { - public FGpuViewableData Base; - - [NativeTypeName("Coplt::FResState")] - public FResState m_state; + public FBufferRange2 Base; - [NativeTypeName("Coplt::FCpuAccess")] - public FCpuAccess m_cpu_access; + [NativeTypeName("Coplt::u32")] + public uint Index; } - [Guid("F99DCEEC-2F0C-4A28-B666-BEB7C35219D6")] - [NativeTypeName("struct FGpuResource : Coplt::FGpuViewable")] - public unsafe partial struct FGpuResource : FGpuResource.Interface, INativeGuid + public unsafe partial struct FMeshBuffers2 { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuResource)); - - public void** lpVtbl; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() - { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuResource*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuResource*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuResource*)Unsafe.AsPointer(ref this)); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuResource*)Unsafe.AsPointer(ref this), id); - } + [NativeTypeName("Coplt::FMeshLayout *")] + public FMeshLayout* MeshLayout; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuResource*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::FBufferRange2")] + public FBufferRange2 IndexBuffer; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) - { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuResource*)Unsafe.AsPointer(ref this), &result, name); - } + [NativeTypeName("Coplt::u32")] + public uint VertexBufferCount; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuViewableData *")] - public FGpuViewableData* GpuViewableData() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuResource*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::u32")] + public uint VertexBuffersIndex; + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuResourceData *")] - public FGpuResourceData* GpuResourceData() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuResource*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("struct FCmdSetMeshBuffers : Coplt::FCmdBase")] + public partial struct FCmdSetMeshBuffers + { + public FCmdBase Base; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::ResourceType")] - public ResourceType GetResourceType() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuResource*)Unsafe.AsPointer(ref this)); - } + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat IndexFormat; - public interface Interface : FGpuViewable.Interface - { - [return: NativeTypeName("Coplt::FGpuResourceData *")] - FGpuResourceData* GpuResourceData(); + [NativeTypeName("Coplt::u32")] + public uint VertexStartSlot; - [return: NativeTypeName("Coplt::ResourceType")] - ResourceType GetResourceType(); - } + [NativeTypeName("Coplt::u32")] + public uint PayloadIndex; } - [NativeTypeName("struct FGpuBufferCreateOptions : Coplt::FGpuResourceCreateOptions")] - public partial struct FGpuBufferCreateOptions + [NativeTypeName("struct FCmdDraw : Coplt::FCmdBase")] + public partial struct FCmdDraw { - public FGpuResourceCreateOptions Base; + public FCmdBase Base; - [NativeTypeName("Coplt::u64")] - public ulong Size; + [NativeTypeName("Coplt::u32")] + public uint VertexOrIndexCount; [NativeTypeName("Coplt::u32")] - public uint Count; + public uint InstanceCount; [NativeTypeName("Coplt::u32")] - public uint Stride; + public uint FirstVertexOrIndex; - [NativeTypeName("Coplt::FBufferUsage")] - public FBufferUsage Usage; + [NativeTypeName("Coplt::u32")] + public uint FirstInstance; + + [NativeTypeName("Coplt::u32")] + public uint VertexOffset; + + [NativeTypeName("Coplt::b8")] + public B8 Indexed; } - [NativeTypeName("struct FGpuBufferData : Coplt::FGpuResourceData")] - public partial struct FGpuBufferData + [NativeTypeName("struct FCmdDispatch : Coplt::FCmdBase")] + public partial struct FCmdDispatch { - public FGpuResourceData Base; + public FCmdBase Base; - [NativeTypeName("Coplt::u64")] - public ulong m_size; + [NativeTypeName("Coplt::u32")] + public uint GroupCountX; [NativeTypeName("Coplt::u32")] - public uint m_count; + public uint GroupCountY; [NativeTypeName("Coplt::u32")] - public uint m_stride; + public uint GroupCountZ; - [NativeTypeName("Coplt::FBufferUsage")] - public FBufferUsage m_usage; + [NativeTypeName("Coplt::FDispatchType")] + public FDispatchType Type; } - [Guid("283740E3-FE96-41D0-830A-0A4C6A725336")] - [NativeTypeName("struct FGpuBuffer : Coplt::FGpuResource")] - public unsafe partial struct FGpuBuffer : FGpuBuffer.Interface, INativeGuid + public partial struct FCmdItem { - static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuBuffer)); - - public void** lpVtbl; + [NativeTypeName("__AnonymousRecord_Cmd_L360_C9")] + public _Anonymous_e__Union Anonymous; - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Dispose() + [UnscopedRef] + public ref FCmdType Type { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Type; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint Release() + [UnscopedRef] + public ref FCmdLabel Label { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Label; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("size_t")] - public nuint AddRef() + [UnscopedRef] + public ref FCmdBeginScope BeginScope { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.BeginScope; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + [UnscopedRef] + public ref FCmdEndScope EndScope { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuBuffer*)Unsafe.AsPointer(ref this), id); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.EndScope; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::u64")] - public ulong ObjectId() + [UnscopedRef] + public ref FCmdPreparePresent PreparePresent { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.PreparePresent; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + [UnscopedRef] + public ref FCmdClearColor ClearColor { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, name); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.ClearColor; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuViewableData *")] - public FGpuViewableData* GpuViewableData() + [UnscopedRef] + public ref FCmdClearDepthStencil ClearDepthStencil { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.ClearDepthStencil; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuResourceData *")] - public FGpuResourceData* GpuResourceData() + [UnscopedRef] + public ref FCmdBufferCopy BufferCopy { - 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)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.BufferCopy; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuBufferData *")] - public FGpuBufferData* GpuBufferData() + [UnscopedRef] + public ref FCmdBufferImageCopy BufferImageCopy { - return ((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.BufferImageCopy; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Map(void** ptr, [NativeTypeName("Coplt::b8")] B8 Discard) + [UnscopedRef] + public ref FCmdRender Render { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, ptr, Discard); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Render; + } } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Unmap([NativeTypeName("Coplt::b8")] B8 Discard) + [UnscopedRef] + public ref FCmdCompute Compute { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, Discard); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Compute; + } } - public interface Interface : FGpuResource.Interface + [UnscopedRef] + public ref FCmdSetPipeline SetPipeline { - [return: NativeTypeName("Coplt::FGpuBufferData *")] - FGpuBufferData* GpuBufferData(); - - [return: NativeTypeName("Coplt::FResult")] - FResult Map(void** ptr, [NativeTypeName("Coplt::b8")] B8 Discard); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.SetPipeline; + } + } - [return: NativeTypeName("Coplt::FResult")] - FResult Unmap([NativeTypeName("Coplt::b8")] B8 Discard); + [UnscopedRef] + public ref FCmdSetBinding SetBinding + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.SetBinding; + } } - } - public partial struct FOptimizedClearColor - { - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat Format; + [UnscopedRef] + public ref FCmdSetViewportScissor SetViewportScissor + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.SetViewportScissor; + } + } - [NativeTypeName("__AnonymousRecord_Resource_L175_C9")] - public _Anonymous_e__Union Anonymous; + [UnscopedRef] + public ref FCmdSetMeshBuffers SetMeshBuffers + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.SetMeshBuffers; + } + } [UnscopedRef] - public Span Color + public ref FCmdDraw Draw { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return Anonymous.Color; + return ref Anonymous.Draw; } } [UnscopedRef] - public ref float Depth + public ref FCmdDispatch Dispatch { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return ref Anonymous.Anonymous.Depth; + return ref Anonymous.Dispatch; } } [UnscopedRef] - public ref byte Stencil + public Span _pad { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return ref Anonymous.Anonymous.Stencil; + return Anonymous._pad; } } @@ -2379,156 +2522,174 @@ public ref byte Stencil public partial struct _Anonymous_e__Union { [FieldOffset(0)] - [NativeTypeName("f32[4]")] - public _Color_e__FixedBuffer Color; + [NativeTypeName("Coplt::FCmdType")] + public FCmdType Type; [FieldOffset(0)] - [NativeTypeName("__AnonymousRecord_Resource_L179_C13")] - public _Anonymous_e__Struct Anonymous; + [NativeTypeName("Coplt::FCmdLabel")] + public FCmdLabel Label; - public partial struct _Anonymous_e__Struct - { - [NativeTypeName("Coplt::f32")] - public float Depth; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdBeginScope")] + public FCmdBeginScope BeginScope; - [NativeTypeName("Coplt::u8")] - public byte Stencil; - } + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdEndScope")] + public FCmdEndScope EndScope; - [InlineArray(4)] - public partial struct _Color_e__FixedBuffer - { - public float e0; - } - } - } + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdPreparePresent")] + public FCmdPreparePresent PreparePresent; - [NativeTypeName("Coplt::u8")] - public enum FImageDimension : byte - { - One, - Two, - Three, - Cube, - } + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdClearColor")] + public FCmdClearColor ClearColor; - [NativeTypeName("Coplt::u8")] - public enum FImageLayout : byte - { - Undefined, - RowMajor, - Undefined64kSwizzle, - Standard64kSwizzle, - } + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdClearDepthStencil")] + public FCmdClearDepthStencil ClearDepthStencil; - [NativeTypeName("struct FGpuImageCreateOptions : Coplt::FGpuResourceCreateOptions")] - public partial struct FGpuImageCreateOptions - { - public FGpuResourceCreateOptions Base; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdBufferCopy")] + public FCmdBufferCopy BufferCopy; - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat Format; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdBufferImageCopy")] + public FCmdBufferImageCopy BufferImageCopy; - [NativeTypeName("Coplt::u32")] - public uint Width; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdRender")] + public FCmdRender Render; - [NativeTypeName("Coplt::u32")] - public uint Height; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdCompute")] + public FCmdCompute Compute; - [NativeTypeName("Coplt::u32")] - public uint DepthOrLength; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdSetPipeline")] + public FCmdSetPipeline SetPipeline; - [NativeTypeName("Coplt::u16")] - public ushort MipLevels; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdSetBinding")] + public FCmdSetBinding SetBinding; - [NativeTypeName("Coplt::FOptimizedClearColor")] - public FOptimizedClearColor OptimizedClearValue; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdSetViewportScissor")] + public FCmdSetViewportScissor SetViewportScissor; - [NativeTypeName("Coplt::b8")] - public B8 HasOptimizedClearValue; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdSetMeshBuffers")] + public FCmdSetMeshBuffers SetMeshBuffers; - [NativeTypeName("Coplt::u8")] - public byte MultisampleCount; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdDraw")] + public FCmdDraw Draw; - [NativeTypeName("Coplt::FImageDimension")] - public FImageDimension Dimension; + [FieldOffset(0)] + [NativeTypeName("Coplt::FCmdDispatch")] + public FCmdDispatch Dispatch; - [NativeTypeName("Coplt::FImageLayout")] - public FImageLayout Layout; + [FieldOffset(0)] + [NativeTypeName("u8[32]")] + public __pad_e__FixedBuffer _pad; + + [InlineArray(32)] + public partial struct __pad_e__FixedBuffer + { + public byte e0; + } + } } - [NativeTypeName("struct FGpuImageData : Coplt::FGpuResourceData")] - public partial struct FGpuImageData + [NativeTypeName("Coplt::u8")] + public enum FShaderStage : byte { - public FGpuResourceData Base; + Compute = 0, + Pixel = 1, + Vertex = 2, + Mesh = 3, + Task = 4, + } - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat m_format; + [NativeTypeName("Coplt::u32")] + public enum FShaderStageFlags : uint + { + None = 0, + Compute = 1 << 0, + Pixel = 1 << 1, + Vertex = 1 << 2, + Mesh = 1 << 3, + Task = 1 << 4, + } - [NativeTypeName("Coplt::u32")] - public uint m_width; + public unsafe partial struct FShaderModuleCreateOptions + { + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; - [NativeTypeName("Coplt::u32")] - public uint m_height; + [NativeTypeName("Coplt::FString8 *")] + public FString8* EntryPoint; - [NativeTypeName("Coplt::u32")] - public uint m_depth_or_length; + public void* Data; - [NativeTypeName("Coplt::u16")] - public ushort m_mip_levels; + [NativeTypeName("Coplt::usize")] + public nuint Size; - [NativeTypeName("Coplt::u8")] - public byte m_multisample_count; + [NativeTypeName("Coplt::FShaderStage")] + public FShaderStage Stage; + } - [NativeTypeName("Coplt::u8")] - public byte m_planes; + public unsafe partial struct FShaderModuleData + { + [NativeTypeName("Coplt::u8 *")] + public byte* Data; - [NativeTypeName("Coplt::FImageDimension")] - public FImageDimension m_dimension; + [NativeTypeName("Coplt::usize")] + public nuint Size; - [NativeTypeName("Coplt::FImageLayout")] - public FImageLayout m_layout; + [NativeTypeName("Coplt::FShaderStage")] + public FShaderStage Stage; } - [Guid("667EFA36-21C7-4561-ABAD-85780FA4929E")] - [NativeTypeName("struct FGpuImage : Coplt::FGpuResource")] - public unsafe partial struct FGpuImage : FGpuImage.Interface, INativeGuid + [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_FGpuImage)); + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShaderModule)); public void** lpVtbl; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuImage*)Unsafe.AsPointer(ref this)); + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShaderModule*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("size_t")] public nuint Release() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuImage*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FShaderModule*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("size_t")] public nuint AddRef() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuImage*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FShaderModule*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) { - return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuImage*)Unsafe.AsPointer(ref this), id); + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FShaderModule*)Unsafe.AsPointer(ref this), id); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NativeTypeName("Coplt::u64")] public ulong ObjectId() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuImage*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FShaderModule*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2536,301 +2697,241 @@ public ulong ObjectId() public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) { FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuImage*)Unsafe.AsPointer(ref this), &result, name); + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderModule*)Unsafe.AsPointer(ref this), &result, name); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuViewableData *")] - public FGpuViewableData* GpuViewableData() + [return: NativeTypeName("Coplt::FShaderModuleData *")] + public FShaderModuleData* ShaderModuleData() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuImage*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderModule*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuResourceData *")] - public FGpuResourceData* GpuResourceData() + [return: NativeTypeName("Coplt::FString8 *")] + public FString8* GetEntryPoint() { - return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuImage*)Unsafe.AsPointer(ref this)); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FShaderModule*)Unsafe.AsPointer(ref this)); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::ResourceType")] - public ResourceType GetResourceType() + public interface Interface : FGpuObject.Interface { - return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuImage*)Unsafe.AsPointer(ref this)); + [return: NativeTypeName("Coplt::FShaderModuleData *")] + FShaderModuleData* ShaderModuleData(); + + [return: NativeTypeName("Coplt::FString8 *")] + FString8* GetEntryPoint(); } + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FGpuImageData *")] - public FGpuImageData* GpuImageData() - { - return ((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuImage*)Unsafe.AsPointer(ref this)); - } + public unsafe partial struct FShaderModuleCreateResult + { + [NativeTypeName("Coplt::FShaderModule *")] + public FShaderModule* ShaderModule; - public interface Interface : FGpuResource.Interface - { - [return: NativeTypeName("Coplt::FGpuImageData *")] - FGpuImageData* GpuImageData(); - } + [NativeTypeName("Coplt::FShaderModuleData *")] + public FShaderModuleData* Data; } - [NativeTypeName("Coplt::u8")] - public enum FViewType : byte + public partial struct FShaderLayout { - None, - Buffer, - Image, - Sampler, } - public unsafe partial struct FView + [Guid("552A498E-8F3A-47FF-A335-7AF2DE0901E8")] + [NativeTypeName("struct FShaderLayout : Coplt::FGpuObject")] + public unsafe partial struct FShaderLayout : FShaderLayout.Interface, INativeGuid { - [NativeTypeName("__AnonymousRecord_Resource_L268_C9")] - public _Anonymous_e__Union Anonymous; + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShaderLayout)); - [NativeTypeName("Coplt::FViewType")] - public FViewType Type; + public void** lpVtbl; - [UnscopedRef] - public ref FGpuBuffer* Buffer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Buffer; - } + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShaderLayout*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FGpuImage* Image + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Image; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FShaderLayout*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FGpuSampler* Sampler + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Sampler; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FShaderLayout*)Unsafe.AsPointer(ref this)); } - [StructLayout(LayoutKind.Explicit)] - public unsafe partial struct _Anonymous_e__Union + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) { - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuBuffer *")] - public FGpuBuffer* Buffer; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuImage *")] - public FGpuImage* Image; + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FShaderLayout*)Unsafe.AsPointer(ref this), id); + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuSampler *")] - public FGpuSampler* Sampler; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FShaderLayout*)Unsafe.AsPointer(ref this)); } - } - [NativeTypeName("Coplt::u8")] - public enum FPresentMode : byte - { - NoBuffer, - DoubleBuffer, - TripleBuffer, - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderLayout*)Unsafe.AsPointer(ref this), &result, name); + } - [NativeTypeName("Coplt::u8")] - public enum FOutputAlphaMode : byte - { - Opaque, - PrePremultiplied, - PostPremultiplied, - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderLayoutData *")] + public FShaderLayoutData* ShaderLayoutData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderLayout*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::u8")] - public enum FHdrType : byte - { - None, - UNorm10, - Float16, + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FShaderLayoutData *")] + FShaderLayoutData* ShaderLayoutData(); + } } - public partial struct FGpuOutputFormatSelector + public partial struct FShaderInputLayout { - [NativeTypeName("Coplt::b8")] - public B8 Specify; - - [NativeTypeName("Coplt::b8")] - public B8 Srgb; - - [NativeTypeName("Coplt::FHdrType")] - public FHdrType Hdr; } - public partial struct FGpuOutputFromSwapChainCreateOptions + [Guid("70229C9A-FB3D-46B4-B534-72FDB167D807")] + [NativeTypeName("struct FShaderInputLayout : Coplt::FGpuObject")] + public unsafe partial struct FShaderInputLayout : FShaderInputLayout.Interface, INativeGuid { - [NativeTypeName("Coplt::b8")] - public B8 VSync; - } + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShaderInputLayout)); - public partial struct FGpuOutputCreateOptions - { - [NativeTypeName("Coplt::FStr8or16")] - public FStr8or16 Name; + public void** lpVtbl; - [NativeTypeName("Coplt::u32")] - public uint Width; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShaderInputLayout*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::u32")] - public uint Height; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FShaderInputLayout*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat Format; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FShaderInputLayout*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::FPresentMode")] - public FPresentMode PresentMode; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FShaderInputLayout*)Unsafe.AsPointer(ref this), id); + } - [NativeTypeName("Coplt::FOutputAlphaMode")] - public FOutputAlphaMode AlphaMode; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FShaderInputLayout*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::b8")] - public B8 VSync; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FShaderInputLayout*)Unsafe.AsPointer(ref this), &result, name); + } - [NativeTypeName("Coplt::FGpuOutputFormatSelector")] - public FGpuOutputFormatSelector FormatSelector; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("const FShaderInputLayoutElement *")] + public FShaderInputLayoutElement* GetElements([NativeTypeName("Coplt::u32 *")] uint* out_count) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderInputLayout*)Unsafe.AsPointer(ref this), out_count); + } - public partial struct FCommandSubmit - { + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("const FShaderInputLayoutElement *")] + FShaderInputLayoutElement* GetElements([NativeTypeName("Coplt::u32 *")] uint* out_count); + } } - public unsafe partial struct FCommandSubmit + public unsafe partial struct FShaderCreateOptions { - [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::FStr8or16")] + public FStr8or16 Name; - [NativeTypeName("Coplt::u32")] - public uint CommandCount; + [NativeTypeName("Coplt::FShaderLayout *")] + public FShaderLayout* Layout; - [NativeTypeName("Coplt::u32")] - public uint ResourceCount; + [NativeTypeName("Coplt::FShaderInputLayout *")] + public FShaderInputLayout* InputLayout; - [NativeTypeName("Coplt::u32")] - public uint SyncBindingCount; + public FShaderModule** Modules; - [NativeTypeName("Coplt::u32")] - public uint GrowingResourceBindingCapacity; + [NativeTypeName("Coplt::u8")] + public byte Count; + } - [NativeTypeName("Coplt::u32")] - public uint GrowingSamplerBindingCapacity; + public partial struct FShaderData + { + [NativeTypeName("Coplt::FShaderStageFlags")] + public FShaderStageFlags Stages; } - [Guid("F1C59CB4-7EE6-4EE2-80F4-07CC568920D2")] - [NativeTypeName("struct FGpuOutput : Coplt::FGpuExecutor")] - public unsafe partial struct FGpuOutput : FGpuOutput.Interface, INativeGuid + [Guid("DE1352D5-023D-42B0-BEAC-122B3B296C9C")] + [NativeTypeName("struct FShader : Coplt::FGpuObject")] + public unsafe partial struct FShader : FShader.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_FShader)); 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; + [NativeTypeName("const u32")] + public const uint MaxShaderModuleCount = 3; [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { - ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuOutput*)Unsafe.AsPointer(ref this)); + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShader*)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]))((FShader*)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]))((FShader*)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]))((FShader*)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]))((FShader*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2838,1774 +2939,1651 @@ 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]))((FShader*)Unsafe.AsPointer(ref this), &result, name); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult Wait() + [return: NativeTypeName("Coplt::FShaderData *")] + public FShaderData* ShaderData() { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuOutput*)Unsafe.AsPointer(ref this), &result); + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShader*)Unsafe.AsPointer(ref this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - [return: NativeTypeName("Coplt::FResult")] - public FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable) + [return: NativeTypeName("Coplt::FShaderLayout *")] + public FShaderLayout* Layout() { - FResult result; - return *((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuOutput*)Unsafe.AsPointer(ref this), &result, Enable); + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FShader*)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]))((FGpuOutput*)Unsafe.AsPointer(ref this), &result, Width, Height); + [return: NativeTypeName("Coplt::FShaderInputLayout *")] + public FShaderInputLayout* InputLayout() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FShader*)Unsafe.AsPointer(ref this)); } - public interface Interface : FGpuExecutor.Interface + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderModule *")] + public FShaderModule* Compute() { - [return: NativeTypeName("Coplt::FResult")] - FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable); - - [return: NativeTypeName("Coplt::FResult")] - FResult Resize([NativeTypeName("Coplt::u32")] uint Width, [NativeTypeName("Coplt::u32")] uint Height); + return ((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FShader*)Unsafe.AsPointer(ref this)); } - } - [NativeTypeName("Coplt::u8")] - public enum FImagePlane : byte - { - All = 0, - Depth = 0, - Stencil = 1, - Y = 0, - CbCr = 1, - } - - public enum FGraphicsFormat - { - Unknown = 0, - R32G32B32A32_TypeLess = 1, - R32G32B32A32_Float = 2, - R32G32B32A32_UInt = 3, - R32G32B32A32_SInt = 4, - R32G32B32_TypeLess = 5, - R32G32B32_Float = 6, - R32G32B32_UInt = 7, - R32G32B32_SInt = 8, - R16G16B16A16_TypeLess = 9, - R16G16B16A16_Float = 10, - R16G16B16A16_UNorm = 11, - R16G16B16A16_UInt = 12, - R16G16B16A16_SNorm = 13, - R16G16B16A16_SInt = 14, - R32G32_TypeLess = 15, - R32G32_Float = 16, - R32G32_UInt = 17, - R32G32_SInt = 18, - R32G8X24_TypeLess = 19, - D32_Float_S8X24_UInt = 20, - R32_Float_X8X24_TypeLess = 21, - X32_TypeLess_G8X24_Float = 22, - R10G10B10A2_TypeLess = 23, - R10G10B10A2_UNorm = 24, - R10G10B10A2_UInt = 25, - R11G11B10_Float = 26, - R8G8B8A8_TypeLess = 27, - R8G8B8A8_UNorm = 28, - R8G8B8A8_UNorm_sRGB = 29, - R8G8B8A8_UInt = 30, - R8G8B8A8_SNorm = 31, - R8G8B8A8_SInt = 32, - R16G16_TypeLess = 33, - R16G16_Float = 34, - R16G16_UNorm = 35, - R16G16_UInt = 36, - R16G16_SNorm = 37, - R16G16_SInt = 38, - R32_TypeLess = 39, - D32_Float = 40, - R32_Float = 41, - R32_UInt = 42, - R32_SInt = 43, - R24G8_TypeLess = 44, - D24_UNorm_S8_UInt = 45, - R24_UNorm_X8_TypeLess = 46, - X24_TypeLess_G8_UInt = 47, - R8G8_TypeLess = 48, - R8G8_UNorm = 49, - R8G8_UInt = 50, - R8G8_SNorm = 51, - R8G8_SInt = 52, - R16_TypeLess = 53, - R16_Float = 54, - D16_UNorm = 55, - R16_UNorm = 56, - R16_UInt = 57, - R16_SNorm = 58, - R16_SInt = 59, - R8_TypeLess = 60, - R8_UNorm = 61, - R8_UInt = 62, - R8_SNorm = 63, - R8_SInt = 64, - A8_UNorm = 65, - R1_UNorm = 66, - R9G9B9E5_SharedExp = 67, - R8G8_B8G8_UNorm = 68, - G8R8_G8B8_UNorm = 69, - BC1_TypeLess = 70, - BC1_UNorm = 71, - BC1_UNorm_sRGB = 72, - BC2_TypeLess = 73, - BC2_UNorm = 74, - BC2_UNorm_sRGB = 75, - BC3_TypeLess = 76, - BC3_UNorm = 77, - BC3_UNorm_sRGB = 78, - BC4_TypeLess = 79, - BC4_UNorm = 80, - BC4_SNorm = 81, - BC5_TypeLess = 82, - BC5_UNorm = 83, - BC5_SNorm = 84, - B5G6R5_UNorm = 85, - B5G5R5A1_UNorm = 86, - B8G8R8A8_UNorm = 87, - B8G8R8X8_UNorm = 88, - R10G10B10_XR_Bias_A2_UNorm = 89, - B8G8R8A8_TypeLess = 90, - B8G8R8A8_UNorm_sRGB = 91, - B8G8R8X8_TypeLess = 92, - B8G8R8X8_UNorm_sRGB = 93, - BC6H_TypeLess = 94, - BC6H_UF16 = 95, - 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_L64_C9")] - public _Anonymous_e__Union Anonymous; - - [NativeTypeName("Coplt::FResourceRefType")] - public FResourceRefType Type; - - [UnscopedRef] - public ref FGpuOutput* Output + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderModule *")] + public FShaderModule* Pixel() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Output; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FShader*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FGpuBuffer* Buffer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderModule *")] + public FShaderModule* Vertex() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Buffer; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FShader*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FGpuImage* Image + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderModule *")] + public FShaderModule* Mesh() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Image; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FShader*)Unsafe.AsPointer(ref this)); } - [StructLayout(LayoutKind.Explicit)] - public unsafe partial struct _Anonymous_e__Union + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderModule *")] + public FShaderModule* Task() { - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuOutput *")] - public FGpuOutput* Output; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuBuffer *")] - public FGpuBuffer* Buffer; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FGpuImage *")] - public FGpuImage* Image; + return ((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FShader*)Unsafe.AsPointer(ref this)); } - } - public partial struct FResourceRef - { - [NativeTypeName("Coplt::u32")] - public uint ResourceIndex; - } + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FShaderData *")] + FShaderData* ShaderData(); - public partial struct FSubResourceRange - { - [NativeTypeName("Coplt::u32")] - public uint IndexOrFirstMipLevel; + [return: NativeTypeName("Coplt::FShaderLayout *")] + FShaderLayout* Layout(); - [NativeTypeName("Coplt::u32")] - public uint NumMipLevels; + [return: NativeTypeName("Coplt::FShaderInputLayout *")] + FShaderInputLayout* InputLayout(); - [NativeTypeName("Coplt::u32")] - public uint FirstArraySlice; + [return: NativeTypeName("Coplt::FShaderModule *")] + FShaderModule* Compute(); - [NativeTypeName("Coplt::u32")] - public uint NumArraySlices; + [return: NativeTypeName("Coplt::FShaderModule *")] + FShaderModule* Pixel(); - [NativeTypeName("Coplt::u32")] - public uint FirstPlane; + [return: NativeTypeName("Coplt::FShaderModule *")] + FShaderModule* Vertex(); - [NativeTypeName("Coplt::u32")] - public uint NumPlanes; - } + [return: NativeTypeName("Coplt::FShaderModule *")] + FShaderModule* Mesh(); - [NativeTypeName("Coplt::u32")] - public enum FImageBarrierFlags : uint - { - None, - Discard = 1 << 0, - CrossQueue = 1 << 1, + [return: NativeTypeName("Coplt::FShaderModule *")] + FShaderModule* Task(); + } } - public partial struct FImageBarrier + public unsafe partial struct FShaderCreateResult { - [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::FShader *")] + public FShader* Shader; - [NativeTypeName("Coplt::FImageBarrierFlags")] - public FImageBarrierFlags Flags; + [NativeTypeName("Coplt::FShaderData *")] + public FShaderData* Data; } - public partial struct FBufferBarrier + public partial struct FSetBindItem { - [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::FView")] + public FView View; - [NativeTypeName("Coplt::u64")] - public ulong Offset; + [NativeTypeName("Coplt::u32")] + public uint Slot; - [NativeTypeName("Coplt::u64")] - public ulong Size; + [NativeTypeName("Coplt::u32")] + public uint Index; } - public partial struct FGlobalBarrier + public unsafe partial struct FShaderBindGroupCreateOptions { - [NativeTypeName("Coplt::FResAccess")] - public FResAccess AccessBefore; + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; - [NativeTypeName("Coplt::FResAccess")] - public FResAccess AccessAfter; + [NativeTypeName("Coplt::FBindGroupLayout *")] + public FBindGroupLayout* Layout; - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags StagesBefore; + [NativeTypeName("Coplt::FSetBindItem *")] + public FSetBindItem* Bindings; - [NativeTypeName("Coplt::FShaderStageFlags")] - public FShaderStageFlags StagesAfter; + [NativeTypeName("Coplt::u32")] + public uint NumBindings; } - [NativeTypeName("Coplt::u8")] - public enum FBarrierType : byte + public partial struct FShaderBindGroupData { - None, - Global, - Buffer, - Image, + [NativeTypeName("Coplt::u32")] + public uint CountSlots; } - public partial struct FBarrier + [Guid("AE54EFE5-C372-4291-B995-55298758D2B2")] + [NativeTypeName("struct FShaderBindGroup : Coplt::FGpuObject")] + public unsafe partial struct FShaderBindGroup : FShaderBindGroup.Interface, INativeGuid { - [NativeTypeName("Coplt::FBarrierType")] - public FBarrierType Type; + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShaderBindGroup)); - [NativeTypeName("__AnonymousRecord_Command_L170_C9")] - public _Anonymous_e__Union Anonymous; + public void** lpVtbl; - [UnscopedRef] - public ref FGlobalBarrier Global + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Global; - } + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShaderBindGroup*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FBufferBarrier Buffer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Buffer; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FShaderBindGroup*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FImageBarrier Image + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Image; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FShaderBindGroup*)Unsafe.AsPointer(ref this)); } - [StructLayout(LayoutKind.Explicit)] - public partial struct _Anonymous_e__Union + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) { - [FieldOffset(0)] - [NativeTypeName("Coplt::FGlobalBarrier")] - public FGlobalBarrier Global; + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FShaderBindGroup*)Unsafe.AsPointer(ref this), id); + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FBufferBarrier")] - public FBufferBarrier Buffer; + [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); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FShaderBindGroupData *")] + public FShaderBindGroupData* ShaderBindGroupData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FShaderBindGroup*)Unsafe.AsPointer(ref this)); + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FImageBarrier")] - public FImageBarrier Image; + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FShaderBindGroupData *")] + FShaderBindGroupData* ShaderBindGroupData(); } } - public partial struct FRect + public unsafe partial struct FShaderBindGroupCreateResult { - [NativeTypeName("Coplt::u32")] - public uint Left; + [NativeTypeName("Coplt::FShaderBindGroup *")] + public FShaderBindGroup* BindGroup; - [NativeTypeName("Coplt::u32")] - public uint Top; + [NativeTypeName("Coplt::FShaderBindGroupData *")] + public FShaderBindGroupData* Data; + } - [NativeTypeName("Coplt::u32")] - public uint Right; + public unsafe partial struct FSetBindGroupItem + { + [NativeTypeName("Coplt::FShaderBindGroup *")] + public FShaderBindGroup* BindGroup; [NativeTypeName("Coplt::u32")] - public uint Bottom; + public uint Index; } - public partial struct FViewport + public unsafe partial struct FShaderBindingCreateOptions { - [NativeTypeName("Coplt::f32")] - public float X; - - [NativeTypeName("Coplt::f32")] - public float Y; - - [NativeTypeName("Coplt::f32")] - public float Width; + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; - [NativeTypeName("Coplt::f32")] - public float Height; + [NativeTypeName("Coplt::FBindingLayout *")] + public FBindingLayout* Layout; - [NativeTypeName("Coplt::f32")] - public float MinDepth; + [NativeTypeName("Coplt::FSetBindGroupItem *")] + public FSetBindGroupItem* BindGroups; - [NativeTypeName("Coplt::f32")] - public float MaxDepth; + [NativeTypeName("Coplt::u32")] + public uint NumBindGroups; } - [NativeTypeName("Coplt::u8")] - public enum FDepthStencilClearFlags : byte + public partial struct FShaderBindingData { - None = 0, - Depth = 1, - Stencil = 2, } - public partial struct FUploadLoc + [Guid("A3CA644A-0E02-4D25-9A18-8835D66600F7")] + [NativeTypeName("struct FShaderBinding : Coplt::FGpuObject")] + public unsafe partial struct FShaderBinding : FShaderBinding.Interface, INativeGuid { - [NativeTypeName("Coplt::u32")] - public uint Index; - } + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FShaderBinding)); - [StructLayout(LayoutKind.Explicit)] - public partial struct FBufferRef - { - [FieldOffset(0)] - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Buffer; + public void** lpVtbl; - [FieldOffset(0)] - [NativeTypeName("Coplt::FUploadLoc")] - public FUploadLoc Upload; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FShaderBinding*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FShaderBinding*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FShaderBinding*)Unsafe.AsPointer(ref this)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FShaderBinding*)Unsafe.AsPointer(ref this), id); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FShaderBinding*)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]))((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(); + } } - [NativeTypeName("Coplt::u8")] - public enum FBufferRefType : byte + public unsafe partial struct FShaderBindingCreateResult { - Buffer = 0, - Upload, + [NativeTypeName("Coplt::FShaderBinding *")] + public FShaderBinding* Binding; + + [NativeTypeName("Coplt::FShaderBindingData *")] + public FShaderBindingData* Data; } - public partial struct FBufferCopyRange + public unsafe partial struct FUploadBufferBlock { - [NativeTypeName("Coplt::u64")] - public ulong Size; + [NativeTypeName("Coplt::u8 *")] + public byte* mapped_ptr; [NativeTypeName("Coplt::u64")] - public ulong DstOffset; + public ulong cur_offset; [NativeTypeName("Coplt::u64")] - public ulong SrcOffset; + public ulong size; } - public partial struct FBufferImageCopyRange + [Guid("15B4821D-0648-4B78-9C21-C6A5B6A5ED75")] + [NativeTypeName("struct FRecordContext : Coplt::FGpuObject")] + public unsafe partial struct FRecordContext : FRecordContext.Interface, INativeGuid { - [NativeTypeName("Coplt::u64")] - public ulong BufferOffset; + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FRecordContext)); - [NativeTypeName("Coplt::u32")] - public uint BytesPerRow; + public void** lpVtbl; - [NativeTypeName("Coplt::u32")] - public uint RowsPerImage; + public FList m_upload_buffer; - [NativeTypeName("u32[3]")] - public _ImageOffset_e__FixedBuffer ImageOffset; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FRecordContext*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("u32[3]")] - public _ImageExtent_e__FixedBuffer ImageExtent; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FRecordContext*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::u32")] - public uint ImageIndex; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FRecordContext*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::u32")] - public uint ImageCount; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FRecordContext*)Unsafe.AsPointer(ref this), id); + } - [NativeTypeName("Coplt::u16")] - public ushort MipLevel; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FRecordContext*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::FImagePlane")] - public FImagePlane Plane; + [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); + } - [InlineArray(3)] - public partial struct _ImageOffset_e__FixedBuffer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult GrowUploadBuffer([NativeTypeName("Coplt::u64")] ulong min_required_size) { - public uint e0; + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FRecordContext*)Unsafe.AsPointer(ref this), &result, min_required_size); } - [InlineArray(3)] - public partial struct _ImageExtent_e__FixedBuffer + public interface Interface : FGpuObject.Interface { - public uint e0; + [return: NativeTypeName("Coplt::FResult")] + FResult GrowUploadBuffer([NativeTypeName("Coplt::u64")] ulong min_required_size); } } [NativeTypeName("Coplt::u8")] - public enum FResolveMode : byte - { - Decompress, - Min, - Max, - Average, - } - - public partial struct FResolveInfo + public enum FGpuQueueType : byte { - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Src; - - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Dst; - - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat Format; - - [NativeTypeName("Coplt::FResolveMode")] - public FResolveMode Mode; + Direct, + Compute, + Copy, + VideoEncode, + VideoDecode, + VideoProcess, } [NativeTypeName("Coplt::u8")] - public enum FLoadOp : byte + public enum FGpuQueueFlags : byte { - Load, - Clear, - Discard, - NoAccess, + None = 0, + Direct = 1 << 0, + Compute = 1 << 1, + Copy = 1 << 2, + VideoEncode = 1 << 3, + VideoDecode = 1 << 4, + VideoProcess = 1 << 5, } - [NativeTypeName("Coplt::u8")] - public enum FStoreOp : byte + public partial struct FGpuQueueData { - Store, - Discard, - Resolve, - NoAccess, + [NativeTypeName("Coplt::FGpuQueueType")] + public FGpuQueueType QueueType; } - public partial struct FRenderInfo + [Guid("FC94E4D0-5F01-4D4F-894C-6AEFAAD90499")] + [NativeTypeName("struct FGpuQueue2 : Coplt::FGpuObject")] + public unsafe partial struct FGpuQueue2 : FGpuQueue2.Interface, INativeGuid { - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Dsv; + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuQueue2)); - [NativeTypeName("Coplt::u32")] - public uint NumRtv; + 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)); + } - [NativeTypeName("FResourceRef[8]")] - public _Rtv_e__FixedBuffer Rtv; + public interface Interface : FGpuObject.Interface + { + [return: NativeTypeName("Coplt::FGpuQueueData *")] + FGpuQueueData* GpuQueueData(); - [NativeTypeName("u32[8]")] - public _ResolveInfoIndex_e__FixedBuffer ResolveInfoIndex; + void* GetRawQueue(); + } + } - [NativeTypeName("Coplt::u32")] - public uint DsvResolveInfoIndex; + public unsafe partial struct FGpuQueueCreateResult + { + [NativeTypeName("Coplt::FGpuQueue2 *")] + public FGpuQueue2* Queue; - [NativeTypeName("FGraphicsFormat[8]")] - public _RtvFormat_e__FixedBuffer RtvFormat; + [NativeTypeName("Coplt::FGpuQueueData *")] + public FGpuQueueData* Data; + } - [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat DsvFormat; + [Guid("EDAB0989-E0C2-4B1E-826F-C73380088FC6")] + [NativeTypeName("struct FGpuExecutor : Coplt::FGpuObject")] + public unsafe partial struct FGpuExecutor : FGpuExecutor.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuExecutor)); - [NativeTypeName("f32[32]")] - public _Color_e__FixedBuffer Color; + public void** lpVtbl; - [NativeTypeName("Coplt::f32")] - public float Depth; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuExecutor*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::u8")] - public byte Stencil; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuExecutor*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("FLoadOp[2]")] - public _DsvLoadOp_e__FixedBuffer DsvLoadOp; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuExecutor*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("FStoreOp[2]")] - public _DsvStoreOp_e__FixedBuffer DsvStoreOp; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuExecutor*)Unsafe.AsPointer(ref this), id); + } - [NativeTypeName("FLoadOp[8]")] - public _RtvLoadOp_e__FixedBuffer RtvLoadOp; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuExecutor*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("FStoreOp[8]")] - public _RtvStoreOp_e__FixedBuffer RtvStoreOp; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuExecutor*)Unsafe.AsPointer(ref this), &result, name); + } - [NativeTypeName("Coplt::b8")] - public B8 HasUavWrites; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Wait() + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuExecutor*)Unsafe.AsPointer(ref this), &result); + } - [InlineArray(8)] - public partial struct _Rtv_e__FixedBuffer + public interface Interface : FGpuObject.Interface { - public FResourceRef e0; + [return: NativeTypeName("Coplt::FResult")] + FResult Wait(); } + } - [InlineArray(8)] - public partial struct _ResolveInfoIndex_e__FixedBuffer + [Guid("B3AEB8A5-1FA6-4866-97EF-1A5FA401E18F")] + [NativeTypeName("struct FGpuViewable : Coplt::FGpuObject")] + public unsafe partial struct FGpuViewable : FGpuViewable.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuViewable)); + + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() { - public uint e0; + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuViewable*)Unsafe.AsPointer(ref this)); } - [InlineArray(8)] - public partial struct _RtvFormat_e__FixedBuffer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() { - public FGraphicsFormat e0; + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuViewable*)Unsafe.AsPointer(ref this)); } - [InlineArray(32)] - public partial struct _Color_e__FixedBuffer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() { - public float e0; + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuViewable*)Unsafe.AsPointer(ref this)); } - [InlineArray(2)] - public partial struct _DsvLoadOp_e__FixedBuffer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) { - public FLoadOp e0; + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuViewable*)Unsafe.AsPointer(ref this), id); } - [InlineArray(2)] - public partial struct _DsvStoreOp_e__FixedBuffer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() { - public FStoreOp e0; + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuViewable*)Unsafe.AsPointer(ref this)); } - [InlineArray(8)] - public partial struct _RtvLoadOp_e__FixedBuffer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) { - public FLoadOp e0; + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuViewable*)Unsafe.AsPointer(ref this), &result, name); } - [InlineArray(8)] - public partial struct _RtvStoreOp_e__FixedBuffer + public interface Interface : FGpuObject.Interface { - public FStoreOp e0; } } - public partial struct FComputeInfo + [NativeTypeName("Coplt::u8")] + public enum FViewType : byte { + None = 0, + Buffer = 1, + Image = 2, + Sampler = 3, } - public partial struct FBufferRange + public unsafe partial struct FView { - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Buffer; + [NativeTypeName("Coplt::FGpuViewable *")] + public FGpuViewable* Viewable; - [NativeTypeName("Coplt::u32")] - public uint Offset; - - [NativeTypeName("Coplt::u32")] - public uint Size; + [NativeTypeName("Coplt::FViewType")] + public FViewType Type; } - [NativeTypeName("struct FVertexBufferRange : Coplt::FBufferRange")] - public partial struct FVertexBufferRange + [NativeTypeName("Coplt::u8")] + public enum FCpuAccess : byte { - public FBufferRange Base; - - [NativeTypeName("Coplt::u32")] - public uint Index; + None = 0, + Write = 1, + Read = 2, + ReadWrite = 3, } - public unsafe partial struct FMeshBuffers + [NativeTypeName("Coplt::u32")] + public enum FResourcePurpose : uint { - [NativeTypeName("Coplt::FMeshLayout *")] - public FMeshLayout* MeshLayout; + 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::FBufferRange")] - public FBufferRange IndexBuffer; + public partial struct FGpuResourceCreateOptions + { + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; - [NativeTypeName("Coplt::u32")] - public uint VertexBufferCount; + [NativeTypeName("Coplt::FCpuAccess")] + public FCpuAccess CpuAccess; - [NativeTypeName("Coplt::u32")] - public uint VertexBuffersIndex; + [NativeTypeName("Coplt::FResourcePurpose")] + public FResourcePurpose Purpose; } [NativeTypeName("Coplt::u8")] - public enum FDispatchType : byte - { - Compute, - Mesh, - } - - public partial struct FCommandBase + public enum ResourceType : byte { - [NativeTypeName("Coplt::FCommandType")] - public FCommandType Type; + Unknown = 0, + Buffer = 1, + Image = 2, } - [NativeTypeName("struct FCommandLabel : Coplt::FCommandBase")] - public partial struct FCommandLabel + public unsafe partial struct FGpuResourceData { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint StringIndex; - - [NativeTypeName("Coplt::u32")] - public uint StringLength; - - [NativeTypeName("Coplt::FStrType")] - public FStrType StrType; + public void* m_raw_resource_ptr; - [NativeTypeName("u8[3]")] - public _Color_e__FixedBuffer Color; + [NativeTypeName("Coplt::FResourcePurpose")] + public FResourcePurpose m_purpose; - [NativeTypeName("Coplt::b8")] - public B8 HasColor; + [NativeTypeName("Coplt::FCpuAccess")] + public FCpuAccess m_cpu_access; - [InlineArray(3)] - public partial struct _Color_e__FixedBuffer - { - public byte e0; - } + [NativeTypeName("Coplt::ResourceType")] + public ResourceType m_resource_type; } - [NativeTypeName("struct FCommandBeginScope : Coplt::FCommandBase")] - public partial struct FCommandBeginScope + [Guid("F99DCEEC-2F0C-4A28-B666-BEB7C35219D6")] + [NativeTypeName("struct FGpuResource : Coplt::FGpuViewable")] + public unsafe partial struct FGpuResource : FGpuResource.Interface, INativeGuid { - public FCommandBase Base; + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuResource)); - [NativeTypeName("Coplt::u32")] - public uint StringIndex; + public void** lpVtbl; - [NativeTypeName("Coplt::u32")] - public uint StringLength; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuResource*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::FStrType")] - public FStrType StrType; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuResource*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("u8[3]")] - public _Color_e__FixedBuffer Color; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuResource*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::b8")] - public B8 HasColor; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuResource*)Unsafe.AsPointer(ref this), id); + } - [InlineArray(3)] - public partial struct _Color_e__FixedBuffer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() { - public byte e0; + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuResource*)Unsafe.AsPointer(ref this)); } - } - [NativeTypeName("struct FCommandEndScope : Coplt::FCommandBase")] - public partial struct FCommandEndScope - { - public FCommandBase Base; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuResource*)Unsafe.AsPointer(ref this), &result, name); + } - [NativeTypeName("struct FCommandPresent : Coplt::FCommandBase")] - public partial struct FCommandPresent - { - public FCommandBase Base; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuResourceData *")] + public FGpuResourceData* GpuResourceData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuResource*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Image; + public interface Interface : FGpuViewable.Interface + { + [return: NativeTypeName("Coplt::FGpuResourceData *")] + FGpuResourceData* GpuResourceData(); + } } - [NativeTypeName("struct FCommandBarrier : Coplt::FCommandBase")] - public partial struct FCommandBarrier + [NativeTypeName("Coplt::u8")] + public enum FBufferUsage : byte { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint BarrierIndex; - - [NativeTypeName("Coplt::u32")] - public uint BarrierCount; + Undefined, + Structured, + Raw, } - [NativeTypeName("struct FCommandClearColor : Coplt::FCommandBase")] - public partial struct FCommandClearColor + [NativeTypeName("struct FGpuBufferCreateOptions : Coplt::FGpuResourceCreateOptions")] + public partial struct FGpuBufferCreateOptions { - public FCommandBase Base; + public FGpuResourceCreateOptions Base; - [NativeTypeName("Coplt::u32")] - public uint RectCount; + [NativeTypeName("Coplt::u64")] + public ulong Size; [NativeTypeName("Coplt::u32")] - public uint RectIndex; - - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Image; + public uint Count; - [NativeTypeName("f32[4]")] - public _Color_e__FixedBuffer Color; + [NativeTypeName("Coplt::u32")] + public uint Stride; - [InlineArray(4)] - public partial struct _Color_e__FixedBuffer - { - public float e0; - } + [NativeTypeName("Coplt::FBufferUsage")] + public FBufferUsage Usage; } - [NativeTypeName("struct FCommandClearDepthStencil : Coplt::FCommandBase")] - public partial struct FCommandClearDepthStencil + [NativeTypeName("struct FGpuBufferData : Coplt::FGpuResourceData")] + public partial struct FGpuBufferData { - public FCommandBase Base; + public FGpuResourceData Base; - [NativeTypeName("Coplt::u32")] - public uint RectCount; + [NativeTypeName("Coplt::u64")] + public ulong m_size; [NativeTypeName("Coplt::u32")] - public uint RectIndex; - - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Image; - - [NativeTypeName("Coplt::f32")] - public float Depth; + public uint m_count; - [NativeTypeName("Coplt::u8")] - public byte Stencil; + [NativeTypeName("Coplt::u32")] + public uint m_stride; - [NativeTypeName("Coplt::FDepthStencilClearFlags")] - public FDepthStencilClearFlags Clear; + [NativeTypeName("Coplt::FBufferUsage")] + public FBufferUsage m_usage; } - [NativeTypeName("struct FCommandBind : Coplt::FCommandBase")] - public unsafe partial struct FCommandBind + [Guid("283740E3-FE96-41D0-830A-0A4C6A725336")] + [NativeTypeName("struct FGpuBuffer : Coplt::FGpuResource")] + public unsafe partial struct FGpuBuffer : FGpuBuffer.Interface, INativeGuid { - public FCommandBase Base; - - [NativeTypeName("Coplt::u32")] - public uint ItemCount; + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuBuffer)); - [NativeTypeName("Coplt::u32")] - public uint ItemsIndex; + public void** lpVtbl; - [NativeTypeName("Coplt::FShaderBinding *")] - public FShaderBinding* Binding; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() + { + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("struct FCommandBufferCopy : Coplt::FCommandBase")] - public partial struct FCommandBufferCopy - { - public FCommandBase Base; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::u32")] - public uint RangeIndex; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::FBufferRef")] - public FBufferRef Dst; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuBuffer*)Unsafe.AsPointer(ref this), id); + } - [NativeTypeName("Coplt::FBufferRef")] - public FBufferRef Src; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::FBufferRefType")] - public FBufferRefType DstType; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, name); + } - [NativeTypeName("Coplt::FBufferRefType")] - public FBufferRefType SrcType; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuResourceData *")] + public FGpuResourceData* GpuResourceData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("struct FCommandBufferImageCopy : Coplt::FCommandBase")] - public partial struct FCommandBufferImageCopy - { - public FCommandBase Base; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuBufferData *")] + public FGpuBufferData* GpuBufferData() + { + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuBuffer*)Unsafe.AsPointer(ref this)); + } - [NativeTypeName("Coplt::u32")] - public uint RangeIndex; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Map(void** ptr, [NativeTypeName("Coplt::b8")] B8 discard) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, ptr, discard); + } - [NativeTypeName("Coplt::FResourceRef")] - public FResourceRef Image; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Unmap([NativeTypeName("Coplt::b8")] B8 discard) + { + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuBuffer*)Unsafe.AsPointer(ref this), &result, discard); + } - [NativeTypeName("Coplt::FBufferRef")] - public FBufferRef Buffer; + public interface Interface : FGpuResource.Interface + { + [return: NativeTypeName("Coplt::FGpuBufferData *")] + FGpuBufferData* GpuBufferData(); - [NativeTypeName("Coplt::FBufferRefType")] - public FBufferRefType BufferType; + [return: NativeTypeName("Coplt::FResult")] + FResult Map(void** ptr, [NativeTypeName("Coplt::b8")] B8 discard); - [NativeTypeName("Coplt::b8")] - public B8 ImageToBuffer; + [return: NativeTypeName("Coplt::FResult")] + FResult Unmap([NativeTypeName("Coplt::b8")] B8 discard); + } } - [NativeTypeName("struct FCommandRender : Coplt::FCommandBase")] - public partial struct FCommandRender + public partial struct FOptimizedClearColor { - public FCommandBase Base; + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat Format; - [NativeTypeName("Coplt::u32")] - public uint InfoIndex; + [NativeTypeName("__AnonymousRecord_Resource_L120_C9")] + public _Anonymous_e__Union Anonymous; - [NativeTypeName("Coplt::u32")] - public uint CommandStartIndex; + [UnscopedRef] + public Span Color + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return Anonymous.Color; + } + } - [NativeTypeName("Coplt::u32")] - public uint CommandCount; - } + [UnscopedRef] + public ref float Depth + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Anonymous.Depth; + } + } - [NativeTypeName("struct FCommandCompute : Coplt::FCommandBase")] - public partial struct FCommandCompute - { - public FCommandBase Base; + [UnscopedRef] + public ref byte Stencil + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref Anonymous.Anonymous.Stencil; + } + } - [NativeTypeName("Coplt::u32")] - public uint InfoIndex; + [StructLayout(LayoutKind.Explicit)] + public partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + [NativeTypeName("f32[4]")] + public _Color_e__FixedBuffer Color; - [NativeTypeName("Coplt::u32")] - public uint CommandStartIndex; + [FieldOffset(0)] + [NativeTypeName("__AnonymousRecord_Resource_L124_C13")] + public _Anonymous_e__Struct Anonymous; - [NativeTypeName("Coplt::u32")] - public uint CommandCount; - } + public partial struct _Anonymous_e__Struct + { + [NativeTypeName("Coplt::f32")] + public float Depth; - [NativeTypeName("struct FCommandSetPipeline : Coplt::FCommandBase")] - public unsafe partial struct FCommandSetPipeline - { - public FCommandBase Base; + [NativeTypeName("Coplt::u8")] + public byte Stencil; + } - [NativeTypeName("Coplt::FShaderPipeline *")] - public FShaderPipeline* Pipeline; + [InlineArray(4)] + public partial struct _Color_e__FixedBuffer + { + public float e0; + } + } } - [NativeTypeName("struct FCommandSetBinding : Coplt::FCommandBase")] - public unsafe partial struct FCommandSetBinding + [NativeTypeName("Coplt::u8")] + public enum FImageDimension : byte { - public FCommandBase Base; - - [NativeTypeName("Coplt::FShaderBinding *")] - public FShaderBinding* Binding; + One, + Two, + Three, + Cube, } - [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("Coplt::u8")] + public enum FImageLayout : byte + { + Undefined, + RowMajor, + Undefined64kSwizzle, + Standard64kSwizzle, } - [NativeTypeName("struct FCommandSetMeshBuffers : Coplt::FCommandBase")] - public partial struct FCommandSetMeshBuffers + [NativeTypeName("struct FGpuImageCreateOptions : Coplt::FGpuResourceCreateOptions")] + public partial struct FGpuImageCreateOptions { - public FCommandBase Base; + public FGpuResourceCreateOptions Base; [NativeTypeName("Coplt::FGraphicsFormat")] - public FGraphicsFormat IndexFormat; + public FGraphicsFormat Format; [NativeTypeName("Coplt::u32")] - public uint VertexStartSlot; + public uint Width; [NativeTypeName("Coplt::u32")] - public uint PayloadIndex; - } - - [NativeTypeName("struct FCommandDraw : Coplt::FCommandBase")] - public partial struct FCommandDraw - { - public FCommandBase Base; + public uint Height; [NativeTypeName("Coplt::u32")] - public uint VertexOrIndexCount; + public uint DepthOrLength; - [NativeTypeName("Coplt::u32")] - public uint InstanceCount; + [NativeTypeName("Coplt::u16")] + public ushort MipLevels; - [NativeTypeName("Coplt::u32")] - public uint FirstVertexOrIndex; + [NativeTypeName("Coplt::FOptimizedClearColor")] + public FOptimizedClearColor OptimizedClearValue; - [NativeTypeName("Coplt::u32")] - public uint FirstInstance; + [NativeTypeName("Coplt::b8")] + public B8 HasOptimizedClearValue; - [NativeTypeName("Coplt::u32")] - public uint VertexOffset; + [NativeTypeName("Coplt::u8")] + public byte MultisampleCount; - [NativeTypeName("Coplt::b8")] - public B8 Indexed; + [NativeTypeName("Coplt::FImageDimension")] + public FImageDimension Dimension; + + [NativeTypeName("Coplt::FImageLayout")] + public FImageLayout Layout; } - [NativeTypeName("struct FCommandDispatch : Coplt::FCommandBase")] - public partial struct FCommandDispatch + [NativeTypeName("struct FGpuImageData : Coplt::FGpuResourceData")] + public partial struct FGpuImageData { - public FCommandBase Base; + public FGpuResourceData Base; + + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat m_format; [NativeTypeName("Coplt::u32")] - public uint GroupCountX; + public uint m_width; [NativeTypeName("Coplt::u32")] - public uint GroupCountY; + public uint m_height; [NativeTypeName("Coplt::u32")] - public uint GroupCountZ; + public uint m_depth_or_length; - [NativeTypeName("Coplt::FDispatchType")] - public FDispatchType Type; - } + [NativeTypeName("Coplt::u16")] + public ushort m_mip_levels; - [NativeTypeName("Coplt::u8")] - public enum FBindingSyncType : byte - { - Transient, - Persistent, - } + [NativeTypeName("Coplt::u8")] + public byte m_multisample_count; - [NativeTypeName("struct FCommandSyncBinding : Coplt::FCommandBase")] - public partial struct FCommandSyncBinding - { - public FCommandBase Base; + [NativeTypeName("Coplt::u8")] + public byte m_planes; - [NativeTypeName("Coplt::u32")] - public uint Index; + [NativeTypeName("Coplt::FImageDimension")] + public FImageDimension m_dimension; - [NativeTypeName("Coplt::FBindingSyncType")] - public FBindingSyncType Type; + [NativeTypeName("Coplt::FImageLayout")] + public FImageLayout m_layout; } - public partial struct FCommandItem + [Guid("667EFA36-21C7-4561-ABAD-85780FA4929E")] + [NativeTypeName("struct FGpuImage : Coplt::FGpuResource")] + public unsafe partial struct FGpuImage : FGpuImage.Interface, INativeGuid { - [NativeTypeName("__AnonymousRecord_Command_L528_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; - } - } + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuImage)); - [UnscopedRef] - public ref FCommandBarrier Barrier - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Barrier; - } - } + public void** lpVtbl; - [UnscopedRef] - public ref FCommandClearColor ClearColor + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.ClearColor; - } + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuImage*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandClearDepthStencil ClearDepthStencil + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.ClearDepthStencil; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuImage*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandBind Bind + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Bind; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuImage*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandBufferCopy BufferCopy + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.BufferCopy; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuImage*)Unsafe.AsPointer(ref this), id); } - [UnscopedRef] - public ref FCommandBufferImageCopy BufferImageCopy + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.BufferImageCopy; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuImage*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandRender Render + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Render; - } + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuImage*)Unsafe.AsPointer(ref this), &result, name); } - [UnscopedRef] - public ref FCommandCompute Compute + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuResourceData *")] + public FGpuResourceData* GpuResourceData() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Compute; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuImage*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandSyncBinding SyncBinding + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuImageData *")] + public FGpuImageData* GpuImageData() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SyncBinding; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuImage*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public Span _pad + public interface Interface : FGpuResource.Interface { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return Anonymous._pad; - } + [return: NativeTypeName("Coplt::FGpuImageData *")] + FGpuImageData* GpuImageData(); } + } - [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; + [NativeTypeName("Coplt::u8")] + public enum FPresentMode : byte + { + NoBuffer, + DoubleBuffer, + TripleBuffer, + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandPresent")] - public FCommandPresent Present; + [NativeTypeName("Coplt::u8")] + public enum FOutputAlphaMode : byte + { + Opaque, + PrePremultiplied, + PostPremultiplied, + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBarrier")] - public FCommandBarrier Barrier; + [NativeTypeName("Coplt::u8")] + public enum FHdrType : byte + { + None, + UNorm10, + Float16, + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandClearColor")] - public FCommandClearColor ClearColor; + public partial struct FGpuOutputData + { + [NativeTypeName("Coplt::FGraphicsFormat")] + public FGraphicsFormat Format; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandClearDepthStencil")] - public FCommandClearDepthStencil ClearDepthStencil; + [NativeTypeName("Coplt::u32")] + public uint Width; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBind")] - public FCommandBind Bind; + [NativeTypeName("Coplt::u32")] + public uint Height; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBufferCopy")] - public FCommandBufferCopy BufferCopy; + [NativeTypeName("Coplt::b8")] + public B8 Srgb; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBufferImageCopy")] - public FCommandBufferImageCopy BufferImageCopy; + [NativeTypeName("Coplt::FHdrType")] + public FHdrType Hdr; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandRender")] - public FCommandRender Render; + [NativeTypeName("Coplt::FPresentMode")] + public FPresentMode PresentMode; + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandCompute")] - public FCommandCompute Compute; + public partial struct FGpuOutput2CreateOptions + { + [NativeTypeName("Coplt::FStr8or16")] + public FStr8or16 Name; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSyncBinding")] - public FCommandSyncBinding SyncBinding; + [NativeTypeName("Coplt::FPresentMode")] + public FPresentMode PresentMode; - [FieldOffset(0)] - [NativeTypeName("u8[32]")] - public __pad_e__FixedBuffer _pad; + [NativeTypeName("Coplt::b8")] + public B8 Srgb; - [InlineArray(32)] - public partial struct __pad_e__FixedBuffer - { - public byte e0; - } - } + [NativeTypeName("Coplt::FHdrType")] + public FHdrType Hdr; } - public partial struct FRenderCommandItem + [Guid("3F82BE7F-2CF5-48A9-8CA4-BB2F9CFE58B2")] + [NativeTypeName("struct FGpuOutput2 : Coplt::FGpuExecutor")] + public unsafe partial struct FGpuOutput2 : FGpuOutput2.Interface, INativeGuid { - [NativeTypeName("__AnonymousRecord_Command_L559_C9")] - public _Anonymous_e__Union Anonymous; + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FGpuOutput2)); - [UnscopedRef] - public ref FCommandType Type + public void** lpVtbl; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Dispose() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Type; - } + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandLabel Label + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Label; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[1]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandBeginScope BeginScope + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint AddRef() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.BeginScope; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[2]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandEndScope EndScope + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* QueryInterface([NativeTypeName("const Guid &")] Guid* id) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.EndScope; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[3]))((FGpuOutput2*)Unsafe.AsPointer(ref this), id); } - [UnscopedRef] - public ref FCommandSetPipeline SetPipeline + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::u64")] + public ulong ObjectId() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetPipeline; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[4]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandSetBinding SetBinding + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetName([NativeTypeName("const FStr8or16 &")] FStr8or16* name) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetBinding; - } + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[5]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result, name); } - [UnscopedRef] - public ref FCommandSetViewportScissor SetViewportScissor + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Wait() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetViewportScissor; - } + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[6]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); } - [UnscopedRef] - public ref FCommandSetMeshBuffers SetMeshBuffers + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("const FGpuOutputData *")] + public FGpuOutputData* GpuOutputData() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetMeshBuffers; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[7]))((FGpuOutput2*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandDraw Draw + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Resize([NativeTypeName("Coplt::u32")] uint Width, [NativeTypeName("Coplt::u32")] uint Height) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Draw; - } + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result, Width, Height); } - [UnscopedRef] - public ref FCommandDispatch Dispatch + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Present() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Dispatch; - } + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); } - [UnscopedRef] - public ref FCommandSyncBinding SyncBinding + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult PresentNoWait() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SyncBinding; - } + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuOutput2*)Unsafe.AsPointer(ref this), &result); } - [UnscopedRef] - public Span _pad + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool IsAvailable() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return Anonymous._pad; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuOutput2*)Unsafe.AsPointer(ref this)) != 0; } - [StructLayout(LayoutKind.Explicit)] - public partial struct _Anonymous_e__Union + public interface Interface : FGpuExecutor.Interface { - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandType")] - public FCommandType Type; + [return: NativeTypeName("const FGpuOutputData *")] + FGpuOutputData* GpuOutputData(); - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandLabel")] - public FCommandLabel Label; + [return: NativeTypeName("Coplt::FResult")] + FResult Resize([NativeTypeName("Coplt::u32")] uint Width, [NativeTypeName("Coplt::u32")] uint Height); - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBeginScope")] - public FCommandBeginScope BeginScope; + [return: NativeTypeName("Coplt::FResult")] + FResult Present(); - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandEndScope")] - public FCommandEndScope EndScope; + [return: NativeTypeName("Coplt::FResult")] + FResult PresentNoWait(); - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetPipeline")] - public FCommandSetPipeline SetPipeline; + bool IsAvailable(); + } + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetBinding")] - public FCommandSetBinding SetBinding; + [NativeTypeName("struct FGpuSwapChainData : Coplt::FGpuOutputData")] + public partial struct FGpuSwapChainData + { + public FGpuOutputData Base; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetViewportScissor")] - public FCommandSetViewportScissor SetViewportScissor; + [NativeTypeName("Coplt::FOutputAlphaMode")] + public FOutputAlphaMode AlphaMode; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetMeshBuffers")] - public FCommandSetMeshBuffers SetMeshBuffers; + [NativeTypeName("Coplt::b8")] + public B8 VSync; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandDraw")] - public FCommandDraw Draw; + [NativeTypeName("Coplt::b8")] + public B8 Srgb; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandDispatch")] - public FCommandDispatch Dispatch; + [NativeTypeName("Coplt::FHdrType")] + public FHdrType Hdr; + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSyncBinding")] - public FCommandSyncBinding SyncBinding; + [NativeTypeName("struct FGpuSwapChainCreateOptions : Coplt::FGpuOutput2CreateOptions")] + public partial struct FGpuSwapChainCreateOptions + { + public FGpuOutput2CreateOptions Base; - [FieldOffset(0)] - [NativeTypeName("u8[32]")] - public __pad_e__FixedBuffer _pad; + [NativeTypeName("Coplt::u32")] + public uint Width; - [InlineArray(32)] - public partial struct __pad_e__FixedBuffer - { - public byte e0; - } - } + [NativeTypeName("Coplt::u32")] + public uint Height; + + [NativeTypeName("Coplt::FOutputAlphaMode")] + public FOutputAlphaMode AlphaMode; + + [NativeTypeName("Coplt::b8")] + public B8 VSync; } - public partial struct FComputeCommandItem + [NativeTypeName("struct FGpuSwapChainFromExistsCreateOptions : Coplt::FGpuOutput2CreateOptions")] + public unsafe partial struct FGpuSwapChainFromExistsCreateOptions { - [NativeTypeName("__AnonymousRecord_Command_L584_C9")] - public _Anonymous_e__Union Anonymous; + public FGpuOutput2CreateOptions Base; - [UnscopedRef] - public ref FCommandType Type + 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() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Type; - } + ((delegate* unmanaged[Thiscall])(lpVtbl[0]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandLabel Label + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("size_t")] + public nuint Release() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Label; - } + 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)); } - [UnscopedRef] - public ref FCommandBeginScope BeginScope + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Resize([NativeTypeName("Coplt::u32")] uint Width, [NativeTypeName("Coplt::u32")] uint Height) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.BeginScope; - } + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[8]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result, Width, Height); } - [UnscopedRef] - public ref FCommandEndScope EndScope + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult Present() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.EndScope; - } + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[9]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result); } - [UnscopedRef] - public ref FCommandSetPipeline SetPipeline + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult PresentNoWait() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetPipeline; - } + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[10]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result); } - [UnscopedRef] - public ref FCommandSetBinding SetBinding + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool IsAvailable() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SetBinding; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[11]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)) != 0; } - [UnscopedRef] - public ref FCommandDispatch Dispatch + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("const FGpuSwapChainData *")] + public FGpuSwapChainData* GpuSwapChainData() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.Dispatch; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[12]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public ref FCommandSyncBinding SyncBinding + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FGpuIsolate *")] + public FGpuIsolate* GetIsolate() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref Anonymous.SyncBinding; - } + return ((delegate* unmanaged[Thiscall])(lpVtbl[13]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); } - [UnscopedRef] - public Span _pad + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [return: NativeTypeName("Coplt::FResult")] + public FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable) { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return Anonymous._pad; - } + FResult result; + return *((delegate* unmanaged[Thiscall])(lpVtbl[14]))((FGpuSwapChain*)Unsafe.AsPointer(ref this), &result, Enable); } - [StructLayout(LayoutKind.Explicit)] - public partial struct _Anonymous_e__Union + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void* GetRawPtr() { - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandType")] - public FCommandType Type; - - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandLabel")] - public FCommandLabel Label; + return ((delegate* unmanaged[Thiscall])(lpVtbl[15]))((FGpuSwapChain*)Unsafe.AsPointer(ref this)); + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandBeginScope")] - public FCommandBeginScope BeginScope; + public interface Interface : FGpuOutput2.Interface + { + [return: NativeTypeName("const FGpuSwapChainData *")] + FGpuSwapChainData* GpuSwapChainData(); - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandEndScope")] - public FCommandEndScope EndScope; + [return: NativeTypeName("Coplt::FGpuIsolate *")] + FGpuIsolate* GetIsolate(); - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetPipeline")] - public FCommandSetPipeline SetPipeline; + [return: NativeTypeName("Coplt::FResult")] + FResult SetVSync([NativeTypeName("Coplt::b8")] B8 Enable); - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSetBinding")] - public FCommandSetBinding SetBinding; + void* GetRawPtr(); + } + } - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandDispatch")] - public FCommandDispatch Dispatch; + public unsafe partial struct FGpuSwapChainCreateResult + { + [NativeTypeName("Coplt::FGpuSwapChain *")] + public FGpuSwapChain* SwapChain; - [FieldOffset(0)] - [NativeTypeName("Coplt::FCommandSyncBinding")] - public FCommandSyncBinding SyncBinding; + [NativeTypeName("Coplt::FGpuSwapChainData *")] + public FGpuSwapChainData* Data; + } - [FieldOffset(0)] - [NativeTypeName("u8[32]")] - public __pad_e__FixedBuffer _pad; + [NativeTypeName("Coplt::u8")] + public enum FImagePlane : byte + { + All = 0, + Depth = 0, + Stencil = 1, + Y = 0, + CbCr = 1, + } - [InlineArray(32)] - public partial struct __pad_e__FixedBuffer - { - public byte e0; - } - } + public enum FGraphicsFormat + { + Unknown = 0, + R32G32B32A32_TypeLess = 1, + R32G32B32A32_Float = 2, + R32G32B32A32_UInt = 3, + R32G32B32A32_SInt = 4, + R32G32B32_TypeLess = 5, + R32G32B32_Float = 6, + R32G32B32_UInt = 7, + R32G32B32_SInt = 8, + R16G16B16A16_TypeLess = 9, + R16G16B16A16_Float = 10, + R16G16B16A16_UNorm = 11, + R16G16B16A16_UInt = 12, + R16G16B16A16_SNorm = 13, + R16G16B16A16_SInt = 14, + R32G32_TypeLess = 15, + R32G32_Float = 16, + R32G32_UInt = 17, + R32G32_SInt = 18, + R32G8X24_TypeLess = 19, + D32_Float_S8X24_UInt = 20, + R32_Float_X8X24_TypeLess = 21, + X32_TypeLess_G8X24_Float = 22, + R10G10B10A2_TypeLess = 23, + R10G10B10A2_UNorm = 24, + R10G10B10A2_UInt = 25, + R11G11B10_Float = 26, + R8G8B8A8_TypeLess = 27, + R8G8B8A8_UNorm = 28, + R8G8B8A8_UNorm_sRGB = 29, + R8G8B8A8_UInt = 30, + R8G8B8A8_SNorm = 31, + R8G8B8A8_SInt = 32, + R16G16_TypeLess = 33, + R16G16_Float = 34, + R16G16_UNorm = 35, + R16G16_UInt = 36, + R16G16_SNorm = 37, + R16G16_SInt = 38, + R32_TypeLess = 39, + D32_Float = 40, + R32_Float = 41, + R32_UInt = 42, + R32_SInt = 43, + R24G8_TypeLess = 44, + D24_UNorm_S8_UInt = 45, + R24_UNorm_X8_TypeLess = 46, + X24_TypeLess_G8_UInt = 47, + R8G8_TypeLess = 48, + R8G8_UNorm = 49, + R8G8_UInt = 50, + R8G8_SNorm = 51, + R8G8_SInt = 52, + R16_TypeLess = 53, + R16_Float = 54, + D16_UNorm = 55, + R16_UNorm = 56, + R16_UInt = 57, + R16_SNorm = 58, + R16_SInt = 59, + R8_TypeLess = 60, + R8_UNorm = 61, + R8_UInt = 62, + R8_SNorm = 63, + R8_SInt = 64, + A8_UNorm = 65, + R1_UNorm = 66, + R9G9B9E5_SharedExp = 67, + R8G8_B8G8_UNorm = 68, + G8R8_G8B8_UNorm = 69, + BC1_TypeLess = 70, + BC1_UNorm = 71, + BC1_UNorm_sRGB = 72, + BC2_TypeLess = 73, + BC2_UNorm = 74, + BC2_UNorm_sRGB = 75, + BC3_TypeLess = 76, + BC3_UNorm = 77, + BC3_UNorm_sRGB = 78, + BC4_TypeLess = 79, + BC4_UNorm = 80, + BC4_SNorm = 81, + BC5_TypeLess = 82, + BC5_UNorm = 83, + BC5_SNorm = 84, + B5G6R5_UNorm = 85, + B5G5R5A1_UNorm = 86, + B8G8R8A8_UNorm = 87, + B8G8R8X8_UNorm = 88, + R10G10B10_XR_Bias_A2_UNorm = 89, + B8G8R8A8_TypeLess = 90, + B8G8R8A8_UNorm_sRGB = 91, + B8G8R8X8_TypeLess = 92, + B8G8R8X8_UNorm_sRGB = 93, + BC6H_TypeLess = 94, + BC6H_UF16 = 95, + 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::u8")] @@ -4625,15 +4603,7 @@ public enum FShaderLayoutItemView : byte Uav, Sampler, Constants, - } - - [NativeTypeName("Coplt::u8")] - public enum FShaderLayoutGroupView : byte - { - Cbv, - Srv, - Uav, - Sampler, + StaticSampler, } [NativeTypeName("Coplt::u8")] @@ -4657,23 +4627,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; @@ -4681,7 +4642,7 @@ public partial struct FShaderLayoutItemDefine public uint Space; [NativeTypeName("Coplt::u32")] - public uint CountOrIndex; + public uint Count; [NativeTypeName("Coplt::FGraphicsFormat")] public FGraphicsFormat Format; @@ -4695,98 +4656,283 @@ 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("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 FGetEmptyBindingLayoutOptions { [NativeTypeName("Coplt::FShaderLayoutFlags")] public FShaderLayoutFlags Flags; } + [Guid("BC0B662E-2918-4769-9D0C-1FEE25B32C5D")] + [NativeTypeName("struct FBindingLayout : Coplt::FGpuObject")] + public unsafe partial struct FBindingLayout : FBindingLayout.Interface, INativeGuid + { + static Guid* INativeGuid.NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_FBindingLayout)); + + 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 { [NativeTypeName("Coplt::FStr8or16")] @@ -4907,6 +5053,9 @@ public unsafe partial struct FShaderPipelineCreateOptions [NativeTypeName("Coplt::FShader *")] public FShader* Shader; + + [NativeTypeName("Coplt::FBindingLayout *")] + public FBindingLayout* Layout; } [Guid("356A2610-34E3-4C01-9904-22E3C5CE2F4E")] @@ -4966,10 +5115,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)] @@ -4984,8 +5133,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(); @@ -5049,10 +5198,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)] @@ -5136,10 +5285,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)] @@ -5589,7 +5738,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)); @@ -5644,13 +5793,62 @@ 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(); } } + [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); @@ -5673,15 +5871,21 @@ 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_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); + 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_FFrameContext = new Guid(0x3A22DE68, 0x8377, 0x4E57, 0xA1, 0x67, 0x3E, 0xFD, 0xB9, 0x7C, 0x10, 0x2A); + 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); @@ -5693,10 +5897,16 @@ 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); 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.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.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/CMakeLists.txt b/Coplt.Graphics.Native/Api/CMakeLists.txt index 06b08c2..e346225 100644 --- a/Coplt.Graphics.Native/Api/CMakeLists.txt +++ b/Coplt.Graphics.Native/Api/CMakeLists.txt @@ -21,11 +21,9 @@ 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 - FFI/Command.h FFI/Resource.h FFI/Shader.h Src/Shader.h @@ -56,6 +54,13 @@ add_library(${target_name} STATIC Include/GpuObject.h Include/Option.h FFI/Sampler.h + FFI/Isolate.h + FFI/Record.h + Include/Finally.h + 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/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/Binding.h b/Coplt.Graphics.Native/Api/FFI/Binding.h index 65e737f..7aa8e57 100644 --- a/Coplt.Graphics.Native/Api/FFI/Binding.h +++ b/Coplt.Graphics.Native/Api/FFI/Binding.h @@ -6,19 +6,66 @@ namespace Coplt { - struct FShaderBindingCreateOptions + struct FSetBindItem + { + // 绑定内容 + FView View{}; + // 绑定槽的索引 + u32 Slot{}; + // 如果绑定是数组的话,数组中的索引 + u32 Index{}; + }; + + struct FShaderBindGroupCreateOptions { FStr8or16 Name{}; - FShaderLayout* Layout{}; + FBindGroupLayout* Layout{}; + FSetBindItem* Bindings{}; + u32 NumBindings{}; }; - struct FBindItem + struct FShaderBindGroupData { - FView View{}; + u32 CountSlots{}; + }; + + COPLT_INTERFACE_DEFINE(FShaderBindGroup, "ae54efe5-c372-4291-b995-55298758d2b2", FGpuObject) + { + virtual FShaderBindGroupData* ShaderBindGroupData() noexcept = 0; + }; + + struct FShaderBindGroupCreateResult + { + FShaderBindGroup* BindGroup{}; + FShaderBindGroupData* Data{}; + }; + + struct FSetBindGroupItem + { + FShaderBindGroup* BindGroup{}; u32 Index{}; }; + struct FShaderBindingCreateOptions + { + FStr8or16 Name{}; + FBindingLayout* Layout{}; + FSetBindGroupItem* BindGroups{}; + u32 NumBindGroups{}; + }; + + struct FShaderBindingData + { + }; + 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/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/Cmd.h b/Coplt.Graphics.Native/Api/FFI/Cmd.h new file mode 100644 index 0000000..267dea8 --- /dev/null +++ b/Coplt.Graphics.Native/Api/FFI/Cmd.h @@ -0,0 +1,391 @@ +#pragma once + +#include "List.h" +#include "Structs.h" +#include "Output.h" +#include "Binding.h" +#include "Pipeline.h" + +namespace Coplt +{ + enum class FCmdType : u32 + { + None = 0, + End = 1, + + Label, + BeginScope, + EndScope, + + PreparePresent, + + ClearColor, + ClearDepthStencil, + + BufferCopy, + BufferImageCopy, + + Render, + Compute, + + // Render / Compute + SetPipeline, + SetBinding, + + // Render + SetViewportScissor, + SetMeshBuffers, + Draw, + + // Render / Compute + Dispatch, + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + 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 + { + FGpuOutput2* Output{}; + FGpuBuffer* Buffer; + FGpuImage* Image; + }; + + FCmdResType Type{}; + + #ifdef FFI_SRC + FGpuObject* GetObjectPtr() const + { + switch (Type) + { + case FCmdResType::Image: + return Image; + case FCmdResType::Buffer: + return Buffer; + case FCmdResType::Output: + return Output; + } + return nullptr; + } + #endif + }; + + struct FResIndex + { + u32 Value{}; + + #ifdef FFI_SRC + explicit FResIndex(const u32 Value) : Value(Value) + { + } + + operator u32() const { return Value; } + #endif + }; + + struct FCmdResRef + { + u32 IndexPlusOne{}; + + #ifdef FFI_SRC + explicit operator bool() const { return IndexPlusOne != 0; } + + FResIndex ResIndex() const { return FResIndex{IndexPlusOne - 1}; } + #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{}; + }; + + union FBufferRef2 + { + FCmdResRef Buffer; + FUploadLoc Upload; + }; + + enum class FBufferRefType2 : u8 + { + // GpuBuffer 对象资源引用 + Buffer = 0, + // 当前帧上下文中第几个上传缓冲区 + Upload, + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + 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 FCmdPreparePresent : FCmdBase + { + FCmdResRef Output{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdClearColor : FCmdBase + { + // 有多少个 Rect + u32 RectCount{}; + // 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 FCmdBufferCopy : FCmdBase + { + // 类型为 FBufferCopyRange + u32 RangeIndex{}; + FBufferRef2 Dst{}; + FBufferRef2 Src{}; + FBufferRefType2 DstType{}; + FBufferRefType2 SrcType{}; + }; + + struct FCmdBufferImageCopy : FCmdBase + { + // 类型为 FBufferImageCopyRange + u32 RangeIndex{}; + FCmdResRef Image; + FBufferRef2 Buffer{}; + FBufferRefType2 BufferType{}; + // false 为 Buffer To Image + b8 ImageToBuffer{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdRender : FCmdBase + { + // 类型为 FRenderInfo2 + u32 InfoIndex{}; + u32 CommandCount{}; + }; + + struct FCmdCompute : FCmdBase + { + u32 CommandCount{}; + }; //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdSetPipeline : FCmdBase + { + FShaderPipeline* Pipeline{}; + }; + + struct FCmdBinding + { + FShaderBinding* Binding{}; + }; + + struct FBindingChange + { + // Payload 中的索引,类型为 FCmdBinding + u32 Binding{}; + }; + + struct FCmdSetBinding : FCmdBase + { + // Payload 中的索引,类型为 FCmdBinding + u32 Binding{}; + // 第几个 Set + u32 Index{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdSetViewportScissor : FCmdBase + { + // 有多少个 Viewport + u32 ViewportCount{}; + // Payload 内的索引 + u32 ViewportIndex{}; + // 有多少个 Rect + u32 ScissorRectCount{}; + // Payload 内的索引, 类型为 FRect + 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{}; + // 类型为 FMeshBuffers2 + u32 PayloadIndex{}; + }; + + struct FCmdDraw : FCmdBase + { + u32 VertexOrIndexCount{}; + u32 InstanceCount{}; + u32 FirstVertexOrIndex{}; + u32 FirstInstance{}; + // 仅 Indexed 使用 + u32 VertexOffset{}; + b8 Indexed{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdDispatch : FCmdBase + { + u32 GroupCountX{}; + u32 GroupCountY{}; + u32 GroupCountZ{}; + FDispatchType Type{}; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////// + + struct FCmdItem + { + union + { + FCmdType Type{}; + + FCmdLabel Label; + FCmdBeginScope BeginScope; + FCmdEndScope EndScope; + + FCmdPreparePresent PreparePresent; + + FCmdClearColor ClearColor; + FCmdClearDepthStencil ClearDepthStencil; + + FCmdBufferCopy BufferCopy; + FCmdBufferImageCopy BufferImageCopy; + + FCmdRender Render; + FCmdCompute Compute; + + FCmdSetPipeline SetPipeline; + FCmdSetBinding SetBinding; + + FCmdSetViewportScissor SetViewportScissor; + 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 deleted file mode 100644 index 654d318..0000000 --- a/Coplt.Graphics.Native/Api/FFI/Command.h +++ /dev/null @@ -1,641 +0,0 @@ -#pragma once - -#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::max 表示 empty - 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; - }; - }; - - 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, - Depth = 1, - Stencil = 2, - }; - - struct FUploadLoc - { - u32 Index{}; - }; - - union FBufferRef - { - FResourceRef Buffer; - FUploadLoc Upload; - }; - - enum class FBufferRefType : u8 - { - // GpuBuffer 对象资源引用 - Buffer = 0, - // 当前帧上下文中第几个上传缓冲区 - 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{}; - }; - - enum class FResolveMode : u8 - { - Decompress, - Min, - Max, - Average, - }; - - struct FResolveInfo - { - FResourceRef Src{}; - FResourceRef Dst{}; - FGraphicsFormat Format{}; - FResolveMode Mode{}; - }; - - enum class FLoadOp : u8 - { - Load, - Clear, - Discard, - NoAccess, - }; - - enum class FStoreOp : u8 - { - Store, - Discard, - Resolve, - NoAccess, - }; - - 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{}; - }; - - enum class FDispatchType : u8 - { - Compute, - Mesh, - }; - - //////////////////////////////////////////////////////////////////////////////////////////////////// - - 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/Common.h b/Coplt.Graphics.Native/Api/FFI/Common.h index 370da4c..8053507 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 @@ -56,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) @@ -63,6 +85,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 +141,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/Api/FFI/Context.h b/Coplt.Graphics.Native/Api/FFI/Context.h index 1a5849f..30ea0e9 100644 --- a/Coplt.Graphics.Native/Api/FFI/Context.h +++ b/Coplt.Graphics.Native/Api/FFI/Context.h @@ -14,7 +14,7 @@ namespace Coplt u64 size{}; }; - COPLT_INTERFACE_DEFINE(FFrameContext, "3a22de68-8377-4e57-a167-3efdb97c102a", 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 a61919b..4da9b41 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" @@ -76,21 +77,35 @@ 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, FGpuIsolateCreateResult& out) noexcept = 0; - virtual FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModule** 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 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, FShader** 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 CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroupCreateResult* out) noexcept = 0; + virtual FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBindingCreateResult* out) noexcept = 0; + virtual FResult CreateGraphicsPipeline(const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out) noexcept = 0; virtual FResult CreateBuffer(const FGpuBufferCreateOptions& options, FGpuBuffer** out) noexcept = 0; 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..6656c36 100644 --- a/Coplt.Graphics.Native/Api/FFI/Features.h +++ b/Coplt.Graphics.Native/Api/FFI/Features.h @@ -58,5 +58,11 @@ namespace Coplt b8 DynBindless{}; // 仅动态无绑定模式,将无法使用着色器绑定,着色器布局中只能具有根常量/常量推送,此模式具有设备全局描述符堆 b8 DynBindlessOnly{}; + // 可以任意创建隔离,dx12 永远为 true,vk 永远为 false + b8 ExtraIsolate{}; + // 是否是缓存一致的 UMA 架构 + b8 UMA{}; + // 是否是缓存一致的 UMA 架构 + b8 CacheCoherentUMA{}; }; } diff --git a/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h b/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h index 82262eb..f032a00 100644 --- a/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h +++ b/Coplt.Graphics.Native/Api/FFI/GraphicsFormat.h @@ -625,6 +625,120 @@ 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 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/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 new file mode 100644 index 0000000..2149aad --- /dev/null +++ b/Coplt.Graphics.Native/Api/FFI/Isolate.h @@ -0,0 +1,71 @@ +#pragma once + +#include "GpuObject.h" +#include "Output.h" +#include "Queue.h" + +namespace Coplt +{ + struct FGpuRecord; + struct FGpuRecordCreateResult; + + enum class FGpuIsolateType + { + // 包含 Direct Compute Copy 队列,最多同时具有这3个队列 + // 可以提交异步任务自动调度到队列上,同时如果不支持多队列将回退到主 Direct 队列 + Main, + // 仅包含 Copy 队列,不一定有 + Copy, + // todo video + }; + + struct FGpuIsolateCreateOptions + { + // 可选 + FStr8or16 Name{}; + FGpuIsolateType Type{}; + }; + + 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) + { + virtual FGpuIsolateData* GpuIsolateData() 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 系统上会报错 + 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 + { + FGpuIsolate* Isolate{}; + FGpuIsolateData* Data{}; + }; +} diff --git a/Coplt.Graphics.Native/Api/FFI/Layout.h b/Coplt.Graphics.Native/Api/FFI/Layout.h index 7aab7a6..8bc2541 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,107 +123,157 @@ 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 将会尽可能使用根描述符 + // 只有缓冲区可以使用根描述符,且建议小缓冲区(几个 32 位值)尽量使用根常量 + Dynamic = 1, }; - struct FGetEmptyShaderLayoutOptions + struct FBindGroupLayoutCreateOptions { - FShaderLayoutFlags Flags{}; + FStr8or16 Name{}; + FBindGroupItem* Items{}; + FStaticSamplerInfo* StaticSamplers{}; + u32 NumItems{}; + u32 NumStaticSamplers{}; + FBindGroupUsage Usage{}; }; - COPLT_INTERFACE_DEFINE(FShaderLayout, "552a498e-8f3a-47ff-a335-7af2de0901e8", FGpuObject) + struct FBindGroupLayoutData { - FShaderLayoutFlags Flags{}; + const FBindGroupItem* Items{}; + const FStaticSamplerInfo* StaticSamplers{}; + u32 NumItems{}; + u32 NumStaticSamplers{}; + FBindGroupUsage Usage{}; + }; - 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; + COPLT_INTERFACE_DEFINE(FBindGroupLayout, "312c75eb-30f5-40b3-b79e-acb5498ca9dc", FGpuObject) + { + 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 FBindGroupLayoutCreateResult + { + 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{}; @@ -261,6 +294,8 @@ namespace Coplt #endif }; + //////////////////////////////////////////////////////////////////////////////////////////////////// + struct FMeshLayoutCreateOptions { FStr8or16 Name{}; diff --git a/Coplt.Graphics.Native/Api/FFI/List.h b/Coplt.Graphics.Native/Api/FFI/List.h index 1785bc2..b21ee10 100644 --- a/Coplt.Graphics.Native/Api/FFI/List.h +++ b/Coplt.Graphics.Native/Api/FFI/List.h @@ -5,14 +5,13 @@ #if FFI_SRC #include +#include #endif 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{}; @@ -20,7 +19,7 @@ namespace Coplt size_t m_len{}; size_t m_cap{}; -#ifdef FFI_SRC + #ifdef FFI_SRC constexpr static size_t InitCapacity = 4; @@ -76,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; @@ -91,11 +96,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))); } @@ -135,6 +142,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/Output.h b/Coplt.Graphics.Native/Api/FFI/Output.h index 8f0cb88..fb0177a 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,52 +26,80 @@ namespace Coplt Float16, }; - // 输出格式选择器,按选择器选择,不符合将回退,保证成功;指定格式不保证 - struct FGpuOutputFormatSelector + struct FGpuOutputData { - // 指定格式,忽略选择器 - b8 Specify{}; - // 如果可能,使用 srgb 格式 + FGraphicsFormat Format{}; + u32 Width{}; + u32 Height{}; b8 Srgb{}; - // 如果可能,使用 hdr 格式,和 srgb 冲突,并且优先级更高 FHdrType Hdr{}; + FPresentMode PresentMode{}; + }; + + struct FGpuOutput2CreateOptions + { + FStr8or16 Name{}; + // 呈现模式,实现可以选择忽略 + FPresentMode PresentMode{}; + b8 Srgb{}; + FHdrType Hdr{}; + }; + + 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 FGpuOutputFromSwapChainCreateOptions + struct FGpuSwapChainData : FGpuOutputData { + FOutputAlphaMode AlphaMode{}; b8 VSync{}; + // 是否使用 srgb,实现可以选择忽略 + b8 Srgb{}; + // 是否使用 hdr,实现可以选择忽略 + FHdrType Hdr{}; }; - struct FGpuOutputCreateOptions + struct FGpuSwapChainCreateOptions : FGpuOutput2CreateOptions { - FStr8or16 Name{}; u32 Width{}; u32 Height{}; - FGraphicsFormat Format{}; - // 呈现模式,实现可以选择忽略 - FPresentMode PresentMode{}; FOutputAlphaMode AlphaMode{}; b8 VSync{}; - FGpuOutputFormatSelector FormatSelector{}; }; - using WhenDoneFn = void COPLT_CDECL(void* obj); + struct FGpuSwapChainFromExistsCreateOptions : FGpuOutput2CreateOptions + { + // d3d12 是 IDXGISwapChain3* + void* ExistsSwapChain{}; + FOutputAlphaMode AlphaMode{}; + b8 VSync{}; + }; - struct FCommandSubmit; + struct FGpuIsolate; - COPLT_INTERFACE_DEFINE(FGpuOutput, "f1c59cb4-7ee6-4ee2-80f4-07cc568920d2", FGpuExecutor) + COPLT_INTERFACE_DEFINE(FGpuSwapChain, "2bc677a1-77fc-4540-89e2-1fb7e3417dc2", FGpuOutput2) { - FResState m_state{}; - // 外部不允许修改 - FGraphicsFormat m_format{}; - // 外部不允许修改 - u32 m_width{}; - // 外部不允许修改 - u32 m_height{}; + virtual const FGpuSwapChainData* GpuSwapChainData() noexcept = 0; + virtual FGpuIsolate* GetIsolate() noexcept = 0; // 设置垂直同步,实现可以选择忽略 virtual FResult SetVSync(b8 Enable) noexcept = 0; - virtual FResult Resize(u32 Width, u32 Height) noexcept = 0; + // dx 后端是 IDXGISwapChain3* + virtual void* GetRawPtr() const noexcept = 0; + }; + + struct FGpuSwapChainCreateResult + { + FGpuSwapChain* SwapChain{}; + FGpuSwapChainData* Data{}; }; } 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/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 9c657c0..72d3427 100644 --- a/Coplt.Graphics.Native/Api/FFI/Queue.h +++ b/Coplt.Graphics.Native/Api/FFI/Queue.h @@ -1,55 +1,46 @@ #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, Compute, Copy, - Video, + VideoEncode, + VideoDecode, + 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) + struct FGpuQueueData { - // 不安全的内存暴露,外部不能修改,每帧必须保证当前指向可用的帧上下文 - FFrameContext* m_context{}; - // 不安全的内存暴露,外部不能修改,每次提交都会增加计数 - u64 m_submit_id{}; - // 不安全的内存暴露,外部不能修改 - FGpuQueueType m_queue_type{}; + FGpuQueueType QueueType{}; + }; + COPLT_INTERFACE_DEFINE(FGpuQueue2, "fc94e4d0-5f01-4d4f-894c-6aefaad90499", FGpuObject) + { + virtual FGpuQueueData* GpuQueueData() noexcept = 0; // 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 FGpuQueueCreateResult + { + FGpuQueue2* Queue{}; + FGpuQueueData* Data{}; }; } diff --git a/Coplt.Graphics.Native/Api/FFI/Record.h b/Coplt.Graphics.Native/Api/FFI/Record.h new file mode 100644 index 0000000..1d7f9ba --- /dev/null +++ b/Coplt.Graphics.Native/Api/FFI/Record.h @@ -0,0 +1,82 @@ +#pragma once + +#include "Cmd.h" +#include "GpuObject.h" +#include "Isolate.h" + +namespace Coplt +{ + enum class FGpuRecordMode : u8 + { + Direct = 0, + Compute = 1, + Copy = 2, + }; + + struct FGpuRecordData; + + 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 + { + u64 Id{}; + u64 Version{}; + FRecordContext* Context{}; + FList Commands; + FList Resources; + FList Bindings; + FList BindingChange; + FList PayloadRect; + FList PayloadViewport; + FList PayloadRenderInfo; + FList PayloadResolveInfo; + FList PayloadBufferCopyRange; + FList PayloadBufferImageCopyRange; + FList PayloadMeshBuffers; + FList PayloadVertexBufferRange; + FList Blob; + u32 NumSetBindings{}; + b8 Ended{}; + FGpuRecordMode Mode{}; + + #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), + PayloadBufferImageCopyRange(allocator), PayloadMeshBuffers(allocator), PayloadVertexBufferRange(allocator), Blob(allocator) + { + } + + void ClearData() + { + Commands.Clear(); + Resources.Clear(); + Bindings.Clear(); + BindingChange.Clear(); + PayloadRect.Clear(); + PayloadViewport.Clear(); + PayloadRenderInfo.Clear(); + PayloadResolveInfo.Clear(); + PayloadBufferCopyRange.Clear(); + PayloadBufferImageCopyRange.Clear(); + PayloadMeshBuffers.Clear(); + PayloadVertexBufferRange.Clear(); + Blob.Clear(); + NumSetBindings = 0; + } + #endif + }; + + struct FGpuRecordCreateResult + { + FGpuRecord* Record{}; + FGpuRecordData* Data{}; + }; +} 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 a7c8200..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,8 +44,33 @@ 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; }; + + 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 ce254e0..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" @@ -35,7 +39,7 @@ namespace Coplt FShaderStage Stage{}; }; - COPLT_INTERFACE_DEFINE(FShaderModule, "5c0e1fdb-2acd-4fce-b985-09e12a7a1aad", FGpuObject) + struct FShaderModuleData { // 外部只读 u8* Data{}; @@ -43,9 +47,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 +86,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 +111,75 @@ 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{}; + }; + + #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/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/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/FFI/Structs.h b/Coplt.Graphics.Native/Api/FFI/Structs.h new file mode 100644 index 0000000..375ea3e --- /dev/null +++ b/Coplt.Graphics.Native/Api/FFI/Structs.h @@ -0,0 +1,95 @@ +#pragma once + +#include "Common.h" +#include "GraphicsFormat.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; + }; + + COPLT_ENUM_FLAGS(FDepthStencilClearFlags, u8) + { + None = 0, + 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, + }; + + 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{}; + }; + + enum class FDispatchType : u8 + { + Compute, + Mesh, + }; +} diff --git a/Coplt.Graphics.Native/Api/FFI/Types.h b/Coplt.Graphics.Native/Api/FFI/Types.h index f440899..f27a8ad 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 @@ -61,9 +62,14 @@ 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; + #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/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/Api/Include/Error.h b/Coplt.Graphics.Native/Api/Include/Error.h index 97a9913..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); @@ -308,4 +314,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/Api/Include/Finally.h b/Coplt.Graphics.Native/Api/Include/Finally.h new file mode 100644 index 0000000..cdc5f17 --- /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() noexcept(false) + { + f(); + } + }; +} diff --git a/Coplt.Graphics.Native/Api/Include/HashMap.h b/Coplt.Graphics.Native/Api/Include/HashMap.h index 423741f..887306a 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); @@ -425,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; } @@ -569,7 +567,7 @@ namespace Coplt } // 返回是否添加 - template CreateValue> + template > CreateValue> bool TryAdd(const Key& key, CreateValue create_value) { return TryInsert( @@ -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/Object.h b/Coplt.Graphics.Native/Api/Include/Object.h index 58f8f04..37b7a48 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,27 @@ 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); + } + }; + + template + struct SubObject : Base + { + void* ObjectStart() noexcept override + { + This* self = static_cast(this); + return self; } }; @@ -650,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; } @@ -659,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/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/Api/Include/Utils.h b/Coplt.Graphics.Native/Api/Include/Utils.h index fb864e6..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 @@ -12,6 +15,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) @@ -52,4 +64,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/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/CMakeLists.txt b/Coplt.Graphics.Native/D3d12/CMakeLists.txt index d68c01a..aea41f4 100644 --- a/Coplt.Graphics.Native/D3d12/CMakeLists.txt +++ b/Coplt.Graphics.Native/D3d12/CMakeLists.txt @@ -14,21 +14,15 @@ 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 - FFI/Layout.h Src/Layout.h Src/Layout.cc Include/ShaderVisibility.h Include/PipelineState.h - Src/CmdListPack.h Src/Buffer.h Src/Buffer.cc FFI/Resource.h @@ -37,13 +31,9 @@ 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 - Src/DescriptorManager.cc Include/View.h - Src/Executor.h FFI/Adapter.h Src/Adapter.h Src/Adapter.cc @@ -55,6 +45,19 @@ add_library(${target_name} SHARED Src/Sampler.h Src/Sampler.cc Include/Sampler.h + Src/Isolate.h + Src/Isolate.cc + Src/Record.h + Src/Record.cc + Src/SwapChain.h + Src/SwapChain.cc + Src/Barrier.h + Src/Barrier.cc + Include/ResState.h + 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/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/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/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/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/FFI/Queue.h b/Coplt.Graphics.Native/D3d12/FFI/Queue.h index 23c4e65..b0b84ec 100644 --- a/Coplt.Graphics.Native/D3d12/FFI/Queue.h +++ b/Coplt.Graphics.Native/D3d12/FFI/Queue.h @@ -4,7 +4,7 @@ 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..91cfe46 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 @@ -164,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/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/Include/ResState.h b/Coplt.Graphics.Native/D3d12/Include/ResState.h new file mode 100644 index 0000000..5461932 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Include/ResState.h @@ -0,0 +1,121 @@ +#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, + ShadingRateSource, + VideoEncodeRead, + VideoEncodeWrite, + VideoDecodeRead, + VideoDecodeWrite, + VideoProcessRead, + VideoProcessWrite, + }; + + struct ResState + { + 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 Same(const ResState& other) const; + }; + + struct LayoutState + { + ResLayout Layout{}; + }; + + bool IsValid(ResAccess access); + + ResUseType GetUseType(ResAccess access); + + bool IsReadOnly(ResAccess access); + + bool IsCompatible(ResAccess Old, ResAccess New); + + D3D12_RESOURCE_STATES GetResourceState(ResAccess access); + + D3D12_RESOURCE_STATES GetResourceState(ResLayout layout); + + D3D12_BARRIER_ACCESS GetBarrierAccess(ResAccess access); + + D3D12_BARRIER_LAYOUT GetBarrierLayout(ResLayout layout); + + D3D12_BARRIER_SYNC GetBarrierSync(ResAccess access, ResUsage usage); +} 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/States.h b/Coplt.Graphics.Native/D3d12/Include/States.h index 2f3b210..1a3a8b3 100644 --- a/Coplt.Graphics.Native/D3d12/Include/States.h +++ b/Coplt.Graphics.Native/D3d12/Include/States.h @@ -6,298 +6,7 @@ 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::Video: - 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> + template F> inline D3D12_RENDER_PASS_BEGINNING_ACCESS ToDx(const FLoadOp load, F SetClearValue) { D3D12_RENDER_PASS_BEGINNING_ACCESS acc{}; @@ -320,7 +29,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/Include/View.h b/Coplt.Graphics.Native/D3d12/Include/View.h index 180b249..e8be9c8 100644 --- a/Coplt.Graphics.Native/D3d12/Include/View.h +++ b/Coplt.Graphics.Native/D3d12/Include/View.h @@ -2,79 +2,56 @@ #include +#include +#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 { - struct View final + COPLT_INTERFACE_DEFINE(ID3d12GpuViewable, "597cbbb5-add9-45e3-bbba-802f63465c8e", FGpuViewable) { - enum class Type : u8 - { - None, - Buffer, - Image, - Sampler, - }; + virtual bool IsCompatible(const FBindGroupItem& def) const = 0; + }; - private: - union - { - Rc m_buffer; - Rc m_image; - Rc m_sampler; - }; + struct ID3d12GpuBuffer; + struct ID3d12GpuImage; + struct ID3d12GpuSampler; - Type m_type; + struct View final + { + Rc m_viewable{}; + FViewType 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() = default; - ~View(); + View& swap(View& other) noexcept; - View(); + View(const View& other) noexcept = default; + View& operator=(const View& view) = default; - View(const View& other); - View(View&& other) noexcept; - View& operator=(const View& view) noexcept; - View& operator=(View&& view) noexcept; + View(View&& other) noexcept = default; + View& operator=(View&& view) = default; 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); - - 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; + 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; + Ptr TryGetSampler() 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/Adapter.cc b/Coplt.Graphics.Native/D3d12/Src/Adapter.cc index 0be8f25..55cbdd3 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) @@ -57,13 +58,16 @@ 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, 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/Barrier.cc b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc new file mode 100644 index 0000000..bba3d8a --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.cc @@ -0,0 +1,586 @@ +#include "Barrier.h" + +#include "Record.h" + +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(); +} + +bool ID3d12EnhancedBarrierAnalyzer::Group::IsEmpty() const +{ + return m_buffer_barriers.empty() && m_texture_barriers.empty(); +} + +ID3d12EnhancedBarrierAnalyzer::ResInfo::ResInfo(const u32 ResIndex) : ResIndex(ResIndex) +{ +} + +void ID3d12EnhancedBarrierAnalyzer::ResInfo::SetNewState(const ResState state) +{ + OldState = State; + State = state; +} + +namespace Coplt::Enhanced +{ + EnhancedBarrierMarshal::EnhancedBarrierMarshal(const D3d12GpuIsolate& isolate) + : m_isolate_config(isolate.m_config), m_device(isolate.m_device) + { + } + + Rc EnhancedBarrierMarshal::CreateAnalyzer() + { + return new EnhancedBarrierAnalyzer(*this); + } + + Rc EnhancedBarrierMarshal::CreateCombiner() + { + return new EnhancedBarrierCombiner(m_device); + } + + EnhancedBarrierAnalyzer::EnhancedBarrierAnalyzer(const EnhancedBarrierMarshal& marshal) + : m_isolate_config(marshal.m_isolate_config), m_device(marshal.m_device) + { + } + + std::span EnhancedBarrierAnalyzer::Inputs() const + { + return m_inputs; + } + + std::span EnhancedBarrierAnalyzer::Outputs() const + { + return m_outputs; + } + + std::span EnhancedBarrierAnalyzer::Groups() + { + return m_groups; + } + + ID3d12EnhancedBarrierAnalyzer::Group& EnhancedBarrierAnalyzer::CurGroup() + { + return m_groups.back(); + } + + const ID3d12EnhancedBarrierAnalyzer::Group& EnhancedBarrierAnalyzer::CurGroup() const + { + return m_groups.back(); + } + + u32 EnhancedBarrierAnalyzer::CurGroupIndex() const + { + return m_groups.size() - 1; + } + + void EnhancedBarrierAnalyzer::Clear() + { + m_resources.clear(); + m_inputs.clear(); + m_outputs.clear(); + m_groups.clear(); + } + + void EnhancedBarrierAnalyzer::StartAnalyze(NonNull record) + { + m_record = record; + Clear(); + m_use_split_barrier = m_isolate_config->UseSplitBarrier; + m_groups.push_back({}); + } + + void EnhancedBarrierAnalyzer::EndAnalyze() + { + 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(IOResState{.ResIndex = i, .LstGroup = info.LstGroup, .State = info.State}); + } + else + { + CreateBarrier(info); + } + m_outputs.push_back(IOResState{.ResIndex = i, .LstGroup = info.LstGroup, .State = info.State}); + } + m_record = NonNull::Unchecked(nullptr); + } + + 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) + { + 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 (need_split) Split(); + info.PreGroup = 0; + info.LstGroup = info.CurGroup = CurGroupIndex(); + return; + } + else if (info.InfoState == InfoState::Input) + { + if (info.State.IsCompatible(new_state, true)) + { + info.State = info.State.Merge(new_state); + goto End; + } + info.InfoState = InfoState::Used; + m_inputs.push_back(IOResState{.ResIndex = ResIndex, .LstGroup = info.LstGroup, .State = info.State}); + if (info.CurGroup == CurGroupIndex() || need_split) Split(); + goto EndState; + } + else + { + if (info.State.IsCompatible(new_state, true)) + { + info.State = info.State.Merge(new_state); + goto End; + } + } + if (info.CurGroup == CurGroupIndex() || need_split) Split(); + CreateBarrier(info); + EndState: + info.SetNewState(new_state); + info.PreGroup = info.CurGroup; + info.LstGroup = info.CurGroup = CurGroupIndex(); + return; + End: + info.CurGroup = CurGroupIndex(); + return; + } + + void EnhancedBarrierAnalyzer::OnUse(const FResIndex ResIndex, const View& View, const Layout::GroupItemInfo& 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(const FResIndex 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.CurGroup = CurGroupIndex(); + } + + void EnhancedBarrierAnalyzer::OnCmd() + { + m_last_cmd_count++; + } + + void EnhancedBarrierAnalyzer::CmdNext() + { + CurGroup().m_cmd_count++; + } + + void EnhancedBarrierAnalyzer::Split() + { + 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 EnhancedBarrierAnalyzer::CreateBarrier(const ResInfo& info) + { + 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); + 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& barrier) + { + if (BeforeListIndex >= AfterListIndex) + { + barrier.SyncAfter = SyncAfter; + m_groups[AfterListIndex].Push(barrier); + } + else if (m_use_split_barrier) + { + m_groups[BeforeListIndex].Push(barrier); + + barrier.SyncBefore = D3D12_BARRIER_SYNC_SPLIT; + barrier.SyncAfter = SyncAfter; + m_groups[AfterListIndex].Push(barrier); + } + else + { + barrier.SyncAfter = SyncAfter; + m_groups[BeforeListIndex].Push(barrier); + } + }; + if (res.IsImage()) + { + const auto img_data = res.GetImageData(); + 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 = res.GetResource(), + .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(barrier); + } + else + { + const auto buffer_data = res.GetBufferData(); + D3D12_BUFFER_BARRIER barrier{ + .SyncBefore = SyncBefore, + .SyncAfter = D3D12_BARRIER_SYNC_SPLIT, + .AccessBefore = AccessBefore, + .AccessAfter = AccessAfter, + .pResource = res.GetResource(), + .Offset = 0, + .Size = buffer_data->m_size, + }; + push(barrier); + } + } + + 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) + { + 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(); + } + } + + EnhancedBarrierCombiner::EnhancedBarrierCombiner(const Rc& device) + { + m_device = device; + } + + void EnhancedBarrierCombiner::EndSubmit() + { + Base::EndSubmit(); + m_tmp_group.Clear(); + } + + void EnhancedBarrierCombiner::Process(NonNull isolate, std::span> records) + { + for (const auto& record : records) + { + const auto resource_infos = record->ResourceInfos(); + 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()) + { + const auto& res = resource_infos[input.ResIndex]; + bool exist; + auto& sr = m_submit_resources.GetOrAdd(res.Resource->ObjectId(), exist, [&](auto& p) + { + p.put(ResInfo{ + .Record = record, + .ResIndex = input.ResIndex, + .State = res.GetState(), + }); + }); + if (!exist) + { + if (sr.State->Layout != input.State.Layout) + { + auto& group = result_list ? m_tmp_group : barrier_analyzer->Groups()[0]; + if (res.IsImage()) + { + 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, + .SyncAfter = SyncAfter, + .AccessBefore = D3D12_BARRIER_ACCESS_NO_ACCESS, + .AccessAfter = GetBarrierAccess(input.State.Access), + .LayoutBefore = GetBarrierLayout(sr.State->Layout), + .LayoutAfter = GetBarrierLayout(input.State.Layout), + .pResource = res.GetResource(), + .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 = 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 = res.GetResource(), + .Offset = 0, + .Size = buffer_data->m_size, + }; + barrier.SyncAfter = SyncAfter; + group.Push(barrier); + } + } + } + // todo + } + + #pragma endregion + + #pragma region 完成录制 记录 list 节点 + + { + ListNode node{}; + // todo fence + node.Queue = FGpuQueueType::Direct; // todo 选择队列 + node.ListIndex = m_lists.size(); + node.ListCount++; + + if (!m_tmp_group.IsEmpty()) + { + auto allocator = context->m_cmd_alloc_pool->RentCommandAllocator(GetType(record->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(record->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)); + } + + m_list_node.push_back(node); + } + + #pragma endregion + + #pragma region 记录输出状态 + + for (const auto& output : barrier_analyzer->Outputs()) + { + const auto& res = resource_infos[output.ResIndex]; + const auto state = res.GetState(); + state->Layout = output.State.Layout; + m_submit_resources.AddOrReplace( + res.Resource->ObjectId(), ResInfo{ + .Record = record, + .ResIndex = output.ResIndex, + .State = state, + } + ); + } + + #pragma endregion + } + } +} + +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; +} + +bool AD3d12BarrierCombiner::Submit(NonNull isolate, std::span> records) +{ + StartSubmit(); + Process(isolate, records); + 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& node : m_list_node) + { + const auto& queue = isolate->GetQueue(node.Queue); + for (u32 i = 0; i < node.DepCount; ++i) + { + 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(node.ListCount, m_lists.data() + node.ListIndex); + } + + #pragma endregion + + #pragma region 在主队列中等待其他队列 + + { + 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 + + #pragma region 所有录制都在主队列中等待执行结束 + + const auto fence_value = main_queue->Signal(); + for (const auto& record : records) + { + record->RegisterWaitPoint(QueueWaitPoint(main_queue, fence_value)); + } + + #pragma endregion + } + EndSubmit(); + for (const auto& record : records) + { + record->AfterSubmit(); + } + return has_submit; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Barrier.h b/Coplt.Graphics.Native/D3d12/Src/Barrier.h new file mode 100644 index 0000000..8d427ab --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Barrier.h @@ -0,0 +1,198 @@ +#pragma once + +#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" +#include "../Include/View.h" + +namespace Coplt +{ + struct IOResState + { + u32 ResIndex{}; + u32 LstGroup{}; + ResState State{}; + }; + + struct ID3d12BarrierAnalyzer; + struct ID3d12BarrierCombiner; + struct D3d12GpuRecord; + struct ResourceInfo; + + COPLT_INTERFACE_DEFINE(ID3d12BarrierMarshal, "792f273c-376d-4027-af99-0d14d3d71302", FUnknown) + { + virtual Rc CreateAnalyzer() = 0; + virtual Rc CreateCombiner() = 0; + }; + + 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 StartAnalyze(NonNull record) = 0; + virtual void EndAnalyze() = 0; + 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::GroupItemInfo& info) = 0; + virtual void UpdateUse(FResIndex ResIndex) = 0; + 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) + { + // 返回是否有实际提交,如果没有实际提交可以直接回收录制,不然就需要等待提交执行完成 + virtual bool Submit(NonNull isolate, std::span> records) = 0; + }; + + struct AD3d12BarrierCombiner : Object + { + struct ResInfo + { + NonNull Record; + u32 ResIndex{}; + NonNull State; + }; + + struct ListNode + { + u32 DepIndex{}; + u32 DepCount{}; + 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{}; + 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; + }; + + 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(); + bool IsEmpty() const; + }; + + struct ResInfo + { + u32 ResIndex; + ResState State{}; + ResState OldState{}; + u32 PreGroup{COPLT_U32_MAX}; + u32 LstGroup{COPLT_U32_MAX}; + u32 CurGroup{COPLT_U32_MAX}; + InfoState InfoState{}; + + explicit ResInfo(u32 ResIndex); + + void SetNewState(ResState state); + }; + + virtual std::span Groups() = 0; + }; + + namespace Enhanced + { + struct EnhancedBarrierMarshal final : Object + { + SRc m_isolate_config{}; + Rc m_device; + + explicit EnhancedBarrierMarshal(const D3d12GpuIsolate& isolate); + + Rc CreateAnalyzer() override; + Rc CreateCombiner() override; + }; + + struct EnhancedBarrierAnalyzer final : Object + { + SRc m_isolate_config{}; + Rc m_device{}; + std::vector m_resources{}; + std::vector m_inputs{}; + std::vector m_outputs{}; + 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); + + 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 StartAnalyze(NonNull record) override; + void EndAnalyze() override; + void OnAddRes() override; + + void OnUse(FResIndex ResIndex, ResAccess Access, ResUsage Usage, ResLayout Layout) override; + void OnUse(FResIndex ResIndex, const View& View, const Layout::GroupItemInfo& info) override; + void UpdateUse(FResIndex ResIndex) override; + void OnCmd() override; + void CmdNext() override; + + void Split(); + 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); + + ID3d12EnhancedBarrierAnalyzer::Group m_tmp_group{}; + + void EndSubmit() override; + + void Process(NonNull isolate, std::span> records) override; + }; + } +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.cc b/Coplt.Graphics.Native/D3d12/Src/Binding.cc index e5c23bc..6788291 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.cc @@ -2,148 +2,286 @@ #include "Layout.h" #include "../../Api/Include/Error.h" -#include "../FFI/Layout.h" #include "Queue.h" #include "../../Api/Include/AllocObjectId.h" #include "../Include/GraphicsFormat.h" 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)) { - m_dx_device = m_device->m_device; - - m_layout = Rc::UnsafeClone(options.Layout->QueryInterface()); - if (m_layout == nullptr) + const auto layout = NonNull(options.Layout)->QueryInterface(); + if (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) + m_layout = Rc::UnsafeClone(layout); + const auto items = m_layout->GetItems(); + usize sum_count = 0; + for (const auto& item : items) + { + sum_count += std::max(1u, item.Count); + } + 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) { - 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) + m_item_indexes.push_back(off); + const auto count = std::max(1u, items[i].Count); + off += count; + for (int j = 0; j < count; ++j) { - const auto& meta = group.Metas[j]; - items[j].reserve(meta.Ranges.size()); + m_define_indexes.push_back(i); } } - - const auto infos = m_layout->GetItemInfos(); - for (size_t i = 0; i < infos.size(); ++i) + 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()) { - const auto& info = infos[i]; - m_item_indexes[info.Class][info.Group].push_back(i); + m_name = options.Name.ToString(); + DoSetName(m_name->GetStr()); } + Set(std::span(options.Bindings, options.Bindings + options.NumBindings)); } -FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept +FResult D3d12ShaderBindGroup::SetName(const FStr8or16& name) noexcept { - return FResult::None(); + return feb([&] + { + m_name = name.ToString(); + DoSetName(name); + }); } -void D3d12ShaderBinding::Set(const std::span bindings) +void D3d12ShaderBindGroup::DoSetName(const FStr8or16& name) const { - auto infos = m_layout->GetItemInfos(); - auto item_defines = m_layout->GetItemDefines(); - for (const auto& [View, Index] : bindings) + if (name.is_null()) return; + if (m_resource_heap) { - 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) + if (name.is8()) { - 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; + const auto str = fmt::format("[{}]::ResourceDescriptorHeap", name.str8); + chr | m_resource_heap >> SetNameEx(FStr8or16(str)); } - m_views[Index] = View; - if (info.Place == FShaderLayoutItemPlace::Grouped) + else { - m_changed_groups.Add((static_cast(info.Class) << 32) | static_cast(info.Group)); + 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; +} + +u64 D3d12ShaderBindGroup::Version() const noexcept +{ + return m_version; } -const Rc& D3d12ShaderBinding::Layout() noexcept +const Rc& D3d12ShaderBindGroup::Layout() const noexcept { return m_layout; } -std::span D3d12ShaderBinding::Views() noexcept +std::span D3d12ShaderBindGroup::Views() const noexcept { return m_views; } -bool D3d12ShaderBinding::Changed() noexcept +std::span D3d12ShaderBindGroup::ItemIndexes() const noexcept { - return !m_changed_groups.IsEmpty(); + return m_item_indexes; } -const HashSet& D3d12ShaderBinding::ChangedGroups() noexcept +std::span D3d12ShaderBindGroup::DefineIndexes() const noexcept { - return m_changed_groups; + return m_define_indexes; } -std::span>> D3d12ShaderBinding::DescHeaps() noexcept +RwLock& D3d12ShaderBindGroup::SelfLock() noexcept { - return m_desc_heaps; + return m_self_lock; } -void D3d12ShaderBinding::Update(NonNull queue) +void D3d12ShaderBindGroup::Set(const std::span items) { - 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()) + if (items.empty()) return; + const auto defs = m_layout->GetItems(); + const auto slots = m_layout->Slots(); + for (const auto& item : items) { - 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) + 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) { - 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); + 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); + const auto& slot = slots[item.Slot]; + if (slot.Place == Layout::BindSlotPlace::NonTable) continue; + m_changed_marks[index] = true; + } + m_changed = true; + m_version++; +} + +bool D3d12ShaderBindGroup::EnsureAvailable() +{ + if (!m_changed) return false; + std::lock_guard guard(m_desc_lock); + 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) + { + 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]) 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; + 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; + 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)) +{ + 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.BindGroups, options.BindGroups + options.NumBindGroups)); +} + +FResult D3d12ShaderBinding::SetName(const FStr8or16& name) noexcept +{ + return FResult::None(); } -void D3d12ShaderBinding::ApplyChange() +FShaderBindingData* D3d12ShaderBinding::ShaderBindingData() noexcept { - m_changed_groups.Clear(); + return this; +} + +u64 D3d12ShaderBinding::Version() const noexcept +{ + return m_version; +} + +const Rc& D3d12ShaderBinding::Layout() const noexcept +{ + return m_layout; +} + +std::span> D3d12ShaderBinding::Groups() const noexcept +{ + return m_groups; +} + +RwLock& D3d12ShaderBinding::SelfLock() noexcept +{ + return m_self_lock; +} + +void D3d12ShaderBinding::Set(const std::span items) +{ + if (items.size() == 0) return; + for (const auto& item : items) + { + if (item.Index >= m_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_version++; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Binding.h b/Coplt.Graphics.Native/D3d12/Src/Binding.h index 4c8000c..0c58245 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Binding.h +++ b/Coplt.Graphics.Native/D3d12/Src/Binding.h @@ -2,70 +2,108 @@ #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 "../FFI/Layout.h" #include "../Include/View.h" +#include "Device.h" +#include "Layout.h" namespace Coplt { struct DescriptorHeap; - struct D3d12GpuQueue; + struct ID3d12ShaderBinding; struct DescriptorAllocation; - COPLT_INTERFACE_DEFINE(ID3d12ShaderBinding, "84f2b3e2-bb16-4276-ba3f-5da54eda462d", FD3d12ShaderBinding) + COPLT_INTERFACE_DEFINE(ID3d12ShaderBindGroup, "5bb948b9-ad31-4eb8-b881-98017e048259", FShaderBindGroup) { - 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)}; - }); - } + 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 bool EnsureAvailable() = 0; + + virtual const ComPtr& ResourceHeap() noexcept = 0; + virtual const ComPtr& SamplerHeap() noexcept = 0; }; - struct D3d12ShaderBinding final : GpuObject + struct D3d12ShaderBindGroup final : GpuObject, FShaderBindGroupData { + volatile u64 m_version{}; + Rc m_name{}; Rc m_device{}; - ComPtr m_dx_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{}; - std::vector>> m_item_indexes{}; - std::vector>> m_desc_heaps{}; - // std::vector> m_allocations{}; - HashSet m_changed_groups{}; + // 这里就是 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 D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); + explicit D3d12ShaderBindGroup(Rc&& device, const FShaderBindGroupCreateOptions& options); + FResult SetName(const FStr8or16& name) noexcept override; + void DoSetName(const FStr8or16& name) const; + + 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; + std::span DefineIndexes() const noexcept override; + RwLock& SelfLock() noexcept override; + + // 需要外部锁 m_self_lock 必须是 Write 锁定状态 + void Set(std::span items); + // 需要外部锁 m_self_lock 必须是 Read 锁定状态 + 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; + }; + + struct D3d12ShaderBinding final : GpuObject, FShaderBindingData + { + volatile u64 m_version{}; + Rc m_device{}; + Rc m_layout{}; + std::vector> m_groups{}; + // 绑定修改锁 + RwLock m_self_lock{}; + + explicit D3d12ShaderBinding(Rc&& device, const FShaderBindingCreateOptions& options); FResult SetName(const FStr8or16& name) noexcept override; - void Set(std::span bindings) override; + FShaderBindingData* ShaderBindingData() noexcept 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; + u64 Version() const noexcept override; + const Rc& Layout() const noexcept override; + std::span> Groups() const noexcept override; + RwLock& SelfLock() noexcept override; - void Update(NonNull queue) override; - void ApplyChange() override; + // 需要外部锁 m_self_lock 必须是 Write 锁定状态 + void Set(std::span items); }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Buffer.cc b/Coplt.Graphics.Native/D3d12/Src/Buffer.cc index ac037cb..166303e 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,24 +57,24 @@ FResult D3d12GpuBuffer::SetName(const FStr8or16& name) noexcept }); } -ResourceType D3d12GpuBuffer::GetResourceType() noexcept +FGpuResourceData* D3d12GpuBuffer::GpuResourceData() noexcept { - return ResourceType::Buffer; + return this; } -FGpuViewableData* D3d12GpuBuffer::GpuViewableData() noexcept +FGpuBufferData* D3d12GpuBuffer::GpuBufferData() noexcept { return this; } -FGpuResourceData* D3d12GpuBuffer::GpuResourceData() noexcept +NonNull D3d12GpuBuffer::Data() { return this; } -FGpuBufferData* D3d12GpuBuffer::GpuBufferData() noexcept +NonNull D3d12GpuBuffer::State() { - return this; + return &m_layout_state; } void* D3d12GpuBuffer::GetRawResourcePtr() noexcept @@ -102,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 c2bfc29..cb45a96 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Buffer.h +++ b/Coplt.Graphics.Native/D3d12/Src/Buffer.h @@ -9,16 +9,21 @@ #include "Resource.h" #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; + virtual NonNull State() = 0; }; struct D3d12GpuBuffer final : GpuObject, FGpuBufferData { + LayoutState m_layout_state{}; Rc m_device{}; Rc m_name{}; ComPtr m_allocator{}; @@ -29,15 +34,17 @@ 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; + NonNull State() override; void* GetRawResourcePtr() noexcept override; NonNull GetResourcePtr() override; 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/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 6133207..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->GetDataPtr(); - 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 a7a7aa3..abb11df 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Context.cc @@ -2,32 +2,20 @@ using namespace Coplt; -D3d12FrameContext::D3d12FrameContext(Rc&& queue) : m_queue(std::move(queue)) +D3d12RecordContext::D3d12RecordContext(NonNull isolate) { - m_device = m_queue->m_device; - m_dx_device = m_queue->m_dx_device; - - m_descriptors = new DescriptorContext(m_dx_device); - + 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()); - - 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 +FResult D3d12RecordContext::SetName(const FStr8or16& name) noexcept { - return feb([&] - { - }); + return FResult::None(); } -FResult D3d12FrameContext::GrowUploadBuffer(const u64 min_required_size) noexcept +FResult D3d12RecordContext::GrowUploadBuffer(u64 min_required_size) noexcept { return feb([&] { @@ -60,9 +48,10 @@ FResult D3d12FrameContext::GrowUploadBuffer(const u64 min_required_size) noexcep }); } -void D3d12FrameContext::Recycle() +void D3d12RecordContext::Recycle() { - chr | m_command_allocator->Reset(); + m_recycled_command_allocators.clear(); + if (!m_upload_buffers.empty()) { { @@ -79,3 +68,328 @@ void D3d12FrameContext::Recycle() } } } + +D3d12CommandPool::D3d12CommandPool(const Rc& device, const D3D12_COMMAND_LIST_TYPE type) + : m_device(device), m_type(type) +{ + m_command_allocator_pool = box(); + m_command_list_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(); +} + +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)) +{ +} + +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); +} + +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)) +{ +} + +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)); +} + +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 b766439..f02ea63 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Context.h +++ b/Coplt.Graphics.Native/D3d12/Src/Context.h @@ -1,28 +1,33 @@ #pragma once +#include + #include "../../Api/FFI/Context.h" #include "../../Api/Include/Object.h" -#include "CmdListPack.h" #include "Device.h" +#include "Isolate.h" #include "Queue.h" #include "Resource.h" namespace Coplt { - struct D3d12FrameContext final : GpuObject + struct D3d12CommandList; + struct D3d12RentedCommandList; + struct D3d12RentedCommandAllocator; + + struct D3d12RecordContext 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{}; + DescriptorManager m_descriptor_manager{}; + 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{}; - explicit D3d12FrameContext(Rc&& queue); + explicit D3d12RecordContext(NonNull isolate); FResult SetName(const FStr8or16& name) noexcept override; @@ -31,4 +36,127 @@ 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); + + private: + friend struct D3d12RentedCommandList; + friend struct D3d12RentedCommandAllocator; + + 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 + { + 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; + + void Close(); + }; + + // 必须等待队列 fence 完成才能析构,或者可以 move 走 + struct D3d12RentedCommandAllocator final + { + Rc m_pool{}; + ComPtr m_allocator{}; + + D3d12RentedCommandAllocator() = default; + 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; + + operator bool() const noexcept; + }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc index 3d0a0c9..c44d2ef 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.cc @@ -1,239 +1,134 @@ #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 u64 offset) + : m_heap(heap), 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 +CD3DX12_CPU_DESCRIPTOR_HANDLE DescriptorAllocation::GetCpuHandle() const { - return m_heap; + if (!m_heap) return {}; + return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_heap->m_heap->GetCPUDescriptorHandleForHeapStart(), m_offset, m_heap->m_inc); } -u64 DescriptorHeap::Id() const +CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorAllocation::GetGpuHandle() const { - return m_id; + if (!m_heap) return {}; + return CD3DX12_GPU_DESCRIPTOR_HANDLE(m_heap->m_heap->GetGPUDescriptorHandleForHeapStart(), m_offset, m_heap->m_inc); } -u64 DescriptorHeap::Version() const +DescriptorAllocation::operator bool() const { - return m_version; + return m_heap != nullptr; } -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_half_size(init_size), m_type(type) { - return m_type; -} - -u32 DescriptorHeap::Stride() const -{ - return m_stride; -} + { + D3D12_DESCRIPTOR_HEAP_DESC desc{}; + desc.Type = 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)); -bool DescriptorHeap::IsRemote() const -{ - return m_gpu; -} + m_inc = m_device->GetDescriptorHandleIncrementSize(type); + } -u32 DescriptorHeap::Size() const -{ - return m_size; + { + 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); + } } -CD3DX12_CPU_DESCRIPTOR_HANDLE DescriptorHeap::GetLocalHandle(const u32 offset) const +void DescriptorHeap::ReadyFrame(const u32 cap) { - return CD3DX12_CPU_DESCRIPTOR_HANDLE(m_heap->GetCPUDescriptorHandleForHeapStart(), static_cast(offset), m_stride); + m_tmp_offset = 0; + EnsureCapacity(cap); } -CD3DX12_GPU_DESCRIPTOR_HANDLE DescriptorHeap::GetRemoteHandle(const u32 offset) const +void DescriptorHeap::EnsureCapacity(u32 cap) { - return CD3DX12_GPU_DESCRIPTOR_HANDLE(m_heap->GetGPUDescriptorHandleForHeapStart(), static_cast(offset), m_stride); -} + cap = std::bit_ceil(cap); + if (m_need_grow) cap = std::max(cap, m_half_size * 2); + else if (cap <= m_half_size) return; -void DescriptorHeap::IncVersion() -{ + m_half_size = cap; m_version++; -} + m_virtual_block->Clear(); + m_allocations.Clear(); -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(); + 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)); } - 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++; -} -void DescriptorAllocator::AllocateTransient(u32 Size, DescriptorAllocation*& al) -{ - if (Size == 0) { - *al = DescriptorAllocation(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 = m_half_size; + desc.pAllocationCallbacks = &allocation_callbacks; + chr | CreateVirtualBlock(&desc, &m_virtual_block); } - 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) +DescriptorAllocation DescriptorHeap::Allocate(const u64 ObjectId, const u32 Size, bool& IsOld) { - if (Heap->Size() == 0) - { - IsOld = true; - *al = PersistDescriptorAllocation(0, 0, 0); - return; - } - if (!m_heap) - COPLT_THROW("Descriptor heap is null"); - auto& ref = m_persist_allocations.GetOrAdd(Heap->Id(), IsOld, [&](auto& p) + const auto& allocation = m_allocations.GetOrAdd(ObjectId, IsOld, [this, Size](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); + 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}); + } }); - ref.AllocatorVersion = m_version; - al = &ref; -} - -void DescriptorAllocator::Upload(const DescriptorAllocation& Al, const Rc& Heap, const u32 Offset) const -{ - if (Al.Size == 0) return; - m_device->CopyDescriptorsSimple( - Al.Size, - GetLocalHandle(Al.Offset), - Heap->GetLocalHandle(Offset), - m_type - ); + return DescriptorAllocation(this, allocation.m_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) +DescriptorAllocation DescriptorHeap::AllocateTmp(const u32 Size) { - 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; + 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); } -void DescriptorContext::EndFrame() +DescriptorManager::DescriptorManager(NonNull device) { - m_in_frame = false; + 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 DescriptorContext::SyncTmp() const -// { -// m_resource->SyncTmp(); -// m_sampler->SyncTmp(); -// } - -std::array DescriptorContext::GetDescriptorHeaps() const +void DescriptorManager::ReadyFrame(const u32 res_cap, const u32 smp_cap) const { - return {m_resource->Heap()->Heap().Get(), m_sampler->Heap()->Heap().Get()}; + 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 f0cd7ea..7074cb3 100644 --- a/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h +++ b/Coplt.Graphics.Native/D3d12/Src/DescriptorManager.h @@ -1,144 +1,79 @@ #pragma once -#include "directx/d3dx12.h" - -#include -#include -#include -#include - -#include "Device.h" +#include +#include +#include "D3D12MemAlloc.h" +#include "../../Api/Include/HashMap.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; - - 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 D3d12GpuDevice; + struct DescriptorHeap; + // 分配只能在帧内使用 struct DescriptorAllocation { - u32 Offset{COPLT_U32_MAX}; - u32 Size{}; + DescriptorHeap* m_heap; + u64 m_offset{}; DescriptorAllocation() = default; + explicit DescriptorAllocation(DescriptorHeap* heap, u64 offset); - explicit DescriptorAllocation(u32 Offset, u32 Size) : Offset(Offset), Size(Size) - { - } + CD3DX12_CPU_DESCRIPTOR_HANDLE GetCpuHandle() const; + CD3DX12_GPU_DESCRIPTOR_HANDLE GetGpuHandle() const; - operator bool() const { return Offset != COPLT_U32_MAX; } + explicit operator bool() const; }; - struct PersistDescriptorAllocation : DescriptorAllocation - { - u64 Version{}; - PersistDescriptorAllocation() = default; - - explicit PersistDescriptorAllocation(u64 Version, u32 Offset, u32 Size) - : DescriptorAllocation(Offset, Size), Version(Version) - { - } - }; - - struct PersistDescriptorAllocation_Internal : PersistDescriptorAllocation + struct DescriptorHeap final : Object { - u64 AllocatorVersion{}; - - PersistDescriptorAllocation_Internal() = default; - - explicit PersistDescriptorAllocation_Internal(u64 Version, u32 Offset, u32 Size, u64 AllocatorVersion) - : PersistDescriptorAllocation(Version, Offset, Size), AllocatorVersion(AllocatorVersion) + struct Allocation { - } - }; + D3D12MA::VirtualAllocation m_allocation{}; + u64 m_offset{}; + }; - struct DescriptorAllocator 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; - - void InitFrame(u32 GrowthCapacity); - - 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; + 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); + + void ReadyFrame(u32 cap); + void EnsureCapacity(u32 cap); + + DescriptorAllocation Allocate(u64 ObjectId, u32 Size, bool& IsOld); + DescriptorAllocation AllocateTmp(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); + constexpr static u32 InitResHeapSize = 1024; + constexpr static u32 InitSmpHeapSize = 64; - NonNull ResourceHeap() const; - NonNull SamplerHeap() const; + Rc m_res{}; + Rc m_smp{}; - void InitFrame(u32 ResourceCap, u32 SamplerCap); - void EndFrame(); + DescriptorManager() = default; - // // 将临时堆复制到 gpu 可见堆 - // void SyncTmp() const; + explicit DescriptorManager(NonNull device); - std::array GetDescriptorHeaps() const; + void ReadyFrame(u32 res_cap, u32 smp_cap) const; }; } diff --git a/Coplt.Graphics.Native/D3d12/Src/Device.cc b/Coplt.Graphics.Native/D3d12/Src/Device.cc index 41383b0..1cdcccd 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Device.cc @@ -4,14 +4,13 @@ #include "../../Api/Src/Shader.h" #include "Adapter.h" -#include "DescriptorManager.h" #include "Buffer.h" #include "GraphicsPipeline.h" #include "Image.h" +#include "Isolate.h" #include "Layout.h" #include "Queue.h" #include "Sampler.h" -#include "../../Api/Include/AllocObjectId.h" using namespace Coplt; @@ -45,7 +44,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; @@ -62,6 +61,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.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_WRITE_BACK; + 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); @@ -79,6 +88,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() @@ -119,21 +136,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) @@ -145,61 +169,106 @@ const Rc& D3d12GpuDevice::GetEmptyMeshLayout() return m_empty_mesh_layout; } -FResult D3d12GpuDevice::CreateMainQueue(const FMainQueueCreateOptions& options, FGpuQueue** out) noexcept +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([&] { - *out = new D3d12GpuQueue(this->CloneThis(), options); + 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::CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayoutCreateResult* out) noexcept { return feb([&] { - *out = ShaderModule::Create(options); + const auto ptr = new D3d12ShaderLayout(options); + out->Layout = ptr; + out->Data = ptr; }); } -FResult D3d12GpuDevice::CreateShaderLayout(const FShaderLayoutCreateOptions& options, FShaderLayout** out) noexcept +FResult D3d12GpuDevice::CreateBindGroupLayout(const FBindGroupLayoutCreateOptions& options, FBindGroupLayoutCreateResult* out) noexcept { return feb([&] { - *out = new D3d12ShaderLayout(this->CloneThis(), options); + const auto ptr = new D3d12BindGroupLayout(options); + out->Layout = ptr; + out->Data = ptr; }); } -FResult D3d12GpuDevice::GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayout** out) noexcept +FResult D3d12GpuDevice::CreateBindingLayout(const FBindingLayoutCreateOptions& options, FBindingLayout** out) noexcept { return feb([&] { - Rc r = GetEmptyLayout(options.Flags); - *out = r.leak(); + *out = new D3d12BindingLayout(this->CloneThis(), options); }); } -FResult D3d12GpuDevice::CreateShaderInputLayout(const FShaderInputLayoutCreateOptions& options, - FShaderInputLayout** out) noexcept +FResult D3d12GpuDevice::GetEmptyShaderLayout(const FGetEmptyShaderLayoutOptions& options, FShaderLayoutCreateResult* out) noexcept { return feb([&] { - *out = new D3d12ShaderInputLayout(this->CloneThis(), options); + 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::CreateShader(const FShaderCreateOptions& options, FShader** out) noexcept +FResult D3d12GpuDevice::GetEmptyBindingLayout(const FGetEmptyBindingLayoutOptions& options, FBindingLayout** out) noexcept { return feb([&] { - *out = new Shader(this->CloneThis(), options); + Rc r = GetEmptyBindingLayout(options.Flags); + *out = r.leak(); }); } -FResult D3d12GpuDevice::CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept +FResult D3d12GpuDevice::CreateShaderInputLayout(const FShaderInputLayoutCreateOptions& options, FShaderInputLayout** out) noexcept { return feb([&] { - *out = new D3d12ShaderBinding(this->CloneThis(), options); + *out = new D3d12ShaderInputLayout(this->CloneThis(), options); }); } @@ -211,9 +280,47 @@ FResult D3d12GpuDevice::CreateMeshLayout(const FMeshLayoutCreateOptions& options }); } -FResult D3d12GpuDevice::CreateGraphicsPipeline( - const FGraphicsShaderPipelineCreateOptions& options, FGraphicsShaderPipeline** out -) noexcept +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::CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept +{ + return feb([&] + { + const auto ptr = new Shader(this->CloneThis(), options); + out->Shader = ptr; + out->Data = ptr; + }); +} + +FResult D3d12GpuDevice::CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroupCreateResult* out) noexcept +{ + return feb([&] + { + const auto ptr = new D3d12ShaderBindGroup(this->CloneThis(), options); + out->BindGroup = ptr; + out->Data = ptr; + }); +} + +FResult D3d12GpuDevice::CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBindingCreateResult* out) noexcept +{ + return feb([&] + { + const auto ptr = new D3d12ShaderBinding(this->CloneThis(), options); + out->Binding = ptr; + out->Data = ptr; + }); +} + +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 5540569..4d3e0ee 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Device.h +++ b/Coplt.Graphics.Native/D3d12/Src/Device.h @@ -1,23 +1,27 @@ #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 { 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,11 +29,14 @@ namespace Coplt ComPtr m_device0{}; ComPtr m_info_queue{}; ComPtr m_gpu_allocator{}; - Box m_empty_layouts{}; + ComPtr m_uma_pool{}; + Box m_empty_layouts{}; + Rc m_empty_bind_group_layout{}; + Box m_empty_binding_layout{}; 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; @@ -43,27 +50,30 @@ 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 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 CreateMeshLayout(const FMeshLayoutCreateOptions& options, FMeshLayout** out) noexcept override; - FResult CreateMainQueue(const FMainQueueCreateOptions& options, FGpuQueue** out) noexcept override; - - FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModule** 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 CreateShader(const FShaderCreateOptions& options, FShader** out) noexcept override; - FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBinding** out) noexcept override; + FResult CreateShaderModule(const FShaderModuleCreateOptions& options, FShaderModuleCreateResult* out) noexcept override; + FResult CreateShader(const FShaderCreateOptions& options, FShaderCreateResult* out) noexcept override; - FResult CreateMeshLayout(const FMeshLayoutCreateOptions& options, FMeshLayout** out) noexcept override; + FResult CreateShaderBindGroup(const FShaderBindGroupCreateOptions& options, FShaderBindGroupCreateResult* out) noexcept override; + FResult CreateShaderBinding(const FShaderBindingCreateOptions& options, FShaderBindingCreateResult* 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/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/GraphicsPipeline.cc b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.cc index fba52e0..67f6131 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(); @@ -135,15 +135,17 @@ 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()) + 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,60 +154,54 @@ 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{}; 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 | 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); } - 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); @@ -235,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 @@ -245,14 +246,14 @@ FShader* D3d12GraphicsShaderPipeline::GetShader() noexcept return m_shader.get(); } -FShaderLayout* D3d12GraphicsShaderPipeline::GetLayout() noexcept +FBindingLayout* D3d12GraphicsShaderPipeline::GetLayout() noexcept { return m_layout.get(); } 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/GraphicsPipeline.h b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h index 79351d7..56d7d58 100644 --- a/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h +++ b/Coplt.Graphics.Native/D3d12/Src/GraphicsPipeline.h @@ -2,38 +2,36 @@ #include -#include "Device.h" #include "../../Api/Include/Object.h" -#include "../FFI/Layout.h" -#include "../Include/Utils.h" -#include "../FFI/Pipeline.h" +#include "Device.h" +#include "Layout.h" +#include "Pipeline.h" namespace Coplt { - struct D3d12GraphicsShaderPipeline final : GpuObject + struct D3d12GraphicsShaderPipeline final : GpuObject { 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{}; 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; - 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/Image.cc b/Coplt.Graphics.Native/D3d12/Src/Image.cc index 195197b..fc561a6 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,29 +104,24 @@ FResult D3d12GpuImage::SetName(const FStr8or16& name) noexcept }); } -ResourceType D3d12GpuImage::GetResourceType() noexcept -{ - return ResourceType::Image; -} - -FGpuViewableData* D3d12GpuImage::GpuViewableData() noexcept +FGpuResourceData* D3d12GpuImage::GpuResourceData() noexcept { return this; } -FGpuResourceData* D3d12GpuImage::GpuResourceData() noexcept +FGpuImageData* D3d12GpuImage::GpuImageData() noexcept { return this; } -FGpuImageData* D3d12GpuImage::GpuImageData() noexcept +NonNull D3d12GpuImage::Data() { return this; } -NonNull D3d12GpuImage::GetDataPtr() noexcept +NonNull D3d12GpuImage::State() { - return NonNull::Unchecked(this); + return &m_layout_state; } void* D3d12GpuImage::GetRawResourcePtr() noexcept @@ -137,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 9d0867e..d619494 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Image.h +++ b/Coplt.Graphics.Native/D3d12/Src/Image.h @@ -10,17 +10,21 @@ #include "Resource.h" #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; - virtual NonNull GetDataPtr() noexcept = 0; + virtual NonNull State() = 0; }; struct D3d12GpuImage final : GpuObject, FGpuImageData { + LayoutState m_layout_state{}; Rc m_device{}; Rc m_name{}; ComPtr m_allocator{}; @@ -30,13 +34,14 @@ 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 GetDataPtr() noexcept override; + NonNull Data() override; + NonNull State() override; void* GetRawResourcePtr() noexcept override; NonNull GetResourcePtr() override; + + bool IsCompatible(const FBindGroupItem& def) const override; }; } 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/Coplt.Graphics.Native/D3d12/Src/Isolate.cc b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc new file mode 100644 index 0000000..06cb968 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.cc @@ -0,0 +1,293 @@ +#include "Isolate.h" + +#include "Record.h" +#include "SwapChain.h" +#include "Context.h" +#include "../../Api/FFI/Record.h" +#include "Barrier.h" + +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); + + #pragma region 创建队列 + + m_main_queue = new D3d12GpuQueue2(this, FGpuQueueType::Direct); + m_compute_queue = new D3d12GpuQueue2(this, FGpuQueueType::Compute); + m_copy_queue = new D3d12GpuQueue2(this, FGpuQueueType::Copy); + + #pragma endregion + + m_barrier_marshal = new Enhanced::EnhancedBarrierMarshal(*this); + m_barrier_combiner = m_barrier_marshal->CreateCombiner(); + + m_cmd_alloc_pool = new D3d12CommandListPoolCluster(m_device); + + 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(); + feb(m_device->m_instance->m_logger, [&] + { + Rc records[8]{}; + re: + if (const auto count = m_waiting_record->try_dequeue_bulk(records, 8); count > 0) + { + for (auto i = 0; i < count; ++i) + { + records[i]->WaitAndRecycle(m_event); + m_record_pool->enqueue(std::move(records[i])); + } + goto re; + } + }); + } + }); +} + +D3d12GpuIsolate::~D3d12GpuIsolate() +{ + m_exited = true; + m_waiting_signal.release(1); + m_wait_thread.join(); + CloseHandle(m_event); +} + +FResult D3d12GpuIsolate::SetName(const FStr8or16& name) noexcept +{ + return FResult::None(); +} + +FGpuIsolateData* D3d12GpuIsolate::GpuIsolateData() noexcept +{ + return this; +} + +const Rc& D3d12GpuIsolate::GetQueue(const FGpuQueueType type) +{ + switch (type) + { + case FGpuQueueType::Direct: + return m_main_queue; + case FGpuQueueType::Compute: + return m_compute_queue; + case FGpuQueueType::Copy: + return m_copy_queue; + default: + break; + } + return m_main_queue; +} + +FResult D3d12GpuIsolate::RentRecords(const u32 NumRecords, FGpuRecordCreateResult* OutRecords) noexcept +{ + return feb([&] + { + 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); + }); +} + +FResult D3d12GpuIsolate::CreateSwapChainFromExists(const FGpuSwapChainFromExistsCreateOptions& options, FGpuSwapChainCreateResult& out) noexcept +{ + return feb([&] + { + const auto ptr = new D3d12GpuSwapChain(this, options); + out.SwapChain = ptr; + out.Data = ptr; + }); +} + +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, hwnd, SwapChainFor::Hwnd); + out.SwapChain = ptr; + 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::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) + { + 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::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); + RentRecords(out); +} + +void D3d12GpuIsolate::SubmitReturn(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) +{ + std::lock_guard lock(m_mutex); + SubmitNoLock(records); +} + +void D3d12GpuIsolate::SubmitNoLock(std::span> records) +{ + for (const auto& record : records) + { + record->EnsureEnd(); + } + 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 new file mode 100644 index 0000000..879760b --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Isolate.h @@ -0,0 +1,75 @@ +#pragma once + +#include + +#include "concurrentqueue.h" + +#include "Device.h" +#include "Queue.h" +#include "../../Api/FFI/Isolate.h" +#include "../../Api/Include/GpuObject.h" +#include "../../Api/FFI/Cmd.h" + +namespace Coplt +{ + struct D3d12CommandListPoolCluster; + + COPLT_INTERFACE_DEFINE(ID3d12GpuIsolate, "1c507c7f-140a-4717-809e-88096b475fea", FGpuIsolate) + { + Rc m_device{}; + std::mutex m_mutex{}; + }; + + struct ID3d12GpuRecord; + struct ID3d12BarrierMarshal; + struct ID3d12BarrierCombiner; + + struct D3d12GpuIsolate final : GpuObject, FGpuIsolateData + { + using RecordQueue = moodycamel::ConcurrentQueue>; + + SRc m_config{}; + Rc m_main_queue{}; + Rc m_compute_queue{}; + Rc m_copy_queue{}; + Rc m_barrier_marshal{}; + Rc m_barrier_combiner{}; + 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}; + std::atomic m_record_inc{0}; + + explicit D3d12GpuIsolate(Rc device, const FGpuIsolateCreateOptions& options); + + ~D3d12GpuIsolate() override; + + FResult SetName(const FStr8or16& name) noexcept override; + FGpuIsolateData* GpuIsolateData() noexcept override; + + const Rc& GetQueue(FGpuQueueType type); + + 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 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); + 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); + + void SubmitNoLock(std::span> records); + }; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Layout.cc b/Coplt.Graphics.Native/D3d12/Src/Layout.cc index 6282628..febe186 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.cc @@ -4,89 +4,251 @@ #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 +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; + + m_slots.reserve(m_items.size()); + for (u32 i = 0; i < m_items.size(); ++i) { - FShaderLayoutGroupScope Scope{}; - bool Sampler{}; - - TableGroupKey() = default; - - explicit TableGroupKey(const FShaderLayoutGroupScope Scope, const bool Sampler) : Scope(Scope), Sampler(Sampler) + BindSlotInfo info{}; + const auto& item = m_items[i]; + const auto count = std::max(1u, item.Count); + switch (item.View) { - } - - struct Hasher - { - size_t operator()(const TableGroupKey& value) const + case FShaderLayoutItemView::Cbv: + case FShaderLayoutItemView::Srv: + case FShaderLayoutItemView::Uav: + if (Usage == FBindGroupUsage::Dynamic && item.Count <= 1 && IsBuffer(item.Type)) { - return std::hash{}(static_cast(value.Scope) | (static_cast(value.Sampler) << 8)); + 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); + } +} - struct Eq - { - bool operator()(const TableGroupKey& lhs, const TableGroupKey& rhs) const - { - return lhs.Scope == rhs.Scope && lhs.Sampler == rhs.Sampler; - } - }; - }; +FResult D3d12BindGroupLayout::SetName(const FStr8or16& name) noexcept +{ + return FResult::None(); +} - struct TableDefine - { - u8 Index{}; - u32 IndexInc{}; - HashMap Map{}; - }; +FBindGroupLayoutData* D3d12BindGroupLayout::BindGroupLayoutData() noexcept +{ + return this; } -D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderLayoutCreateOptions& options) - : m_device(std::move(device)) +const D3d12BindGroupLayoutData& D3d12BindGroupLayout::Data() const noexcept { - m_dx_device = m_device->m_device; + return *this; +} - Flags = options.Flags; +std::span D3d12BindGroupLayout::Slots() const noexcept +{ + return m_slots; +} - m_layout_item_defines = std::vector(options.Items, options.Items + options.Count); - m_item_infos = std::vector(options.Count, {}); +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++) + { + 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)); + } - std::vector root_parameters{}; + 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) + { + 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 + ); + } + } + m_group_item_infos.reserve(options.NumGroups); + for (u32 g = 0; g < options.NumGroups; g++) + { + 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(); + group_item_infos.reserve(items.size()); + for (u32 i = 0; i < items.size(); ++i) + { + const auto& item = items[i]; + 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); + 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; + switch (def.UavAccess) + { + case FResourceAccess::ReadOnly: + 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 (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: + group_item_info.UavAccess = FResourceAccess::ReadWrite; + break; + } + } + group_item_infos.push_back(group_item_info); + } + m_group_item_infos.push_back(std::move(group_item_infos)); + } - HashMap tables{}; - u8 TableGroupIndexInc{}; + 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({}); - 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 +259,39 @@ 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); + + BindItemInfo item_info{}; + item_info.Group = info.Group; + 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; } + // 组未提供绑定,使用隐藏组创建描述符,并且永远保持默认值 + 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; - goto DefineDescriptorTable; - case FShaderLayoutItemUsage::Persist: - table_scope = FShaderLayoutGroupScope::Persist; + if (item.View == FShaderLayoutItemView::StaticSampler) + goto DefineStaticSampler; + if (item.View == FShaderLayoutItemView::Sampler) goto DefineDescriptorTable; - case FShaderLayoutItemUsage::Instant: - if (item.CountOrIndex > 1 || !IsBuffer(item.Type)) + + const auto usage = group->Data().Usage; + if (usage == FBindGroupUsage::Dynamic) + { + if (item.Count > 1 || !IsBuffer(item.Type)) { - table_scope = FShaderLayoutGroupScope::Dynamic; goto DefineDescriptorTable; } switch (item.View) @@ -135,17 +305,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 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; + 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 = slot.OffsetInTable; + info.SigIndex = static_cast(table.Ranges.size()); + info.SigPlace = SigPlace::Grouped; + table.Ranges.push_back(range); + continue; + } DefineDescriptor: { D3D12_ROOT_PARAMETER1 param{}; @@ -154,100 +348,63 @@ 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); + + BindItemInfo item_info{}; + item_info.Group = info.Group; + 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; } - 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); + + BindItemInfo item_info{}; + item_info.Group = Info.Group; + 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)); } D3D12_VERSIONED_ROOT_SIGNATURE_DESC desc{}; @@ -258,11 +415,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 +436,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 +446,7 @@ D3d12ShaderLayout::D3d12ShaderLayout(Rc&& device, const FShaderL } } -FResult D3d12ShaderLayout::SetName(const FStr8or16& name) noexcept +FResult D3d12BindingLayout::SetName(const FStr8or16& name) noexcept { return feb([&] { @@ -297,32 +455,44 @@ FResult D3d12ShaderLayout::SetName(const FStr8or16& name) noexcept }); } -void* D3d12ShaderLayout::GetRootSignaturePtr() noexcept +const D3d12BindingLayoutData& D3d12BindingLayout::Data() const noexcept +{ + return *this; +} + +const Rc& D3d12BindingLayout::ShaderLayout() const noexcept +{ + return m_shader_layout; +} + +std::span> D3d12BindingLayout::Groups() const noexcept +{ + return m_groups; +} + +const ComPtr& D3d12BindingLayout::RootSignature() const noexcept { - return m_root_signature.Get(); + return m_root_signature; } -const FShaderLayoutItemDefine* D3d12ShaderLayout::GetItemDefines(u32* out_count) noexcept +std::span D3d12BindingLayout::SlotInfos() const noexcept { - *out_count = static_cast(m_layout_item_defines.size()); - return m_layout_item_defines.data(); + return m_slot_infos; } -const FShaderLayoutItemInfo* D3d12ShaderLayout::GetItemInfos(u32* out_count) noexcept +std::span D3d12BindingLayout::BindItemInfos() const noexcept { - *out_count = static_cast(m_item_infos.size()); - return m_item_infos.data(); + return m_bind_item_infos; } -const FShaderLayoutGroupClass* D3d12ShaderLayout::GetGroupClasses(u32* out_count) noexcept +std::span> D3d12BindingLayout::TableInfos() const noexcept { - *out_count = static_cast(m_group_classes.size()); - return m_group_classes.data(); + return m_tables; } -std::span D3d12ShaderLayout::GetTableGroups() noexcept +std::span> D3d12BindingLayout::GroupItemInfos() const noexcept { - return m_table_groups; + 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 d90e5a2..abf58e1 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Layout.h +++ b/Coplt.Graphics.Native/D3d12/Src/Layout.h @@ -7,67 +7,249 @@ #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); + + enum class BindSlotPlace : u8 { - std::vector Ranges{}; - u32 Size{}; - u32 Index{}; + NonTable, + ResourceTable, + SamplerTable, + }; + + struct BindSlotInfo + { + u32 OffsetInTable{}; + BindSlotPlace Place{}; + }; + + struct TableInfo final + { + u32 Group{}; u32 RootIndex{}; FShaderStage Stage{}; - FShaderLayoutGroupView View{}; + D3D12_DESCRIPTOR_RANGE_TYPE Type{}; + }; + + 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)); + } + + bool operator==(const TableKey& other) const + { + return Stage == other.Stage && Type == other.Type; + } + }; + + struct BindSlot final + { + 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; + } + }; + + enum class SigPlace : u8 + { + None, + Const, + Direct, + Grouped, + StaticSampler, + }; + + struct SlotInfo final + { + // Shader Layout 中的 index + u32 Index{}; + u32 Group{COPLT_U32_MAX}; + u32 IndexInGroup{COPLT_U32_MAX}; + // Place 为 Grouped 时是组内的 Index,StaticSampler 时是 StaticSampler 的 Index, 其他是 Root 的 Index + u32 SigIndex{}; + SigPlace SigPlace{}; - TableMeta() = default; + SlotInfo() = default; - explicit TableMeta(const u32 index, const FShaderStage stage, const FShaderLayoutGroupView view) + explicit SlotInfo(const u32 index) : Index(index) { - Index = index; - Stage = stage; - View = view; } }; - struct TableGroup + struct GroupItemInfo + { + u32 Group{}; + u32 IndexInGroup{}; + FGraphicsFormat Format{}; + FShaderStageFlags Stages{}; + FShaderLayoutItemView View{}; + FShaderLayoutItemType Type{}; + FResourceAccess UavAccess{}; + }; + + enum class BindItemPlace : u8 { - std::vector Metas{}; - std::vector Infos{}; - FShaderLayoutGroupScope Scope{}; - bool Sampler{}; + Table, + Direct, + Const, }; - virtual std::span GetTableGroups() noexcept = 0; + enum class BindItemType : u8 + { + Resource, + Sampler, + }; + + struct BindItemInfo + { + u32 Group{}; + // Place 为 Table 时永远为 0 + u32 IndexInGroup{}; + u32 RootIndex{}; + BindItemPlace Place{}; + BindItemType Type{}; + }; + } + + struct D3d12ShaderLayout final : GpuObject, FShaderLayoutData + { + std::vector m_items{}; + + explicit D3d12ShaderLayout(const FShaderLayoutCreateOptions& options); + + FResult SetName(const FStr8or16& name) noexcept override; + + FShaderLayoutData* ShaderLayoutData() noexcept override; }; - struct D3d12ShaderLayout final : GpuObject + struct D3d12BindGroupLayoutData : FBindGroupLayoutData { - 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{}; + 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; + }; - explicit D3d12ShaderLayout(Rc&& device, const FShaderLayoutCreateOptions& options); + 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; - void* GetRootSignaturePtr() noexcept override; + FBindGroupLayoutData* BindGroupLayoutData() noexcept override; + const D3d12BindGroupLayoutData& Data() const noexcept override; + std::span Slots() const noexcept override; + }; + + struct D3d12BindingLayoutData + { + u32 SumTableResourceSlots{}; + u32 SumTableSamplerSlots{}; + }; - const FShaderLayoutItemDefine* GetItemDefines(u32* out_count) noexcept override; - const FShaderLayoutItemInfo* GetItemInfos(u32* out_count) noexcept override; - const FShaderLayoutGroupClass* GetGroupClasses(u32* out_count) noexcept override; + COPLT_INTERFACE_DEFINE(ID3d12BindingLayout, "7271c0de-ec05-44be-9d1b-4b54894e297e", FBindingLayout) + { + using SlotInfo = Layout::SlotInfo; + 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> GroupItemInfos() const noexcept = 0; + }; + + struct D3d12BindingLayout final : GpuObject, D3d12BindingLayoutData + { + using BindSlot = Layout::BindSlot; + + Rc m_device{}; + ComPtr m_root_signature{}; + 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_group_item_infos{}; + + explicit D3d12BindingLayout(Rc&& device, const FBindingLayoutCreateOptions& options); + + FResult SetName(const FStr8or16& name) noexcept override; - std::span GetTableGroups() 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 BindItemInfos() const noexcept override; + std::span> TableInfos() const noexcept override; + std::span> GroupItemInfos() const noexcept override; }; - struct D3d12ShaderInputLayout final : GpuObject + struct D3d12ShaderInputLayout final : GpuObject { Rc m_device{}; std::vector> m_slot_names{}; @@ -80,7 +262,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/Output.cc b/Coplt.Graphics.Native/D3d12/Src/Output.cc index 7152b43..7d37d56 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Output.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Output.cc @@ -1,369 +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.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; -} - -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 9f7ad91..fe135bf 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Output.h +++ b/Coplt.Graphics.Native/D3d12/Src/Output.h @@ -2,86 +2,21 @@ #include #include +#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 + COPLT_INTERFACE_DEFINE(ID3d12GpuOutput2, "59aa68d8-91bd-4032-ba51-6a05795945b6", FGpuOutput2) { - 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; + virtual NonNull State() = 0; + 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/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/Queue.cc b/Coplt.Graphics.Native/D3d12/Src/Queue.cc index 0fe7933..a061683 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.cc @@ -1,139 +1,101 @@ #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; -D3d12GpuQueue::D3d12GpuQueue( - Rc&& device, - const FMainQueueCreateOptions& options -) : m_device(std::move(device)), m_command_interpreter(this) +QueueWaitPoint::QueueWaitPoint(Rc&& queue, const u64 fence_value) : m_queue(std::move(queue)), m_fence_value(fence_value) { - m_queue_type = FGpuQueueType::Direct; +} - m_dx_device = m_device->m_device; +void QueueWaitPoint::Wait(const HANDLE event) const +{ + m_queue->WaitFenceValue(m_fence_value, event); +} + +D3d12GpuQueue2::D3d12GpuQueue2(const NonNull isolate, const FGpuQueueType type) + : FGpuQueueData() +{ + m_device = isolate->m_device; + QueueType = type; + const NonNull device = m_device->m_device.Get(); 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; + desc.Type = ToDx(type); + desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; - chr | m_dx_device->CreateCommandQueue(&desc, IID_PPV_ARGS(&m_queue)); + chr | 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)); + chr | device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence)); + m_fence_value = 1; +} - if (m_device->Debug()) - { - chr | m_queue >> SetNameEx(options.Name); - } +FGpuQueueData* D3d12GpuQueue2::GpuQueueData() noexcept +{ + return this; } -FResult D3d12GpuQueue::SetName(const FStr8or16& name) noexcept +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)); + } }); } -void* D3d12GpuQueue::GetRawQueue() noexcept +void* D3d12GpuQueue2::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 +u64 D3d12GpuQueue2::Signal() { - return feb([&] - { - *out = new D3d12GpuSwapChainOutput(this->CloneThis(), options, static_cast(hwnd)); - }); + std::lock_guard lock(m_mutex); + return SignalNoLock(); } -D3d12GpuQueue::~D3d12GpuQueue() noexcept +QueueWaitPoint D3d12GpuQueue2::SignalWaitPointer() { - // ReSharper disable once CppFunctionResultShouldBeUsed - m_cmd->Close(); + return QueueWaitPoint(this->CloneThis(), Signal()); } -void D3d12GpuQueue::Submit( - Rc& frame_context, /* 可选 */ const FCommandSubmit* submit -) +u64 D3d12GpuQueue2::SignalNoLock() { - std::lock_guard lock(m_mutex); - SubmitNoLock(frame_context, submit); + const auto fence_value = m_fence_value; + chr | m_queue->Signal(m_fence.Get(), fence_value); + m_fence_value++; + return fence_value; } -void D3d12GpuQueue::SubmitNoLock( - Rc& frame_context, /* 可选 */ const FCommandSubmit* submit -) +void D3d12GpuQueue2::WaitFenceValue(const u64 fence_value, const HANDLE event) { - if (submit == nullptr) + if (m_fence->GetCompletedValue() < fence_value) { - chr | m_cmd->Close(); + chr | m_fence->SetEventOnCompletion(fence_value, event); + WaitForSingleObject(event, INFINITE); } - 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 +void D3d12GpuQueue2::Wait(D3d12GpuQueue2& other, const u64 fence_value) { - return feb([&] - { - const auto executor = Executor->QueryInterface(); - if (executor == nullptr) - COPLT_THROW("Executors from different backends"); - executor->SubmitNoWait(this, submit); - }); + 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 f80769e..161eaa3 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Queue.h +++ b/Coplt.Graphics.Native/D3d12/Src/Queue.h @@ -3,59 +3,18 @@ #include #include -#include "CmdListPack.h" +#include "concurrentqueue.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) @@ -66,8 +25,61 @@ 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; + struct D3d12GpuQueue2; + + struct QueueWaitPoint final + { + Rc m_queue{}; + u64 m_fence_value{}; + + QueueWaitPoint() = default; + explicit QueueWaitPoint(Rc&& queue, u64 fence_value); + + void Wait(HANDLE event) const; + }; + + struct D3d12GpuQueue2; + + COPLT_INTERFACE_DEFINE(ID3d12GpuQueue, "a60df5da-ecff-4ae4-a38b-6ddef7db5922", FD3d12GpuQueue2) + { + Rc m_device{}; + ComPtr m_queue{}; + ComPtr m_fence{}; + u64 m_fence_value{}; + 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; + virtual void Wait(D3d12GpuQueue2& other, u64 fence_value) = 0; + }; + + struct D3d12GpuQueue2 final : GpuObject, FGpuQueueData + { + explicit D3d12GpuQueue2(NonNull isolate, FGpuQueueType type); + + FGpuQueueData* GpuQueueData() noexcept override; + FResult SetName(const FStr8or16& name) noexcept override; + void* GetRawQueue() noexcept override; + + u64 Signal() override; + QueueWaitPoint SignalWaitPointer() override; + 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 new file mode 100644 index 0000000..3e194b0 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Record.cc @@ -0,0 +1,1366 @@ +#include "Record.h" + +#include + +#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" +#include "../../Api/Include/Finally.h" + +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; + Layout = nullptr; + GPipeline = nullptr; + Binding = nullptr; + PipelineChanged = false; + BindingChanged = false; +} + +void D3d12GpuRecord::PipelineContext::SetPipeline(NonNull pipeline, u32 i) +{ + if (Pipeline && pipeline->ObjectId() == Pipeline->ObjectId()) return; + const Ptr dx_pipeline = pipeline->QueryInterface(); + if (!dx_pipeline) + { + COPLT_THROW_FMT( + "[{}] Pipeline({:#x}) from different backends", + i, static_cast(pipeline) + ); + } + Pipeline = dx_pipeline; + Layout = Pipeline->Layout(); + const auto stages = pipeline->GetStages(); + GPipeline = nullptr; + if (HasFlags(stages, FShaderStageFlags::Pixel)) + { + 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 = g_pipeline; + } + PipelineChanged = true; + if (Binding && Binding->Layout()->ObjectId() != Layout->ObjectId()) + { + Binding = nullptr; + } +} + +void D3d12GpuRecord::PipelineContext::SetBinding(NonNull binding, u32 i, const FCmdSetBinding& cmd) +{ + if (Binding && binding->ObjectId() == Binding->ObjectId()) return; + const Ptr 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 = dx_binding; + SetBindingIndex = cmd.Index; +} + +D3d12GpuRecord::D3d12GpuRecord(const NonNull isolate) + : 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++; + m_context = new D3d12RecordContext(isolate); + m_barrier_analyzer = isolate->m_barrier_marshal->CreateAnalyzer(); + FGpuRecordData::Context = m_context.get(); +} + +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; +} + +std::span D3d12GpuRecord::ResourceInfos() noexcept +{ + return m_resource_infos; +} + +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; +} + +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) + { + wait_point.Wait(event); + } + Recycle(); +} + +void D3d12GpuRecord::Recycle() +{ + m_queue_wait_points.clear(); + m_barrier_analyzer->Clear(); + 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; +} + +FResult D3d12GpuRecord::End() noexcept +{ + return feb([&] + { + DoEnd(); + }); +} + +void D3d12GpuRecord::EnsureEnd() +{ + if (Ended) return; + DoEnd(); +} + +void D3d12GpuRecord::DoEnd() +{ + if (Ended) + 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(); + u32 MinResHeapSize{}, MinSmpHeapSize{}; + ReadyBindings(MinResHeapSize, MinSmpHeapSize); + m_context->m_descriptor_manager.ReadyFrame(MinResHeapSize, MinSmpHeapSize); + Analyze(); + m_barrier_analyzer->EndAnalyze(); + 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 = {}; +} + +ResourceInfo& D3d12GpuRecord::GetRes(const FCmdResRef& ref) +{ + return m_resource_infos[ref.ResIndex()]; +} + +const ResourceInfo& D3d12GpuRecord::GetRes(const FCmdResRef& ref) const +{ + return m_resource_infos[ref.ResIndex()]; +} + +void D3d12GpuRecord::ResetState() +{ + m_state = RecordState::Main; + m_cur_render = {}; + 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_resource_infos.clear(); + m_resource_infos.reserve(Resources.size()); + for (u32 i = 0; i < Resources.size(); ++i) + { + const auto& res = Resources[i]; + const auto index = AddResource(res); + COPLT_DEBUG_ASSERT(index == i); + } +} + +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) + { + 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() +{ + const auto commands = Commands.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::BufferImageCopy: + Analyze_BufferImageCopy(i, command.BufferImageCopy); + 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: + Analyze_SetBinding(i, command.SetBinding); + break; + case FCmdType::SetMeshBuffers: + Analyze_SetMeshBuffers(i, command.SetMeshBuffers); + break; + case FCmdType::SetViewportScissor: + if (Mode != FGpuRecordMode::Direct) + COPLT_THROW_FMT("[{}] Can only SetViewportScissor on the direct mode", i); + break; + case FCmdType::Draw: + if (Mode != FGpuRecordMode::Direct) + COPLT_THROW_FMT("[{}] Can only Draw on the direct mode", i); + break; + case FCmdType::Dispatch: + Analyze_Dispatch(i, command.Dispatch); + break; + } + } +} + +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.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.ResIndex(), 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.ResIndex(), 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.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.ResIndex(), 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_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) + 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.ResIndex(), ResAccess::DepthStencilWrite, ResUsage::Common, ResLayout::DepthStencilWrite); + } + for (u32 n = 0; n < num_rtv; ++n) + { + m_barrier_analyzer->OnUse(info.Rtv[n].ResIndex(), 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 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->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(); +} + +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) +{ + 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::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, cmd)) return; + const NonNull binding = m_pipeline_context.Binding; + ReadGuard binding_guard(binding->SelfLock()); + Finally clear_lock([&] { m_tmp_locks.clear(); }); + const auto groups = binding->Groups(); + for (u32 g = 0; g < groups.size(); ++g) + { + const auto& group = groups[g]; + if (!group) continue; + 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 = group_item_infos[g][v]; + m_barrier_analyzer->OnUse(res_index, view, info); + } + 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(); + DescriptorAllocation resource_allocation{}; + DescriptorAllocation sampler_allocation{}; + // todo 确定是最后一次修改 + const auto f = [&]( + const bool last, const u32 size, const Rc& heap, + const ComPtr& dh, DescriptorAllocation& allocation + ) + { + if (size == 0) return; + if (data.Usage == FBindGroupUsage::Dynamic && !last) + { + allocation = heap->AllocateTmp(size); + } + else + { + bool exists = false; + allocation = heap->Allocate(object_id, size, exists); + if (exists) return; + } + m_device->m_device->CopyDescriptorsSimple(size, allocation.GetCpuHandle(), dh->GetCPUDescriptorHandleForHeapStart(), heap->m_type); + }; + 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) + { + BindItem item{}; + // todo 直接资源和常量 + m_bind_items.push_back(item); + } + } + 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(); +} + +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.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.ResIndex(), ResAccess::VertexBufferRead, ResUsage::VertexOrMesh, ResLayout::Undefined); + } + 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::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) + { + 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 == 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(list, i, command.Label); + break; + case FCmdType::BeginScope: + Interpret_BeginScope(list, i, command.BeginScope); + break; + case FCmdType::EndScope: + Interpret_EndScope(list, i, command.EndScope); + break; + case FCmdType::ClearColor: + Interpret_ClearColor(list, i, command.ClearColor); + break; + case FCmdType::ClearDepthStencil: + Interpret_ClearDepthStencil(list, i, command.ClearDepthStencil); + break; + 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; + case FCmdType::Compute: + COPLT_THROW("TODO"); + case FCmdType::SetPipeline: + Interpret_SetPipeline(list, i, command.SetPipeline); + break; + case FCmdType::SetBinding: + Interpret_SetBinding(list, i, command.SetBinding); + break; + case FCmdType::SetViewportScissor: + Interpret_SetViewportScissor(list, i, command.SetViewportScissor); + break; + case FCmdType::SetMeshBuffers: + Interpret_SetMeshBuffers(list, i, command.SetMeshBuffers); + break; + case FCmdType::Draw: + Interpret_Draw(list, i, command.Draw); + break; + case FCmdType::Dispatch: + Interpret_Dispatch(list, i, command.Dispatch); + break; + } + } +} + +void D3d12GpuRecord::Interpret_Label(const CmdList& list, u32 i, const FCmdLabel& cmd) const +{ + if (!m_device->Debug()) return; + 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(const CmdList& list, u32 i, const FCmdBeginScope& cmd) const +{ + if (!m_device->Debug()) return; + if (!list->g0) return; + 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) + { + 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(const CmdList& list, u32 i, const FCmdEndScope& cmd) const +{ + if (!m_device->Debug()) return; + if (!list->g0) return; + PIXEndEvent(list->g0.Get()); +} + +void D3d12GpuRecord::Interpret_ClearColor(const CmdList& list, const u32 i, const FCmdClearColor& cmd) +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use ClearColor in sub scope", i); + const auto rtv = GetRes(cmd.Image).GetRtv(); + list->g0->ClearRenderTargetView( + rtv, cmd.Color, cmd.RectCount, + cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) + ); +} + +void D3d12GpuRecord::Interpret_ClearDepthStencil(const CmdList& list, const u32 i, const FCmdClearDepthStencil& cmd) +{ + if (m_state != RecordState::Main) + COPLT_THROW_FMT("[{}] Cannot use ClearDepthStencil in sub scope", i); + 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; + list->g0->ClearDepthStencilView( + dsv, flags, cmd.Depth, cmd.Stencil, cmd.RectCount, + cmd.RectCount == 0 ? nullptr : reinterpret_cast(&PayloadRect[cmd.RectIndex]) + ); +} + +void D3d12GpuRecord::Interpret_BufferCopy(const CmdList& list, u32 i, const FCmdBufferCopy& cmd) +{ + 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) + { + 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); + } + else + { + list->g0->CopyBufferRegion(dst, range.DstOffset, src, range.SrcOffset, range.Size); + } + } + else if (cmd.SrcType == FBufferRefType2::Upload && cmd.DstType == FBufferRefType2::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]; + if (range.SrcOffset + range.Size >= src_obj.m_size) + COPLT_THROW_FMT("[{}] Size out of range", i); + const auto src = src_obj.m_resource.m_resource.Get(); + list->g0->CopyBufferRegion(dst, range.DstOffset, src, range.SrcOffset, range.Size); + } + else + { + COPLT_THROW_FMT( + "[{}] Unsupported copy combination {{ SrcType = {} DstType = {} }}", + i, static_cast(cmd.SrcType), static_cast(cmd.DstType) + ); + } +} + +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) + 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 (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) + { + 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 = dsv.GetDsv(); + 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 = GetRes(res_info.Src).GetResource(); + res.pDstResource = GetRes(res_info.Dst).GetResource(); + 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 = GetRes(res_info.Src).GetResource(); + res.pDstResource = GetRes(res_info.Dst).GetResource(); + res.SubresourceCount = 0; + res.ResolveMode = ToDx(res_info.Mode); + }); + ds[0] = desc; + } + for (u32 n = 0; n < num_rtv; ++n) + { + 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 = rtv.GetRtv(); + 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 = GetRes(res_info.Src).GetResource(); + res.pDstResource = GetRes(res_info.Dst).GetResource(); + 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; + list->g4->BeginRenderPass(info.NumRtv, rts, info.Dsv ? ds : nullptr, flags); + } + else + { + COPLT_THROW_FMT("[{}] Render pass is not supported, please check the agility sdk version", i); + } +} + +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 or some end is missing", 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); + } + 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) +{ + 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_SetBinding(const CmdList& list, 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, 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]; + 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, al.GetGpuHandle()); + } + else + { + list->g0->SetComputeRootDescriptorTable(bind_item_info.RootIndex, al.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 +{ + 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_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 = GetRes(buffers.IndexBuffer.Buffer).GetResource(); + 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 = GetRes(range.Buffer).GetResource(); + 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) + 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); + } + else + { + list->g0->DrawInstanced(cmd.VertexOrIndexCount, cmd.InstanceCount, cmd.FirstVertexOrIndex, cmd.FirstInstance); + } +} + +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 (m_pipeline_context.Pipeline && pipeline->ObjectId() == m_pipeline_context.Pipeline->ObjectId()) return; + m_pipeline_context.SetPipeline(pipeline, 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, cmd); + return true; +} + +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(); + if (HasFlags(stages, FShaderStageFlags::Compute)) + { + 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(m_pipeline_context.Layout->RootSignature().Get()); + } + list->g0->SetPipelineState(m_pipeline_context.Pipeline->GetPipelineState().Get()); +} + +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; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Record.h b/Coplt.Graphics.Native/D3d12/Src/Record.h new file mode 100644 index 0000000..ca8ae87 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/Record.h @@ -0,0 +1,242 @@ +#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; + + // 可空 + virtual const D3d12RentedCommandList& ResultList() 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& 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; + }; + + struct ID3d12ShaderPipeline; + struct ID3d12GraphicsShaderPipeline; + + struct D3d12GpuRecord final : GpuObject, FGpuRecordData + { + using CmdList = D3d12RentedCommandList; + + enum class RecordState : u8 + { + Main, + Render, + Compute, + }; + + struct RenderState + { + u32 StartIndex{}; + FCmdRender Cmd{}; + }; + + struct ComputeState + { + u32 StartIndex{}; + FCmdCompute Cmd{}; + }; + + struct PipelineContext + { + Ptr Pipeline{}; + Ptr Layout{}; + // 如果不是图形管线将不会设置 + Ptr GPipeline{}; + + Ptr Binding{}; + u32 SetBindingIndex{}; + + bool PipelineChanged{}; + bool BindingChanged{}; + + void Reset(); + void SetPipeline(NonNull pipeline, 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 直接资源和常量 + }; + }; + + struct AllocationPoint + { + DescriptorAllocation Resource{}; + DescriptorAllocation Sampler{}; + }; + + u64 m_isolate_id{}; + u64 m_record_id{}; + SRc m_isolate_config{}; + Rc m_device{}; + Rc m_context{}; + 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{}; + RecordState m_state{}; + D3d12RentedCommandList m_result_list{}; + + 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; + std::span ResourceInfos() noexcept override; + const Rc& Context() const noexcept override; + const D3d12RentedCommandList& ResultList() const noexcept override; + + const Rc& BarrierAnalyzer() override; + + void RegisterWaitPoint(QueueWaitPoint&& wait_point) override; + void WaitAndRecycle(HANDLE event) override; + void Recycle() override; + + FResult End() noexcept override; + void EnsureEnd() override; + void DoEnd(); + + void AfterSubmit() override; + + 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(u32& MinResHeapSize, u32& MinSmpHeapSize); + + 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_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); + 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; + + 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; + 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_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); + 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); + // 返回是否改变 + bool SetBinding(NonNull binding, u32 i, const FCmdSetBinding& cmd); + void SetPipeline(const CmdList& list, NonNull pipeline, u32 i); + }; + + D3D12_COMMAND_LIST_TYPE GetType(FGpuRecordMode Mode); +} diff --git a/Coplt.Graphics.Native/D3d12/Src/ResState.cc b/Coplt.Graphics.Native/D3d12/Src/ResState.cc new file mode 100644 index 0000000..03e7634 --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/ResState.cc @@ -0,0 +1,395 @@ +#include "../Include/ResState.h" + +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 ResState::Same(const ResState& other) const +{ + return Access == other.Access && Layout == other.Layout; +} + +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 + ); +} + +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; + 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_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; + 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(ResLayout layout) +{ + 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::ShadingRateSource: + 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: + return D3D12_BARRIER_LAYOUT_GENERIC_READ; + case ResLayout::UnorderedAccess: + return D3D12_BARRIER_LAYOUT_UNORDERED_ACCESS; + case ResLayout::ShaderResource: + return D3D12_BARRIER_LAYOUT_SHADER_RESOURCE; + case ResLayout::CopySource: + return D3D12_BARRIER_LAYOUT_COPY_SOURCE; + case ResLayout::CopyDest: + return D3D12_BARRIER_LAYOUT_COPY_DEST; + case ResLayout::Common: + default: + 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; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/Resource.cc b/Coplt.Graphics.Native/D3d12/Src/Resource.cc index bb5ef0c..8ee3f15 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Resource.cc +++ b/Coplt.Graphics.Native/D3d12/Src/Resource.cc @@ -6,50 +6,60 @@ 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; + 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: + 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; + } - D3D12_BARRIER_LAYOUT layout = D3D12_BARRIER_LAYOUT_UNDEFINED; + layout = ResLayout::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 +89,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/Sampler.cc b/Coplt.Graphics.Native/D3d12/Src/Sampler.cc index 75486f9..b95887f 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 @@ -49,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 7c622d8..010c48c 100644 --- a/Coplt.Graphics.Native/D3d12/Src/Sampler.h +++ b/Coplt.Graphics.Native/D3d12/Src/Sampler.h @@ -4,10 +4,12 @@ #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; }; @@ -22,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/SwapChain.cc b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc new file mode 100644 index 0000000..e04e9ed --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.cc @@ -0,0 +1,404 @@ +#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; + this->Hdr = options.Hdr; + this->Srgb = options.Srgb; + + m_layout_state.Layout = ResLayout::Common; + + 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); + + 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) + : 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; + + 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(); +} + +D3d12GpuSwapChain::D3d12GpuSwapChain( + const NonNull isolate, const FGpuSwapChainCreateOptions& options, void* handle, SwapChainFor For +) : D3d12GpuSwapChain(isolate, options, options.AlphaMode, options.VSync) +{ + bool is_hdr = false; + 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(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: + m_frame_count = desc.BufferCount = 1; + break; + case FPresentMode::DoubleBuffer: + m_frame_count = desc.BufferCount = 2; + break; + case FPresentMode::TripleBuffer: + default: + m_frame_count = desc.BufferCount = 3; + 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; + + 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); + + if (this->Format == FGraphicsFormat::R10G10B10A2_UNorm) + { + 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(); +} + +FGraphicsFormat D3d12GpuSwapChain::SelectFormat(const FGpuSwapChainCreateOptions& 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; +} + +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])); + D3D12_RENDER_TARGET_VIEW_DESC desc{}; + desc.Format = ToDx(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); + } +} + +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(); +} + +NonNull D3d12GpuSwapChain::State() +{ + return &m_layout_state; +} + +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([&] + { + 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(); + m_image_data.m_width = this->Width = width; + m_image_data.m_height = 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); +} + +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 new file mode 100644 index 0000000..2f735be --- /dev/null +++ b/Coplt.Graphics.Native/D3d12/Src/SwapChain.h @@ -0,0 +1,97 @@ +#pragma once + +#include "Output.h" +#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; + }; + + enum class SwapChainFor + { + Hwnd, + CoreWindow, + Composition, + }; + + struct D3d12GpuSwapChain final : GpuObject, FGpuSwapChainData + { + Rc m_isolate{}; + // 可空 + Rc m_name{}; + ComPtr m_device{}; + ComPtr m_queue{}; + 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{}; + 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{}; + + 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, void* handle, SwapChainFor For); + + 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; + + NonNull State() 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; + + 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; + + void* GetRawPtr() const noexcept override; + }; +} diff --git a/Coplt.Graphics.Native/D3d12/Src/View.cc b/Coplt.Graphics.Native/D3d12/Src/View.cc index 1f4ff39..72892fe 100644 --- a/Coplt.Graphics.Native/D3d12/Src/View.cc +++ b/Coplt.Graphics.Native/D3d12/Src/View.cc @@ -1,259 +1,118 @@ #include "../Include/View.h" #include "../Include/GraphicsFormat.h" +#include "Buffer.h" +#include "Image.h" +#include "Sampler.h" using namespace Coplt; -enum View::Type View::Type() const +View& View::swap(View& other) noexcept { - 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; + std::swap(m_viewable, other.m_viewable); + std::swap(m_type, other.m_type); + return *this; } -View::~View() +View::View(const FView& view) { - // ReSharper disable once CppDefaultCaseNotHandledInSwitchStatement - switch (m_type) + if (view.Type != FViewType::None && view.Viewable) { - 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; + const auto viewable = view.Viewable->QueryInterface(); + if (!viewable) + COPLT_THROW("Viewable from different backends"); + m_viewable = Rc::UnsafeClone(viewable); + m_type = view.Type; } - std::unreachable(); } -// ReSharper disable once CppPossiblyUninitializedMember -View::View() : m_type(Type::None) +View& View::operator=(const FView& view) { + return View(view).swap(*this); } -View::View(const View& other) : m_type(other.m_type) +View::operator bool() const { - 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; - } + return m_viewable && m_type != FViewType::None; } -View::View(View&& other) noexcept : m_type(std::exchange(other.m_type, Type::None)) +bool View::IsCompatible(const FBindGroupItem& def) const { 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) - { 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; + return m_viewable->IsCompatible(def); } + return true; } -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) +bool View::IsBuffer() const { - new(std::addressof(m_buffer)) Rc(std::move(buffer)); + return m_type == FViewType::Buffer; } -View& View::operator=(const Rc& buffer) +bool View::IsImage() const { - this->~View(); - new(this) View(buffer); - return *this; + return m_type == FViewType::Image; } -View& View::operator=(Rc&& buffer) +bool View::IsSampler() const { - this->~View(); - new(this) View(std::forward>(buffer)); - return *this; + return m_type == FViewType::Sampler; } -View::View(const Rc& image) : m_type(Type::Image) +NonNull View::GetViewable() const { - new(std::addressof(m_image)) Rc(image); + return m_viewable; } -View::View(Rc&& image) : m_type(Type::Image) +Ptr View::TryGetBuffer() const { - new(std::addressof(m_image)) Rc(std::move(image)); + return m_viewable->QueryInterface(); } -View& View::operator=(const Rc& image) +Ptr View::TryGetImage() const { - this->~View(); - new(this) View(image); - return *this; + return m_viewable->QueryInterface(); } -View& View::operator=(Rc&& image) +Ptr View::TryGetSampler() const { - this->~View(); - new(this) View(std::forward>(image)); - return *this; + return m_viewable->QueryInterface(); } -void View::CreateDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, const CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView type -) const +void View::CreateDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const { - switch (Type()) + switch (m_type) { - case Type::None: - CreateNullDescriptor(device, def, handle, type); + case FViewType::None: + CreateNullDescriptor(device, def, handle); break; - case Type::Buffer: - CreateBufferDescriptor(device, def, handle, type); + case FViewType::Buffer: + CreateBufferDescriptor(device, def, handle); break; - case Type::Image: - CreateImageDescriptor(device, def, handle, type); + case FViewType::Image: + CreateImageDescriptor(device, def, handle); break; - case Type::Sampler: - CreateSamplerDescriptor(device, def, handle, type); + case FViewType::Sampler: + CreateSamplerDescriptor(device, def, handle); break; } } -void View::CreateNullDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, const FShaderLayoutGroupView view -) +void View::CreateNullDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) { - switch (view) + switch (def.View) { - case FShaderLayoutGroupView::Cbv: + case FShaderLayoutItemView::Cbv: { device->CreateConstantBufferView(nullptr, handle); break; } - case FShaderLayoutGroupView::Srv: + case FShaderLayoutItemView::Srv: { D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; desc.Format = ToDx(def.Format); @@ -344,7 +203,7 @@ void View::CreateNullDescriptor( device->CreateShaderResourceView(nullptr, &desc, handle); break; } - case FShaderLayoutGroupView::Uav: + case FShaderLayoutItemView::Uav: { D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; desc.Format = ToDx(def.Format); @@ -417,7 +276,7 @@ void View::CreateNullDescriptor( device->CreateUnorderedAccessView(nullptr, nullptr, &desc, handle); break; } - case FShaderLayoutGroupView::Sampler: + case FShaderLayoutItemView::Sampler: { D3D12_SAMPLER_DESC desc{}; desc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; @@ -433,16 +292,14 @@ void View::CreateNullDescriptor( } } -void View::CreateBufferDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type -) const +void View::CreateBufferDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const { - const auto buffer = Buffer().get(); + const NonNull buffer = TryGetBuffer(); const auto resource = buffer->GetResourcePtr(); const auto data = buffer->GpuBufferData(); - switch (type) + switch (def.View) { - case FShaderLayoutGroupView::Cbv: + case FShaderLayoutItemView::Cbv: { D3D12_CONSTANT_BUFFER_VIEW_DESC desc{}; desc.BufferLocation = resource->GetGPUVirtualAddress(); @@ -450,7 +307,7 @@ void View::CreateBufferDescriptor( device->CreateConstantBufferView(&desc, handle); break; } - case FShaderLayoutGroupView::Srv: + case FShaderLayoutItemView::Srv: { D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; desc.Format = ToDx(def.Format); @@ -499,7 +356,7 @@ void View::CreateBufferDescriptor( device->CreateShaderResourceView(resource, &desc, handle); break; } - case FShaderLayoutGroupView::Uav: + case FShaderLayoutItemView::Uav: { D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; desc.Format = ToDx(def.Format); @@ -546,23 +403,23 @@ void View::CreateBufferDescriptor( device->CreateUnorderedAccessView(resource, nullptr, &desc, handle); break; } - case FShaderLayoutGroupView::Sampler: + case FShaderLayoutItemView::Sampler: COPLT_THROW("Buffer cannot be used as a sampler"); + default: + std::unreachable(); } } -void View::CreateImageDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type -) const +void View::CreateImageDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const { - const auto image = Image().get(); + const NonNull image = TryGetImage(); const auto resource = image->GetResourcePtr(); const auto data = image->GpuImageData(); - switch (type) + switch (def.View) { - case FShaderLayoutGroupView::Cbv: + case FShaderLayoutItemView::Cbv: COPLT_THROW("Image cannot be used as a Cbv"); - case FShaderLayoutGroupView::Srv: + case FShaderLayoutItemView::Srv: { D3D12_SHADER_RESOURCE_VIEW_DESC desc{}; desc.Format = ToDx(data->m_format); @@ -678,7 +535,7 @@ void View::CreateImageDescriptor( device->CreateShaderResourceView(resource, &desc, handle); break; } - case FShaderLayoutGroupView::Uav: + case FShaderLayoutItemView::Uav: { D3D12_UNORDERED_ACCESS_VIEW_DESC desc{}; desc.Format = ToDx(data->m_format); @@ -767,26 +624,28 @@ void View::CreateImageDescriptor( device->CreateUnorderedAccessView(resource, nullptr, &desc, handle); break; } - case FShaderLayoutGroupView::Sampler: + case FShaderLayoutItemView::Sampler: COPLT_THROW("Image cannot be used as a sampler"); + default: + std::unreachable(); } } -void View::CreateSamplerDescriptor( - NonNull device, const FShaderLayoutItemDefine& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle, FShaderLayoutGroupView type -) const +void View::CreateSamplerDescriptor(NonNull device, const FBindGroupItem& def, CD3DX12_CPU_DESCRIPTOR_HANDLE handle) const { - const auto sampler = Sampler().get(); - switch (type) + const NonNull sampler = TryGetSampler(); + switch (def.View) { - case FShaderLayoutGroupView::Cbv: + case FShaderLayoutItemView::Cbv: COPLT_THROW("Sampler cannot be used as a Cbv"); - case FShaderLayoutGroupView::Srv: + case FShaderLayoutItemView::Srv: COPLT_THROW("Sampler cannot be used as a Srv"); - case FShaderLayoutGroupView::Uav: + case FShaderLayoutItemView::Uav: COPLT_THROW("Sampler cannot be used as a Uav"); - case FShaderLayoutGroupView::Sampler: + case FShaderLayoutItemView::Sampler: device->CreateSampler(sampler->Desc(), handle); break; + default: + std::unreachable(); } } 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/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/Colorful/Example.cs b/Examples/Colorful/Example.cs index 2d38465..9e6b1a3 100644 --- a/Examples/Colorful/Example.cs +++ b/Examples/Colorful/Example.cs @@ -6,31 +6,47 @@ 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 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(CommandList cmd) + 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); - ShaderBinding = Device.CreateShaderBinding(Layout, Name: Name); + BindingLayout = Device.CreateBindingLayout( + ShaderLayout, [ + BindGroupLayout = Device.CreateBindGroupLayout( + [ + new() + { + Id = 0, + Stages = ShaderStageFlags.Pixel, + View = ShaderLayoutItemView.Cbv, + Type = ShaderLayoutItemType.ConstantBuffer, + } + ] + ) + ], Name: Name + ); + Shader = Device.CreateShader(modules, ShaderLayout); Pipeline = Device.CreateGraphicsShaderPipeline( Shader, new() { @@ -45,9 +61,9 @@ protected override async Task LoadResources(CommandList cmd) } }, Topology = PrimitiveTopologyType.TriangleStrip, - }, Name: Name + }, BindingLayout, Name: Name ); - ArgBuffer = Device.CreateBuffer( + ArgBuffer = Isolate.CreateBuffer( new() { Purpose = ResourcePurpose.ConstantBuffer, @@ -55,12 +71,13 @@ protected override async Task LoadResources(CommandList cmd) }, Name: "Args" ); - cmd.Bind(ShaderBinding, [new(0, ArgBuffer)]); + BindGroup = Isolate.CreateBindGroup(BindGroupLayout, [new(0, ArgBuffer)]); + Binding = Isolate.CreateBinding(BindingLayout, [new(0, BindGroup)]); } - protected override void Render(CommandList cmd, Time time) + 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); + using var render = cmd.Render([new(Output, LoadOp.Discard)]); + render.Draw(Pipeline, 4, Binding: Binding); } } diff --git a/Examples/ExampleBase/ExampleBase.cs b/Examples/ExampleBase/ExampleBase.cs index 2ce86d1..6b704b1 100644 --- a/Examples/ExampleBase/ExampleBase.cs +++ b/Examples/ExampleBase/ExampleBase.cs @@ -13,7 +13,9 @@ public abstract class ExampleBase(IntPtr Handle, uint Width, uint Height) public bool IsClosed = false; public GraphicsInstance Graphics = null!; public GpuDevice Device = null!; - public GpuOutput Output = null!; + public GpuIsolate Isolate = null!; + public GpuSwapChain Output = null!; + public GpuRecord Record = null!; public IntPtr Handle = Handle; public abstract string Name { get; } @@ -31,31 +33,36 @@ 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 } ); - Output = Device.MainQueue.CreateOutputForHwnd( - new() + Isolate = Device.MainIsolate; + Output = Isolate.CreateSwapChainForHwnd( + Handle, new() { Width = Width, Height = Height, // VSync = true, - }, Handle + // Srgb = false, + } ); + 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) @@ -72,12 +79,15 @@ public void DoInitGraphics() Delta = delta_time }; - Render(cmd, time); + Render(Record, time); + Record.PreparePresent(Output); + Isolate.Submit(Record); Output.Present(); } catch (Exception e) { Log.Error(e, ""); + Environment.Exit(1); } } } @@ -86,6 +96,7 @@ public void DoInitGraphics() catch (Exception e) { Log.Error(e, ""); + Environment.Exit(1); } } @@ -122,13 +133,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..ca73c3c 100644 --- a/Examples/HelloTriangle/Example.cs +++ b/Examples/HelloTriangle/Example.cs @@ -10,7 +10,7 @@ public class Example(IntPtr Handle, uint Width, uint Height) : ExampleBase(Handl 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([])); @@ -30,9 +30,9 @@ protected override async Task LoadResources(CommandList cmd) }, Name: Name ); } - protected override void Render(CommandList cmd, Time time) + protected override void Render(GpuRecord cmd, Time time) { - using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); + 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/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); diff --git a/Examples/HelloTriangleVertex/Example.cs b/Examples/HelloTriangleVertex/Example.cs index 534f583..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; @@ -13,7 +14,7 @@ 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) + protected override async Task LoadResources(GpuRecord cmd) { var SlotId_Position = Graphics.GetSlotId("Position"); var SlotId_Color = Graphics.GetSlotId("Color"); @@ -52,14 +53,14 @@ protected override async Task LoadResources(CommandList 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, @@ -81,9 +82,9 @@ protected override async Task LoadResources(CommandList cmd) ] ); } - protected override void Render(CommandList cmd, Time time) + protected override void Render(GpuRecord cmd, Time time) { - using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))]); + using var render = cmd.Render([new(Output, new Color(0.83f, 0.8f, 0.97f))], Name: Name); render.SetMeshBuffers( MeshLayout, [ new(0, PositionColorBuffer), 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, diff --git a/Examples/Image/Example.cs b/Examples/Image/Example.cs index f58dbe7..941dd47 100644 --- a/Examples/Image/Example.cs +++ b/Examples/Image/Example.cs @@ -8,39 +8,63 @@ 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) + 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.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 ); - Shader = Device.CreateShader(modules, Layout); - ShaderBinding = Device.CreateShaderBinding(Layout, 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() { @@ -55,17 +79,17 @@ protected override async Task LoadResources(CommandList cmd) } }, Topology = PrimitiveTopologyType.TriangleStrip, - }, Name: Name + }, BindingLayout, 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); + 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, @@ -76,11 +100,12 @@ protected override async Task LoadResources(CommandList cmd) Name: "Test Image" ); 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)]); } - protected override void Render(CommandList cmd, Time time) + protected override void Render(GpuRecord cmd, Time time) { using var render = cmd.Render([new(Output, LoadOp.Discard)]); - 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); ``` 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..edf8c5e --- /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 +} \ No newline at end of file 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +