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.

AsyncGPUReadback not working on Metal

Discussion in 'General Graphics' started by fendercodes, Dec 24, 2020.

  1. fendercodes

    fendercodes

    Joined:
    Feb 4, 2019
    Posts:
    166
    I am capturing a screenshot of my game and rendering it to my UI via a RenderTexture.

    This is working flawlessly Android and Windows but does not work on Metal (Mac standalone or iOS). There are no errors and OnReadbackCompleted is fired successfully but nothing is actually captured or rendered to the UI.

    Code (CSharp):
    1. public RawImage photoRenderTexture;
    2. private RenderTexture renderTexture;
    3.  
    4.     void TakeScreenshot() {
    5.         StartCoroutine(CreateRenderTexture());
    6.     }
    7.  
    8.     IEnumerator CreateRenderTexture()
    9.     {
    10.         yield return new WaitForEndOfFrame();
    11.         renderTexture = new RenderTexture(Screen.width, Screen.height, 0, RenderTextureFormat.ARGB32);
    12. ScreenCapture.CaptureScreenshotIntoRenderTexture(renderTexture);
    13.         AsyncGPUReadback.Request(renderTexture, 0, TextureFormat.ARGB32, OnReadbackCompleted);
    14.     }
    15.  
    16.     void OnReadbackCompleted(AsyncGPUReadbackRequest request)
    17.     {
    18.         if (request.hasError)
    19.         {
    20.             Debug.LogError("GPU readback error detected.");
    21.             ResetPhotoRenderer();
    22.             return;
    23.         }
    24.  
    25.         photoRenderTexture.enabled = true;
    26.         photoRenderTexture.texture = renderTexture;
    27.     }
    What's interesting is if I use RenderTextureFormat.Default it works fine except there is an error:
    'B8G8R8A8_SRGB' doesn't support ReadPixels usage on this platform. Async GPU readback failed.

    Should I just ignore the error? Seems like bad form to me.
     
  2. Arthur-LVGameDev

    Arthur-LVGameDev

    Joined:
    Mar 14, 2016
    Posts:
    222
    Sorry to semi-necro, but we stumbled across this same issue today, with AsyncGPUReadbackRequest on Metal. This forum post, along with this bug tracker ticket, are the two top relevant search results.

    Error for context & future searchers:



    We'll work around it for now, but it's not real clear why we'd see the error on this default/"plain" format -- unless I'm totally missing something. The bug tracker ticket similarly isn't clear on why the formats are so restrictive.

    If my memory is correct, I think it was less restrictive previously, in prior versions, but I'm not positive on that (has been a year or two since I've used async GPU readback w/ Metal).
     
  3. met5678

    met5678

    Joined:
    Dec 9, 2021
    Posts:
    2
    I also got this same issue, also running on a Mac.
    'B8G8R8A8_SRGB' doesn't support ReadPixels usage on this platform. Async GPU readback failed.


    I'm using AsyncGPUReadback on videoPlayer's texture, and reading from/writing to a RGBA32 texture:

    Code (CSharp):
    1.             // Start the async GPU readback process
    2.             AsyncGPUReadback.Request(_videoPlayer.texture, 0, TextureFormat.RGBA32, readbackRequest =>
    3.             {
    4.                 Debug.Log("Request complete for frame " + frameNum);
    5.                 if (readbackRequest.hasError)
    6.                 {
    7.                     Debug.LogError("GPU readback failed ");
    8.                     return;
    9.                 }
    10.  
    11.                 var texture = new Texture2D(_videoPlayer.texture.width, _videoPlayer.texture.height,
    12.                     TextureFormat.RGBA32, false);
    13.                 var data = readbackRequest.GetData<byte>();
    14.                 texture.LoadRawTextureData(data);
    15.                 texture.Apply();
    16.  
    17.                 _frameTextures[frameIdx] = texture;
    18.                 OnRenderProgress?.Invoke(frameNum / (float)NumFrames);
    19.              
    20.                 AdvanceFrame((int)frameIdx);
    21.             });
    22.  
    It seems to be working but I do get the error on every frame, which is a major nuisance since I'm extracting a LOT of frames. Is there any way I can suppress this error?