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!