diff --git a/apps/docs/content/api/install-webgpu.mdx b/apps/docs/content/api/install-webgpu.mdx index 7fc323bfc..30c9fe29b 100644 --- a/apps/docs/content/api/install-webgpu.mdx +++ b/apps/docs/content/api/install-webgpu.mdx @@ -1,10 +1,10 @@ --- title: installWebGPU -description: Install WebGPU flag constants on a worklet runtime. +description: Install navigator.gpu and the WebGPU flag constants on a worklet runtime. --- -On a worklet runtime, the WebGPU constants are not available by default. -Call `installWebGPU()` once at the top of a worklet to install the needed globals for that runtime. +On a worklet runtime, neither `navigator.gpu` nor the WebGPU flag constants are available by default. +Call `installWebGPU()` once at the top of a worklet to install the needed globals for that runtime: `navigator.gpu` plus `GPUBufferUsage`, `GPUTextureUsage`, `GPUShaderStage`, `GPUColorWrite`, and `GPUMapMode`. On the main JS thread these are already installed when the native module loads; calling `installWebGPU()` there is a safe no-op. @@ -72,4 +72,30 @@ const gpuWork = (device: GPUDevice) => { }; runOnRuntime(runtime, gpuWork)(device); -``` \ No newline at end of file +``` + +### navigator.gpu on a worklet runtime + +After `installWebGPU()`, a worklet can request its own adapter and device instead of receiving them from the main thread. The returned promises settle on the calling runtime. + +```tsx twoslash +import { installWebGPU } from "react-native-webgpu"; +import { runOnUI } from "react-native-worklets"; + +runOnUI(() => { + "worklet"; + installWebGPU(); + globalThis.navigator.gpu.requestAdapter().then((adapter) => { + // … + }); +})(); +``` + +## Known limitations + +* `globalThis.navigator` instead of `navigator`: inside a worklet, read `navigator` through `globalThis.navigator`. The Worklets babel plugin does not currently treat a bare `navigator` as a known global, so without the prefix it captures the main runtime's `navigator` object by closure instead of reading the one installed on the worklet runtime. This is fixed upstream ([software-mansion/react-native-reanimated#10364](https://github.com/software-mansion/react-native-reanimated/pull/10364)); once you are on a version of `react-native-worklets` that includes it, a bare `navigator` works and the prefix is no longer needed. +* `device.lost` and `uncapturederror` are main-thread only: spontaneous device events are only delivered for devices created on the main JS runtime: + - `device.lost` read on a worklet runtime returns a promise that never settles, unless the device is already lost at that point, in which case it resolves normally. + - `uncapturederror` listeners registered on a device created on a worklet runtime never fire. + + If you need to observe device loss or uncaptured errors, create the device on the main JS thread, attach the handlers there, and pass the device into the worklet. \ No newline at end of file diff --git a/apps/docs/content/docs/integrations/worklets.mdx b/apps/docs/content/docs/integrations/worklets.mdx index 8cf88c4f3..e7114bd97 100644 --- a/apps/docs/content/docs/integrations/worklets.mdx +++ b/apps/docs/content/docs/integrations/worklets.mdx @@ -18,7 +18,7 @@ Follow the Worklets installation guide for the babel plugin and native setup. We ## installWebGPU -Worklet runtimes start without WebGPU flag globals (`GPUBufferUsage`, `GPUTextureUsage`, etc.). Call [`installWebGPU()`](/api/install-webgpu) once at the top of a worklet: +Worklet runtimes start without the WebGPU globals (`navigator.gpu`, `GPUBufferUsage`, `GPUTextureUsage`, etc.). Call [`installWebGPU()`](/api/install-webgpu) once at the top of a worklet to install all of them for that runtime: ```tsx twoslash import type { RNCanvasContext, CanvasRef } from "react-native-webgpu"; diff --git a/apps/docs/next-env.d.ts b/apps/docs/next-env.d.ts index 9edff1c7c..c4b7818fb 100644 --- a/apps/docs/next-env.d.ts +++ b/apps/docs/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/example/src/Diagnostics/WorkletRequestAdapter.tsx b/apps/example/src/Diagnostics/WorkletRequestAdapter.tsx index 3ba989544..fb426a396 100644 --- a/apps/example/src/Diagnostics/WorkletRequestAdapter.tsx +++ b/apps/example/src/Diagnostics/WorkletRequestAdapter.tsx @@ -1,5 +1,6 @@ import React, { useState } from "react"; import { Button, StyleSheet, Text, View } from "react-native"; +import { installWebGPU } from "react-native-webgpu"; import { runOnUI, scheduleOnRN } from "react-native-worklets"; // Repro for a crash when the first WebGPU call happens on a worklet runtime @@ -43,6 +44,24 @@ export const WorkletRequestAdapter = () => { })(); }; + const workletNavigator = () => { + // No WebGPU object crosses explicitly here: installWebGPU() carries the + // GPU instance in its own closure and installs it as navigator.gpu on the + // calling runtime (globalThis. prefix required, see install.ts). + runOnUI(() => { + "worklet"; + installWebGPU(); + globalThis.navigator.gpu.requestAdapter().then((adapter) => { + scheduleOnRN( + append, + `UI (worklet) runtime: installWebGPU() + navigator.gpu -> ${ + adapter ? "GPUAdapter" : "null" + }`, + ); + }); + })(); + }; + return (