using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Win32.Graphics.Direct3D12; namespace Ghost.Graphics.RHI; /// /// Root signature interface /// public interface IRootSignature : IDisposable { /// /// Root signature name for debugging /// string Name { get; set; } } /// /// Pipeline types /// public enum PipelineType { Graphics, Compute } [StructLayout(LayoutKind.Explicit)] public struct ResourceDesc { [FieldOffset(0)] public TextureDesc textureDescription; [FieldOffset(0)] public BufferDesc bufferDescription; public static ResourceDesc Buffer(BufferDesc desc) { return new ResourceDesc { bufferDescription = desc }; } public static ResourceDesc Texture(TextureDesc desc) { return new ResourceDesc { textureDescription = desc }; } internal static ResourceDesc FromD3D12(ResourceDescription desc) { if (desc.Dimension == ResourceDimension.Buffer) { return Buffer(new BufferDesc { Size = desc.Width, Stride = 0, Usage = BufferUsage.None, CreationFlags = BufferCreationFlags.None, MemoryType = MemoryType.Default }); } else { return Texture(new TextureDesc { Width = (uint)desc.Width, Height = desc.Height, Slice = desc.DepthOrArraySize, Format = desc.Format.ToTextureFormat(), Dimension = desc.Dimension.ToTextureDimension(), MipLevels = desc.MipLevels, Usage = TextureUsage.None, CreationFlags = TextureCreationFlags.None }); } } } /// /// Render target description /// Supports either color OR depth rendering, not both /// public struct RenderTargetDesc { /// /// Width of the render target /// public uint Width { get; set; } /// /// Height of the render target /// public uint Height { get; set; } /// /// Slice of the render target /// public uint Slice { get; set; } /// /// Type of render target /// public RenderTargetType Type { get; set; } /// /// Target texture format /// public TextureFormat Format { get; set; } /// /// Texture dimension /// public TextureDimension Dimension { get; set; } /// /// Creation flags for the render target /// public RenderTargetCreationFlags CreationFlags { get; set; } /// /// Number of mip levels. 0 to generate full mip chain /// public uint MipLevels { get; set; } /// /// Number of samples for MSAA /// public uint SampleCount { get; set; } /// /// Creates a color render target /// public static RenderTargetDesc Color(uint width, uint height, uint slice = 1, TextureFormat format = TextureFormat.R8G8B8A8_UNorm, TextureDimension dimension = TextureDimension.Texture2D, RenderTargetCreationFlags creationFlags = RenderTargetCreationFlags.AllowUAV | RenderTargetCreationFlags.DynamicallyScalable | RenderTargetCreationFlags.GenerateMips, uint mipLevels = 0u, uint sampleCount = 1) { return new RenderTargetDesc { Width = width, Height = height, Slice = slice, Type = RenderTargetType.Color, Format = format, Dimension = dimension, CreationFlags = creationFlags, MipLevels = mipLevels, SampleCount = sampleCount }; } /// /// Creates a depth render target /// public static RenderTargetDesc Depth(uint width, uint height, uint slice = 1, TextureFormat format = TextureFormat.D24_UNorm_S8_UInt, TextureDimension dimension = TextureDimension.Texture2D, RenderTargetCreationFlags creationFlags = RenderTargetCreationFlags.AllowUAV | RenderTargetCreationFlags.DynamicallyScalable, uint mipLevels = 0u, uint sampleCount = 1) { return new RenderTargetDesc { Width = width, Height = height, Slice = slice, Type = RenderTargetType.Depth, Format = format, Dimension = dimension, CreationFlags = creationFlags, MipLevels = mipLevels, SampleCount = sampleCount }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TextureDesc ToTextureDescripton(RenderTargetDesc desc) { var usage = desc.Type == RenderTargetType.Color ? TextureUsage.RenderTarget : TextureUsage.DepthStencil; if (desc.CreationFlags.HasFlag(RenderTargetCreationFlags.AllowUAV)) { usage |= TextureUsage.UnorderedAccess; } return new TextureDesc { Width = desc.Width, Height = desc.Height, Slice = desc.Slice, Format = desc.Format, Dimension = desc.Dimension, MipLevels = desc.MipLevels, Usage = usage, CreationFlags = TextureCreationFlags.Bindless }; } } /// /// Texture description /// public struct TextureDesc { /// /// Width of the texture /// public uint Width { get; set; } /// /// Height of the texture /// public uint Height { get; set; } /// /// Slice of the texture /// public uint Slice { get; set; } /// /// Texture format /// public TextureFormat Format { get; set; } /// /// Texture dimension /// public TextureDimension Dimension { get; set; } /// /// Number of mip levels. 0 to generate full mip chain /// public uint MipLevels { get; set; } /// /// Texture usage flags /// public TextureUsage Usage { get; set; } /// /// Texture creation flags /// public TextureCreationFlags CreationFlags { get; set; } } /// /// Buffer description /// public struct BufferDesc { /// /// Size of the buffer in bytes /// public ulong Size { get; set; } public uint Stride { get; set; } /// /// Buffer usage flags /// public BufferUsage Usage { get; set; } public BufferCreationFlags CreationFlags { get; set; } /// /// Memory type for the buffer /// public MemoryType MemoryType { get; set; } } /// /// Texture usage flags /// [Flags] public enum TextureUsage { None = 0, ShaderResource = 1 << 0, RenderTarget = 1 << 1, DepthStencil = 1 << 2, UnorderedAccess = 1 << 3 } /// /// Dimensions of the texture /// public enum TextureDimension { Unknown = -1, None = 0, Texture2D = 1, Texture3D = 2, TextureCube = 3, Texture2DArray = 4, TextureCubeArray = 5 } public static class TextureDimensionExtension { public static TextureDimension ToTextureDimension(this ResourceDimension dimension) { return dimension switch { ResourceDimension.Texture1D => TextureDimension.Texture2D, ResourceDimension.Texture2D => TextureDimension.Texture2D, ResourceDimension.Texture3D => TextureDimension.Texture3D, _ => TextureDimension.Unknown, }; } } /// /// Render target creation flags /// [Flags] public enum RenderTargetCreationFlags { None = 0, AllowUAV = 1 << 0, AllowMSAA = 1 << 1, DynamicallyScalable = 1 << 2, GenerateMips = 1 << 3 } /// /// Memory types for resources /// public enum MemoryType { Default, // GPU memory Upload, // CPU-to-GPU memory Readback // GPU-to-CPU memory } [Flags] public enum TextureCreationFlags { None = 0, Bindless = 1 << 0 }