AsyncGPUReadbackPlugin
On Unity 2018.2 was introduced a really neat feature: being able get a frame from the gpu to the cpu without blocking the rendering. This feature is really useful for screenshot or network stream of a game camera because we need the frame on the cpu, but we don't care if there is a little delay.
However this feature is only available on platform supporting DirectX (Windows) and Metal (Apple), but not OpenGL and it's not planned. (source: https://forum.unity.com/threads/graphics-asynchronous-gpu-readback-api.529901/#post-3487735).
This plugin aim to provide this feature for OpenGL platform. It tries to match the official AsyncGPUReadback as closes as possible to let you easily switch between the plugin or the official API. Under the hood, it use the official API if available on the current platform.
I created this plugin for a specific use case of running our Unity project under linux, so the plugin is only built for Linux and the plugin API doen't provide all the feature that the official one does (like callback, choosing mipIndex, the destination format, etc.), but if you need one of them, contact me, I will see what we can do.
Use it
Install
This plugin has two parts that you need to copy inside your project :
libAsyncGPUReadbackPlugin.so
: It's the linux native plugin that talk directly to OpenGL.- Copy it from
NativePlugin/build/libAsyncGPUReadbackPlugin.so
to/Assets/Plugins
in your project.
- Copy it from
AsyncGPUReadbackPlugin.dll
: It's the C# part of the plugin that interface with the C++ native plugin. (Yes, that dll work under linux, it's just C# inside)- Copy it from
ManagedPlugin/bin/Release/netstandard2.0/AsyncGPUReadbackPlugin.dll
to anywhere under your/Assets
folder.
- Copy it from
The API
Once you copied the plugin, add using AsyncGPUReadbackPluginNs
at the beginning of the script where you want to use it.
static AsyncGPUReadbackPluginRequest AsyncGPUReadbackPlugin.Request(Texture src)
Same as the official API except that it doesn't implement all the other form. It request the texture from the gpu and return a AsyncGPUReadbackPluginRequest
object to let you watch the state of the operation and get data back.
AsyncGPUReadbackPluginRequest
This object let you see if the request is done and get the data you asked for.
Attributes
hasError
: True if the request faileddone
: True if the request is done and data available
Methods
NativeArray<T> GetData<T>()
: This let you get the data you asked for in the format you want once it is available.void Update(bool force = false)
: This method has to be called regularly to refresh request state. It differs from the official API because you have to call it manualy if you want the request to finish. It will do nothing if the official API is used and ifforce == false
.void Dispose()
: This plugin doens't free its buffer automatically, you have to call this methode manually once you finished working on the data you received fromGetData()
.
Example
To see a working example you can open UnityExampleProject
with the Unity editor. It saves screenshot of the camera every 60 frames. The script taking screenshot is in UnityExampleProject/Scripts/UsePlugin.cs
Differences with the official API
There is two major differences:
- Update(): You have to manually call Update() regularly
- Dispose(): You have to manually call Dispose() when you finished with the data to avoid memory leak.
Troubleshoots
The type or namespace name 'AsyncGPUReadbackPluginNs' could not be found. Are you missing an assembly reference?
If you click on AsyncGPUReadbackPlugin.dll
under Unity Editor, you will see
Plugin targets .NET 4.x and is marked as compatible with Editor, Editor can only use assemblies targeting .NET 3.5 or lower, please unselect Editor as compatible platform
In this case a solution is to change you runtime version in:
Editor > Project Settings > Player > Other Settings > Scripting Runtime Version : Set it to '.NET 4.x Equivalent'.
Build it!
Native plugin
cd NativePlugin
make # The makefile only work for linux, but you could add other target inside if you want
You can find the built file under
NativePlugin/build/libAsyncGPUReadbackPlugin.so
Managed plugin
You have to install the .Net SDK first to get the dotnet
command: https://dotnet.microsoft.com/download/linux-package-manager/ubuntu18-04/sdk-current
cd ManagedPlugin
dotnet build -c Release
You can then find the built file under
ManagedPlugin/bin/Release/netstandard2.0/AsyncGPUReadbackPlugin.dll
Thanks
This project was my first Unity plugin and the first time that I played with OpenGL, so I used a lot of internet ressources to do it. Here is some work that helped me: