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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

AsyncGPUReadbackRequest.GetData with permanant allocator?

Discussion in '2018.1 Beta' started by noph42, Mar 21, 2018.

  1. noph42

    noph42

    Joined:
    Mar 20, 2018
    Posts:
    2
    Hi,

    I am trying to make a tool that bake 3D animations into 2D sprite sheets. My goal is to render and save as much images as possible while leveraging Unity real-time rendering and graphical workflow.

    I currently use AsyncGPUReadbackRequest to render my frames and pass an array of Color32 into a thread that is then going to convert it to an array of byte, encode it in PNG and save it.

    I am not using UnityEngine’s EncodeToPNG as it can only be executed on the main thread and would have heavy overhead as images can size up to 1024x1024.

    My current solution is functional but isn’t pulling out enough images per seconds to be a viable solution. Currently 60-90% of the time is spent on copying the NativeArray<Color32> returned by GetData() to a Color32[].

    The NativeArray that GetData() return is not accessible when my thread start. My guess is that either the allocator is temporary or the the AsyncGPUReadbackRequest dispose it after like a frame or so (?)

    Is there any way to get a NativeArray with a permanent allocator from GetData() and dispose it ourselves? or any work around to be able to make the copy of the NativeArray from the worker thread instead of the main one?
     
  2. valyard

    valyard

    Unity Technologies

    Joined:
    Jun 4, 2010
    Posts:
    291
    A reply from our dev:

    No unfortunately it's not possible. This is a design choice to guarantee data integrity to the user (no concurrent reads and writes). As the user stated the solution is to spawn a job to perform the copy. And during the same frame because, he guessed right, the readback is performed to tmp memory.​
     
  3. noph42

    noph42

    Joined:
    Mar 20, 2018
    Posts:
    2
    Thanks a lot for the answer!

    I tried to spawn a job to perform the copy and stumble upon an issue: when the image is large (1024x1024) the NativeArray<Color32>.CopyTo(…) throw a “Object reference not set to an instance of an object”.

    This is not happening when the image is smaller (like 256x256). I don’t especially understand the low-level mechanism of how jobs are handled but my guess would be that a 1024x1024 image takes more than 1 frame to copy therefore throwing an exception when the NativeArray is disposed.