GraphicsBuffer's GetData always returning 0s

I’m trying to clone a mesh using GraphicsBuffer because its read/write option is false, and I can’t change that. This is my current code:

    public static bool Run(Mesh sourceMesh, out Mesh generatedMesh)
    {
        GraphicsBuffer sourceDataBuffer = sourceMesh.GetVertexBuffer(0);
        GraphicsBuffer sourceIndexBuffer = sourceMesh.GetIndexBuffer();

        var vertexCount = sourceDataBuffer.count;
        var indexCount = sourceIndexBuffer.count;

        byte[] sourceData = new byte[vertexCount * (sourceDataBuffer.stride / sizeof(byte))];
        byte[] sourceIndex = new byte[(int)(indexCount * ((float)sourceIndexBuffer.stride / sizeof(byte)))];

        sourceDataBuffer.GetData(sourceData);
        sourceIndexBuffer.GetData(sourceIndex);

        var attributes = sourceMesh.GetVertexAttributes();

        generatedMesh = new Mesh();
        generatedMesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;

        generatedMesh.SetVertexBufferParams(vertexCount, attributes);
        generatedMesh.SetVertexBufferData(sourceData, 0, 0, sourceData.Length);
        generatedMesh.SetIndexBufferParams(indexCount, sourceMesh.indexFormat);
        generatedMesh.SetIndexBufferData(sourceIndex, 0, 0, sourceIndex.Length);

        generatedMesh.subMeshCount = sourceMesh.subMeshCount;
        for (int i = 0; i < sourceMesh.subMeshCount; i++)
        {
            var subMeshDescriptor = sourceMesh.GetSubMesh(i);
            generatedMesh.SetSubMesh(i, subMeshDescriptor);
        }

        sourceDataBuffer.Release();
        sourceIndexBuffer.Release();

        generatedMesh.RecalculateBounds();

        return true; // No error
    }

It works like a charm in my test project. But when I try to clone things in my main project, GetData(sourceData) and GetData(sourceIndex) both return arrays of 0s. What could be causing that? Could it be because of the read/write being disabled?

1 Like

If the sourceDatabuffer is 0 the byte array is vertexcount multiplied by (0 * size of byte)

Just a stab in the dark.

Usually if readwrite is disabled you’ll get an error thrown reminding you.

Thanks for your answer! The count and stride from the buffer are both correct, not 0. The array size is right. I have replaced the GetData with AsyncGPUReadback.Request, and now I’m getting the error AsyncGPUReadback - GfxBufferID is invalid. This doesn’t happen in my test project, and I think it can be related to the problem, though I don’t know what it means.

Apparently, the problem only happens when I instantiate my GameObject from an asset bundle. Doesn’t GetData work with meshes loaded from asset bundles?

Do you need to directly instantiate the object from the asset bundle or do you need to recreate a new guide object in its image based on the stencil of the object in the asset bundle?

generally I will take my meshes that I want to import during runtime, and I will convert them into raw data for recreation. No short cuts for me.

I’m not sure if any of this was any use to you

Hopefully somebody else can take a look for you because it’s a-bit over my head this to be honest.

They’re being instantiated from the bundle.

I figured out the cause is that the mesh is not readable. I thought GraphicsBuffer would work despite that, but it doesn’t. Bundles with readable meshes are working

I figured out the cause is that the mesh is not readable.
That’s not really an explanation for why you can’t access vertex data from the GPU. The data exists on the GPU, why can’t we transfer it to the CPU without the overhead of always maintaining a copy on the CPU (which apparently happens when you make the mesh readable)?

I am getting the same AsyncGPUReadback - GfxBufferID is invalid error. It goes away when you set the vertexBufferTarget to Raw, but then it still just returns all 0s. Maybe a Unity dev could explain this issue? It seems like a bug that we get an error like this (or just all zeroes) instead of “mesh not set to readable”, but again, I think it should be possible.