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

@@ -64,6 +64,8 @@ public readonly unsafe ref struct RenderingContext
if (staticMesh)
{
meshData.ReleaseCpuResources();
_directCmd.ResourceBarrier(vertexHandle, ResourceState.NonPixelShaderResource);
_directCmd.ResourceBarrier(indexHandle, ResourceState.NonPixelShaderResource);
}
return mesh;
@@ -91,7 +93,7 @@ public readonly unsafe ref struct RenderingContext
{
ref var meshRef = ref ResourceDatabase.GetMeshReference(mesh);
_directCmd.ResourceBarrier(meshRef.VertexBuffer.AsResource(),ResourceState.CopyDest);
_directCmd.ResourceBarrier(meshRef.VertexBuffer.AsResource(), ResourceState.CopyDest);
_directCmd.ResourceBarrier(meshRef.IndexBuffer.AsResource(), ResourceState.CopyDest);
_directCmd.UploadBuffer(meshRef.VertexBuffer, meshRef.Vertices.AsSpan());
@@ -122,7 +124,7 @@ public readonly unsafe ref struct RenderingContext
_directCmd.ResourceBarrier(bufferHandle, ResourceState.CopyDest);
_directCmd.UploadBuffer(meshData.ObjectDataBuffer, [data]);
_directCmd.ResourceBarrier(bufferHandle, ResourceState.VertexAndConstantBuffer);
_directCmd.ResourceBarrier(bufferHandle, ResourceState.NonPixelShaderResource | ResourceState.PixelShaderResource);
}
public Handle<Texture> CreateTexture<T>(ref readonly TextureDesc desc, ReadOnlySpan<T> data, bool tempResource = false)
@@ -176,14 +178,20 @@ public readonly unsafe ref struct RenderingContext
throw new InvalidOperationException("Shader pass not found in the material's shader.");
}
var passPipelineKey = new PassPipelineKey([TextureFormat.B8G8R8A8_UNorm], TextureFormat.Unknown);
var materialPipelineKey = materialRef.GetPassPipelineKey(passIndex);
var pipelineKey = GraphicsPipelineKey.Combine(materialPipelineKey, passPipelineKey);
ref var pass = ref shader.GetPassReference(passIndex);
var passPipelineHash = new PassPipelineHash([TextureFormat.B8G8R8A8_UNorm], TextureFormat.Unknown);
var materialPipeline = materialRef.GetPassPipelineOverride(passIndex);
// Mask out the keywords that are not used in this pass.
var variantMask = materialRef._keywordMask & pass.KeywordIDs;
var shaderVariantKey = RHIUtility.CreateShaderVariantKey(pass.Key, in variantMask);
var pipelineKey = RHIUtility.CreateGraphicsPipelineKey(shaderVariantKey, materialPipeline, passPipelineHash);
if (!_engine.PipelineLibrary.HasPipeline(pipelineKey))
{
var pass = shader.GetPassReference(passIndex);
var r = _engine.ShaderCompiler.LoadCompiledCache(pass.Identifier);
var r = _engine.ShaderCompiler.LoadCompiledCache(shaderVariantKey);
if (r.IsFailure)
{
throw new InvalidOperationException("Failed to load compiled shader cache for pipeline state object creation.");
@@ -191,7 +199,7 @@ public readonly unsafe ref struct RenderingContext
var psoDes = new GraphicsPSODescriptor
{
PassId = pass.Identifier,
VariantKey = shaderVariantKey,
PipelineOption = materialRef.GetPassPipelineOverride(passIndex),
RtvFormats = [TextureFormat.B8G8R8A8_UNorm],
@@ -203,14 +211,15 @@ public readonly unsafe ref struct RenderingContext
}
_directCmd.SetPipelineState(pipelineKey);
_directCmd.SetConstantBufferView(RootSignatureLayout.PER_OBJECT_BUFFER_SLOT, meshRef.ObjectDataBuffer);
// NOTE: We use fixed root signature layout for bindless rendering.
var cache = materialRef.CBufferCache;
if (cache.IsCreated)
var data = new PushConstantsData
{
_directCmd.SetConstantBufferView(RootSignatureLayout.PER_MATERIAL_BUFFER_SLOT, cache.GpuResource);
}
objectIndex = _engine.ResourceDatabase.GetBindlessIndex(meshRef.ObjectDataBuffer.AsResource()).GetValueOrThrow(),
materialIndex = _engine.ResourceDatabase.GetBindlessIndex(materialRef._cBufferCache.GpuResource.AsResource()).GetValueOrThrow(),
};
var pushConstantSpan = new ReadOnlySpan<uint>(&data, sizeof(PushConstantsData) / sizeof(uint));
_directCmd.SetGraphicsRoot32Constants(RootSignatureLayout.PUSH_CONSTANT_SLOT, pushConstantSpan);
var threadGroupCountX = ((uint)meshRef.IndexCount + numThreadsX - 1) / numThreadsX;
_directCmd.DispatchMesh(threadGroupCountX, 1, 1);