using Ghost.Core; using Ghost.Graphics.Core; using Ghost.Graphics.RHI; using System.Runtime.CompilerServices; namespace Ghost.Graphics.RenderGraphModule; internal enum RenderGraphResourceType : int { Texture, Buffer, // AccelerationStructure, Count } /// /// Specifies how texture dimensions are determined. /// public enum RGTextureSizeMode : byte { /// /// Fixed pixel dimensions (width, height). /// Absolute, /// /// Scale relative to view state (scaleX * viewportWidth, scaleY * viewportHeight). /// Relative } /// /// View state information for resolving relative texture sizes. /// public struct ViewState : IEquatable { public uint viewportWidth; public uint viewportHeight; public ViewState(uint width, uint height) { viewportWidth = width; viewportHeight = height; } public readonly bool Equals(ViewState other) { return viewportWidth == other.viewportWidth && viewportHeight == other.viewportHeight; } public override readonly bool Equals(object? obj) { return obj is ViewState other && Equals(other); } public override readonly int GetHashCode() { return HashCode.Combine(viewportWidth, viewportHeight); } public static bool operator ==(ViewState left, ViewState right) { return left.Equals(right); } public static bool operator !=(ViewState left, ViewState right) { return !left.Equals(right); } } /// /// Render graph texture descriptor with support for relative sizing and clear operations. /// public struct RGTextureDesc : IEquatable { public RGTextureSizeMode sizeMode; // Size specification (union-like - only one set is used based on sizeMode) public uint width; // For Absolute mode public uint height; // For Absolute mode public float scaleX; // For Relative mode public float scaleY; // For Relative mode // Common texture properties public TextureFormat format; public TextureDimension dimension; public uint mipLevels; public uint slice; public TextureUsage usage; public bool clearAtFirstUse; public bool discardAtLastUse; // Clear operation support public Color128 clearColor; public float clearDepth; public byte clearStencil; /// /// Creates a texture descriptor with absolute dimensions. /// public static RGTextureDesc Absolute( uint width, uint height, TextureFormat format, Color128 clearColor = default, bool clearAtFirstUse = true, bool discardAtLastUse = true, TextureDimension dimension = TextureDimension.Texture2D, uint mipLevels = 1, uint slice = 1, TextureUsage usage = TextureUsage.RenderTarget | TextureUsage.ShaderResource) { return new RGTextureDesc { sizeMode = RGTextureSizeMode.Absolute, width = width, height = height, format = format, clearColor = clearColor, clearAtFirstUse = clearAtFirstUse, discardAtLastUse = discardAtLastUse, clearDepth = 1.0f, clearStencil = 0, dimension = dimension, mipLevels = mipLevels, slice = slice, usage = usage }; } /// /// Creates a texture descriptor with relative dimensions (uniform scale). /// public static RGTextureDesc Relative( float scale, TextureFormat format, Color128 clearColor = default, bool clearAtFirstUse = true, bool discardAtLastUse = true, TextureDimension dimension = TextureDimension.Texture2D, uint mipLevels = 1, uint slice = 1, TextureUsage usage = TextureUsage.RenderTarget | TextureUsage.ShaderResource) { return new RGTextureDesc { sizeMode = RGTextureSizeMode.Relative, scaleX = scale, scaleY = scale, format = format, clearColor = clearColor, clearAtFirstUse = clearAtFirstUse, discardAtLastUse = discardAtLastUse, clearDepth = 1.0f, clearStencil = 0, dimension = dimension, mipLevels = mipLevels, slice = slice, usage = usage }; } /// /// Creates a texture descriptor with relative dimensions (non-uniform scale). /// public static RGTextureDesc Relative( float scaleX, float scaleY, TextureFormat format, Color128 clearColor = default, bool clearAtFirstUse = true, bool discardAtLastUse = true, TextureDimension dimension = TextureDimension.Texture2D, uint mipLevels = 1, uint slice = 1, TextureUsage usage = TextureUsage.RenderTarget | TextureUsage.ShaderResource) { return new RGTextureDesc { sizeMode = RGTextureSizeMode.Relative, scaleX = scaleX, scaleY = scaleY, format = format, clearColor = clearColor, clearAtFirstUse = clearAtFirstUse, discardAtLastUse = discardAtLastUse, clearDepth = 1.0f, clearStencil = 0, dimension = dimension, mipLevels = mipLevels, slice = slice, usage = usage }; } /// /// Creates a depth texture descriptor with relative dimensions. /// public static RGTextureDesc RelativeDepth( float scale, float clearDepth = 1.0f, byte clearStencil = 0, bool clearAtFirstUse = true, bool discardAtLastUse = true, TextureFormat format = TextureFormat.D32_Float) { return new RGTextureDesc { sizeMode = RGTextureSizeMode.Relative, scaleX = scale, scaleY = scale, format = format, clearColor = default, clearDepth = clearDepth, clearStencil = clearStencil, clearAtFirstUse = clearAtFirstUse, discardAtLastUse = discardAtLastUse, dimension = TextureDimension.Texture2D, mipLevels = 1, slice = 1, usage = TextureUsage.DepthStencil | TextureUsage.ShaderResource }; } /// /// Converts to RHI TextureDesc using resolved dimensions. /// public readonly TextureDesc ToTextureDesc(uint resolvedWidth, uint resolvedHeight) { return new TextureDesc { Width = resolvedWidth, Height = resolvedHeight, Format = format, Dimension = dimension, MipLevels = mipLevels, Slice = slice, Usage = usage }; } public readonly bool Equals(RGTextureDesc other) { return sizeMode == other.sizeMode && format == other.format && dimension == other.dimension && mipLevels == other.mipLevels && slice == other.slice && usage == other.usage && clearAtFirstUse == other.clearAtFirstUse && discardAtLastUse == other.discardAtLastUse && (sizeMode == RGTextureSizeMode.Absolute ? width == other.width && height == other.height : scaleX == other.scaleX && scaleY == other.scaleY); } public override readonly bool Equals(object? obj) { return obj is RGTextureDesc other && Equals(other); } public override readonly int GetHashCode() { if (sizeMode == RGTextureSizeMode.Absolute) { return HashCode.Combine(sizeMode, width, height, format, dimension, mipLevels, slice, usage); } else { return HashCode.Combine(sizeMode, scaleX, scaleY, format, dimension, mipLevels, slice, usage); } } public static bool operator ==(RGTextureDesc left, RGTextureDesc right) { return left.Equals(right); } public static bool operator !=(RGTextureDesc left, RGTextureDesc right) { return !left.Equals(right); } } public struct RGResource; public struct RGTexture; public struct RGBuffer; public static class RGResourceExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Identifier AsResource(this Identifier texture) { return new Identifier(texture.Value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Identifier AsResource(this Identifier buffer) { return new Identifier(buffer.Value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Identifier AsTexture(this Identifier resource) { return new Identifier(resource.Value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Identifier AsBuffer(this Identifier resource) { return new Identifier(resource.Value); } } internal readonly struct TextureAccess { public readonly Identifier id; public readonly AccessFlags accessFlags; public readonly ResourceBarrierData usage; public TextureAccess(Identifier id, AccessFlags accessFlags, ResourceBarrierData usage) { this.id = id; this.accessFlags = accessFlags; this.usage = usage; } } /// /// Tracks buffer access information. /// internal readonly struct BufferAccess { public readonly Identifier id; public readonly AccessFlags accessFlags; public readonly ResourceBarrierData usage; public BufferAccess(Identifier id, AccessFlags accessFlags, ResourceBarrierData usage) { this.id = id; this.accessFlags = accessFlags; this.usage = usage; } } /// /// Base interface for pass data that can be stored in the blackboard. /// public interface IPassData { } /// /// Information about a render target attachment in a native render pass. /// internal struct RenderTargetInfo { public Identifier texture; public AccessFlags access; public AttachmentLoadOp loadOp; public AttachmentStoreOp storeOp; public Color128 clearColor; } /// /// Information about a depth-stencil attachment in a native render pass. /// internal struct DepthStencilInfo { public Identifier texture; public AccessFlags access; public AttachmentLoadOp loadOp; public AttachmentStoreOp storeOp; public float clearDepth; public byte clearStencil; }