refactor(shader): rewrite editor shader compilation bridge with keyword resolution

- Add AssetCatalog.EnumerateByTypes for filtered SQL queries
- Thread LocalKeywordSet through IShaderCompilationBridge API so the
  bridge can resolve keyword bitmask to string defines at compile time
- Eager/lazy popluation of shader-id-to-asset-id map eliminating
  full catalog scan per compilation miss
- Build keyword mapping from PassDescriptor groups to reconstruct
  localIndex -> keywordName in the bridge
- Use CompileShaderPass extension for multi-stage AS/MS/PS compilation
  with correct ShaderModel from descriptor
- Remove double-load of shader asset in compilation flow
- Update test mock to match new interface signature
This commit is contained in:
2026-05-08 19:36:24 +09:00
parent d0076c852f
commit 1cc65e8218
10 changed files with 306 additions and 129 deletions

View File

@@ -179,7 +179,7 @@ public readonly struct ShaderPass
get; init;
}
public LocalKeywordSet KeywordIDs
public LocalKeywordSet DefinedKeywords
{
get; init;
}

View File

@@ -2,13 +2,13 @@ using Ghost.Core;
namespace Ghost.Graphics.RHI;
public interface IShaderCompilationBridge
public interface IShaderCompilationBridge : IDisposable
{
/// <summary>
/// Request the bridge to recompile a shader variant or handle cache misses.
/// This is typically called by the ShaderLibrary when a variant hash is not found.
/// </summary>
void RequestCompilation(ulong shaderId, int passIndex, Key64<ShaderVariant> variantKey);
void RequestCompilation(ulong shaderId, int passIndex, Key64<ShaderVariant> variantKey, LocalKeywordSet keywordMask);
/// <summary>
/// Event triggered when a shader variant has been successfully compiled and updated.

View File

@@ -379,7 +379,7 @@ public readonly unsafe ref struct RenderContext
var variantKey = RHIUtility.CreateShaderVariantKey(entryHash, in keywordSet);
// TODO: Refactor this into a helper method.
var (compiledHash, error) = ShaderLibrary.GetCompiledHash(shader.UniqueID, entryIndex, variantKey);
var (compiledHash, error) = ShaderLibrary.GetCompiledHash(shader.UniqueID, entryIndex, variantKey, keywordSet);
if (error.IsFailure)
{
// TODO: Fallback to an error material.

View File

@@ -119,7 +119,7 @@ public partial struct Shader : IResourceReleasable
{
Key = RHIUtility.GetPassID(_nameHash, i),
DefaultState = pass.localPipeline,
KeywordIDs = keywords,
DefinedKeywords = keywords,
};
_passIDToLocal[GetPassID(pass.name)] = (ushort)i;

View File

@@ -169,10 +169,10 @@ internal sealed class RenderGraphContext : IUnsafeRenderContext
var materialPipeline = material.GetPassPipelineOverride(material.ActivePassIndex);
// Mask out the keywords that are not used in this pass.
var variantMask = material._keywordMask & pass.KeywordIDs;
var variantMask = material._keywordMask & pass.DefinedKeywords;
var variantKey = RHIUtility.CreateShaderVariantKey(pass.Key, in variantMask);
var (compiledHash, error) = _shaderLibrary.GetCompiledHash(shader.UniqueID, material.ActivePassIndex, variantKey);
var (compiledHash, error) = _shaderLibrary.GetCompiledHash(shader.UniqueID, material.ActivePassIndex, variantKey, variantMask);
if (error.IsFailure)
{
// TODO: Fallback to a default shader or show an error material.
@@ -277,7 +277,7 @@ internal sealed class RenderGraphContext : IUnsafeRenderContext
var keywordSet = new LocalKeywordSet(); // TODO: Support keywords in compute shader.
var variantKey = RHIUtility.CreateShaderVariantKey(entryHash, in keywordSet);
var (compiledHash, error) = _shaderLibrary.GetCompiledHash(shader.UniqueID, entryIndex, variantKey);
var (compiledHash, error) = _shaderLibrary.GetCompiledHash(shader.UniqueID, entryIndex, variantKey, keywordSet);
if (error.IsFailure)
{
// TODO: Fallback to a default shader or show an error material.

View File

@@ -195,14 +195,14 @@ internal unsafe class ShaderLibrary : IDisposable
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Result<ulong, Error> GetCompiledHash(ulong id, int passIndex, Key64<ShaderVariant> variantKey)
public Result<ulong, Error> GetCompiledHash(ulong id, int passIndex, Key64<ShaderVariant> variantKey, LocalKeywordSet keywordMask = default)
{
if (_variantToCompiledHash.TryGetValue(variantKey, out var compiledHash))
{
return compiledHash;
}
_shaderCompilationBridge?.RequestCompilation(id, passIndex, variantKey);
_shaderCompilationBridge?.RequestCompilation(id, passIndex, variantKey, keywordMask);
return Error.NotFound;
}