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. 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, GPUBufferUsage, GPUTextureUsage, etc.). 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) works because requestDevice() enables Dawn's implicit-device-synchronization feature by default, which guards the device and its child objects (buffers, textures, queue, pipelines) with a per-device mutex.
This makes the handoff safe, but it is coarse-grained locking, not a license for arbitrary concurrency. Prefer a clear ownership model: set resources up on one thread, render on another, and keep simultaneous use of the same device from several threads to a minimum. In particular:
- Never share a command encoder across threads. Command encoding is explicitly excluded from the implicit synchronization; 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 describes this feature as heavy-handed and notes that some reentrancy cases may still deadlock, so treat heavy cross-thread churn on one device as unsupported territory.
For completeness, the default can be disabled with implicitDeviceSynchronization: false on the device descriptor (a non-standard extension, ignored on the web). This is only for profiling or single-threaded setups; a device created this way must never be touched from a worklet runtime.