react-native-effects 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -13
- package/lib/module/components/ShaderView/index.js +122 -27
- package/lib/module/components/ShaderView/index.js.map +1 -1
- package/lib/module/components/ShaderViewWithPanGesture/index.js +196 -0
- package/lib/module/components/ShaderViewWithPanGesture/index.js.map +1 -0
- package/lib/module/hooks/useParamsSynchronizable.js +37 -0
- package/lib/module/hooks/useParamsSynchronizable.js.map +1 -0
- package/lib/module/hooks/useWGPUSetup.js +62 -13
- package/lib/module/hooks/useWGPUSetup.js.map +1 -1
- package/lib/module/index.js +3 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/shaders/uniforms.js +4 -3
- package/lib/module/shaders/uniforms.js.map +1 -1
- package/lib/module/utils/gpuDevice.js +38 -0
- package/lib/module/utils/gpuDevice.js.map +1 -0
- package/lib/typescript/src/components/Aurora.d.ts +1 -1
- package/lib/typescript/src/components/Aurora.d.ts.map +1 -1
- package/lib/typescript/src/components/CalicoSwirl.d.ts +1 -1
- package/lib/typescript/src/components/CalicoSwirl.d.ts.map +1 -1
- package/lib/typescript/src/components/Campfire.d.ts +1 -1
- package/lib/typescript/src/components/Campfire.d.ts.map +1 -1
- package/lib/typescript/src/components/CircularGradient.d.ts +1 -1
- package/lib/typescript/src/components/CircularGradient.d.ts.map +1 -1
- package/lib/typescript/src/components/Iridescence.d.ts +1 -1
- package/lib/typescript/src/components/Iridescence.d.ts.map +1 -1
- package/lib/typescript/src/components/LinearGradient.d.ts +1 -1
- package/lib/typescript/src/components/LinearGradient.d.ts.map +1 -1
- package/lib/typescript/src/components/LiquidChrome.d.ts +1 -1
- package/lib/typescript/src/components/LiquidChrome.d.ts.map +1 -1
- package/lib/typescript/src/components/ShaderView/index.d.ts +1 -1
- package/lib/typescript/src/components/ShaderView/index.d.ts.map +1 -1
- package/lib/typescript/src/components/ShaderView/types.d.ts +20 -0
- package/lib/typescript/src/components/ShaderView/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ShaderViewWithPanGesture/index.d.ts +35 -0
- package/lib/typescript/src/components/ShaderViewWithPanGesture/index.d.ts.map +1 -0
- package/lib/typescript/src/components/Silk.d.ts +1 -1
- package/lib/typescript/src/components/Silk.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useParamsSynchronizable.d.ts +22 -0
- package/lib/typescript/src/hooks/useParamsSynchronizable.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useWGPUSetup.d.ts +5 -2
- package/lib/typescript/src/hooks/useWGPUSetup.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +6 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/shaders/uniforms.d.ts +3 -3
- package/lib/typescript/src/shaders/uniforms.d.ts.map +1 -1
- package/lib/typescript/src/utils/gpuDevice.d.ts +13 -0
- package/lib/typescript/src/utils/gpuDevice.d.ts.map +1 -0
- package/package.json +31 -30
- package/src/components/ShaderView/index.tsx +140 -32
- package/src/components/ShaderView/types.ts +21 -0
- package/src/components/ShaderViewWithPanGesture/index.tsx +225 -0
- package/src/hooks/useParamsSynchronizable.ts +52 -0
- package/src/hooks/useWGPUSetup.tsx +69 -21
- package/src/index.tsx +10 -1
- package/src/shaders/uniforms.ts +4 -3
- package/src/utils/gpuDevice.ts +38 -0
- package/lib/module/utils/initWebGPU.js +0 -40
- package/lib/module/utils/initWebGPU.js.map +0 -1
- package/lib/typescript/src/utils/initWebGPU.d.ts +0 -23
- package/lib/typescript/src/utils/initWebGPU.d.ts.map +0 -1
- package/src/utils/initWebGPU.ts +0 -47
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { PixelRatio } from 'react-native';
|
|
1
|
+
import { PixelRatio, type LayoutChangeEvent } from 'react-native';
|
|
2
2
|
import {
|
|
3
3
|
useCanvasRef,
|
|
4
4
|
type CanvasRef,
|
|
5
5
|
type RNCanvasContext,
|
|
6
|
-
} from 'react-native-
|
|
7
|
-
import { useEffect, useState } from 'react';
|
|
8
|
-
import type
|
|
9
|
-
import { initWebGPU } from '../utils/initWebGPU';
|
|
6
|
+
} from 'react-native-webgpu';
|
|
7
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
8
|
+
import { type WorkletRuntime } from 'react-native-worklets';
|
|
10
9
|
import { BackgroundRuntime } from '../utils/backgroundRuntime';
|
|
10
|
+
import { getSharedGPUDevice } from '../utils/gpuDevice';
|
|
11
11
|
|
|
12
12
|
type GPUResources = {
|
|
13
13
|
device: GPUDevice;
|
|
@@ -15,10 +15,17 @@ type GPUResources = {
|
|
|
15
15
|
presentationFormat: GPUTextureFormat;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
type CanvasWithSize = RNCanvasContext['canvas'] & {
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
};
|
|
22
|
+
|
|
18
23
|
type WGPUSetupResult = {
|
|
19
24
|
canvasRef: React.RefObject<CanvasRef>;
|
|
20
25
|
runtime: WorkletRuntime;
|
|
21
26
|
resources: GPUResources | null;
|
|
27
|
+
/** Wire to `<Canvas onLayout>` so the surface resizes on rotation/layout change. */
|
|
28
|
+
onCanvasLayout: (event: LayoutChangeEvent) => void;
|
|
22
29
|
};
|
|
23
30
|
|
|
24
31
|
export function useWGPUSetup(): WGPUSetupResult {
|
|
@@ -26,28 +33,31 @@ export function useWGPUSetup(): WGPUSetupResult {
|
|
|
26
33
|
const [resources, setResources] = useState<GPUResources | null>(null);
|
|
27
34
|
const runtime = BackgroundRuntime;
|
|
28
35
|
|
|
36
|
+
// Physical-pixel size the surface is currently configured for. Used to drive
|
|
37
|
+
// resize (and to skip redundant reconfigures when the layout pass reports the
|
|
38
|
+
// same size).
|
|
39
|
+
const configuredSizeRef = useRef<{ width: number; height: number } | null>(
|
|
40
|
+
null
|
|
41
|
+
);
|
|
42
|
+
|
|
29
43
|
useEffect(() => {
|
|
30
44
|
let cancelled = false;
|
|
31
45
|
|
|
32
46
|
(async () => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const device = await adapter.requestDevice();
|
|
39
|
-
if (cancelled) {
|
|
47
|
+
// Shared across every ShaderView — see getSharedGPUDevice. Returns null if
|
|
48
|
+
// no adapter is available.
|
|
49
|
+
const device = await getSharedGPUDevice();
|
|
50
|
+
if (!device || cancelled) {
|
|
40
51
|
return;
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
const context = canvasRef.current!.getContext('webgpu')!;
|
|
44
|
-
const canvas = context.canvas as
|
|
45
|
-
width: number;
|
|
46
|
-
height: number;
|
|
47
|
-
};
|
|
55
|
+
const canvas = context.canvas as CanvasWithSize;
|
|
48
56
|
const dpr = PixelRatio.get();
|
|
49
|
-
|
|
50
|
-
|
|
57
|
+
const width = Math.max(1, Math.round(canvas.width * dpr));
|
|
58
|
+
const height = Math.max(1, Math.round(canvas.height * dpr));
|
|
59
|
+
canvas.width = width;
|
|
60
|
+
canvas.height = height;
|
|
51
61
|
|
|
52
62
|
const presentationFormat = navigator.gpu.getPreferredCanvasFormat();
|
|
53
63
|
context.configure({
|
|
@@ -55,8 +65,7 @@ export function useWGPUSetup(): WGPUSetupResult {
|
|
|
55
65
|
format: presentationFormat,
|
|
56
66
|
alphaMode: 'premultiplied',
|
|
57
67
|
});
|
|
58
|
-
|
|
59
|
-
initWebGPU(runtime);
|
|
68
|
+
configuredSizeRef.current = { width, height };
|
|
60
69
|
|
|
61
70
|
if (!cancelled) {
|
|
62
71
|
setResources({ device, context, presentationFormat });
|
|
@@ -65,9 +74,48 @@ export function useWGPUSetup(): WGPUSetupResult {
|
|
|
65
74
|
|
|
66
75
|
return () => {
|
|
67
76
|
cancelled = true;
|
|
77
|
+
// The device is shared across all ShaderViews and lives for the JS
|
|
78
|
+
// runtime's lifetime, so it must NOT be destroyed here. This view's own
|
|
79
|
+
// GPU resources (the uniform buffer) are torn down by the render loop when
|
|
80
|
+
// it stops; the pipeline/shader modules are released once the loop's
|
|
81
|
+
// worklet closure is garbage-collected.
|
|
68
82
|
};
|
|
69
83
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
70
84
|
}, []);
|
|
71
85
|
|
|
72
|
-
|
|
86
|
+
// Resize the drawing buffer and reconfigure the surface whenever the view's
|
|
87
|
+
// layout changes (most notably device rotation). Without this the buffer keeps
|
|
88
|
+
// its original dimensions and the shader renders stretched / wrong-aspect. The
|
|
89
|
+
// render loop reads `canvas.width/height` each frame, so the resolution uniform
|
|
90
|
+
// picks up the new size on the next frame. No-op until GPU resources are ready
|
|
91
|
+
// (initial sizing is handled by the setup effect above).
|
|
92
|
+
const onCanvasLayout = useCallback(
|
|
93
|
+
(event: LayoutChangeEvent) => {
|
|
94
|
+
if (!resources) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const { width, height } = event.nativeEvent.layout;
|
|
98
|
+
const dpr = PixelRatio.get();
|
|
99
|
+
const w = Math.max(1, Math.round(width * dpr));
|
|
100
|
+
const h = Math.max(1, Math.round(height * dpr));
|
|
101
|
+
|
|
102
|
+
const prev = configuredSizeRef.current;
|
|
103
|
+
if (prev && prev.width === w && prev.height === h) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const canvas = resources.context.canvas as CanvasWithSize;
|
|
108
|
+
canvas.width = w;
|
|
109
|
+
canvas.height = h;
|
|
110
|
+
resources.context.configure({
|
|
111
|
+
device: resources.device,
|
|
112
|
+
format: resources.presentationFormat,
|
|
113
|
+
alphaMode: 'premultiplied',
|
|
114
|
+
});
|
|
115
|
+
configuredSizeRef.current = { width: w, height: h };
|
|
116
|
+
},
|
|
117
|
+
[resources]
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
return { canvasRef, runtime, resources, onCanvasLayout };
|
|
73
121
|
}
|
package/src/index.tsx
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
import CircularGradient from './components/CircularGradient';
|
|
2
2
|
import LinearGradient from './components/LinearGradient';
|
|
3
3
|
import ShaderView from './components/ShaderView';
|
|
4
|
+
import ShaderViewWithPanGesture from './components/ShaderViewWithPanGesture';
|
|
4
5
|
import Iridescence from './components/Iridescence';
|
|
5
6
|
import LiquidChrome from './components/LiquidChrome';
|
|
6
7
|
import Silk from './components/Silk';
|
|
7
8
|
import Campfire from './components/Campfire';
|
|
8
9
|
import CalicoSwirl from './components/CalicoSwirl';
|
|
9
10
|
import Aurora from './components/Aurora';
|
|
11
|
+
import { useParamsSynchronizable } from './hooks/useParamsSynchronizable';
|
|
10
12
|
|
|
11
|
-
export type {
|
|
13
|
+
export type {
|
|
14
|
+
ShaderViewProps,
|
|
15
|
+
ParamsSynchronizable,
|
|
16
|
+
} from './components/ShaderView/types';
|
|
17
|
+
export type { ShaderViewWithPanGestureProps } from './components/ShaderViewWithPanGesture';
|
|
18
|
+
export type { ColorInput } from './utils/colors';
|
|
12
19
|
|
|
13
20
|
export {
|
|
14
21
|
CircularGradient,
|
|
15
22
|
LinearGradient,
|
|
16
23
|
ShaderView,
|
|
24
|
+
ShaderViewWithPanGesture,
|
|
17
25
|
Iridescence,
|
|
18
26
|
LiquidChrome,
|
|
19
27
|
Silk,
|
|
20
28
|
Campfire,
|
|
21
29
|
CalicoSwirl,
|
|
22
30
|
Aurora,
|
|
31
|
+
useParamsSynchronizable,
|
|
23
32
|
};
|
package/src/shaders/uniforms.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
export const UNIFORM_BUFFER_SIZE =
|
|
1
|
+
/** 112 bytes = 7 × vec4<f32> */
|
|
2
|
+
export const UNIFORM_BUFFER_SIZE = 112;
|
|
3
3
|
|
|
4
4
|
/** Number of float32 values in the uniform buffer */
|
|
5
|
-
export const UNIFORM_FLOAT_COUNT = UNIFORM_BUFFER_SIZE / 4; //
|
|
5
|
+
export const UNIFORM_FLOAT_COUNT = UNIFORM_BUFFER_SIZE / 4; // 28
|
|
6
6
|
|
|
7
7
|
export const UNIFORMS_WGSL = /* wgsl */ `
|
|
8
8
|
struct Uniforms {
|
|
@@ -12,6 +12,7 @@ struct Uniforms {
|
|
|
12
12
|
color1: vec4<f32>, // colors[1] RGBA
|
|
13
13
|
params0: vec4<f32>, // params[0..3]
|
|
14
14
|
params1: vec4<f32>, // params[4..7]
|
|
15
|
+
live: vec4<f32>, // paramsSynchronizable (touch/scroll/audio); (0,0,0,0) when unused
|
|
15
16
|
};
|
|
16
17
|
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
17
18
|
`;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
let devicePromise: Promise<GPUDevice | null> | null = null;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Lazily requests a single GPUDevice shared by every ShaderView.
|
|
5
|
+
*
|
|
6
|
+
* Requesting an adapter + device per view is expensive (real GPU/memory cost and
|
|
7
|
+
* slower init), and a screen that mounts several effects would otherwise spin up
|
|
8
|
+
* N devices on the one background runtime. The promise is cached for the lifetime
|
|
9
|
+
* of the JS runtime so every view awaits the same device.
|
|
10
|
+
*
|
|
11
|
+
* If the device is ever lost, the cache is cleared so the next ShaderView mount
|
|
12
|
+
* requests a fresh one instead of awaiting a dead device forever.
|
|
13
|
+
*/
|
|
14
|
+
export function getSharedGPUDevice(): Promise<GPUDevice | null> {
|
|
15
|
+
if (devicePromise) {
|
|
16
|
+
return devicePromise;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const promise = (async () => {
|
|
20
|
+
const adapter = await navigator.gpu.requestAdapter();
|
|
21
|
+
if (!adapter) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const device = await adapter.requestDevice();
|
|
26
|
+
device.lost?.then(() => {
|
|
27
|
+
// Only clear if we're still the cached promise, so we don't clobber a
|
|
28
|
+
// newer device that a later mount may already have requested.
|
|
29
|
+
if (devicePromise === promise) {
|
|
30
|
+
devicePromise = null;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return device;
|
|
34
|
+
})();
|
|
35
|
+
|
|
36
|
+
devicePromise = promise;
|
|
37
|
+
return promise;
|
|
38
|
+
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { scheduleOnRuntime } from 'react-native-worklets';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Installs WebGPU globals on the given worklet runtime.
|
|
7
|
-
*
|
|
8
|
-
* Worklet runtimes run on a separate JS context that lacks browser-like globals.
|
|
9
|
-
* This function captures WebGPU constants and `navigator.gpu` from the RN thread
|
|
10
|
-
* and injects them into the worklet's `globalThis` so that WebGPU code can run
|
|
11
|
-
* as if it were in a browser environment.
|
|
12
|
-
*
|
|
13
|
-
* @param runtime - The worklet runtime to initialize
|
|
14
|
-
*/
|
|
15
|
-
export function initWebGPU(runtime) {
|
|
16
|
-
const navigator = globalThis.navigator;
|
|
17
|
-
const GPUBufferUsage = globalThis.GPUBufferUsage;
|
|
18
|
-
const GPUColorWrite = globalThis.GPUColorWrite;
|
|
19
|
-
const GPUMapMode = globalThis.GPUMapMode;
|
|
20
|
-
const GPUShaderStage = globalThis.GPUShaderStage;
|
|
21
|
-
const GPUTextureUsage = globalThis.GPUTextureUsage;
|
|
22
|
-
scheduleOnRuntime(runtime, () => {
|
|
23
|
-
'worklet';
|
|
24
|
-
|
|
25
|
-
if (globalThis.self) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
globalThis.self = globalThis;
|
|
29
|
-
globalThis.navigator = {
|
|
30
|
-
gpu: navigator.gpu
|
|
31
|
-
};
|
|
32
|
-
globalThis.GPUBufferUsage = GPUBufferUsage;
|
|
33
|
-
globalThis.GPUColorWrite = GPUColorWrite;
|
|
34
|
-
globalThis.GPUMapMode = GPUMapMode;
|
|
35
|
-
globalThis.GPUShaderStage = GPUShaderStage;
|
|
36
|
-
globalThis.GPUTextureUsage = GPUTextureUsage;
|
|
37
|
-
globalThis.setImmediate = globalThis.requestAnimationFrame;
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
//# sourceMappingURL=initWebGPU.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["scheduleOnRuntime","initWebGPU","runtime","navigator","globalThis","GPUBufferUsage","GPUColorWrite","GPUMapMode","GPUShaderStage","GPUTextureUsage","self","gpu","setImmediate","requestAnimationFrame"],"sourceRoot":"../../../src","sources":["utils/initWebGPU.ts"],"mappings":";;AAAA,SAASA,iBAAiB,QAA6B,uBAAuB;;AAE9E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CAACC,OAAuB,EAAE;EAClD,MAAMC,SAAS,GAAGC,UAAU,CAACD,SAAyB;EACtD,MAAME,cAAc,GAAGD,UAAU,CAACC,cAAc;EAChD,MAAMC,aAAa,GAAGF,UAAU,CAACE,aAAa;EAC9C,MAAMC,UAAU,GAAGH,UAAU,CAACG,UAAU;EACxC,MAAMC,cAAc,GAAGJ,UAAU,CAACI,cAAc;EAChD,MAAMC,eAAe,GAAGL,UAAU,CAACK,eAAe;EAElDT,iBAAiB,CAACE,OAAO,EAAE,MAAM;IAC/B,SAAS;;IAET,IAAIE,UAAU,CAACM,IAAI,EAAE;MACnB;IACF;IACAN,UAAU,CAACM,IAAI,GAAGN,UAAU;IAC5BA,UAAU,CAACD,SAAS,GAAG;MAAEQ,GAAG,EAAER,SAAS,CAACQ;IAAI,CAAyB;IACrEP,UAAU,CAACC,cAAc,GAAGA,cAAc;IAC1CD,UAAU,CAACE,aAAa,GAAGA,aAAa;IACxCF,UAAU,CAACG,UAAU,GAAGA,UAAU;IAClCH,UAAU,CAACI,cAAc,GAAGA,cAAc;IAC1CJ,UAAU,CAACK,eAAe,GAAGA,eAAe;IAC5CL,UAAU,CAACQ,YAAY,GACrBR,UAAU,CAACS,qBAA4C;EAC3D,CAAC,CAAC;AACJ","ignoreList":[]}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { type WorkletRuntime } from 'react-native-worklets';
|
|
2
|
-
/**
|
|
3
|
-
* Installs WebGPU globals on the given worklet runtime.
|
|
4
|
-
*
|
|
5
|
-
* Worklet runtimes run on a separate JS context that lacks browser-like globals.
|
|
6
|
-
* This function captures WebGPU constants and `navigator.gpu` from the RN thread
|
|
7
|
-
* and injects them into the worklet's `globalThis` so that WebGPU code can run
|
|
8
|
-
* as if it were in a browser environment.
|
|
9
|
-
*
|
|
10
|
-
* @param runtime - The worklet runtime to initialize
|
|
11
|
-
*/
|
|
12
|
-
export declare function initWebGPU(runtime: WorkletRuntime): void;
|
|
13
|
-
declare global {
|
|
14
|
-
var self: typeof globalThis;
|
|
15
|
-
var _WORKLET: boolean | undefined;
|
|
16
|
-
var performance: {
|
|
17
|
-
now(): number;
|
|
18
|
-
};
|
|
19
|
-
interface Navigator {
|
|
20
|
-
gpu: GPU;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=initWebGPU.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"initWebGPU.d.ts","sourceRoot":"","sources":["../../../../src/utils/initWebGPU.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE/E;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,cAAc,QAwBjD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,IAAI,EAAE,OAAO,UAAU,CAAC;IAC5B,IAAI,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,IAAI,WAAW,EAAE;QAAE,GAAG,IAAI,MAAM,CAAA;KAAE,CAAC;IAEnC,UAAU,SAAS;QACjB,GAAG,EAAE,GAAG,CAAC;KACV;CACF"}
|
package/src/utils/initWebGPU.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { scheduleOnRuntime, type WorkletRuntime } from 'react-native-worklets';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Installs WebGPU globals on the given worklet runtime.
|
|
5
|
-
*
|
|
6
|
-
* Worklet runtimes run on a separate JS context that lacks browser-like globals.
|
|
7
|
-
* This function captures WebGPU constants and `navigator.gpu` from the RN thread
|
|
8
|
-
* and injects them into the worklet's `globalThis` so that WebGPU code can run
|
|
9
|
-
* as if it were in a browser environment.
|
|
10
|
-
*
|
|
11
|
-
* @param runtime - The worklet runtime to initialize
|
|
12
|
-
*/
|
|
13
|
-
export function initWebGPU(runtime: WorkletRuntime) {
|
|
14
|
-
const navigator = globalThis.navigator as NavigatorGPU;
|
|
15
|
-
const GPUBufferUsage = globalThis.GPUBufferUsage;
|
|
16
|
-
const GPUColorWrite = globalThis.GPUColorWrite;
|
|
17
|
-
const GPUMapMode = globalThis.GPUMapMode;
|
|
18
|
-
const GPUShaderStage = globalThis.GPUShaderStage;
|
|
19
|
-
const GPUTextureUsage = globalThis.GPUTextureUsage;
|
|
20
|
-
|
|
21
|
-
scheduleOnRuntime(runtime, () => {
|
|
22
|
-
'worklet';
|
|
23
|
-
|
|
24
|
-
if (globalThis.self) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
globalThis.self = globalThis;
|
|
28
|
-
globalThis.navigator = { gpu: navigator.gpu } as unknown as Navigator;
|
|
29
|
-
globalThis.GPUBufferUsage = GPUBufferUsage;
|
|
30
|
-
globalThis.GPUColorWrite = GPUColorWrite;
|
|
31
|
-
globalThis.GPUMapMode = GPUMapMode;
|
|
32
|
-
globalThis.GPUShaderStage = GPUShaderStage;
|
|
33
|
-
globalThis.GPUTextureUsage = GPUTextureUsage;
|
|
34
|
-
globalThis.setImmediate =
|
|
35
|
-
globalThis.requestAnimationFrame as typeof setImmediate;
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
declare global {
|
|
40
|
-
var self: typeof globalThis;
|
|
41
|
-
var _WORKLET: boolean | undefined;
|
|
42
|
-
var performance: { now(): number };
|
|
43
|
-
|
|
44
|
-
interface Navigator {
|
|
45
|
-
gpu: GPU;
|
|
46
|
-
}
|
|
47
|
-
}
|