Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Fastest way to copy a NativeList to a DynamicBuffer

Discussion in 'Entity Component System' started by PhilSA, Aug 19, 2020.

  1. PhilSA

    PhilSA

    Joined:
    Jul 11, 2013
    Posts:
    1,926
    Let's say I have a MyBufferElement, NativeList<MyBufferElement> and a DynamicBuffer<MyBufferElement>

    What's the fastest way to copy the contents of the NativeList into the DynamicBuffer from within a job? Is there a better way than a for loop?

    -------------------------
    Context:
    I have a satic utility function that is basically a "FillBufferWithThings(ref DynamicBuffer<MyBufferElement> myBuffer)", but I would like this utility function to also be usable with a NativeList<MyBufferElement>. I thought the INativeList interface would allow me to use it for both NativeLists and DynamicBuffers, but it doesn't have an Add() function. So I'm guessing the next best thing would be to make it work with a NativeList, but then we can copy the contents of the NativeList to a DynamicBuffer if we want to. But unless the copy is extremely fast, I'd rather just make two different functions. I might need to be copying 1000 lists of up to 10 elements per frame
     
    Last edited: Aug 19, 2020
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,984
    UnsafeUtility.MemCpy? The nice thing about that is it is fast both in and out of Burst as it will always call into a native routine.
     
  3. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    258

    You can either use UnsafeUtility or you can use DynamicBuffer.AddRange(NativeArray<T>) since NativeList can be implicitly converted to a NativeArray. I suspect that the UnsafeUtility is truly the faster way (I have not tested performance), but I prefer to avoid unsafe code whenever convient.
     
    DreamingImLatios likes this.
  4. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,627
    AddRange just does a memcpy under the hood

    Code (CSharp):
    1. public void AddRange(NativeArray<T> newElems)
    2. {
    3.     CheckWriteAccess();
    4.     int elemSize = UnsafeUtility.SizeOf<T>();
    5.     int oldLength = Length;
    6.     ResizeUninitialized(oldLength + newElems.Length);
    7.  
    8.     byte* basePtr = BufferHeader.GetElementPointer(m_Buffer);
    9.     UnsafeUtility.MemCpy(basePtr + (long)oldLength * elemSize, newElems.GetUnsafeReadOnlyPtr<T>(), (long)elemSize * newElems.Length);
    10. }
    Apart from some minor safety checks, it really isn't going to be any different, just does all the work for you.