I can't get AsyncGPUReadback.RequestIntoNativeArray to work. Error in Job with owner being Invalidated.

Hey guys, I’d love to get AsyncGPUReadback.RequestIntoNativeArray working, as streaming the data from my compute shader directly into a native array would just be beautiful.

Note that the compute shader really doesn’t generate any important data. I want to get this concept working in the test environment so that I can build jobs into a bigger project I have going with dynamic mesh generation.

However, I’m getting the following error and can’t figure out why!

InvalidOperationException: The
Unity.Collections.NativeArray`1[DataTest+test_struct]
SimpleJob.my_test_data can no longer
be accessed, since its owner has been
invalidated. You can simply Dispose()
the container and create a new one.
Unity.Jobs.LowLevel.Unsafe.JobsUtility.Schedule
(Unity.Jobs.LowLevel.Unsafe.JobsUtility+JobScheduleParameters&
parameters) (at
:0)
Unity.Jobs.IJobExtensions.Schedule[T]
(T jobData, Unity.Jobs.JobHandle
dependsOn) (at
:0)
DataTest+d__3.MoveNext
() (at Assets/DataTest/DataTest.cs:54)

Here’s my struct on the processor:

   public struct test_struct
    {
        public int val;
    }

Here’s the Coroutine that runs my compute shader and my job

IEnumerator computeShaderThenJob()
    {
        ComputeBuffer test_buffer = new ComputeBuffer(10, sizeof(byte) * 4, ComputeBufferType.Raw);
        
        int kernalHandle = compute_test.FindKernel("CSMain");
        compute_test.SetBuffer(kernalHandle, "TestBuffer", test_buffer);
        compute_test.Dispatch(kernalHandle, 10, 1, 1);

        NativeArray<test_struct> test_data = new NativeArray<test_struct>(10, Allocator.Persistent);
        AsyncGPUReadbackRequest test_data_request = AsyncGPUReadback.RequestIntoNativeArray(ref test_data, test_buffer);

        while (!test_data_request.done)
        {
            yield return null;
        }

        test_buffer.Dispose();

        MeshFilter meshFilter = GetComponent<MeshFilter>();
        Mesh mesh = meshFilter.mesh;

        Mesh.MeshDataArray mesh_data = Mesh.AllocateWritableMeshData(1);

        SimpleJob myJob = new SimpleJob();

        myJob.my_test_data = test_data;
        myJob.outputMesh = mesh_data[0];


        JobHandle handle = myJob.Schedule();

        while (!handle.IsCompleted)
        {
            yield return null;
        }

        handle.Complete();

        mesh.name = "tetrahedron";
        Mesh.ApplyAndDisposeWritableMeshData(mesh_data, mesh);
        mesh.RecalculateTangents();
        mesh.RecalculateBounds();

        test_data.Dispose();
    }

My Compute Shader:

// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain

// Create a RenderTexture with enableRandomWrite flag and set it
// with cs.SetTexture
struct test_struct
{
	int value;
};

RWStructuredBuffer<test_struct> TestBuffer;

[numthreads(1,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
	TestBuffer[0].value = 5;
}

My Job:

 private struct SimpleJob : Unity.Jobs.IJob
    {
        [ReadOnly] public NativeArray<test_struct> my_test_data;
        public Mesh.MeshData outputMesh;       

        public void Execute()
        {
            int num_vertices = 12;
            int num_triangle_indices = 12;
            outputMesh.SetVertexBufferParams(num_vertices, 
                new VertexAttributeDescriptor(VertexAttribute.Position), 
                new VertexAttributeDescriptor(VertexAttribute.Normal, stream: 1));
            NativeArray<Vector3> vertex_data = outputMesh.GetVertexData<Vector3>();
            NativeArray<Vector3> normals_data = outputMesh.GetVertexData<Vector3>(stream: 1);

            // Four tetrahedron vertex positions:
            var sqrt075 = Mathf.Sqrt(0.75f);
            var p0 = new Vector3(0, 0, 0);
            var p1 = new Vector3(1, 0, 0);
            var p2 = new Vector3(0.5f, 0, sqrt075);
            var p3 = new Vector3(0.5f, sqrt075, sqrt075 / 3);

            vertex_data[0] = p0; vertex_data[1] = p1; vertex_data[2] = p2;
            vertex_data[3] = p0; vertex_data[4] = p2; vertex_data[5] = p3;
            vertex_data[6] = p2; vertex_data[7] = p1; vertex_data[8] = p3;
            vertex_data[9] = p0; vertex_data[10] = p3; vertex_data[11] = p1;


            outputMesh.SetIndexBufferParams(num_triangle_indices, IndexFormat.UInt16);
            NativeArray<ushort> triangle_data = outputMesh.GetIndexData<ushort>();

            for (ushort i = 0; i < triangle_data.Length; ++i)
                triangle_data *= i;*

for (ushort i = 0; i < triangle_data.Length; ++i)
normals_data = new Vector3(1, 1, 1);

outputMesh.subMeshCount = 1;
outputMesh.SetSubMesh(0, new SubMeshDescriptor(0, num_triangle_indices));
}
}
This has got me well and truly stumped. Any pointers in the right direction would be greatly appreciated.
Thanks!

I’m having a similar issue - did you manage to fix it?
Cheers