@motion-core/motion-gpu 0.4.1 → 0.5.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.
Files changed (228) hide show
  1. package/README.md +99 -0
  2. package/dist/advanced.d.ts +1 -0
  3. package/dist/advanced.d.ts.map +1 -0
  4. package/dist/advanced.js +14 -6
  5. package/dist/core/advanced.d.ts +1 -0
  6. package/dist/core/advanced.d.ts.map +1 -0
  7. package/dist/core/advanced.js +14 -5
  8. package/dist/core/compute-shader.d.ts +87 -0
  9. package/dist/core/compute-shader.d.ts.map +1 -0
  10. package/dist/core/compute-shader.js +205 -0
  11. package/dist/core/compute-shader.js.map +1 -0
  12. package/dist/core/current-value.d.ts +1 -0
  13. package/dist/core/current-value.d.ts.map +1 -0
  14. package/dist/core/current-value.js +35 -34
  15. package/dist/core/current-value.js.map +1 -0
  16. package/dist/core/error-diagnostics.d.ts +1 -0
  17. package/dist/core/error-diagnostics.d.ts.map +1 -0
  18. package/dist/core/error-diagnostics.js +70 -137
  19. package/dist/core/error-diagnostics.js.map +1 -0
  20. package/dist/core/error-report.d.ts +2 -1
  21. package/dist/core/error-report.d.ts.map +1 -0
  22. package/dist/core/error-report.js +247 -233
  23. package/dist/core/error-report.js.map +1 -0
  24. package/dist/core/frame-registry.d.ts +1 -0
  25. package/dist/core/frame-registry.d.ts.map +1 -0
  26. package/dist/core/frame-registry.js +546 -662
  27. package/dist/core/frame-registry.js.map +1 -0
  28. package/dist/core/index.d.ts +6 -2
  29. package/dist/core/index.d.ts.map +1 -0
  30. package/dist/core/index.js +13 -12
  31. package/dist/core/material-preprocess.d.ts +1 -0
  32. package/dist/core/material-preprocess.d.ts.map +1 -0
  33. package/dist/core/material-preprocess.js +131 -152
  34. package/dist/core/material-preprocess.js.map +1 -0
  35. package/dist/core/material.d.ts +23 -6
  36. package/dist/core/material.d.ts.map +1 -0
  37. package/dist/core/material.js +290 -317
  38. package/dist/core/material.js.map +1 -0
  39. package/dist/core/recompile-policy.d.ts +1 -0
  40. package/dist/core/recompile-policy.d.ts.map +1 -0
  41. package/dist/core/recompile-policy.js +18 -13
  42. package/dist/core/recompile-policy.js.map +1 -0
  43. package/dist/core/render-graph.d.ts +8 -3
  44. package/dist/core/render-graph.d.ts.map +1 -0
  45. package/dist/core/render-graph.js +77 -68
  46. package/dist/core/render-graph.js.map +1 -0
  47. package/dist/core/render-targets.d.ts +1 -0
  48. package/dist/core/render-targets.d.ts.map +1 -0
  49. package/dist/core/render-targets.js +52 -53
  50. package/dist/core/render-targets.js.map +1 -0
  51. package/dist/core/renderer.d.ts +1 -0
  52. package/dist/core/renderer.d.ts.map +1 -0
  53. package/dist/core/renderer.js +1337 -1081
  54. package/dist/core/renderer.js.map +1 -0
  55. package/dist/core/runtime-loop.d.ts +3 -2
  56. package/dist/core/runtime-loop.d.ts.map +1 -0
  57. package/dist/core/runtime-loop.js +353 -362
  58. package/dist/core/runtime-loop.js.map +1 -0
  59. package/dist/core/scheduler-helpers.d.ts +1 -0
  60. package/dist/core/scheduler-helpers.d.ts.map +1 -0
  61. package/dist/core/scheduler-helpers.js +52 -51
  62. package/dist/core/scheduler-helpers.js.map +1 -0
  63. package/dist/core/shader.d.ts +10 -1
  64. package/dist/core/shader.d.ts.map +1 -0
  65. package/dist/core/shader.js +109 -115
  66. package/dist/core/shader.js.map +1 -0
  67. package/dist/core/storage-buffers.d.ts +37 -0
  68. package/dist/core/storage-buffers.d.ts.map +1 -0
  69. package/dist/core/storage-buffers.js +95 -0
  70. package/dist/core/storage-buffers.js.map +1 -0
  71. package/dist/core/texture-loader.d.ts +1 -0
  72. package/dist/core/texture-loader.d.ts.map +1 -0
  73. package/dist/core/texture-loader.js +209 -273
  74. package/dist/core/texture-loader.js.map +1 -0
  75. package/dist/core/textures.d.ts +13 -0
  76. package/dist/core/textures.d.ts.map +1 -0
  77. package/dist/core/textures.js +111 -116
  78. package/dist/core/textures.js.map +1 -0
  79. package/dist/core/types.d.ts +147 -4
  80. package/dist/core/types.d.ts.map +1 -0
  81. package/dist/core/types.js +0 -4
  82. package/dist/core/uniforms.d.ts +1 -0
  83. package/dist/core/uniforms.d.ts.map +1 -0
  84. package/dist/core/uniforms.js +170 -191
  85. package/dist/core/uniforms.js.map +1 -0
  86. package/dist/index.d.ts +1 -0
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +13 -6
  89. package/dist/passes/BlitPass.d.ts +1 -0
  90. package/dist/passes/BlitPass.d.ts.map +1 -0
  91. package/dist/passes/BlitPass.js +23 -18
  92. package/dist/passes/BlitPass.js.map +1 -0
  93. package/dist/passes/ComputePass.d.ts +83 -0
  94. package/dist/passes/ComputePass.d.ts.map +1 -0
  95. package/dist/passes/ComputePass.js +92 -0
  96. package/dist/passes/ComputePass.js.map +1 -0
  97. package/dist/passes/CopyPass.d.ts +1 -0
  98. package/dist/passes/CopyPass.d.ts.map +1 -0
  99. package/dist/passes/CopyPass.js +58 -52
  100. package/dist/passes/CopyPass.js.map +1 -0
  101. package/dist/passes/FullscreenPass.d.ts +1 -0
  102. package/dist/passes/FullscreenPass.d.ts.map +1 -0
  103. package/dist/passes/FullscreenPass.js +127 -130
  104. package/dist/passes/FullscreenPass.js.map +1 -0
  105. package/dist/passes/PingPongComputePass.d.ts +104 -0
  106. package/dist/passes/PingPongComputePass.d.ts.map +1 -0
  107. package/dist/passes/PingPongComputePass.js +132 -0
  108. package/dist/passes/PingPongComputePass.js.map +1 -0
  109. package/dist/passes/ShaderPass.d.ts +1 -0
  110. package/dist/passes/ShaderPass.d.ts.map +1 -0
  111. package/dist/passes/ShaderPass.js +41 -37
  112. package/dist/passes/ShaderPass.js.map +1 -0
  113. package/dist/passes/index.d.ts +3 -0
  114. package/dist/passes/index.d.ts.map +1 -0
  115. package/dist/passes/index.js +6 -3
  116. package/dist/react/FragCanvas.d.ts +3 -2
  117. package/dist/react/FragCanvas.d.ts.map +1 -0
  118. package/dist/react/FragCanvas.js +234 -211
  119. package/dist/react/FragCanvas.js.map +1 -0
  120. package/dist/react/MotionGPUErrorOverlay.d.ts +1 -0
  121. package/dist/react/MotionGPUErrorOverlay.d.ts.map +1 -0
  122. package/dist/react/MotionGPUErrorOverlay.js +200 -14
  123. package/dist/react/MotionGPUErrorOverlay.js.map +1 -0
  124. package/dist/react/Portal.d.ts +1 -0
  125. package/dist/react/Portal.d.ts.map +1 -0
  126. package/dist/react/Portal.js +18 -21
  127. package/dist/react/Portal.js.map +1 -0
  128. package/dist/react/advanced.d.ts +1 -0
  129. package/dist/react/advanced.d.ts.map +1 -0
  130. package/dist/react/advanced.js +14 -6
  131. package/dist/react/frame-context.d.ts +1 -0
  132. package/dist/react/frame-context.d.ts.map +1 -0
  133. package/dist/react/frame-context.js +88 -94
  134. package/dist/react/frame-context.js.map +1 -0
  135. package/dist/react/index.d.ts +6 -2
  136. package/dist/react/index.d.ts.map +1 -0
  137. package/dist/react/index.js +12 -9
  138. package/dist/react/motiongpu-context.d.ts +1 -0
  139. package/dist/react/motiongpu-context.d.ts.map +1 -0
  140. package/dist/react/motiongpu-context.js +18 -15
  141. package/dist/react/motiongpu-context.js.map +1 -0
  142. package/dist/react/use-motiongpu-user-context.d.ts +1 -0
  143. package/dist/react/use-motiongpu-user-context.d.ts.map +1 -0
  144. package/dist/react/use-motiongpu-user-context.js +83 -82
  145. package/dist/react/use-motiongpu-user-context.js.map +1 -0
  146. package/dist/react/use-texture.d.ts +1 -0
  147. package/dist/react/use-texture.d.ts.map +1 -0
  148. package/dist/react/use-texture.js +132 -152
  149. package/dist/react/use-texture.js.map +1 -0
  150. package/dist/svelte/FragCanvas.svelte +2 -2
  151. package/dist/svelte/FragCanvas.svelte.d.ts +3 -2
  152. package/dist/svelte/FragCanvas.svelte.d.ts.map +1 -0
  153. package/dist/svelte/MotionGPUErrorOverlay.svelte +137 -7
  154. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts +1 -0
  155. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts.map +1 -0
  156. package/dist/svelte/Portal.svelte.d.ts +1 -0
  157. package/dist/svelte/Portal.svelte.d.ts.map +1 -0
  158. package/dist/svelte/advanced.d.ts +1 -0
  159. package/dist/svelte/advanced.d.ts.map +1 -0
  160. package/dist/svelte/advanced.js +13 -6
  161. package/dist/svelte/frame-context.d.ts +1 -0
  162. package/dist/svelte/frame-context.d.ts.map +1 -0
  163. package/dist/svelte/frame-context.js +27 -27
  164. package/dist/svelte/frame-context.js.map +1 -0
  165. package/dist/svelte/index.d.ts +6 -2
  166. package/dist/svelte/index.d.ts.map +1 -0
  167. package/dist/svelte/index.js +12 -9
  168. package/dist/svelte/motiongpu-context.d.ts +1 -0
  169. package/dist/svelte/motiongpu-context.d.ts.map +1 -0
  170. package/dist/svelte/motiongpu-context.js +24 -21
  171. package/dist/svelte/motiongpu-context.js.map +1 -0
  172. package/dist/svelte/use-motiongpu-user-context.d.ts +1 -0
  173. package/dist/svelte/use-motiongpu-user-context.d.ts.map +1 -0
  174. package/dist/svelte/use-motiongpu-user-context.js +69 -70
  175. package/dist/svelte/use-motiongpu-user-context.js.map +1 -0
  176. package/dist/svelte/use-texture.d.ts +1 -0
  177. package/dist/svelte/use-texture.d.ts.map +1 -0
  178. package/dist/svelte/use-texture.js +125 -147
  179. package/dist/svelte/use-texture.js.map +1 -0
  180. package/package.json +12 -7
  181. package/src/lib/advanced.ts +6 -0
  182. package/src/lib/core/advanced.ts +12 -0
  183. package/src/lib/core/compute-shader.ts +326 -0
  184. package/src/lib/core/current-value.ts +64 -0
  185. package/src/lib/core/error-diagnostics.ts +236 -0
  186. package/src/lib/core/error-report.ts +535 -0
  187. package/src/lib/core/frame-registry.ts +1190 -0
  188. package/src/lib/core/index.ts +94 -0
  189. package/src/lib/core/material-preprocess.ts +295 -0
  190. package/src/lib/core/material.ts +748 -0
  191. package/src/lib/core/recompile-policy.ts +31 -0
  192. package/src/lib/core/render-graph.ts +173 -0
  193. package/src/lib/core/render-targets.ts +107 -0
  194. package/src/lib/core/renderer.ts +2161 -0
  195. package/src/lib/core/runtime-loop.ts +537 -0
  196. package/src/lib/core/scheduler-helpers.ts +136 -0
  197. package/src/lib/core/shader.ts +301 -0
  198. package/src/lib/core/storage-buffers.ts +142 -0
  199. package/src/lib/core/texture-loader.ts +482 -0
  200. package/src/lib/core/textures.ts +257 -0
  201. package/src/lib/core/types.ts +743 -0
  202. package/src/lib/core/uniforms.ts +282 -0
  203. package/src/lib/index.ts +6 -0
  204. package/src/lib/passes/BlitPass.ts +54 -0
  205. package/src/lib/passes/ComputePass.ts +136 -0
  206. package/src/lib/passes/CopyPass.ts +80 -0
  207. package/src/lib/passes/FullscreenPass.ts +173 -0
  208. package/src/lib/passes/PingPongComputePass.ts +180 -0
  209. package/src/lib/passes/ShaderPass.ts +89 -0
  210. package/src/lib/passes/index.ts +9 -0
  211. package/src/lib/react/FragCanvas.tsx +345 -0
  212. package/src/lib/react/MotionGPUErrorOverlay.tsx +524 -0
  213. package/src/lib/react/Portal.tsx +34 -0
  214. package/src/lib/react/advanced.ts +36 -0
  215. package/src/lib/react/frame-context.ts +169 -0
  216. package/src/lib/react/index.ts +68 -0
  217. package/src/lib/react/motiongpu-context.ts +88 -0
  218. package/src/lib/react/use-motiongpu-user-context.ts +186 -0
  219. package/src/lib/react/use-texture.ts +233 -0
  220. package/src/lib/svelte/FragCanvas.svelte +249 -0
  221. package/src/lib/svelte/MotionGPUErrorOverlay.svelte +512 -0
  222. package/src/lib/svelte/Portal.svelte +31 -0
  223. package/src/lib/svelte/advanced.ts +32 -0
  224. package/src/lib/svelte/frame-context.ts +87 -0
  225. package/src/lib/svelte/index.ts +68 -0
  226. package/src/lib/svelte/motiongpu-context.ts +97 -0
  227. package/src/lib/svelte/use-motiongpu-user-context.ts +145 -0
  228. package/src/lib/svelte/use-texture.ts +232 -0
