Major refactor of render pipeline and shader system: - Replaced legacy shader properties with source generator and attribute-based HLSL struct generation. - Introduced ShaderPropertiesRegistry for runtime property layout/code registration. - Added modular IRenderPipeline, IRenderPipelineSettings, and IRenderPayload interfaces. - Implemented GhostRenderPipeline and ECS-driven GPUScene management. - Added experimental DirectX 12 Work Graph support. - Refactored shader compilation, variant hashing, and caching. - Updated APIs for consistency and improved codegen for registration. These changes modernize the rendering infrastructure for advanced features like work graphs and dynamic pipelines. BREAKING CHANGE: Shader DSL, pipeline, and property APIs have changed. Existing shaders and pipeline integrations must be updated.
92 lines
3.0 KiB
C#
92 lines
3.0 KiB
C#
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Microsoft.CodeAnalysis.Text;
|
|
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
|
|
namespace Ghost.Generator
|
|
{
|
|
// TODO: this should be per assembly, not global
|
|
[Generator]
|
|
public class ComponentRegistrationGenerator : IIncrementalGenerator
|
|
{
|
|
public void Initialize(IncrementalGeneratorInitializationContext context)
|
|
{
|
|
// 1. Pipeline: Find all structs implementing IComponent
|
|
var componentCandidates = context.SyntaxProvider
|
|
.CreateSyntaxProvider(
|
|
predicate: (s, _) => s is StructDeclarationSyntax,
|
|
transform: GetComponentSymbol)
|
|
.Where(symbol => symbol != null)
|
|
.Collect();
|
|
|
|
// 4. Output: Generate the source using both pieces of data at once
|
|
context.RegisterSourceOutput(componentCandidates, GenerateRegistrationCode);
|
|
}
|
|
|
|
// Extraction Logic for Components
|
|
private static INamedTypeSymbol GetComponentSymbol(GeneratorSyntaxContext ctx, CancellationToken _)
|
|
{
|
|
var structSyntax = (StructDeclarationSyntax)ctx.Node;
|
|
if (!(ctx.SemanticModel.GetDeclaredSymbol(structSyntax) is INamedTypeSymbol symbol))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
var iComponentSymbol = ctx.SemanticModel.Compilation.GetTypeByMetadataName("Ghost.Entities.IComponent");
|
|
if (iComponentSymbol == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
foreach (var iface in symbol.AllInterfaces)
|
|
{
|
|
if (SymbolEqualityComparer.Default.Equals(iface, iComponentSymbol))
|
|
{
|
|
return symbol;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
// The Generation Logic (Stateless)
|
|
private static void GenerateRegistrationCode(SourceProductionContext context, ImmutableArray<INamedTypeSymbol> components)
|
|
{
|
|
if (components.IsDefaultOrEmpty)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var sb = new StringBuilder();
|
|
|
|
foreach (var symbol in components.Distinct(SymbolEqualityComparer.Default))
|
|
{
|
|
if (symbol is null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
sb.AppendLine($@" global::Ghost.Entities.ComponentRegistry.GetOrRegisterComponentID<{symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>();");
|
|
}
|
|
|
|
var typeName = $"g_component_registration";
|
|
var code = $@"// <auto-generated/>
|
|
|
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
|
internal static partial class {typeName}
|
|
{{
|
|
[global::System.Runtime.CompilerServices.ModuleInitializer]
|
|
internal static void RegisterIComponentTypes()
|
|
{{
|
|
{sb}
|
|
}}
|
|
}}";
|
|
|
|
context.AddSource($"{typeName}.gen.cs", code);
|
|
}
|
|
}
|
|
}
|