Refactor asset handler system and catalog for safety
- Introduced AssetHandlerInfo struct for handler registration and lookup, enabling handler caching and decoupling instantiation from extension/type. - Changed CustomAssetHandlerAttribute to use required named properties; updated source generator. - Replaced HandlerTypeId with AssetTypeId throughout metadata, catalog, and sub-asset records for clarity. - Refactored asset catalog to use connection pooling and local command creation for thread safety. - Updated asset handler interfaces and implementations to align with new registration system and removed redundant properties. - Migrated mesh import and meshlet building to async JobScheduler jobs; switched to TLSF allocator and improved safety checks. - Made meshlet/LOD hierarchy building async and job-based with better memory management. - Updated usages and tests for new APIs; refreshed project references and package versions. - Improved documentation and code comments for clarity.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@@ -22,6 +23,29 @@ internal class AssetHandlerRegistrationGenerator : IIncrementalGenerator
|
||||
context.RegisterSourceOutput(handerCandidates, GenerateRegistrationCode);
|
||||
}
|
||||
|
||||
private static T GetValueOrDefault<T>(IDictionary<string, TypedConstant> dictionary, string key, T defaultValue = default)
|
||||
{
|
||||
if (dictionary.TryGetValue(key, out var value))
|
||||
{
|
||||
if (value.Value is T typedValue)
|
||||
{
|
||||
return typedValue;
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static ImmutableArray<TypedConstant> GetValuesOrDefault(IDictionary<string, TypedConstant> dictionary, string key)
|
||||
{
|
||||
if (dictionary.TryGetValue(key, out var value))
|
||||
{
|
||||
return value.Values;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private void GenerateRegistrationCode(SourceProductionContext context, ImmutableArray<INamedTypeSymbol> array)
|
||||
{
|
||||
if (array.IsDefaultOrEmpty)
|
||||
@@ -39,12 +63,24 @@ internal class AssetHandlerRegistrationGenerator : IIncrementalGenerator
|
||||
continue;
|
||||
}
|
||||
|
||||
var id = attribute.ConstructorArguments[0].Value as string;
|
||||
var extensionsTypesConstants = attribute.ConstructorArguments[1].Values;
|
||||
var extensions = $"new string[] {{ {string.Join(", ", extensionsTypesConstants.Select(v => v.ToCSharpString()))} }}";
|
||||
var version = (int)attribute.ConstructorArguments[2].Value;
|
||||
var properties = attribute.NamedArguments.ToDictionary(kv => kv.Key, kv => kv.Value);
|
||||
|
||||
sb.AppendLine($" global::Ghost.Editor.Core.Assets.AssetHandlerRegistry.RegisterHandler(new {symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}(), Guid.Parse(\"{id}\"), {extensions}, {version});");
|
||||
var id = GetValueOrDefault(properties, "AssetTypeId", string.Empty);
|
||||
var runtimeType = GetValueOrDefault(properties, "RuntimeAssetType", 0);
|
||||
var version = GetValueOrDefault(properties, "Version", 1);
|
||||
var allowCaching = GetValueOrDefault(properties, "AllowCaching", false) ? "true" : "false";
|
||||
|
||||
var extensionsTypesConstants = GetValuesOrDefault(properties, "Extensions");
|
||||
var extensions = string.Join(", ", extensionsTypesConstants.Select(v => v.ToCSharpString()));
|
||||
|
||||
sb.AppendLine(" global::Ghost.Editor.Core.Assets.AssetHandlerRegistry.RegisterHandler(");
|
||||
sb.AppendLine($" typeof({symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}),");
|
||||
sb.AppendLine($" System.Guid.Parse(\"{id}\"),");
|
||||
sb.AppendLine($" (Ghost.Engine.AssetType){runtimeType},");
|
||||
sb.AppendLine($" {version},");
|
||||
sb.AppendLine($" {allowCaching},");
|
||||
sb.AppendLine($" new string[] {{ {extensions} }});");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
var registerTypeName = "g_assethandler_registeration";
|
||||
|
||||
@@ -176,6 +176,7 @@ namespace {info.TypeSymbol.ContainingNamespace.ToDisplayString()}
|
||||
[global::System.Runtime.InteropServices.StructLayout(global::System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 4)]
|
||||
{info.TypeSymbol.DeclaredAccessibility.ToString().ToLower()} partial struct {info.TypeSymbol.Name}
|
||||
{{
|
||||
#if DEBUG || GHOST_EDITOR
|
||||
public const string HLSL_SOURCE = @""
|
||||
# ifndef {definedSymbol}
|
||||
# define {definedSymbol}
|
||||
@@ -185,13 +186,14 @@ struct {info.Name}
|
||||
}};
|
||||
# endif // {definedSymbol}"";
|
||||
}}
|
||||
#endif
|
||||
}}";
|
||||
|
||||
context.AddSource($"{info.TypeSymbol.Name}_HLSL.gen.cs", code);
|
||||
codeBuilder.Clear();
|
||||
|
||||
var typeFullName = info.TypeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
|
||||
registerBuilder.AppendLine($@" global::Ghost.DSL.ShaderPropertiesRegistry.Register(""{info.ShaderName}"", {typeFullName}.HLSL_SOURCE, (uint)sizeof({typeFullName}));");
|
||||
registerBuilder.AppendLine($@" global::Ghost.Core.Graphics.ShaderPropertiesRegistry.Register(""{info.ShaderName}"", {typeFullName}.HLSL_SOURCE, (uint)sizeof({typeFullName}));");
|
||||
}
|
||||
|
||||
var registerTypeName = "g_shaderproperty_registeration";
|
||||
|
||||
Reference in New Issue
Block a user