Search Unity

Resolved CommandBuffer.RequestAsyncReadbackIntoNativeArray size of buffer error

Discussion in 'High Definition Render Pipeline' started by CaseyHofland, Jan 17, 2022.

  1. CaseyHofland

    CaseyHofland

    Joined:
    Mar 18, 2016
    Posts:
    613
    I want to read a texture into a native array. It is my understanding that the following code should be perfectly fine:

    Code (CSharp):
    1. ReadExample(CommandBuffer cmd, RenderTexture source)
    2. {
    3.     var pixels = new NativeArray<byte>(source.width * source.height * 4, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
    4.  
    5.     cmd.RequestAsyncReadbackIntoNativeArray(ref pixels, source, 0, (request) =>
    6.     {
    7.         pixels.Dispose();
    8.     });
    9. }
    And yet when I run this, I receive
    Size of buffer cannot be larger than the nativeArray to read into.
    error.

    The full stack trace:

    Code (CSharp):
    1. Size of buffer cannot be larger than the nativeArray to read into.
    2. UnityEngine.StackTraceUtility:ExtractStackTrace ()
    3. UnityEngine.Rendering.ScriptableRenderContext:Submit_Internal ()
    4. UnityEngine.Rendering.ScriptableRenderContext:Submit ()
    5. UnityEngine.Rendering.HighDefinition.HDRenderPipeline:Render (UnityEngine.Rendering.ScriptableRenderContext,System.Collections.Generic.List`1<UnityEngine.Camera>) (at Library/PackageCache/com.unity.render-pipelines.high-definition@12.1.3/Runtime/RenderPipeline/HDRenderPipeline.cs:1906)
    6. UnityEngine.Rendering.RenderPipeline:InternalRender (UnityEngine.Rendering.ScriptableRenderContext,System.Collections.Generic.List`1<UnityEngine.Camera>)
    7. UnityEngine.Rendering.RenderPipelineManager:DoRenderLoop_Internal (UnityEngine.Rendering.RenderPipelineAsset,intptr,System.Collections.Generic.List`1<UnityEngine.Camera/RenderRequest>,Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle)
    8. UnityEditor.EditorGUIUtility:RenderPlayModeViewCamerasInternal (UnityEngine.RenderTexture,int,UnityEngine.Vector2,bool,bool)
    9. UnityEditor.PlayModeView:RenderView (UnityEngine.Vector2,bool)
    10. UnityEditor.GameView:OnGUI ()
    11. UnityEditor.HostView:InvokeOnGUI (UnityEngine.Rect)
    12. UnityEditor.DockArea:DrawView (UnityEngine.Rect)
    13. UnityEditor.DockArea:OldOnGUI ()
    14. UnityEngine.UIElements.IMGUIContainer:DoOnGUI (UnityEngine.Event,UnityEngine.Matrix4x4,UnityEngine.Rect,bool,UnityEngine.Rect,System.Action,bool)
    15. UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent (UnityEngine.Event,UnityEngine.Matrix4x4,UnityEngine.Rect,System.Action,bool)
    16. UnityEngine.UIElements.IMGUIContainer:DoIMGUIRepaint ()
    17. UnityEngine.UIElements.UIR.RenderChainCommand:ExecuteNonDrawMesh (UnityEngine.UIElements.UIR.DrawParams,single,System.Exception&)
    18. UnityEngine.UIElements.UIR.UIRenderDevice:EvaluateChain (UnityEngine.UIElements.UIR.RenderChainCommand,UnityEngine.Material,UnityEngine.Material,UnityEngine.Texture,UnityEngine.Texture,single,Unity.Collections.NativeSlice`1<UnityEngine.UIElements.UIR.Transform3x4>,Unity.Collections.NativeSlice`1<UnityEngine.Vector4>,UnityEngine.MaterialPropertyBlock,bool,System.Exception&)
    19. UnityEngine.UIElements.UIR.RenderChain:Render ()
    20. UnityEngine.UIElements.UIRRepaintUpdater:Update ()
    21. UnityEngine.UIElements.VisualTreeUpdater:UpdateVisualTreePhase (UnityEngine.UIElements.VisualTreeUpdatePhase)
    22. UnityEngine.UIElements.Panel:UpdateForRepaint ()
    23. UnityEngine.UIElements.Panel:Repaint (UnityEngine.Event)
    24. UnityEngine.UIElements.UIElementsUtility:DoDispatch (UnityEngine.UIElements.BaseVisualElementPanel)
    25. UnityEngine.UIElements.UIElementsUtility:UnityEngine.UIElements.IUIElementsUtility.ProcessEvent (int,intptr,bool&)
    26. UnityEngine.UIElements.UIEventRegistration:ProcessEvent (int,intptr)
    27. UnityEngine.UIElements.UIEventRegistration/<>c:<.cctor>b__1_2 (int,intptr)
    28. UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
    29.  
    30. [C:\buildslave\unity\build\Runtime\Graphics\AsyncGPUReadbackManaged.cpp line 336]
    @richardkettlewell I saw you on another forum talking about an AsyncGPUReadback error so I though I would add you here as well.
     
  2. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,285
    what format is the RenderTexture?
     
  3. CaseyHofland

    CaseyHofland

    Joined:
    Mar 18, 2016
    Posts:
    613
    That source is the screen texture and we use it for a post processing effect.

    This code works perfectly fine when the Color Buffer Format in the quality settings is R11G11B10, but in our highest quality settings it is set to R16G16B16A16. Thank you so much! Sorry for taking your time with this one, I should have spotted it.

    This makes me wonder though: if you read back an R11G11B10 texture into a NativeArray<byte>, I assume you get incorrect results, with every 4 bytes being in the format: R8, R3G5, G6B2, B8. If so, would NativeArray<float> capture these values in the right format, or simple capture 1 float for every pixel in the format R11G11B10? Neither does much good: how do I go about capturing the NativeArray correctly?
     
  4. JulienF_Unity

    JulienF_Unity

    Unity Technologies

    Joined:
    Dec 17, 2015
    Posts:
    326
    Hi,

    If you use NativeArray<float> or any compatible <T>, this will not perform a conversion of data, it is really just a reinterpretation, so yes it will only be the R11G11B10 data reinterpreted as float. What you can do is requesting Uint32 and extract RGB data manually with bitwise operations.

    It's worth noting that Async readback also supports some actual data conversion for textures. You can specify a destination texture format when performing a request, in that case the data on GPU will be converted to that format (if they differ). Not all conversions are supported and, if not, you'll get a request with the error flag set. Also note that the conversion comes at a cost on the render thread