I am using the Job system to do some calculations in the editor and at the end I need the data in a managed array. I would think NativeArray.CopyTo was the way to go but this is slow…
A Marshal.Copy from the NativeArray buffer pointer is 10x+ faster.
Is there another solution that does not require “unsafe” code?
It was mostly because I was trying to recreate some of the InputSystem github develop branch without access to 2018.2. But 2018.2 is out now so I dont really need to go that deep and directly access memory blocks.
Is there any chance NativeArray.CopyTo might one day be able to work with writing to multidimensional arrays, such as say a float[,] for a Terrain heightmap? Currently the best I can do is:
float [,] heights = new float [heightMapWidth, heightMapHeight];
float [] tempHeights = new float [heightMapWidth * heightMapHeight];
heightMapNativeArray.CopyTo (tempHeights);
Buffer.BlockCopy (tempHeights, 0, heights, 0, heightMapWidth * heightMapHeight * sizeof (float));
using the tempHeights interim 1D array. But it would be awesome to be able to avoid that extra performance hit if the CopyTo was able to manage the memory side of that behind the scenes.
Hi. try to do something like this. This will add a extention to the NativeArray that copies the data to a multi dimention array in one copy. The target managed array has to be in the correct size. You can add a similar function to NativeSlice.
public static class NativeArrayExtensions
{
public static unsafe void CopyToFast<T>(
this NativeArray<T> nativeArray,
T[,] array)
where T : struct
{
int byteLength = nativeArray.Length * Marshal.SizeOf(default(T));
void* managedBuffer = UnsafeUtility.AddressOf(ref array[0,0]);
void* nativeBuffer = nativeArray.GetUnsafePtr();
Buffer.MemoryCopy(nativeBuffer, managedBuffer, byteLength, byteLength);
}
}
EDIT:
after testing some speed I changed the buffer.MemoryCopy to this copy memory function while on windows platform.
#if PLATFORM_STANDALONE_WIN
[DllImport("msvcrt.dll", EntryPoint = "memcpy")]
public static extern void CopyMemory(IntPtr pDest, IntPtr pSrc, int length);
#endif
Edit2:
UnsafeUtility.MemCpy seems to be the way to go. No need for the external dll call.