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.
This commit is contained in:
2026-04-11 23:10:39 +09:00
parent f9a6e9cbbe
commit c66fda5332
30 changed files with 630 additions and 500 deletions

View File

@@ -99,6 +99,40 @@ public class AntlrShaderCompiler
}
}
private static bool TryGetShaderModel(string model, List<DSLShaderError> errors, out ShaderModel shaderModel)
{
if (string.IsNullOrEmpty(model))
{
shaderModel = ShaderModel.SM_6_6; // Default to lowest supported shader model for compute shaders
}
else
{
switch (model)
{
case "6_6":
shaderModel = ShaderModel.SM_6_6;
break;
case "6_7":
shaderModel = ShaderModel.SM_6_7;
break;
case "6_8":
shaderModel = ShaderModel.SM_6_8;
break;
default:
shaderModel = default;
errors.Add(new DSLShaderError
{
message = $"Unknown shader model '{model}'.",
line = 0,
column = 0
});
return false;
}
}
return true;
}
public static DSLComputeShaderSemantics? ConvertToComputeSemantics(ComputeShaderModel model, out List<DSLShaderError> errors)
{
errors = new List<DSLShaderError>();
@@ -122,29 +156,9 @@ public class AntlrShaderCompiler
hlsl = model.Hlsl?.Code
};
if (string.IsNullOrEmpty(model.SM))
if (TryGetShaderModel(model.ShaderModel, errors, out var shaderModel))
{
semantics.shaderModel = ShaderModel.SM_6_8; // Default to highest supported shader model
}
else
{
semantics.shaderModel = model.SM.ToLower() switch
{
"6_6" => ShaderModel.SM_6_6,
"6_7" => ShaderModel.SM_6_7,
"6_8" => ShaderModel.SM_6_8,
_ => ShaderModel.Invalid
};
if (semantics.shaderModel == ShaderModel.Invalid)
{
errors.Add(new DSLShaderError
{
message = $"Unknown shader model '{model.SM}'.",
line = 0,
column = 0
});
}
semantics.shaderModel = shaderModel;
}
if (model.Keywords != null)
@@ -207,65 +221,6 @@ public class AntlrShaderCompiler
return semantics;
}
public static DSLShaderSemantics? ConvertToSemantics(GraphicsShaderModel model, out List<DSLShaderError> errors)
{
errors = new List<DSLShaderError>();
if (string.IsNullOrWhiteSpace(model.Name))
{
errors.Add(new DSLShaderError
{
message = "Shader name cannot be empty.",
line = 0,
column = 0
});
return null;
}
var semantics = new DSLShaderSemantics
{
name = model.Name,
pipeline = ConvertPipeline(model.Pipeline, errors)
};
if (string.IsNullOrEmpty(model.SM))
{
semantics.shaderModel = ShaderModel.SM_6_8; // Default to highest supported shader model
}
else
{
semantics.shaderModel = model.SM.ToLower() switch
{
"6_6" => ShaderModel.SM_6_6,
"6_7" => ShaderModel.SM_6_7,
"6_8" => ShaderModel.SM_6_8,
_ => ShaderModel.Invalid
};
if (semantics.shaderModel == ShaderModel.Invalid)
{
errors.Add(new DSLShaderError
{
message = $"Unknown shader model '{model.SM}'.",
line = 0,
column = 0
});
}
}
foreach (var pass in model.Passes)
{
var passSemantic = ConvertPass(pass, errors);
if (passSemantic != null)
{
semantics.passes ??= new List<PassSemantic>();
semantics.passes.Add(passSemantic);
}
}
return semantics;
}
private static PipelineSemantic? ConvertPipeline(PipelineBlockModel? pipeline, List<DSLShaderError> errors)
{
if (pipeline == null || pipeline.Statements.Count == 0)
@@ -394,6 +349,45 @@ public class AntlrShaderCompiler
return semantic;
}
public static DSLShaderSemantics? ConvertToSemantics(GraphicsShaderModel model, out List<DSLShaderError> errors)
{
errors = new List<DSLShaderError>();
if (string.IsNullOrWhiteSpace(model.Name))
{
errors.Add(new DSLShaderError
{
message = "Shader name cannot be empty.",
line = 0,
column = 0
});
return null;
}
var semantics = new DSLShaderSemantics
{
name = model.Name,
pipeline = ConvertPipeline(model.Pipeline, errors)
};
if (TryGetShaderModel(model.ShaderModel, errors, out var shaderModel))
{
semantics.shaderModel = shaderModel;
}
foreach (var pass in model.Passes)
{
var passSemantic = ConvertPass(pass, errors);
if (passSemantic != null)
{
semantics.passes ??= new List<PassSemantic>();
semantics.passes.Add(passSemantic);
}
}
return semantics;
}
private class ErrorListener : BaseErrorListener, IAntlrErrorListener<int>, IAntlrErrorListener<IToken>
{
private readonly List<DSLShaderError> _errors;