From c9be05fc606cc01c1721ca987db0387d1694da5d Mon Sep 17 00:00:00 2001 From: Misaki Date: Sat, 27 Dec 2025 15:14:06 +0900 Subject: [PATCH] Added additional config to CompilePass in IShaderCompiler --- Ghost.Core/Graphics/ShaderDescriptor.cs | 1 + Ghost.Graphics/Contracts/IShaderCompiler.cs | 6 +-- Ghost.Graphics/Core/DxcShaderCompiler.cs | 45 ++++++++++--------- Ghost.Graphics/Core/Shader.cs | 12 +++++ Ghost.Graphics/RenderPasses/MeshRenderPass.cs | 10 ++++- 5 files changed, 48 insertions(+), 26 deletions(-) diff --git a/Ghost.Core/Graphics/ShaderDescriptor.cs b/Ghost.Core/Graphics/ShaderDescriptor.cs index 23b5a1c..a49f0b4 100644 --- a/Ghost.Core/Graphics/ShaderDescriptor.cs +++ b/Ghost.Core/Graphics/ShaderDescriptor.cs @@ -62,6 +62,7 @@ public class FullPassDescriptor : IPassDescriptor public ShaderEntryPoint meshShader; public ShaderEntryPoint pixelShader; public List? defines; + public List? includes; public List? keywords; public PipelineState localPipeline; diff --git a/Ghost.Graphics/Contracts/IShaderCompiler.cs b/Ghost.Graphics/Contracts/IShaderCompiler.cs index 6a9b89e..3eeb829 100644 --- a/Ghost.Graphics/Contracts/IShaderCompiler.cs +++ b/Ghost.Graphics/Contracts/IShaderCompiler.cs @@ -33,7 +33,7 @@ public struct GraphicsCompiledResult : IDisposable } } -public ref struct CompilerConfig +public ref struct ShaderCompilationConfig { public ReadOnlySpan defines; public string? include; @@ -143,7 +143,7 @@ public readonly struct ShaderReflectionData public interface IShaderCompiler : IDisposable { - Result Compile(ref readonly CompilerConfig config, Allocator allocator); - Result CompilePass(IPassDescriptor descriptor, string? generatedCodePath); + Result Compile(ref readonly ShaderCompilationConfig config, Allocator allocator); + Result CompilePass(IPassDescriptor descriptor, ref readonly ShaderCompilationConfig additionalConfig, string? generatedCodePath); Result LoadCompiledCache(ShaderPassKey key); } diff --git a/Ghost.Graphics/Core/DxcShaderCompiler.cs b/Ghost.Graphics/Core/DxcShaderCompiler.cs index 69fe336..76f9180 100644 --- a/Ghost.Graphics/Core/DxcShaderCompiler.cs +++ b/Ghost.Graphics/Core/DxcShaderCompiler.cs @@ -49,7 +49,7 @@ internal sealed partial class DxcShaderCompiler }; } - private static List GetCompilerArguments(ref readonly CompilerConfig config) + private static List GetCompilerArguments(ref readonly ShaderCompilationConfig config) { var argsArray = new List { @@ -242,17 +242,13 @@ internal sealed unsafe partial class DxcShaderCompiler : IShaderCompiler } } - public Result Compile(ref readonly CompilerConfig config, Allocator allocator) + public Result Compile(ref readonly ShaderCompilationConfig config, Allocator allocator) { ObjectDisposedException.ThrowIf(_disposed, this); using ComPtr includeHandler = default; using ComPtr sourceBlob = default; - // Create DXC _compiler.Get() and _utils.Get() - var dxccID = CLSID.CLSID_DxcCompiler; - var dxcuID = CLSID.CLSID_DxcUtils; - ThrowIfFailed(_utils.Get()->CreateDefaultIncludeHandler(includeHandler.GetAddressOf())); // Create source blob @@ -344,7 +340,9 @@ internal sealed unsafe partial class DxcShaderCompiler : IShaderCompiler } } - public Result CompilePass(IPassDescriptor descriptor, string? generatedCodePath) + // TODO: This should be shader variant specific compile instead of pass specific. + // TODO: Build final shader code in memory before compiling. + public Result CompilePass(IPassDescriptor descriptor, ref readonly ShaderCompilationConfig additionalConfig, string? generatedCodePath) { ObjectDisposedException.ThrowIf(_disposed, this); @@ -353,20 +351,23 @@ internal sealed unsafe partial class DxcShaderCompiler : IShaderCompiler return Result.Failure("FullPassDescriptor expected."); } + var fullDefines = fullDescriptor.defines ?? new List(); + fullDefines.AddRange(additionalConfig.defines); + ShaderCompileResult tsResult = default; var tsEntry = fullDescriptor.taskShader; if (tsEntry.IsCreated) { - var config = new CompilerConfig + var config = new ShaderCompilationConfig { - defines = fullDescriptor.defines.AsSpan(), + defines = fullDefines.AsSpan(), include = generatedCodePath, shaderPath = tsEntry.shader, entryPoint = tsEntry.entry, stage = ShaderStage.TaskShader, - tier = CompilerTier.Tier0, - optimizeLevel = CompilerOptimizeLevel.O3, - options = CompilerOption.KeepReflections, + tier = additionalConfig.tier, + optimizeLevel = additionalConfig.optimizeLevel, + options = additionalConfig.options, }; var result = Compile(ref config, Allocator.Persistent); @@ -382,16 +383,16 @@ internal sealed unsafe partial class DxcShaderCompiler : IShaderCompiler var msEntry = fullDescriptor.meshShader; if (msEntry.IsCreated) { - var config = new CompilerConfig + var config = new ShaderCompilationConfig { - defines = fullDescriptor.defines.AsSpan(), + defines = fullDefines.AsSpan(), include = generatedCodePath, shaderPath = msEntry.shader, entryPoint = msEntry.entry, stage = ShaderStage.MeshShader, - tier = CompilerTier.Tier0, - optimizeLevel = CompilerOptimizeLevel.O3, - options = CompilerOption.KeepReflections, + tier = additionalConfig.tier, + optimizeLevel = additionalConfig.optimizeLevel, + options = additionalConfig.options, }; var result = Compile(ref config, Allocator.Persistent); @@ -411,16 +412,16 @@ internal sealed unsafe partial class DxcShaderCompiler : IShaderCompiler var psEntry = fullDescriptor.pixelShader; if (psEntry.IsCreated) { - var config = new CompilerConfig + var config = new ShaderCompilationConfig { - defines = fullDescriptor.defines.AsSpan(), + defines = fullDefines.AsSpan(), include = generatedCodePath, shaderPath = psEntry.shader, entryPoint = psEntry.entry, stage = ShaderStage.PixelShader, - tier = CompilerTier.Tier0, - optimizeLevel = CompilerOptimizeLevel.O3, - options = CompilerOption.KeepReflections, + tier = additionalConfig.tier, + optimizeLevel = additionalConfig.optimizeLevel, + options = additionalConfig.options, }; var result = Compile(ref config, Allocator.Persistent); diff --git a/Ghost.Graphics/Core/Shader.cs b/Ghost.Graphics/Core/Shader.cs index eb00909..a57145c 100644 --- a/Ghost.Graphics/Core/Shader.cs +++ b/Ghost.Graphics/Core/Shader.cs @@ -36,6 +36,7 @@ public partial struct Shader private static int s_nextPropertyID = 0; private static readonly Dictionary s_keywordNameToID = new Dictionary(); + private static readonly Dictionary s_keywordIDToName = new Dictionary(); private static int s_nextkeywordID = 0; public static Identifier GetPassID(string passName) @@ -68,9 +69,20 @@ public partial struct Shader id = s_nextkeywordID++; } + s_keywordIDToName[id] = keywordName; return id; } + public static string? GetKeywordName(int keywordID) + { + if (s_keywordIDToName.TryGetValue(keywordID, out var name)) + { + return name; + } + + return null; + } + // TODO: Global keywords } diff --git a/Ghost.Graphics/RenderPasses/MeshRenderPass.cs b/Ghost.Graphics/RenderPasses/MeshRenderPass.cs index 7d84189..c44b9a6 100644 --- a/Ghost.Graphics/RenderPasses/MeshRenderPass.cs +++ b/Ghost.Graphics/RenderPasses/MeshRenderPass.cs @@ -57,7 +57,15 @@ internal class MeshRenderPass : IRenderPass for (var i = 0; i < shaderDescriptor.passes.Count; i++) { var pass = shaderDescriptor.passes[i]; - var compiled = ctx.ShaderCompiler.CompilePass(pass, shaderDescriptor.generatedCodePath).GetValueOrThrow(); + + var config = new ShaderCompilationConfig + { + optimizeLevel = CompilerOptimizeLevel.O3, + options = CompilerOption.KeepReflections, + tier = CompilerTier.Tier2 + }; + + var compiled = ctx.ShaderCompiler.CompilePass(pass, in config, shaderDescriptor.generatedCodePath).GetValueOrThrow(); //if (pass is not FullPassDescriptor fullPass) //{ // continue;