Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice
  2. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  3. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

AsyncGPUReadback GetData<Vector3> not working

Discussion in '2018.1 Beta' started by theFrenchDutch, Mar 7, 2018.

  1. theFrenchDutch

    theFrenchDutch

    Joined:
    May 5, 2014
    Posts:
    25
    I have a setup like the following, where I compute a 65*65 array of Vector3 in a compute shader. Everything works fine with previous method (using buffer.GetData()) but I can't get it working using the new AsyncGPUReadback requests. The request.GetData<> behaves weirdly depending on the data type.

    Compute shader :
    RWStructuredBuffer<float3> vertexBuffer;
    (which is written into when I dispatch the compute shader)

    C# side :
    buffer = new ComputeBuffer(65 * 65, sizeof(float) * 3, ComputeBufferType.Default));
    // Dispatch
    request = AsyncGPUReadback.Request(buffer);
    // wait until done == true (and verify hasError == false)
    Vector3[] data = request.GetData<Vector3>().ToArray();

    Instead of giving me an array of 4225 Vector3s, this returns an array of 1408 Vector3s, filled with 0. Other tries at GetData return weird results too :

    float[] data = request.GetData<float>().ToArray(); // returns 4225 floats filled with zero
    Color32[] data = request.GetData<Color32>().ToArray(); // returns 4225 Color32s filled with random values
    Color[] data = request.GetData<Color>().ToArray(); // returns 1056 Colors filled with zero

    I have tried but I really fail to understand the logic in this. How is one supposed to get Vector3/float3 data using AsyncGPUReadback requests ?
     
  2. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,225
    It works for me as of beta 7
    At first glance you're doing it right, I assume you dispatch your compute shader properly since you said with the old method it works fine.
    My project computes on multiple layers so it gets convoluted but I'll paste a relevant snippet in case it's useful to you.
    Code (CSharp):
    1.            // extract
    2.             List<AsyncGPUReadbackRequest> requestFlow = new List<AsyncGPUReadbackRequest>(settings.Length);
    3.             for (int i = 0; i < settings.Length; i++)
    4.             {
    5.                 requestFlow.Add(AsyncGPUReadback.Request(vectorFlowBuffer[i]));
    6.                 yield return null;
    7.             }
    8.  
    9.             yield return new WaitUntil(() => requestFlow.FindAll(r => r.done == false).Count == 0);
    10.             for (int i = 0; i < settings.Length; i++)
    11.             {
    12.                 vectorFlowBuffer[i].GetData(settings[i].flowVectors);
    13.                 yield return null;
    14.             }
     
  3. theFrenchDutch

    theFrenchDutch

    Joined:
    May 5, 2014
    Posts:
    25
    Thanks for the answer ! You do seem to be using the old method too though, with ComputeBuffer.GetData(array), instead of AsyncGPUReadbackRequest.GetData<T>() ?

    I assumed we need to use the new GetData from the request class for the Async readback to work, maybe I'm wrong.
     
    Last edited: Mar 8, 2018
  4. JulienF_Unity

    JulienF_Unity

    Unity Technologies

    Joined:
    Dec 17, 2015
    Posts:
    324
    Hello,

    This is definitely not expected.
    Can you tell us on which version of 18.1 and with which platform (DX11 ?) you are encountering the issue.
    A minimal project reproducing the issue will be highly appreciated.

    Thanks.
     
  5. theFrenchDutch

    theFrenchDutch

    Joined:
    May 5, 2014
    Posts:
    25
    Turns out it was a bug from my own project. Sorry about the useless thread, I should've tested it out with a minimal project immediatly ! The fact the bug didn't occur with the old getData threw off my judgement. Case closed !
     
    JulienF_Unity likes this.
  6. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,225
    @theFrenchDutch this is definitely not a useless thread, you spotted a mis use of the async stuff.
    But how do you get it work? My code should wait for request to be finished and yet I get an error no data.
    Here is my code:
    Code (CSharp):
    1.       // extract
    2.             List<AsyncGPUReadbackRequest> requestFlow = new List<AsyncGPUReadbackRequest>(settings.Length);
    3.             for (int i = 0; i < settings.Length; i++)
    4.             {
    5.                 requestFlow.Add(AsyncGPUReadback.Request(vectorFlowBuffer[i]));
    6.                 yield return null;
    7.             }
    8.  
    9.             yield return new WaitUntil(() => requestFlow.FindAll(r => r.done == false && r.hasError == true).Count == 0);
    10.             for (int i = 0; i < settings.Length; i++)
    11.             {
    12.                 settings[i].flowVectors = requestFlow[i].GetData<Vector2>().ToArray(); //requestFlow vectorFlowBuffer[i].GetData(settings[i].flowVectors);
    13.                 yield return null;
    14.             }
     
  7. theFrenchDutch

    theFrenchDutch

    Joined:
    May 5, 2014
    Posts:
    25
    I think you shouldn't be checking for "r => r.done == false && r.hasError == true" in your yield, as hasError is always false unless there is an error after the request ended, so I guess your WaitUntil is always finishing right away. Only checking for r.done == false should work though if I'm right !
     
  8. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,225
    You're right, I tripped myself with a double negative. I need || instead of && but anyway this doesn't solve it even with the old GetData so I logged a bug: either hasError is always true by mistake or the console doesn't log compute shader errors. case # 1011661)
     
  9. jbeaudoin11

    jbeaudoin11

    Joined:
    Jan 18, 2018
    Posts:
    8
    Sorry if it doesn't help, but isn't a request only available for 1 frame only ?
    I think you can't use WaitUntil since if some of the request are done, but not all of them, the next frame you lost contents that were ready and may act weird.
     
    Last edited: Mar 10, 2018
  10. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,225
    This is it, thank you.
     
    jbeaudoin11 likes this.
  11. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    6,225
    @theFrenchDutch .ToArray allocates like a a mother F***er, you should instead preallocate data and use request.GetData<Vector3>().CopyTo(data), they fixed it where it doesn't allocate (thanks dev.)
     
  12. theFrenchDutch

    theFrenchDutch

    Joined:
    May 5, 2014
    Posts:
    25
    Hey thanks for that info, I'll use this :)
     
    laurentlavigne likes this.