Merge branch 'managedarray_pool_cache' of https://github.com/GoaLitiuM/FlaxEngine into GoaLitiuM-managedarray_pool_cache
This commit is contained in:
@@ -29,6 +29,8 @@ namespace FlaxEngine.Interop
|
||||
private int _elementSize;
|
||||
private int _length;
|
||||
|
||||
[ThreadStatic] private static Dictionary<ManagedArray, ManagedHandle> pooledArrayHandles;
|
||||
|
||||
public static ManagedArray WrapNewArray(Array arr) => new ManagedArray(arr, arr.GetType());
|
||||
|
||||
public static ManagedArray WrapNewArray(Array arr, Type arrayType) => new ManagedArray(arr, arrayType);
|
||||
@@ -37,22 +39,38 @@ namespace FlaxEngine.Interop
|
||||
/// Returns an instance of ManagedArray from shared pool.
|
||||
/// </summary>
|
||||
/// <remarks>The resources must be released by calling FreePooled() instead of Free()-method.</remarks>
|
||||
public static ManagedArray WrapPooledArray(Array arr)
|
||||
public static (ManagedHandle managedHandle, ManagedArray managedArray) WrapPooledArray(Array arr)
|
||||
{
|
||||
ManagedArray managedArray = ManagedArrayPool.Get();
|
||||
managedArray.WrapArray(arr, arr.GetType());
|
||||
return managedArray;
|
||||
|
||||
if (pooledArrayHandles == null)
|
||||
pooledArrayHandles = new();
|
||||
if (!pooledArrayHandles.TryGetValue(managedArray, out ManagedHandle handle))
|
||||
{
|
||||
handle = ManagedHandle.Alloc(managedArray);
|
||||
pooledArrayHandles.Add(managedArray, handle);
|
||||
}
|
||||
return (handle, managedArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an instance of ManagedArray from shared pool.
|
||||
/// </summary>
|
||||
/// <remarks>The resources must be released by calling FreePooled() instead of Free()-method.</remarks>
|
||||
public static ManagedArray WrapPooledArray(Array arr, Type arrayType)
|
||||
public static ManagedHandle WrapPooledArray(Array arr, Type arrayType)
|
||||
{
|
||||
ManagedArray managedArray = ManagedArrayPool.Get(arr.Length * NativeInterop.GetTypeSize(arr.GetType().GetElementType()));
|
||||
managedArray.WrapArray(arr, arrayType);
|
||||
return managedArray;
|
||||
|
||||
if (pooledArrayHandles == null)
|
||||
pooledArrayHandles = new();
|
||||
if (!pooledArrayHandles.TryGetValue(managedArray, out ManagedHandle handle))
|
||||
{
|
||||
handle = ManagedHandle.Alloc(managedArray);
|
||||
pooledArrayHandles.Add(managedArray, handle);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
internal static ManagedArray AllocateNewArray(int length, Type arrayType, Type elementType)
|
||||
@@ -64,12 +82,20 @@ namespace FlaxEngine.Interop
|
||||
/// <summary>
|
||||
/// Returns an instance of ManagedArray from shared pool.
|
||||
/// </summary>
|
||||
/// <remarks>The resources must be released by calling FreePooled() instead of Free()-method.</remarks>
|
||||
public static ManagedArray AllocatePooledArray<T>(int length) where T : unmanaged
|
||||
/// <remarks>The resources must be released by calling FreePooled() instead of Free()-method. Do not release the returned ManagedHandle.</remarks>
|
||||
public static (ManagedHandle managedHandle, ManagedArray managedArray) AllocatePooledArray<T>(int length) where T : unmanaged
|
||||
{
|
||||
ManagedArray managedArray = ManagedArrayPool.Get(length * Unsafe.SizeOf<T>());
|
||||
managedArray.Allocate<T>(length);
|
||||
return managedArray;
|
||||
|
||||
if (pooledArrayHandles == null)
|
||||
pooledArrayHandles = new();
|
||||
if (!pooledArrayHandles.TryGetValue(managedArray, out ManagedHandle handle))
|
||||
{
|
||||
handle = ManagedHandle.Alloc(managedArray);
|
||||
pooledArrayHandles.Add(managedArray, handle);
|
||||
}
|
||||
return (handle, managedArray);
|
||||
}
|
||||
|
||||
public ManagedArray(Array arr, Type elementType) => WrapArray(arr, elementType);
|
||||
|
||||
@@ -200,14 +200,13 @@ namespace FlaxEngine.Interop
|
||||
public void FromManaged(Array managed)
|
||||
{
|
||||
if (managed != null)
|
||||
managedArray = ManagedArray.WrapPooledArray(managed);
|
||||
(handle, managedArray) = ManagedArray.WrapPooledArray(managed);
|
||||
}
|
||||
|
||||
public IntPtr ToUnmanaged()
|
||||
{
|
||||
if (managedArray == null)
|
||||
return IntPtr.Zero;
|
||||
handle = ManagedHandle.Alloc(managedArray, GCHandleType.Weak);
|
||||
return ManagedHandle.ToIntPtr(handle);
|
||||
}
|
||||
|
||||
@@ -216,7 +215,6 @@ namespace FlaxEngine.Interop
|
||||
if (managedArray == null)
|
||||
return;
|
||||
managedArray.FreePooled();
|
||||
//handle.Free(); // No need to free weak handles
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +333,6 @@ namespace FlaxEngine.Interop
|
||||
#endif
|
||||
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.ManagedToUnmanagedIn, typeof(ArrayMarshaller<,>.ManagedToNative))]
|
||||
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.UnmanagedToManagedOut, typeof(ArrayMarshaller<,>.ManagedToNative))]
|
||||
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.ElementIn, typeof(ArrayMarshaller<,>.ManagedToNative))]
|
||||
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.ManagedToUnmanagedOut, typeof(ArrayMarshaller<,>.NativeToManaged))]
|
||||
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.UnmanagedToManagedIn, typeof(ArrayMarshaller<,>.NativeToManaged))]
|
||||
[CustomMarshaller(typeof(CustomMarshallerAttribute.GenericPlaceholder[]), MarshalMode.ElementOut, typeof(ArrayMarshaller<,>.NativeToManaged))]
|
||||
@@ -388,38 +385,28 @@ namespace FlaxEngine.Interop
|
||||
#if FLAX_EDITOR
|
||||
[HideInEditor]
|
||||
#endif
|
||||
public static class ManagedToNative
|
||||
public ref struct ManagedToNative
|
||||
{
|
||||
public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T[] managed, out int numElements)
|
||||
T[] sourceArray;
|
||||
ManagedArray managedArray;
|
||||
ManagedHandle managedHandle;
|
||||
|
||||
public void FromManaged(T[] managed)
|
||||
{
|
||||
if (managed is null)
|
||||
{
|
||||
numElements = 0;
|
||||
return null;
|
||||
}
|
||||
numElements = managed.Length;
|
||||
ManagedArray managedArray = ManagedArray.AllocatePooledArray<TUnmanagedElement>(managed.Length);
|
||||
return (TUnmanagedElement*)ManagedHandle.ToIntPtr(managedArray, GCHandleType.Normal);
|
||||
}
|
||||
|
||||
public static ReadOnlySpan<T> GetManagedValuesSource(T[] managed) => managed;
|
||||
|
||||
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements)
|
||||
{
|
||||
if (unmanaged == null)
|
||||
return Span<TUnmanagedElement>.Empty;
|
||||
ManagedArray managedArray = Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(new IntPtr(unmanaged)).Target);
|
||||
return managedArray.ToSpan<TUnmanagedElement>();
|
||||
}
|
||||
|
||||
public static void Free(TUnmanagedElement* unmanaged)
|
||||
{
|
||||
if (unmanaged == null)
|
||||
return;
|
||||
ManagedHandle handle = ManagedHandle.FromIntPtr(new IntPtr(unmanaged));
|
||||
(Unsafe.As<ManagedArray>(handle.Target)).FreePooled();
|
||||
//handle.Free(); // No need to free weak handles
|
||||
|
||||
sourceArray = managed;
|
||||
(managedHandle, managedArray) = ManagedArray.AllocatePooledArray<TUnmanagedElement>(managed.Length);
|
||||
}
|
||||
|
||||
public ReadOnlySpan<T> GetManagedValuesSource() => sourceArray;
|
||||
|
||||
public Span<TUnmanagedElement> GetUnmanagedValuesDestination() => managedArray.ToSpan<TUnmanagedElement>();
|
||||
|
||||
public TUnmanagedElement* ToUnmanaged() => (TUnmanagedElement*)ManagedHandle.ToIntPtr(managedHandle);
|
||||
|
||||
public void Free() => managedArray.FreePooled();
|
||||
}
|
||||
|
||||
#if FLAX_EDITOR
|
||||
@@ -427,26 +414,25 @@ namespace FlaxEngine.Interop
|
||||
#endif
|
||||
public struct Bidirectional
|
||||
{
|
||||
T[] managedArray;
|
||||
ManagedArray unmanagedArray;
|
||||
T[] sourceArray;
|
||||
ManagedArray managedArray;
|
||||
ManagedHandle handle;
|
||||
|
||||
public void FromManaged(T[] managed)
|
||||
{
|
||||
if (managed == null)
|
||||
return;
|
||||
managedArray = managed;
|
||||
unmanagedArray = ManagedArray.AllocatePooledArray<TUnmanagedElement>(managed.Length);
|
||||
handle = ManagedHandle.Alloc(unmanagedArray);
|
||||
sourceArray = managed;
|
||||
(handle, managedArray) = ManagedArray.AllocatePooledArray<TUnmanagedElement>(managed.Length);
|
||||
}
|
||||
|
||||
public ReadOnlySpan<T> GetManagedValuesSource() => managedArray;
|
||||
public ReadOnlySpan<T> GetManagedValuesSource() => sourceArray;
|
||||
|
||||
public Span<TUnmanagedElement> GetUnmanagedValuesDestination()
|
||||
{
|
||||
if (unmanagedArray == null)
|
||||
if (managedArray == null)
|
||||
return Span<TUnmanagedElement>.Empty;
|
||||
return unmanagedArray.ToSpan<TUnmanagedElement>();
|
||||
return managedArray.ToSpan<TUnmanagedElement>();
|
||||
}
|
||||
|
||||
public TUnmanagedElement* ToUnmanaged() => (TUnmanagedElement*)ManagedHandle.ToIntPtr(handle);
|
||||
@@ -454,26 +440,22 @@ namespace FlaxEngine.Interop
|
||||
public void FromUnmanaged(TUnmanagedElement* unmanaged)
|
||||
{
|
||||
ManagedArray arr = Unsafe.As<ManagedArray>(ManagedHandle.FromIntPtr(new IntPtr(unmanaged)).Target);
|
||||
if (managedArray == null || managedArray.Length != arr.Length)
|
||||
managedArray = new T[arr.Length];
|
||||
if (sourceArray == null || sourceArray.Length != arr.Length)
|
||||
sourceArray = new T[arr.Length];
|
||||
}
|
||||
|
||||
public ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(int numElements)
|
||||
{
|
||||
if (unmanagedArray == null)
|
||||
if (managedArray == null)
|
||||
return ReadOnlySpan<TUnmanagedElement>.Empty;
|
||||
return unmanagedArray.ToSpan<TUnmanagedElement>();
|
||||
return managedArray.ToSpan<TUnmanagedElement>();
|
||||
}
|
||||
|
||||
public Span<T> GetManagedValuesDestination(int numElements) => managedArray;
|
||||
public Span<T> GetManagedValuesDestination(int numElements) => sourceArray;
|
||||
|
||||
public T[] ToManaged() => managedArray;
|
||||
public T[] ToManaged() => sourceArray;
|
||||
|
||||
public void Free()
|
||||
{
|
||||
unmanagedArray.FreePooled();
|
||||
handle.Free();
|
||||
}
|
||||
public void Free() => managedArray.FreePooled();
|
||||
}
|
||||
|
||||
public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T[] managed, out int numElements)
|
||||
@@ -484,9 +466,8 @@ namespace FlaxEngine.Interop
|
||||
return null;
|
||||
}
|
||||
numElements = managed.Length;
|
||||
ManagedArray managedArray = ManagedArray.AllocatePooledArray<TUnmanagedElement>(managed.Length);
|
||||
IntPtr handle = ManagedHandle.ToIntPtr(managedArray);
|
||||
return (TUnmanagedElement*)handle;
|
||||
(ManagedHandle managedArrayHandle, _) = ManagedArray.AllocatePooledArray<TUnmanagedElement>(managed.Length);
|
||||
return (TUnmanagedElement*)ManagedHandle.ToIntPtr(managedArrayHandle);
|
||||
}
|
||||
|
||||
public static ReadOnlySpan<T> GetManagedValuesSource(T[] managed) => managed;
|
||||
@@ -517,7 +498,6 @@ namespace FlaxEngine.Interop
|
||||
return;
|
||||
ManagedHandle handle = ManagedHandle.FromIntPtr(new IntPtr(unmanaged));
|
||||
Unsafe.As<ManagedArray>(handle.Target).FreePooled();
|
||||
handle.Free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user