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
};
}
///
/// Creates an RGTextureDesc from an RHI TextureDesc (for imported textures).
///
public static RGTextureDesc FromTextureDesc(in TextureDesc desc)
{
return new RGTextureDesc
{
sizeMode = RGTextureSizeMode.Absolute,
width = desc.Width,
height = desc.Height,
format = desc.Format,
clearColor = default,
clearDepth = 1.0f,
clearStencil = 0,
clearAtFirstUse = false,
discardAtLastUse = false,
dimension = desc.Dimension,
mipLevels = desc.MipLevels,
slice = desc.Slice,
usage = desc.Usage
};
}
///
/// 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);
}
}
///
/// Hints for how a buffer will be used in a pass.
/// Used to determine correct resource state transitions.
///
[Flags]
public enum BufferHint
{
///
/// No special usage - buffer will be used as shader resource (SRV) or UAV based on AccessFlags.
///
None = 0,
///
/// Buffer will be used as indirect argument buffer (ExecuteIndirect).
/// Requires ResourceState.IndirectArgument.
///
IndirectArgument = 1 << 0,
}
internal readonly struct TextureAccess
{
public readonly Identifier id;
public readonly AccessFlags accessFlags;
public TextureAccess(Identifier id, AccessFlags accessFlags)
{
this.id = id;
this.accessFlags = accessFlags;
}
}
///
/// Tracks buffer access information including usage hints.
///
internal readonly struct BufferAccess
{
public readonly Identifier id;
public readonly AccessFlags accessFlags;
public readonly BufferHint hint;
public BufferAccess(Identifier id, AccessFlags accessFlags, BufferHint hint = BufferHint.None)
{
this.id = id;
this.accessFlags = accessFlags;
this.hint = hint;
}
}
/////
///// Descriptor for creating a texture resource.
/////
//public readonly struct TextureDescriptor : IEquatable
//{
// public readonly int width;
// public readonly int height;
// public readonly TextureFormat format;
// public readonly string name;
// public TextureDescriptor(int width, int height, TextureFormat format, string name)
// {
// this.width = width;
// this.height = height;
// this.format = format;
// this.name = name;
// }
// public readonly bool Equals(TextureDescriptor other)
// {
// return width == other.width &&
// height == other.height &&
// format == other.format &&
// name == other.name;
// }
// public override readonly bool Equals(object? obj) => obj is TextureDescriptor other && Equals(other);
// public override readonly int GetHashCode() => HashCode.Combine(width, height, format, name);
// public static bool operator ==(TextureDescriptor left, TextureDescriptor right)
// {
// return left.Equals(right);
// }
// public static bool operator !=(TextureDescriptor left, TextureDescriptor right)
// {
// return !(left == right);
// }
//}
//public readonly struct BufferDescriptor : IEquatable
//{
// public readonly uint sizeInBytes;
// public readonly uint stride;
// public readonly BufferUsage usage;
// public readonly string name;
// public BufferDescriptor(uint sizeInBytes, uint stride, BufferUsage usage, string name)
// {
// this.sizeInBytes = sizeInBytes;
// this.stride = stride;
// this.usage = usage;
// this.name = name;
// }
// public readonly bool Equals(BufferDescriptor other)
// {
// return sizeInBytes == other.sizeInBytes &&
// stride == other.stride &&
// usage == other.usage &&
// name == other.name;
// }
// public override readonly bool Equals(object? obj) => obj is BufferDescriptor other && Equals(other);
// public override readonly int GetHashCode() => HashCode.Combine(sizeInBytes, name);
// public static bool operator ==(BufferDescriptor left, BufferDescriptor right)
// {
// return left.Equals(right);
// }
// public static bool operator !=(BufferDescriptor left, BufferDescriptor right)
// {
// return !(left == right);
// }
//}
///
/// 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;
}