Refactor: variant-aware shader/material pipeline overhaul

Major architectural update to graphics/material/shader system:
- Introduced strongly-typed key structs (Key64/Key128) for passes, variants, and pipelines; removed legacy key types.
- Implemented robust hashing and key generation utilities for efficient variant and pipeline lookup/caching.
- Shader compiler now compiles/caches all keyword variants using new key system; includes handled as lists.
- Switched to push constant root signature for per-draw data; updated HLSL and C# codegen accordingly.
- Refactored Material, Shader, and Pass data structures for cache efficiency and variant support.
- Pipeline library and PSO management now use 128-bit keys and variant-specific caching.
- Replaced WorldNode with SceneNode in editor/scene graph; introduced ComponentManager for archetype/query management.
- Migrated math utilities to Misaki.HighPerformance.Mathematics; updated editor controls.
- Updated all HLSL and codegen for new buffer/push constant layouts and macros.
- Misc: project reference cleanup, D3D12 Work Graph support, doc updates, and code modernization.
This commit is contained in:
2026-01-09 22:25:37 +09:00
parent c9be05fc60
commit 6a041f75ba
93 changed files with 1926 additions and 1390 deletions

View File

@@ -1,3 +1,10 @@
using Ghost.Core;
using Ghost.Core.Graphics;
using Ghost.Core.Utilities;
using Ghost.Graphics.Core;
using System.IO.Hashing;
using System.Runtime.InteropServices;
namespace Ghost.Graphics.RHI;
internal static class RHIUtility
@@ -27,7 +34,7 @@ internal static class RHIUtility
var packed = false;
var planar = false;
var bpe = 0u;
//switch (Format)
//{
// case Format.BC1Typeless:
@@ -127,4 +134,49 @@ internal static class RHIUtility
slicePitch = rowPitch * height;
}
}
}
public static Key64<ShaderPass> CreateShaderPassKey(string passID)
{
var passIdSpan = passID.AsSpan();
return new Key64<ShaderPass>(XxHash3.HashToUInt64(MemoryMarshal.AsBytes(passIdSpan)));
}
public static Key64<ShaderVariant> CreateShaderVariantKey(Key64<ShaderPass> passKey, ref readonly LocalKeywordSet keywords)
{
var passHash = passKey.Value;
var keywordHash = keywords.GetHash64();
return new Key64<ShaderVariant>(Hash.Hash64(passHash, keywordHash));
}
public static unsafe Key128<GraphicsPipeline> CreateGraphicsPipelineKey(Key64<ShaderVariant> shaderVariantKey, PipelineState pipelineState, PassPipelineHash passKey)
{
// Order-sensitive 128-bit mix. Cheap and stable, avoids span hashing.
static ulong Mix64(ulong x)
{
x ^= x >> 30;
x *= 0xBF58476D1CE4E5B9ul;
x ^= x >> 27;
x *= 0x94D049BB133111EBul;
x ^= x >> 31;
return x;
}
var mLo = shaderVariantKey.Value;
var mHi = pipelineState.GetHashCode64();
var pPasskey = (ulong*)&passKey.value;
var pLo = pPasskey[0];
var pHi = pPasskey[1];
// Distinct constants + cross-feeding to reduce structural collisions.
var lo = Mix64(mLo ^ (pLo + 0x9E3779B97F4A7C15ul) ^ (mHi * 0xD6E8FEB86659FD93ul));
var hi = Mix64(mHi ^ (pHi + 0xC2B2AE3D27D4EB4Ful) ^ (pLo * 0x165667B19E3779F9ul));
return new Key128<GraphicsPipeline>(new UInt128(lo, hi));
}
public static bool TryGetString(this Key128<GraphicsPipeline> key, Span<char> destination)
{
return key.Value.TryFormat(destination, out var _, "X16");
}
}