feat(asset): asset manager + registration generator

Add runtime AssetManager and AssetHandlerRegistrationGenerator source generator.
Update editor asset handler types and services to work with new registration
mechanism and asset catalog. Remove legacy contracts ICloneable and IReleasable.

Files added:
- src/Runtime/Ghost.Engine/AssetManager.cs
- src/Runtime/Ghost.Generator/AssetHandlerRegistrationGenerator.cs

Major edits:
- Editor asset handler classes and services (Asset*, Texture*, Registry)
- Runtime Handle.cs and project files
- Render graph executor and tests updated accordingly

This commit introduces the foundation for the modern asset pipeline
including generated registration of asset handlers and a centralized
runtime AssetManager that will drive asset lifecycle.
This commit is contained in:
2026-04-15 22:21:00 +09:00
parent 6615fe794e
commit 13bf1501e4
29 changed files with 425 additions and 365 deletions

View File

@@ -0,0 +1,44 @@
using Ghost.Core;
using System.Runtime.InteropServices;
namespace Ghost.Engine;
internal abstract class RuntimeAsset;
internal interface IRuntimeAssetLoader
{
ValueTask<Result<RuntimeAsset>> LoadAsync(Stream cookedData, Guid id, CancellationToken token = default);
}
internal sealed class RuntimeLoaderRegistry
{
private readonly Dictionary<Guid, IRuntimeAssetLoader> _loaders = new();
public void Register(Guid cookedTypeId, IRuntimeAssetLoader loader)
{
_loaders[cookedTypeId] = loader;
}
public IRuntimeAssetLoader? GetLoader(Guid cookedTypeId)
{
_loaders.TryGetValue(cookedTypeId, out var loader);
return loader;
}
}
internal sealed class CookedTextureLoader : IRuntimeAssetLoader
{
public static readonly Guid TYPE_ID = TextureAsset.s_typeGuid;
public async ValueTask<Result<RuntimeAsset>> LoadAsync(Stream cookedData, Guid id, CancellationToken token)
{
// Read the ImageContentHeader you wrote during import
var header = new ImageContentHeader();
cookedData.ReadExactly(MemoryMarshal.AsBytes(new Span<ImageContentHeader>(ref header)));
// Read the rest as raw GPU data (DDS/BC compressed bytes)
var data = new byte[cookedData.Length - cookedData.Position];
await cookedData.ReadExactlyAsync(data, token);
return new TextureAsset(data, header, id);
}
}
public class AssetManager
{
}