AsyncGPUReadback.RequestIntoNativeArray causes InvalidOperationException on NativeArray

@richardkettlewell thanks for keeping an eye on this issue and hope you are returning from a well deserved holiday. I am using Unity 2020.2.0f1 and also experiencing similar issues, But I found it may go deeper than this alone.
A related issue was reported by @jhelbig in this post: AsyncGPUReadback.RequestIntoNativeArray - What am I doing wrong?

The funniest thing is that the exception simply throwing when it shouldn’t may be the problem? i’m using AsyncGPUReadback.RequestIntoNativeArray with the callback argument, same as above and “owner has been invalidated” exception BUT curiously if i continue to step through execution manually everything still works!! I see the results of my Compute buffer being read back in the Native Array, handed off to Mesh API, etc. So obviously the data is being read back and making it all the way through the pipeline, just exception is just being thrown and halting execution when it shouldn’t.

What’s even stranger is that while trying to find a way to optimize this as best i can in the meantime, I found I am able to use AsyncGPUReadback.Request in the coroutine and then in the callback request.GetData into a NativeArray THAT I NEVER INITIALIZED, I merely defined it and nothing more. This mysteriously works great with no exceptions / errors / warnings. It works as if i initialized the NativeArray with Allocator.Persistent on Start or Awake, but I didn’t. and is reproducible even after restarting the Editor and in Builds, still no issue.
If i DO initialize the NativeArray with Allocator.Persistent on Start or Awake like I think I’m supposed to? then everything works great up until exiting play mode, then “A Native Collection has not been disposed, resulting in a memory leak” is thrown with stack trace pointing to the Allocator.Persistent initialization. In other cases when a proper Dispose is expected to occur i get the “[NativeArray…] has been set to undisposable and cannot be deallocated” as @jhelbig also reports.

In all cases, I am calling Dispose() on the persistently allocated NativeArray only once OnDestroy(). So it seems there is a bigger or related issue with not being able to Dispose persistently allocated NativeArrays in some situations possibly when they are used with AsyncGPUReadback and/or coroutines and callbacks. perhaps the “ownership” is not being handled as expected.

I also can’t ignore this blog post by Jackson Dunstan on “Sharing IDisposables” that seems to touch on the possible cause of the problems here, shared ownership as it is related to when / where we are permitted to Dispose of a IDisposable object or when it is marked as Disposable or Undisposable. If anything, it’s the same cast of characters. JacksonDunstan.com | Sharing IDisposables

Presently with holiday I don’t have time to put together a proper bug report and reproducible example for all these cases (I will in a few week if these issues haven’t already been stamped out) but I wanted to at least flag this additional very odd unexpected behavior to try and help connect the dots on these potentially interrelated issues.AsyncGPUReadback is great to have anyway and seems over the past year or so there’s now enough people using it now to get enough feedback and attention to sort out these issues and pain points.

Also heads up to @Soaryn on the above as I know you rely on AsyncGPUReadback as well from your report on that memory leak issue that was already fixed here: AsyncGPUReadBack Request Memory Issue

Happy holidays all!

2 Likes