Refactor asset streaming & resource management system

- Introduce Ghost.Engine.Streaming namespace and split asset entry logic into type-specific classes (TextureAssetEntry, MeshAssetEntry, SceneAssetEntry)
- Make AssetEntry abstract; add AssetEntryFactory for type dispatch
- Update AssetManager and ResourceStreamingProcessor for new entry model, supporting uploadable and processable assets
- Redesign scene/mesh asset loading, serialization, and binary formats with versioning (SceneContentHeader, MeshContentHeader)
- Move SceneLoadingType to Ghost.Engine and make public
- Inline performance-critical APIs with MethodImplOptions.AggressiveInlining
- Add deep cloning and improved resource management for Mesh and meshlet data
- Allow nullable log messages in Logger
- Update Misaki.HighPerformance package references
- Remove obsolete files (Asset.cs, ActivationHandler.cs, old mesh logic)
- Improve resource release logic in ResourceManager
- Update RenderContext and ResourceStreamingContext for new streaming model
- Add UnsafeArray/UnsafeList clone utilities
- Update scene serialization/deserialization for new format
- Update tests for new APIs, asset states, and formats
This commit is contained in:
2026-05-12 22:51:51 +09:00
parent 314b0111f0
commit bb07644580
43 changed files with 1202 additions and 1114 deletions

View File

@@ -1,5 +1,6 @@
using Ghost.Core;
using Ghost.Engine;
using Ghost.Engine.Streaming;
using Ghost.Graphics;
using Ghost.Graphics.RHI;
using Ghost.Graphics.Services;
@@ -88,14 +89,14 @@ public class AssetManagerTest
ResourceDatabase = _graphicsEngine.ResourceDatabase,
ResourceAllocator = _graphicsEngine.ResourceAllocator,
CopyPipeline = _copyPipeline,
GraphicsCommandBuffer = _commandBuffer,
CommandBuffer = _commandBuffer,
};
_processor.ProcessPendingUploads(ctx);
await Task.Delay(1000, TestContext.CancellationToken);
Assert.IsGreaterThanOrEqualTo((int)AssetState.Uploading, entry.StateValue);
Assert.IsGreaterThanOrEqualTo((int)AssetState.Processing, entry.StateValue);
// Trigger the completion of the upload and the transition to shader resource state.
_processor.ProcessPendingUploads(ctx);
@@ -132,14 +133,14 @@ public class AssetManagerTest
ResourceDatabase = _graphicsEngine.ResourceDatabase,
ResourceAllocator = _graphicsEngine.ResourceAllocator,
CopyPipeline = _copyPipeline,
GraphicsCommandBuffer = _commandBuffer,
CommandBuffer = _commandBuffer,
};
_processor.ProcessPendingUploads(ctx);
await Task.Delay(1000, TestContext.CancellationToken);
Assert.IsGreaterThanOrEqualTo((int)AssetState.Uploading, entry.StateValue);
Assert.IsGreaterThanOrEqualTo((int)AssetState.Processing, entry.StateValue);
_processor.ProcessPendingUploads(ctx);
@@ -174,7 +175,7 @@ public class AssetManagerTest
ResourceDatabase = _graphicsEngine.ResourceDatabase,
ResourceAllocator = _graphicsEngine.ResourceAllocator,
CopyPipeline = _copyPipeline,
GraphicsCommandBuffer = _commandBuffer,
CommandBuffer = _commandBuffer,
};
_processor.ProcessPendingUploads(ctx);

View File

@@ -3,6 +3,7 @@ using Ghost.Editor.Core;
using Ghost.Editor.Core.Assets;
using Ghost.Editor.Core.Services;
using Ghost.Engine;
using Ghost.Engine.Streaming;
using Misaki.HighPerformance.LowLevel.Buffer;
using System.Runtime.InteropServices;
using System.Text;
@@ -93,11 +94,11 @@ public class MeshAssetHandlerTests
var header = MemoryMarshal.Read<MeshContentHeader>(headerBytes);
Assert.AreEqual(MeshContentHeader.MAGIC, header.magic);
Assert.AreEqual(MeshContentHeader.VERSION, header.version);
Assert.IsGreaterThan(0u, header.vertexCount);
Assert.IsGreaterThan(0u, header.indexCount);
Assert.IsGreaterThan(0u, header.meshletCount);
Assert.IsGreaterThan(0u, header.meshletGroupCount);
Assert.IsGreaterThan(0u, header.meshletHierarchyNodeCount);
Assert.IsGreaterThan(0, header.vertexCount);
Assert.IsGreaterThan(0, header.indexCount);
Assert.IsGreaterThan(0, header.meshletCount);
Assert.IsGreaterThan(0, header.meshletGroupCount);
Assert.IsGreaterThan(0, header.meshletHierarchyNodeCount);
}
}

View File

@@ -5,6 +5,7 @@ using Ghost.Editor.Core.Services;
using Ghost.Engine;
using Ghost.Engine.Components;
using Ghost.Engine.Core;
using Ghost.Engine.Streaming;
using Ghost.Entities;
using Misaki.HighPerformance.LowLevel.Buffer;
using System.Runtime.InteropServices;
@@ -136,6 +137,7 @@ public class SceneSerializationTests
{
var scene = SceneManager.CreateScene();
CreateSceneEntity(scene);
var parent = CreateEntityWithHierarchy(scene, Entity.Invalid);
var child = CreateEntityWithHierarchy(scene, parent);
@@ -366,7 +368,7 @@ public class SceneSerializationTests
var data = await SceneSerializationService.DeserializeSceneFileAsync(filePath, TestContext.CancellationToken);
Assert.IsNotNull(data);
Assert.AreEqual(999, data!.FormatVersion);
Assert.AreEqual(999u, data!.FormatVersion);
var loadResult = _serializationService.LoadSceneIntoEditorWorld(data);
Assert.IsTrue(loadResult.IsSuccess, loadResult.Message);
@@ -395,7 +397,7 @@ public class SceneSerializationTests
{
fixed (byte* pBinary = binary)
{
var result = SceneLoader.LoadSceneIntoWorld(world, pBinary, binary.Length);
var result = SceneLoader.LoadSceneIntoWorld(world, *(SceneContentHeader*)pBinary, pBinary + sizeof(SceneContentHeader), (nuint)(binary.Length + sizeof(SceneContentHeader)));
Assert.IsTrue(result.IsSuccess, result.Message);
Assert.AreEqual(3, result.Value);
}