forked from Misaki/GhostEngine
Introduces a new Ghost.Shader.Concept project implementing a modern, data-oriented material and shader system with: - Global/local keyword bitsets (fast O(1) ops, 64 bytes) - Multi-pass shader program and per-pass render state overrides - Thread-safe, 16-byte aligned material property blocks - Material pooling to reduce GC pressure - Batch renderer for efficient PSO grouping and async variant warmup - Full demo (Program.cs) and extensive documentation (ARCHITECTURE.md, README.md, PROJECT_SUMMARY.md) - Minor integration: new enums, doc updates, and keyword handling in existing code No breaking changes to the existing engine; all new code is isolated. This serves as a reference implementation for high-performance, extensible material/shader architectures.
127 lines
4.2 KiB
C#
127 lines
4.2 KiB
C#
using System.Runtime.InteropServices;
|
|
|
|
namespace Ghost.Shader.Concept;
|
|
|
|
/// <summary>
|
|
/// Render state configuration for pipeline creation.
|
|
/// Immutable and hashable for PSO caching.
|
|
/// </summary>
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct RenderState : IEquatable<RenderState>
|
|
{
|
|
// Rasterizer State
|
|
public CullMode CullMode;
|
|
public FillMode FillMode;
|
|
public bool FrontCounterClockwise;
|
|
public float DepthBias;
|
|
public float SlopeScaledDepthBias;
|
|
|
|
// Depth-Stencil State
|
|
public bool DepthTestEnable;
|
|
public bool DepthWriteEnable;
|
|
public CompareFunction DepthCompareFunc;
|
|
public bool StencilEnable;
|
|
public byte StencilReadMask;
|
|
public byte StencilWriteMask;
|
|
|
|
// Blend State (per RT, simplified to single RT here)
|
|
public bool BlendEnable;
|
|
public BlendFactor SrcBlend;
|
|
public BlendFactor DestBlend;
|
|
public BlendOperation BlendOp;
|
|
public BlendFactor SrcBlendAlpha;
|
|
public BlendFactor DestBlendAlpha;
|
|
public BlendOperation BlendOpAlpha;
|
|
public ColorWriteMask ColorWriteMask;
|
|
|
|
// Topology
|
|
public PrimitiveTopology Topology;
|
|
|
|
public static RenderState Default => new()
|
|
{
|
|
CullMode = CullMode.Back,
|
|
FillMode = FillMode.Solid,
|
|
FrontCounterClockwise = false,
|
|
DepthTestEnable = true,
|
|
DepthWriteEnable = true,
|
|
DepthCompareFunc = CompareFunction.LessEqual,
|
|
StencilEnable = false,
|
|
StencilReadMask = 0xFF,
|
|
StencilWriteMask = 0xFF,
|
|
BlendEnable = false,
|
|
SrcBlend = BlendFactor.One,
|
|
DestBlend = BlendFactor.Zero,
|
|
BlendOp = BlendOperation.Add,
|
|
SrcBlendAlpha = BlendFactor.One,
|
|
DestBlendAlpha = BlendFactor.Zero,
|
|
BlendOpAlpha = BlendOperation.Add,
|
|
ColorWriteMask = ColorWriteMask.All,
|
|
Topology = PrimitiveTopology.TriangleList
|
|
};
|
|
|
|
public unsafe ulong ComputeHash()
|
|
{
|
|
fixed (RenderState* ptr = &this)
|
|
{
|
|
return ComputeHash64((byte*)ptr, sizeof(RenderState));
|
|
}
|
|
}
|
|
|
|
private static unsafe ulong ComputeHash64(byte* data, int length)
|
|
{
|
|
ulong hash = 0xcbf29ce484222325;
|
|
const ulong prime = 0x100000001b3;
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
hash ^= data[i];
|
|
hash *= prime;
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
public bool Equals(RenderState other)
|
|
{
|
|
return CullMode == other.CullMode &&
|
|
FillMode == other.FillMode &&
|
|
FrontCounterClockwise == other.FrontCounterClockwise &&
|
|
DepthBias == other.DepthBias &&
|
|
SlopeScaledDepthBias == other.SlopeScaledDepthBias &&
|
|
DepthTestEnable == other.DepthTestEnable &&
|
|
DepthWriteEnable == other.DepthWriteEnable &&
|
|
DepthCompareFunc == other.DepthCompareFunc &&
|
|
StencilEnable == other.StencilEnable &&
|
|
StencilReadMask == other.StencilReadMask &&
|
|
StencilWriteMask == other.StencilWriteMask &&
|
|
BlendEnable == other.BlendEnable &&
|
|
SrcBlend == other.SrcBlend &&
|
|
DestBlend == other.DestBlend &&
|
|
BlendOp == other.BlendOp &&
|
|
SrcBlendAlpha == other.SrcBlendAlpha &&
|
|
DestBlendAlpha == other.DestBlendAlpha &&
|
|
BlendOpAlpha == other.BlendOpAlpha &&
|
|
ColorWriteMask == other.ColorWriteMask &&
|
|
Topology == other.Topology;
|
|
}
|
|
|
|
public override bool Equals(object? obj) => obj is RenderState other && Equals(other);
|
|
public override int GetHashCode() => (int)ComputeHash();
|
|
}
|
|
|
|
public enum CullMode : byte { None, Front, Back }
|
|
public enum FillMode : byte { Wireframe, Solid }
|
|
public enum CompareFunction : byte { Never, Less, Equal, LessEqual, Greater, NotEqual, GreaterEqual, Always }
|
|
public enum BlendFactor : byte { Zero, One, SrcColor, InvSrcColor, SrcAlpha, InvSrcAlpha, DestAlpha, InvDestAlpha, DestColor, InvDestColor }
|
|
public enum BlendOperation : byte { Add, Subtract, ReverseSubtract, Min, Max }
|
|
public enum PrimitiveTopology : byte { PointList, LineList, LineStrip, TriangleList, TriangleStrip }
|
|
|
|
[Flags]
|
|
public enum ColorWriteMask : byte
|
|
{
|
|
None = 0,
|
|
Red = 1,
|
|
Green = 2,
|
|
Blue = 4,
|
|
Alpha = 8,
|
|
All = Red | Green | Blue | Alpha
|
|
}
|