Refactor asset import API and mesh streaming pipeline
- Standardize IImportableAssetHandler.ImportAsync to return sub-asset results - Remove ISubAssetImportableAssetHandler, merge into main interface - Update FBX/Texture handlers for new import contract - Add StreamUtility for efficient (async) binary writes - Refactor meshlet/LOD building to use ref structs and safe memory - Use new streaming utilities in mesh import/export and tests - AssetCatalog.Remove now recursively deletes sub-assets - Improve asset registry file watcher for better change detection - Log unhandled exceptions in App instead of breaking - Add interpolated collection support to NativeMemoryManager - Update project references and fix minor bugs
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Misaki.HighPerformance" Version="1.0.9" />
|
||||
<PackageReference Include="Misaki.HighPerformance.Jobs" Version="3.1.6" />
|
||||
<PackageReference Include="Misaki.HighPerformance.LowLevel" Version="1.6.18">
|
||||
<PackageReference Include="Misaki.HighPerformance.LowLevel" Version="1.6.20">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -20,7 +20,7 @@ public unsafe class NativeMemoryManager<T> : MemoryManager<T>
|
||||
}
|
||||
|
||||
public static NativeMemoryManager<T> FromUnsafeCollection<C>(ref readonly C collection)
|
||||
where C : unmanaged, IUnsafeCollection<T>
|
||||
where C : IUnsafeCollection<T>
|
||||
{
|
||||
if (!collection.IsCreated)
|
||||
{
|
||||
@@ -30,6 +30,19 @@ public unsafe class NativeMemoryManager<T> : MemoryManager<T>
|
||||
return new NativeMemoryManager<T>((T*)collection.GetUnsafePtr(), collection.Count);
|
||||
}
|
||||
|
||||
public static NativeMemoryManager<T> FromUnsafeCollectionInterpolated<C, U>(ref readonly C collection)
|
||||
where U : unmanaged
|
||||
where C : IUnsafeCollection<U>
|
||||
{
|
||||
if (!collection.IsCreated)
|
||||
{
|
||||
throw new InvalidOperationException("The collection is not created.");
|
||||
}
|
||||
|
||||
var length = collection.Count * Unsafe.SizeOf<U>() / Unsafe.SizeOf<T>();
|
||||
return new NativeMemoryManager<T>((T*)collection.GetUnsafePtr(), length);
|
||||
}
|
||||
|
||||
public static NativeMemoryManager<T> FromMemoryBlock(MemoryBlock memoryBlock, int start, int length)
|
||||
{
|
||||
return new NativeMemoryManager<T>((T*)memoryBlock.GetUnsafePtr() + start, length);
|
||||
|
||||
55
src/Runtime/Ghost.Core/Utilities/StreamUtility.cs
Normal file
55
src/Runtime/Ghost.Core/Utilities/StreamUtility.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Misaki.HighPerformance.LowLevel.Collections.Contracts;
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ghost.Core.Utilities;
|
||||
|
||||
public static class StreamUtility
|
||||
{
|
||||
public static void Write<T>(this Stream stream, in T value)
|
||||
where T : struct
|
||||
{
|
||||
stream.Write(MemoryMarshal.AsBytes(new ReadOnlySpan<T>(in value)));
|
||||
}
|
||||
|
||||
public static void Write<T>(this Stream stream, ReadOnlySpan<T> values)
|
||||
where T : struct
|
||||
{
|
||||
if (values.IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
stream.Write(MemoryMarshal.AsBytes(values));
|
||||
}
|
||||
|
||||
public static async ValueTask WriteAsync<T, C>(this Stream stream, C collection, CancellationToken cancellationToken = default)
|
||||
where T : unmanaged
|
||||
where C : IUnsafeCollection<T>
|
||||
{
|
||||
if (!collection.IsCreated || collection.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var manager = NativeMemoryManager<byte>.FromUnsafeCollectionInterpolated<C, T>(in collection);
|
||||
await stream.WriteAsync(manager.Memory, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static async ValueTask WriteAsync<T>(this Stream stream, T value, CancellationToken cancellationToken = default)
|
||||
where T : unmanaged
|
||||
{
|
||||
var size = Unsafe.SizeOf<T>();
|
||||
var buffer = ArrayPool<byte>.Shared.Rent(size);
|
||||
try
|
||||
{
|
||||
Unsafe.WriteUnaligned(ref buffer[0], value);
|
||||
await stream.WriteAsync(buffer.AsMemory(0, size), cancellationToken);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -188,6 +188,9 @@ internal unsafe class ShaderLibrary : IDisposable
|
||||
kvp.Value.Dispose();
|
||||
}
|
||||
|
||||
_inMemoryCache.Dispose();
|
||||
_variantToCompiledHash.Dispose();
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user