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 Request AsyncGPUReadback each frame

Discussion in 'General Graphics' started by kmedved, Sep 28, 2023.

  1. kmedved

    kmedved

    Joined:
    Aug 18, 2016
    Posts:
    187
    I have compute shader that dispatches every frame. After each dispatch I invoke AsyncGPUReadback to get compute shader data (array of my struct). When the first AsyncGPUReadback callback is done it has hasError == false. But the rest callbacks have hasError == true, despite of that, the NativeArray data is valid.

    In case if I request AsyncGPUReadback, only when the previous AsyncGPUReadbackRequest.done (not every frame), there's no errors.

    Is it possible to request AsyncGPUReadback each frame without the error? Should I ignore the .hasError flag as the data is valid?

    Code (CSharp):
    1. void Update()
    2. {
    3.     var threadGroups = (int)((Triangles.Length + (threadGroupSize - 1)) / threadGroupSize);
    4.     computeShader.Dispatch(kernel, threadGroups, 1, 1);
    5.  
    6.     var dataArray = new NativeArray<TriangleData>(Triangles.Length, Allocator.Persistent);
    7.     var readBackRequest = AsyncGPUReadback.RequestIntoNativeArray(ref dataArray, outputDataBuffer);
    8.     var request = new ComputeRaycastRequest
    9.     {
    10.        ReadbackRequest = readBackRequest,
    11.        OutputNativeArray = dataArray
    12.     };
    13.     allRequests.Add(request);
    14. }
    15.  
    16. void LateUpdate()
    17. {
    18.     foreach (request in allRequests)
    19.     {
    20.        if (request.ReadbackRequest.done)
    21.        {
    22.            if (request.hasError)
    23.            {
    24.               Debug.Log("Error!");
    25.            }
    26.            request.OutputNativeArray.Dispose();
    27.         }
    28.     }
    29.  
    30.     allRequests.RemoveAll(x => x.ReadbackRequest.done);
    31. }
     
    Last edited: Sep 28, 2023
  2. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    547
    Yes, you can have multiple concurrent async readbacks. You can submit one each frame and read the result from 3 frames earlier. Usually, you need 3 to avoid wait times since by the default there can be up to 3 frames in flight - but depends if you are CPU or GPU bound.

    Unfortunately, I can't say why you get an error, though.
     
    kmedved likes this.
  3. kmedved

    kmedved

    Joined:
    Aug 18, 2016
    Posts:
    187
    Thank you! I debugged my code and found that i get hasError == true when I have 4 active AsyncGPUReadbackRequests.
    Is there any way to avoid it? What if I have a few instances of the component, in this case each component may have 3+ AsyncGPUReadbackRequests?
     
  4. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    547
    Didn't know there was a limit but I never needed more than 3. I don't know what you are using them for but if you need more then 1 per frame-in-flight, you are probably doing something wrong. Having said that, you could combine the results on the GPU into a single buffer with a compute shader and read that back.
     
  5. kmedved

    kmedved

    Joined:
    Aug 18, 2016
    Posts:
    187
    I'm doing raycast system that finds UV of the meshes. Before that I used one compute shader per mesh, but seems that I need pass array of GraphicsBuffer's of all meshes to do it in one dispatch.
     
    Last edited: Sep 29, 2023
  6. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    547
    At least, you'd need to store the result in an buffer that has at least as many elements as there can be raycasts per frame and pass the output index to each dispatch call.

    By the way, you also get the UV coordinates when you do raycasts on the CPU, but I think it requires MeshColliders and that the meshes are CPU readable so your approach does make sense if you don't want that.
    https://docs.unity3d.com/ScriptReference/RaycastHit-textureCoord.html