@@ -0,0 +1,345 @@
1
+ import { createCurrentWritable as currentWritable } from '../core/current-value.js';
2
+ import { toMotionGPUErrorReport, type MotionGPUErrorReport } from '../core/error-report.js';
3
+ import type { FragMaterial } from '../core/material.js';
4
+ import { createFrameRegistry } from '../core/frame-registry.js';
5
+ import { createMotionGPURuntimeLoop } from '../core/runtime-loop.js';
6
+ import type {
7
+ AnyPass,
8
+ OutputColorSpace,
9
+ RenderMode,
10
+ RenderTargetDefinitionMap
11
+ } from '../core/types.js';
12
+ import { useEffect, useRef, useState, type CSSProperties, type ReactNode } from 'react';
13
+ import { FrameRegistryReactContext } from './frame-context.js';
14
+ import { MotionGPUErrorOverlay } from './MotionGPUErrorOverlay.js';
15
+ import { MotionGPUReactContext, type MotionGPUContext } from './motiongpu-context.js';
16
+
17
+ export interface FragCanvasProps {
18
+ material: FragMaterial;
19
+ renderTargets?: RenderTargetDefinitionMap;
20
+ passes?: AnyPass[];
21
+ clearColor?: [number, number, number, number];
22
+ outputColorSpace?: OutputColorSpace;
23
+ renderMode?: RenderMode;
24
+ autoRender?: boolean;
25
+ maxDelta?: number;
26
+ adapterOptions?: GPURequestAdapterOptions;
27
+ deviceDescriptor?: GPUDeviceDescriptor;
28
+ dpr?: number;
29
+ showErrorOverlay?: boolean;
30
+ errorRenderer?: (report: MotionGPUErrorReport) => ReactNode;
31
+ onError?: (report: MotionGPUErrorReport) => void;
32
+ errorHistoryLimit?: number;
33
+ onErrorHistory?: (history: MotionGPUErrorReport[]) => void;
34
+ className?: string;
35
+ style?: CSSProperties;
36
+ children?: ReactNode;
37
+ }
38
+
39
+ interface RuntimePropsSnapshot {
40
+ material: FragMaterial;
41
+ renderTargets: RenderTargetDefinitionMap;
42
+ passes: AnyPass[];
43
+ clearColor: [number, number, number, number];
44
+ outputColorSpace: OutputColorSpace;
45
+ adapterOptions: GPURequestAdapterOptions | undefined;
46
+ deviceDescriptor: GPUDeviceDescriptor | undefined;
47
+ onError: ((report: MotionGPUErrorReport) => void) | undefined;
48
+ errorHistoryLimit: number;
49
+ onErrorHistory: ((history: MotionGPUErrorReport[]) => void) | undefined;
50
+ }
51
+
52
+ interface FragCanvasRuntimeState {
53
+ registry: ReturnType<typeof createFrameRegistry>;
54
+ context: MotionGPUContext;
55
+ canvasRef: { current: HTMLCanvasElement | undefined };
56
+ size: ReturnType<typeof currentWritable<{ width: number; height: number }>>;
57
+ dprState: ReturnType<typeof currentWritable<number>>;
58
+ maxDeltaState: ReturnType<typeof currentWritable<number>>;
59
+ renderModeState: ReturnType<typeof currentWritable<RenderMode>>;
60
+ autoRenderState: ReturnType<typeof currentWritable<boolean>>;
61
+ requestFrameSignalRef: { current: (() => void) | null };
62
+ requestFrame: () => void;
63
+ invalidateFrame: () => void;
64
+ advanceFrame: () => void;
65
+ }
66
+
67
+ function getInitialDpr(): number {
68
+ if (typeof window === 'undefined') {
69
+ return 1;
70
+ }
71
+
72
+ return window.devicePixelRatio ?? 1;
73
+ }
74
+
75
+ function createRuntimeState(initialDpr: number): FragCanvasRuntimeState {
76
+ const registry = createFrameRegistry({ maxDelta: 0.1 });
77
+ const canvasRef = { current: undefined as HTMLCanvasElement | undefined };
78
+ const requestFrameSignalRef = { current: null as (() => void) | null };
79
+ const requestFrame = (): void => {
80
+ requestFrameSignalRef.current?.();
81
+ };
82
+ const invalidateFrame = (): void => {
83
+ registry.invalidate();
84
+ requestFrame();
85
+ };
86
+ const advanceFrame = (): void => {
87
+ registry.advance();
88
+ requestFrame();
89
+ };
90
+
91
+ const size = currentWritable({ width: 0, height: 0 });
92
+ const dprState = currentWritable(initialDpr, requestFrame);
93
+ const maxDeltaState = currentWritable(0.1, (value) => {
94
+ registry.setMaxDelta(value);
95
+ requestFrame();
96
+ });
97
+ const renderModeState = currentWritable<RenderMode>('always', (value) => {
98
+ registry.setRenderMode(value);
99
+ requestFrame();
100
+ });
101
+ const autoRenderState = currentWritable<boolean>(true, (value) => {
102
+ registry.setAutoRender(value);
103
+ requestFrame();
104
+ });
105
+ const userState = currentWritable<Record<string | symbol, unknown>>({});
106
+
107
+ const context: MotionGPUContext = {
108
+ get canvas() {
109
+ return canvasRef.current;
110
+ },
111
+ size,
112
+ dpr: dprState,
113
+ maxDelta: maxDeltaState,
114
+ renderMode: renderModeState,
115
+ autoRender: autoRenderState,
116
+ user: userState,
117
+ invalidate: invalidateFrame,
118
+ advance: advanceFrame,
119
+ scheduler: {
120
+ createStage: registry.createStage,
121
+ getStage: registry.getStage,
122
+ setDiagnosticsEnabled: registry.setDiagnosticsEnabled,
123
+ getDiagnosticsEnabled: registry.getDiagnosticsEnabled,
124
+ getLastRunTimings: registry.getLastRunTimings,
125
+ getSchedule: registry.getSchedule,
126
+ setProfilingEnabled: registry.setProfilingEnabled,
127
+ setProfilingWindow: registry.setProfilingWindow,
128
+ resetProfiling: registry.resetProfiling,
129
+ getProfilingEnabled: registry.getProfilingEnabled,
130
+ getProfilingWindow: registry.getProfilingWindow,
131
+ getProfilingSnapshot: registry.getProfilingSnapshot
132
+ }
133
+ };
134
+
135
+ return {
136
+ registry,
137
+ context,
138
+ canvasRef,
139
+ size,
140
+ dprState,
141
+ maxDeltaState,
142
+ renderModeState,
143
+ autoRenderState,
144
+ requestFrameSignalRef,
145
+ requestFrame,
146
+ invalidateFrame,
147
+ advanceFrame
148
+ };
149
+ }
150
+
151
+ function getNormalizedErrorHistoryLimit(value: number): number {
152
+ if (!Number.isFinite(value) || value <= 0) {
153
+ return 0;
154
+ }
155
+
156
+ return Math.floor(value);
157
+ }
158
+
159
+ export function FragCanvas({
160
+ material,
161
+ renderTargets = {},
162
+ passes = [],
163
+ clearColor = [0, 0, 0, 1],
164
+ outputColorSpace = 'srgb',
165
+ renderMode = 'always',
166
+ autoRender = true,
167
+ maxDelta = 0.1,
168
+ adapterOptions = undefined,
169
+ deviceDescriptor = undefined,
170
+ dpr = getInitialDpr(),
171
+ showErrorOverlay = true,
172
+ errorRenderer,
173
+ onError = undefined,
174
+ errorHistoryLimit = 0,
175
+ onErrorHistory = undefined,
176
+ className = '',
177
+ style,
178
+ children
179
+ }: FragCanvasProps) {
180
+ const runtimeRef = useRef<FragCanvasRuntimeState | null>(null);
181
+ if (!runtimeRef.current) {
182
+ runtimeRef.current = createRuntimeState(getInitialDpr());
183
+ }
184
+ const runtime = runtimeRef.current;
185
+
186
+ const runtimePropsRef = useRef<RuntimePropsSnapshot>({
187
+ material,
188
+ renderTargets,
189
+ passes,
190
+ clearColor,
191
+ outputColorSpace,
192
+ adapterOptions,
193
+ deviceDescriptor,
194
+ onError,
195
+ errorHistoryLimit,
196
+ onErrorHistory
197
+ });
198
+ runtimePropsRef.current = {
199
+ material,
200
+ renderTargets,
201
+ passes,
202
+ clearColor,
203
+ outputColorSpace,
204
+ adapterOptions,
205
+ deviceDescriptor,
206
+ onError,
207
+ errorHistoryLimit,
208
+ onErrorHistory
209
+ };
210
+
211
+ const [errorReport, setErrorReport] = useState<MotionGPUErrorReport | null>(null);
212
+ const [errorHistory, setErrorHistory] = useState<MotionGPUErrorReport[]>([]);
213
+
214
+ useEffect(() => {
215
+ runtime.renderModeState.set(renderMode);
216
+ }, [renderMode, runtime]);
217
+
218
+ useEffect(() => {
219
+ runtime.autoRenderState.set(autoRender);
220
+ }, [autoRender, runtime]);
221
+
222
+ useEffect(() => {
223
+ runtime.maxDeltaState.set(maxDelta);
224
+ }, [maxDelta, runtime]);
225
+
226
+ useEffect(() => {
227
+ runtime.dprState.set(dpr);
228
+ }, [dpr, runtime]);
229
+
230
+ useEffect(() => {
231
+ const limit = getNormalizedErrorHistoryLimit(errorHistoryLimit);
232
+ if (limit <= 0) {
233
+ if (errorHistory.length === 0) {
234
+ return;
235
+ }
236
+ setErrorHistory([]);
237
+ onErrorHistory?.([]);
238
+ return;
239
+ }
240
+
241
+ if (errorHistory.length <= limit) {
242
+ return;
243
+ }
244
+
245
+ const trimmed = errorHistory.slice(errorHistory.length - limit);
246
+ setErrorHistory(trimmed);
247
+ onErrorHistory?.(trimmed);
248
+ }, [errorHistory, errorHistoryLimit, onErrorHistory]);
249
+
250
+ useEffect(() => {
251
+ const canvas = runtime.canvasRef.current;
252
+ if (!canvas) {
253
+ const report = toMotionGPUErrorReport(
254
+ new Error('Canvas element is not available'),
255
+ 'initialization'
256
+ );
257
+ setErrorReport(report);
258
+ const historyLimit = getNormalizedErrorHistoryLimit(
259
+ runtimePropsRef.current.errorHistoryLimit
260
+ );
261
+ if (historyLimit > 0) {
262
+ const nextHistory = [report].slice(-historyLimit);
263
+ setErrorHistory(nextHistory);
264
+ runtimePropsRef.current.onErrorHistory?.(nextHistory);
265
+ }
266
+ runtimePropsRef.current.onError?.(report);
267
+ return () => {
268
+ runtime.registry.clear();
269
+ };
270
+ }
271
+
272
+ const runtimeLoop = createMotionGPURuntimeLoop({
273
+ canvas,
274
+ registry: runtime.registry,
275
+ size: runtime.size,
276
+ dpr: runtime.dprState,
277
+ maxDelta: runtime.maxDeltaState,
278
+ getMaterial: () => runtimePropsRef.current.material,
279
+ getRenderTargets: () => runtimePropsRef.current.renderTargets,
280
+ getPasses: () => runtimePropsRef.current.passes,
281
+ getClearColor: () => runtimePropsRef.current.clearColor,
282
+ getOutputColorSpace: () => runtimePropsRef.current.outputColorSpace,
283
+ getAdapterOptions: () => runtimePropsRef.current.adapterOptions,
284
+ getDeviceDescriptor: () => runtimePropsRef.current.deviceDescriptor,
285
+ getOnError: () => runtimePropsRef.current.onError,
286
+ getErrorHistoryLimit: () => runtimePropsRef.current.errorHistoryLimit,
287
+ getOnErrorHistory: () => runtimePropsRef.current.onErrorHistory,
288
+ reportErrorHistory: (history) => {
289
+ setErrorHistory(history);
290
+ },
291
+ reportError: (report) => {
292
+ setErrorReport(report);
293
+ }
294
+ });
295
+ runtime.requestFrameSignalRef.current = runtimeLoop.requestFrame;
296
+
297
+ return () => {
298
+ runtime.requestFrameSignalRef.current = null;
299
+ runtimeLoop.destroy();
300
+ };
301
+ }, [runtime]);
302
+
303
+ const canvasStyle: CSSProperties = {
304
+ position: 'absolute',
305
+ inset: 0,
306
+ display: 'block',
307
+ width: '100%',
308
+ height: '100%',
309
+ ...style
310
+ };
311
+
312
+ return (
313
+ <FrameRegistryReactContext.Provider value={runtime.registry}>
314
+ <MotionGPUReactContext.Provider value={runtime.context}>
315
+ <div
316
+ className="motiongpu-canvas-wrap"
317
+ style={{
318
+ position: 'relative',
319
+ width: '100%',
320
+ height: '100%',
321
+ minWidth: 0,
322
+ minHeight: 0,
323
+ overflow: 'hidden'
324
+ }}
325
+ >
326
+ <canvas
327
+ className={className}
328
+ style={canvasStyle}
329
+ ref={(node) => {
330
+ runtime.canvasRef.current = node ?? undefined;
331
+ }}
332
+ />
333
+ {showErrorOverlay && errorReport ? (
334
+ errorRenderer ? (
335
+ errorRenderer(errorReport)
336
+ ) : (
337
+ <MotionGPUErrorOverlay report={errorReport} />
338
+ )
339
+ ) : null}
340
+ {children}
341
+ </div>
342
+ </MotionGPUReactContext.Provider>
343
+ </FrameRegistryReactContext.Provider>
344
+ );
345
+ }