Worklets
Run WebGPU rendering off the JS thread on worklet runtimes.
By default, WebGPU rendering runs on the JavaScript thread alongside React.
Using React Native Worklets, you can run WebGPU rendering on the UI thread or on a dedicated worklet runtime.
A worklet loop also runs at the display's rate, 120 Hz on a ProMotion iPhone or iPad, where the JS thread's requestAnimationFrame is capped at 60 Hz (see Frame presentations).
There is even an experimental Bundle Mode that lets you run complex Three.js scenes on a dedicated thread.
You can see an example of Bundle Mode working with Three.js here.
Requirements
npm i react-native-workletsFollow the Worklets installation guide for the babel plugin and native setup. WebGPU objects are automatically registered for Worklets serialization when the module loads - you can pass GPUDevice and GPUCanvasContext directly to worklets.
installWebGPU
Worklet runtimes start without the WebGPU globals (navigator.gpu, the flag constants, the WebGPU classes). Call installWebGPU() once at the top of a worklet to install all of them for that runtime:
import { , } from "react-native-webgpu";
import { } from "react-native-worklets";
const = (: GPUDevice, : ) => {
"worklet";
();
const = .({
,
: . | .,
});
const = .();
// … encode passes …
..([.()]);
.();
};
// Create device on main thread, then run render on the UI thread:
const = await .();
const = .!.("webgpu")!;
(, , );Thread safety
The pattern above (create the device on the JS thread, render from a worklet runtime) is safe: requestDevice() enables Dawn's implicit-device-synchronization feature by default, so a device and its resources (buffers, textures, pipelines, the queue) can be used from several threads. Prefer a clear ownership model all the same, setting resources up on one thread and rendering on another, and follow two rules:
- Never share a command encoder across threads. Create the
GPUCommandEncoder(and its pass encoders) on the thread that uses it. - Don't drive the same canvas context from two threads. Keep
configure(),getCurrentTexture(), andpresent()for a given context on a single runtime.
Dawn's synchronization is coarse-grained, so heavy simultaneous use of one device from many threads is not a supported use case: keep cross-thread traffic to handoffs.
A device that is only ever used from one thread can skip the synchronization with implicitDeviceSynchronization: false. Such a device must never be touched from a worklet runtime.