Last active
October 26, 2023 09:04
-
-
Save OswaldHurlem/10d43704b23d493e190fca15d8197725 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This doesn't seem to work properly | |
//#define USE_UNITY_PIN_FUNCTION | |
using System; | |
using System.Runtime.InteropServices; | |
using Unity.Collections; | |
using Unity.Collections.LowLevel.Unsafe; | |
using UnityEngine; | |
using UnityEngine.Assertions; | |
// Trick for creating a temporary NativeArray which points to the contents of a managed array. | |
// Good for mischief and bleeding-edge perf. BEWARE! Very likely to cause bugs now and break later. | |
public class Test : MonoBehaviour | |
{ | |
unsafe void Start() | |
{ | |
const bool tryToF__kUpTheHeap = true; | |
const bool useTempHandle = true; | |
int[] managedArray = new int[20]; | |
NativeSlice<int> sliceCopy; | |
using (var adapter = new SliceAdapter<int>(managedArray, useTempHandle)) | |
{ | |
adapter.NativeSlice[5] = 5; | |
if (tryToF__kUpTheHeap) { sliceCopy = adapter.NativeSlice; } | |
} | |
if (tryToF__kUpTheHeap) { sliceCopy[2] = 500; } | |
Debug.Log(managedArray[5]); | |
Debug.Log(managedArray[2]); | |
} | |
} | |
public unsafe class SliceAdapter<T> : IDisposable | |
where T : struct | |
{ | |
private readonly bool _handleIsTemp; | |
private readonly AtomicSafetyHandle _safetyHandle; | |
public NativeSlice<T> NativeSlice; | |
#if USE_UNITY_PIN_FUNCTION | |
private readonly ulong _pinHandle; | |
#else | |
private readonly GCHandle _gcHandle; | |
#endif | |
public SliceAdapter(T[] managedArray, bool useTempHandle) | |
{ | |
Assert.IsTrue(UnsafeUtility.IsBlittable<T>()); | |
_safetyHandle = useTempHandle ? AtomicSafetyHandle.GetTempUnsafePtrSliceHandle() : AtomicSafetyHandle.Create(); | |
_handleIsTemp = useTempHandle; | |
#if USE_UNITY_PIN_FUNCTION | |
NativeSlice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice<T>( | |
UnsafeUtility.PinGCObjectAndGetAddress(managedArray, out _pinHandle), | |
UnsafeUtility.SizeOf<T>(), | |
managedArray.Length); | |
#else | |
_gcHandle = GCHandle.Alloc(managedArray, GCHandleType.Pinned); | |
NativeSlice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice<T>( | |
(void*)_gcHandle.AddrOfPinnedObject(), | |
UnsafeUtility.SizeOf<T>(), | |
managedArray.Length); | |
#endif | |
NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref NativeSlice, _safetyHandle); | |
} | |
public void Dispose() | |
{ | |
// DO NOT Release handle if it is shared | |
if (!_handleIsTemp) { AtomicSafetyHandle.Release(_safetyHandle); } | |
#if USE_UNITY_PIN_FUNCTION | |
UnsafeUtility.ReleaseGCObject(_pinHandle); | |
#else | |
_gcHandle.Free(); | |
#endif | |
// DO NOT CALL _nativeArray.Dispose(); | |
NativeSlice = default(NativeArray<T>); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment