Search Unity

  1. Looking for a job or to hire someone for a project? Check out the re-opened job forums.
    Dismiss Notice
  2. Unity 2020 LTS & Unity 2021.1 have been released.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Showcase PSA: How to stop blocking main thread with Texture.Apply using native plugin

Discussion in 'General Graphics' started by Shinyclef, Feb 25, 2021.

  1. Shinyclef


    Nov 20, 2013

    "How can I update a texture every frame without paying serious main thread costs?"
    I tried several things to answer this question, and eventually found this git repo:
    It's brilliant and so I would like to share it with you as I think there are many people looking for this solution. This is a showcase thread for that repo, it's not mine!

    It uses a native plugin to achieve the following goals, and I quote:
    "1. Upload the data on a rendering thread instead of the Unity Thread using IssuePluginCustomTextureUpdate (so this will be faster, have less locks/dispatch etc)
    2. Zero copy: The data that you prepare gets passed to the rendering system as is (the Graphics API then handles the rest, so that's as fast as can do things)

    I have profiled two cases, both in builds (script debugging enabled). In each case I am updating a 2048x2048 texture every frame by filling a NativeArray<Color32> with random greyscale pixels in a bursted parallel job. I did this to simulate a light pixel workload without taking too much time; it's the apply stage that interests me. Once the array is filled, it is used to update the texture.

    LoadRawTextureData + Texture.Apply:
    I don't know why it spikes so much, I don't seem to see the spikes in editor runs... but in build those spikes are all from the 'APPLY' profiler marker (code below in the #if UNITY_EDITOR branch, but for this test modified the code to run that branch in build).

    Native Plugin Texture Update:

    The takeaway I'm getting from these profiling snapshots is that we can completely move the main thread time spent in Apply over to a worker thread. The rendering thread does more work, but this is fine by me.

    There is a known issue with this plugin. Running the optimised native plugin method will crash the editor. Quote from the repo:
    "Because the native thread is calling managed code (to generate the texture), it is causing the editor to hang on domain unload (the second time you press play). The example is currently using Texture2D.LoadRawTextureData in the editor to prevent this issue."
    Thus, you can't get the performance benefit in the editor. At least I don't know how to fix this issue.

    Here is a snippet from the code that shows the editor workaround.
    Code (CSharp):
    1. // NativeArray<Color32> colorBuffer;
    2. #if UNITY_EDITOR
    3.         var tex2d = (Texture2D)texture;
    4.         unsafe
    5.         {
    6.             tex2d.LoadRawTextureData(new IntPtr(colorBuffer.GetUnsafePtr()), colorBuffer.Length * 4);
    7.         }
    8.         tex2d.Apply();
    9. #else
    10.         texture.Update(colorBuffer);
    11. #endif
    Also, I had to figure out how to build a CPP plugin for the first time cause he updated the plugin for all platforms except windows to a newer version, and I wanted to build the updated version for windows too. In my email with the author, he said he made a tool to build CPP plugins for unity easily:
    I had already gone through some trouble building it in VS as a windows dll project, so I have attached the windows dll in anyone needs it. It is built for Windows x64. Try using his tool if you need x86? If you do, post it back :D.

    Also maybe please don't go spamming the original author after I dug up his 2 year old repo :D.
    If anyone can figure out a solution to editor crashing, let me know.

    Curious to see if others find this plugin as useful as I do.

    Attached Files:

    Lo-renzo, joshuacwilde and PutridEx like this.
  2. GuitarBro


    Oct 9, 2014
    Huh. I've never needed this but it sounds really cool. Bookmarking for later. :)
  3. Shinyclef


    Nov 20, 2013
    I have submitted a bug report (1328779) to hopefully have the editor hanging bug fixed...