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

Question Convert a pinned managed array to NativeArray (Getting CheckElementReadAccess error)

Discussion in 'C# Job System' started by DragonCoder, Jul 26, 2023.

  1. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,419
    Hello Community,

    am having a system where I'm manipulating a mesh through a DLL on C++ side. The mesh vertices are sent via a pinned GCHandle gained like:
    GCHandle.Alloc(mesh.vertices, GCHandleType.Pinned);

    This works are expected.
    However now I would also like to read those same vertices array with burst, thus needing a native array - WITHOUT COPYING (since this is for procedural terrain generation in realtime hence why doing the heavy lifting in C++).

    The method
    NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray
    seemed perfect for that and an example like this (unrelated to meshes now) compiles, given unsafe context:

    Code (CSharp):
    1.                 Vector3[] my_verts = new Vector3[100];
    2.                 my_verts[0] = new Vector3(17, 3, 9);
    3.  
    4.                 // Convert the managed array to a NativeArray (without copying the data)
    5.                 GCHandle mesh_vertices_gc = GCHandle.Alloc(my_verts, GCHandleType.Pinned);
    6.                 IntPtr ptr = mesh_vertices_gc.AddrOfPinnedObject();
    7.                 NativeArray<Vector3> nativeArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Vector3>((void*)ptr, 100, Allocator.None);
    8.  
    9.                 Debug.Log("PTR : " + ptr); // A valid looking adress
    10.                 Debug.Log("Length: " + nativeArray.Length); // 100 -> correct
    However trying to access
    nativeArray[0]
    results in:

    Somebody know what I am missing here?

    Huge thanks in advance!
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,934
    ConvertExistingDataToNativeArray for some reason doesn't set the AtomicSafetyHandle. If you are using the Collections package, there's a helper in there that will do that correctly.

    Also, is there a reason you aren't using the MeshData API for this?
     
    DragonCoder likes this.
  3. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,419
    Huge thanks! That was the right thing.

    Well, the C++ side of this system was designed before the new MeshData api existed unfortunately and switching is not so easy since from what I see it puts everything related to a vertex (xyz, UV, normals) in one single consecutive array instead of separate arrays.

    -------

    That said, turns out if I use Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle, the project doesn't build anymore.
    This thread here claims that's even intended: https://forum.unity.com/threads/can...e-to-work-outside-editor-environment.1248019/
    Any idea on this?

    EDIT:
    Can't even steal the handle of another NativeArray because "SetAtomicSafetyHandle" as a whole is unavailable in builds!
     
    Last edited: Jul 30, 2023
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    3,934
    You have to wrap all stuff using AtomicSafetyHandle in a ENABLE_UNITY_COLLECTIONS_CHECKS block.
     
    DragonCoder likes this.
  5. DragonCoder

    DragonCoder

    Joined:
    Jul 3, 2015
    Posts:
    1,419
    Just found that out too.. after trying the opposite and activating COLELCTIONS_CHECKS via define.
    Alright, that all makes sense now.