Skip to content

Alternative to Texture2D.Apply() that doesn't require synchronizing with the render thread, avoiding stalls in the main thread

License

Notifications You must be signed in to change notification settings

gilzoide/unity-texture-apply-async

Repository files navigation

Texture Apply Async

openupm

Alternative to Texture2D.Apply() that doesn't require synchronizing with the render thread, avoiding stalls in the main thread.

Features

  • Asynchronous texture data update in CPU in the render thread, avoiding stalls in the main thread
  • Supports Unity's Built-in Render Pipeline as well as Scriptable Render Pipelines (e.g: URP and HDRP).
  • To guarante the texture is applied before appearing in the screen:
    • In BRP, updates are scheduled in the first Camera's Camera.onPreRender event
    • In SRP, updates are scheduled in RenderPipelineManager.beginContextRendering event
  • Supports registering for updates every frame or for a single frame
  • Prebuilt for Windows, Linux, macOS and Android
  • Built from source in iOS, tvOS, visionOS and WebGL projects

Caveats

  • You should not update the texture's data while the camera/render pipeline is rendering, or else garbage data could be applied to the texture.

How to install

Either:

  • Use the openupm registry and install this package using the openupm-cli:
    openupm add com.gilzoide.texture-apply-async
    
  • Install using the Unity Package Manager with the following URL:
    https://github.com/gilzoide/unity-texture-apply-async.git#1.1.0
    
  • Clone this repository or download a snapshot of it directly inside your project's Assets or Packages folder.

Samples

  • Random Colors: simple sample with a UI that shows random colors.
  • Plasma Color Job: sample scene with a plasma effect UI that is updated using the C# Job System.

How to use

using Gilzoide.TextureApplyAsync;

// 1. Create a `TextureApplyAsyncHandle` for your texture.
var textureApplyAsyncHandle = new TextureApplyAsyncHandle(myTexture);

// 2. If you want to update your texture every frame,
// schedule the apply handle to update every frame.
textureApplyAsyncHandle.ScheduleUpdateEveryFrame();

// 3. Update the texture data normally.
for (int x = 0; x < myTexture.width; x++)
{
    for (int y = 0; y < myTexture.height; y++)
    {
        myTexture.SetPixel(x, y, Random.ColorHSV());
    }
}

// 4. If you want to update your texture only once,
// schedule a one-shot update.
textureApplyAsyncHandle.ScheduleUpdateOnce();

// 5. Cancel updates if necessary.
// Works for both one-shot and every frame updates.
textureApplyAsyncHandle.CancelUpdates();

// 6. Dispose of the `TextureApplyAsyncHandle` when not needed
// anymore, e.g. inside a component's `OnDestroy`.
textureApplyAsyncHandle.Dispose();