Files
GhostEngine/src/Editor/Ghost.DSL/ShaderParser/ComputeShaderVisitor.cs
Misaki c66fda5332 feat(shader): refactor and enhance shader pipeline
Refactored the shader compilation pipeline to introduce modularity, improve performance, and enhance maintainability. Key changes include:

- Added `ShaderCompilationConfig`, `CompilerOptimizeLevel`, and `ShaderStage` enums.
- Replaced `SM` property with `ShaderModel` in shader models.
- Introduced `ShaderLibrary` for in-memory and disk-based shader caching.
- Refactored `DSLShaderCompiler` and `AntlrShaderCompiler` for better hashing and error handling.
- Centralized shader compilation logic in `ShaderCompilerUtility`.
- Removed legacy shader compilation logic from `IShaderCompiler`.
- Updated `RenderGraph`, `ResourceManager`, and `Material` to integrate with the new caching system.
- Improved memory management with `NativeMemoryManager<T>`.

BREAKING CHANGE: Removed legacy shader compilation methods and replaced them with a new caching and compilation system.
2026-04-11 23:10:39 +09:00

150 lines
4.5 KiB
C#

using Antlr4.Runtime.Misc;
using Ghost.DSL.ShaderParser.Model;
using TerraFX.Interop.Windows;
namespace Ghost.DSL.ShaderParser;
internal class ComputeShaderVisitor : GhostComputeShaderParserBaseVisitor<object>
{
public List<ComputeShaderModel> ComputeShaders { get; } = new();
public override object VisitComputeFile([NotNull] GhostComputeShaderParser.ComputeFileContext context)
{
foreach (var shaderContext in context.compute())
{
var shader = (ComputeShaderModel)VisitCompute(shaderContext);
ComputeShaders.Add(shader);
}
return ComputeShaders;
}
private static string StripQuotes(string text)
{
if (text.Length >= 2 && text.StartsWith('"') && text.EndsWith('"'))
{
return text.Substring(1, text.Length - 2);
}
return text;
}
public override object VisitCompute([NotNull] GhostComputeShaderParser.ComputeContext context)
{
var compute = new ComputeShaderModel
{
Name = StripQuotes(context.STRING_LITERAL().GetText())
};
var computeBody = context.computeBody();
if (computeBody != null)
{
compute.ShaderModel = computeBody.shaderModel()?.GetText() ?? string.Empty;
foreach (var definesBlock in computeBody.definesBlock())
{
compute.Defines = (DefinesBlockModel)VisitDefinesBlock(definesBlock);
}
foreach (var includesBlock in computeBody.includesBlock())
{
compute.Includes = (IncludesBlockModel)VisitIncludesBlock(includesBlock);
}
foreach (var keywordsBlock in computeBody.keywordsBlock())
{
compute.Keywords = (KeywordsBlockModel)VisitKeywordsBlock(keywordsBlock);
}
var hlslBlock = computeBody.hlslBlock().FirstOrDefault();
if (hlslBlock != null)
{
compute.Hlsl = (HlslBlockModel)VisitHlslBlock(hlslBlock);
}
foreach (var computeEntry in computeBody.computeEntry())
{
compute.ShaderEntries.Add((ShaderEntryModel)VisitComputeEntry(computeEntry));
}
}
return compute;
}
public override object VisitDefinesBlock([NotNull] GhostComputeShaderParser.DefinesBlockContext context)
{
var defines = new DefinesBlockModel();
foreach (var defineStmt in context.defineStatement())
{
defines.Defines.Add(defineStmt.IDENTIFIER().GetText());
}
return defines;
}
public override object VisitIncludesBlock([NotNull] GhostComputeShaderParser.IncludesBlockContext context)
{
var includes = new IncludesBlockModel();
foreach (var includeStmt in context.includeStatement())
{
includes.Includes.Add(StripQuotes(includeStmt.STRING_LITERAL().GetText()));
}
return includes;
}
public override object VisitKeywordsBlock([NotNull] GhostComputeShaderParser.KeywordsBlockContext context)
{
var keywords = new KeywordsBlockModel();
foreach (var keywordStmt in context.keywordStatement())
{
var group = new KeywordGroupModel();
if (keywordStmt.scope() != null)
{
group.Scope = keywordStmt.scope().GetText();
}
foreach (var identifier in keywordStmt.IDENTIFIER())
{
group.Keywords.Add(identifier.GetText());
}
keywords.Groups.Add(group);
}
return keywords;
}
public override object VisitHlslBlock([NotNull] GhostComputeShaderParser.HlslBlockContext context)
{
var hlsl = new HlslBlockModel();
// Get the text between the braces
var start = context.LBRACE().Symbol.StopIndex + 1;
var stop = context.RBRACE().Symbol.StartIndex - 1;
if (stop >= start)
{
var input = context.Start.InputStream;
hlsl.Code = input.GetText(new Interval(start, stop));
}
return hlsl;
}
public override object VisitComputeEntry([NotNull] GhostComputeShaderParser.ComputeEntryContext context)
{
var entry = new ShaderEntryModel
{
EntryType = context.IDENTIFIER().GetText(),
ShaderPath = StripQuotes(context.STRING_LITERAL(0).GetText()),
EntryPoint = StripQuotes(context.STRING_LITERAL(1).GetText())
};
return entry;
}
}