feat(render): refactor pipeline & shader system for DX12 WG
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.
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Misaki.HighPerformance" Version="1.0.7" />
|
||||
<PackageReference Include="Misaki.HighPerformance.Jobs" Version="1.5.8" />
|
||||
<PackageReference Include="Misaki.HighPerformance.LowLevel" Version="1.6.10">
|
||||
<PackageReference Include="Misaki.HighPerformance.LowLevel" Version="1.6.11">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -33,21 +33,14 @@ public struct KeywordsGroup
|
||||
public List<string> keywords;
|
||||
}
|
||||
|
||||
public struct PropertyDescriptor
|
||||
{
|
||||
public string name;
|
||||
public int offset;
|
||||
public int size;
|
||||
public ShaderPropertyType type;
|
||||
|
||||
public object? defaultValue;
|
||||
}
|
||||
|
||||
public struct PassDescriptor
|
||||
{
|
||||
public string identifier;
|
||||
public ShaderDescriptor shader;
|
||||
|
||||
public ulong identifier;
|
||||
public string name;
|
||||
|
||||
public string? hlsl;
|
||||
public ShaderEntryPoint taskShader;
|
||||
public ShaderEntryPoint meshShader;
|
||||
public ShaderEntryPoint pixelShader;
|
||||
@@ -55,54 +48,23 @@ public struct PassDescriptor
|
||||
public string[] includes;
|
||||
public KeywordsGroup[] keywords;
|
||||
public PipelineState localPipeline;
|
||||
public string? hlsl;
|
||||
}
|
||||
|
||||
public class ShaderDescriptor
|
||||
{
|
||||
public string name = string.Empty;
|
||||
public int cbufferSize;
|
||||
public PropertyDescriptor[] globalProperties = null!;
|
||||
public PropertyDescriptor[] properties = null!;
|
||||
public PassDescriptor[] passes = null!;
|
||||
public string? hlsl;
|
||||
public string propertiesCode = string.Empty;
|
||||
public uint propertyBufferSize;
|
||||
public PassDescriptor[] passes = Array.Empty<PassDescriptor>();
|
||||
}
|
||||
|
||||
public static class ShaderDescriptorExtensions
|
||||
public class ComputeShaderDescriptor
|
||||
{
|
||||
public static int GetSize(this ShaderPropertyType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
ShaderPropertyType.Float
|
||||
or ShaderPropertyType.Int
|
||||
or ShaderPropertyType.UInt
|
||||
or ShaderPropertyType.Bool => 4,
|
||||
|
||||
ShaderPropertyType.Float2
|
||||
or ShaderPropertyType.Int2
|
||||
or ShaderPropertyType.UInt2
|
||||
or ShaderPropertyType.Bool2 => 8,
|
||||
|
||||
ShaderPropertyType.Float3
|
||||
or ShaderPropertyType.Int3
|
||||
or ShaderPropertyType.UInt3
|
||||
or ShaderPropertyType.Bool3 => 12,
|
||||
|
||||
ShaderPropertyType.Float4
|
||||
or ShaderPropertyType.Int4
|
||||
or ShaderPropertyType.UInt4
|
||||
or ShaderPropertyType.Bool4 => 16,
|
||||
|
||||
ShaderPropertyType.Float4x4 => 64,
|
||||
|
||||
ShaderPropertyType.Texture2D
|
||||
or ShaderPropertyType.Texture3D
|
||||
or ShaderPropertyType.TextureCube
|
||||
or ShaderPropertyType.Texture2DArray
|
||||
or ShaderPropertyType.TextureCubeArray
|
||||
or ShaderPropertyType.Sampler => 4, // Bindless resource use uint32
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
public string name = string.Empty;
|
||||
public string propertiesCode = string.Empty;
|
||||
public uint propertyBufferSize;
|
||||
public ShaderEntryPoint entryPoint;
|
||||
public string[] defines = Array.Empty<string>();
|
||||
public string[] includes = Array.Empty<string>();
|
||||
public KeywordsGroup[] keywords = Array.Empty<KeywordsGroup>();
|
||||
}
|
||||
|
||||
41
src/Runtime/Ghost.Core/Graphics/ShaderPropertiesRegistry.cs
Normal file
41
src/Runtime/Ghost.Core/Graphics/ShaderPropertiesRegistry.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
namespace Ghost.Core.Graphics;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Struct)]
|
||||
public class GenerateShaderPropertyAttribute : Attribute
|
||||
{
|
||||
public GenerateShaderPropertyAttribute(string shaderName, string? name = null)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class GenerateAsHLSLTypeAttribute : Attribute
|
||||
{
|
||||
public GenerateAsHLSLTypeAttribute(string hlslTypeName)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG || GHOST_EDITOR
|
||||
public struct ShaderPropertyInfo
|
||||
{
|
||||
public string shaderName;
|
||||
public string code;
|
||||
public uint size;
|
||||
}
|
||||
|
||||
public static class ShaderPropertiesRegistry
|
||||
{
|
||||
private static readonly Dictionary<string, ShaderPropertyInfo> s_nameToCode = new Dictionary<string, ShaderPropertyInfo>(StringComparer.Ordinal);
|
||||
|
||||
public static void Register(string name, string code, uint size)
|
||||
{
|
||||
s_nameToCode[name] = new ShaderPropertyInfo { shaderName = name, code = code, size = size };
|
||||
}
|
||||
|
||||
public static bool TryGetCode(string name, out ShaderPropertyInfo info)
|
||||
{
|
||||
return s_nameToCode.TryGetValue(name, out info);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -186,6 +186,9 @@ public readonly struct Key64<T> : IEquatable<Key64<T>>
|
||||
{
|
||||
return !a.Equals(b);
|
||||
}
|
||||
|
||||
public static implicit operator ulong(Key64<T> key) => key.Value;
|
||||
public static implicit operator Key64<T>(ulong value) => new Key64<T>(value);
|
||||
}
|
||||
|
||||
public readonly struct Key128<T> : IEquatable<Key128<T>>
|
||||
@@ -239,4 +242,7 @@ public readonly struct Key128<T> : IEquatable<Key128<T>>
|
||||
{
|
||||
return !a.Equals(b);
|
||||
}
|
||||
|
||||
public static implicit operator UInt128(Key128<T> key) => key.Value;
|
||||
public static implicit operator Key128<T>(UInt128 value) => new Key128<T>(value);
|
||||
}
|
||||
@@ -10,13 +10,13 @@ public static class Hash
|
||||
private const ulong _PRIME4 = 0x9e3779b97f4a7c15ul; // Golden Ratio
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ulong Hash64(ulong a, ulong b)
|
||||
public static ulong Combine64(ulong a, ulong b)
|
||||
{
|
||||
return a ^ (b * _PRIME4 + (a << 6) + (a >> 2));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ulong Hash64(ulong a, ulong b, ulong c)
|
||||
public static ulong Combine64(ulong a, ulong b, ulong c)
|
||||
{
|
||||
var h1 = a * _PRIME1;
|
||||
var h2 = b * _PRIME2;
|
||||
@@ -29,7 +29,7 @@ public static class Hash
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ulong Hash64(ulong a, ulong b, ulong c, ulong d)
|
||||
public static ulong Combine64(ulong a, ulong b, ulong c, ulong d)
|
||||
{
|
||||
var h1 = a * _PRIME1;
|
||||
var h2 = b * _PRIME2;
|
||||
|
||||
Reference in New Issue
Block a user