@motion-core/motion-gpu 0.1.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 (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +325 -0
  3. package/dist/FragCanvas.svelte +511 -0
  4. package/dist/FragCanvas.svelte.d.ts +26 -0
  5. package/dist/MotionGPUErrorOverlay.svelte +394 -0
  6. package/dist/MotionGPUErrorOverlay.svelte.d.ts +7 -0
  7. package/dist/Portal.svelte +46 -0
  8. package/dist/Portal.svelte.d.ts +8 -0
  9. package/dist/advanced-scheduler.d.ts +44 -0
  10. package/dist/advanced-scheduler.js +58 -0
  11. package/dist/advanced.d.ts +14 -0
  12. package/dist/advanced.js +9 -0
  13. package/dist/core/error-diagnostics.d.ts +40 -0
  14. package/dist/core/error-diagnostics.js +111 -0
  15. package/dist/core/error-report.d.ts +67 -0
  16. package/dist/core/error-report.js +190 -0
  17. package/dist/core/material-preprocess.d.ts +63 -0
  18. package/dist/core/material-preprocess.js +166 -0
  19. package/dist/core/material.d.ts +157 -0
  20. package/dist/core/material.js +358 -0
  21. package/dist/core/recompile-policy.d.ts +27 -0
  22. package/dist/core/recompile-policy.js +15 -0
  23. package/dist/core/render-graph.d.ts +55 -0
  24. package/dist/core/render-graph.js +73 -0
  25. package/dist/core/render-targets.d.ts +39 -0
  26. package/dist/core/render-targets.js +63 -0
  27. package/dist/core/renderer.d.ts +9 -0
  28. package/dist/core/renderer.js +1097 -0
  29. package/dist/core/shader.d.ts +42 -0
  30. package/dist/core/shader.js +196 -0
  31. package/dist/core/texture-loader.d.ts +129 -0
  32. package/dist/core/texture-loader.js +295 -0
  33. package/dist/core/textures.d.ts +114 -0
  34. package/dist/core/textures.js +136 -0
  35. package/dist/core/types.d.ts +523 -0
  36. package/dist/core/types.js +4 -0
  37. package/dist/core/uniforms.d.ts +48 -0
  38. package/dist/core/uniforms.js +222 -0
  39. package/dist/current-writable.d.ts +31 -0
  40. package/dist/current-writable.js +27 -0
  41. package/dist/frame-context.d.ts +287 -0
  42. package/dist/frame-context.js +731 -0
  43. package/dist/index.d.ts +17 -0
  44. package/dist/index.js +11 -0
  45. package/dist/motiongpu-context.d.ts +77 -0
  46. package/dist/motiongpu-context.js +26 -0
  47. package/dist/passes/BlitPass.d.ts +32 -0
  48. package/dist/passes/BlitPass.js +158 -0
  49. package/dist/passes/CopyPass.d.ts +25 -0
  50. package/dist/passes/CopyPass.js +53 -0
  51. package/dist/passes/ShaderPass.d.ts +40 -0
  52. package/dist/passes/ShaderPass.js +182 -0
  53. package/dist/passes/index.d.ts +3 -0
  54. package/dist/passes/index.js +3 -0
  55. package/dist/use-motiongpu-user-context.d.ts +35 -0
  56. package/dist/use-motiongpu-user-context.js +74 -0
  57. package/dist/use-texture.d.ts +35 -0
  58. package/dist/use-texture.js +147 -0
  59. package/package.json +94 -0
@@ -0,0 +1,394 @@
1
+ <script lang="ts">
2
+ import type { MotionGPUErrorReport } from './core/error-report';
3
+ import Portal from './Portal.svelte';
4
+
5
+ interface Props {
6
+ report: MotionGPUErrorReport;
7
+ }
8
+
9
+ let { report }: Props = $props();
10
+
11
+ const normalizeErrorText = (value: string): string => {
12
+ return value
13
+ .trim()
14
+ .replace(/[.:!]+$/g, '')
15
+ .toLowerCase();
16
+ };
17
+
18
+ const shouldShowErrorMessage = (value: MotionGPUErrorReport): boolean => {
19
+ return normalizeErrorText(value.message) !== normalizeErrorText(value.title);
20
+ };
21
+ </script>
22
+
23
+ <Portal>
24
+ <div class="motiongpu-error-overlay" role="presentation">
25
+ <section
26
+ class="motiongpu-error-dialog"
27
+ role="alertdialog"
28
+ aria-live="assertive"
29
+ aria-modal="true"
30
+ data-testid="motiongpu-error"
31
+ >
32
+ <header class="motiongpu-error-header">
33
+ <div class="motiongpu-error-badge-wrap">
34
+ <p class="motiongpu-error-phase">
35
+ {report.phase}
36
+ </p>
37
+ </div>
38
+ <h2 class="motiongpu-error-title">{report.title}</h2>
39
+ </header>
40
+ <div class="motiongpu-error-body">
41
+ {#if shouldShowErrorMessage(report)}
42
+ <p class="motiongpu-error-message">{report.message}</p>
43
+ {/if}
44
+ <p class="motiongpu-error-hint">{report.hint}</p>
45
+ </div>
46
+
47
+ {#if report.source}
48
+ <section class="motiongpu-error-source" aria-label="Source">
49
+ <h3 class="motiongpu-error-source-title">Source</h3>
50
+ <div class="motiongpu-error-source-frame" role="presentation">
51
+ <div class="motiongpu-error-source-tabs" role="tablist" aria-label="Source files">
52
+ <span
53
+ class="motiongpu-error-source-tab motiongpu-error-source-tab-active"
54
+ role="tab"
55
+ aria-selected="true"
56
+ >{report.source.component} (fragment line {report.source
57
+ .line}{#if report.source.column}, col
58
+ {report.source.column}{/if})</span
59
+ >
60
+ <span class="motiongpu-error-source-tab-spacer" aria-hidden="true"></span>
61
+ </div>
62
+
63
+ <div class="motiongpu-error-source-snippet">
64
+ {#each report.source.snippet as snippetLine (`snippet-${snippetLine.number}`)}
65
+ <div
66
+ class="motiongpu-error-source-row"
67
+ class:motiongpu-error-source-row-active={snippetLine.highlight}
68
+ >
69
+ <span class="motiongpu-error-source-line">{snippetLine.number}</span>
70
+ <span class="motiongpu-error-source-code">{snippetLine.code || ' '}</span>
71
+ </div>
72
+ {/each}
73
+ </div>
74
+ </div>
75
+ </section>
76
+ {/if}
77
+
78
+ <div class="motiongpu-error-sections">
79
+ {#if report.details.length > 0}
80
+ <details class="motiongpu-error-details" open>
81
+ <summary>{report.source ? 'Additional diagnostics' : 'Technical details'}</summary>
82
+ <pre>{report.details.join('\n')}</pre>
83
+ </details>
84
+ {/if}
85
+ {#if report.stack.length > 0}
86
+ <details class="motiongpu-error-details">
87
+ <summary>Stack trace</summary>
88
+ <pre>{report.stack.join('\n')}</pre>
89
+ </details>
90
+ {/if}
91
+ </div>
92
+ </section>
93
+ </div>
94
+ </Portal>
95
+
96
+ <style>
97
+ .motiongpu-error-overlay {
98
+ --motiongpu-color-background: var(--color-background, #ffffff);
99
+ --motiongpu-color-background-muted: var(--color-background-inset, #f6f6f7);
100
+ --motiongpu-color-foreground: var(--color-foreground, #262626);
101
+ --motiongpu-color-foreground-muted: var(--color-foreground-muted, rgba(38, 38, 38, 0.64));
102
+ --motiongpu-color-card: var(--color-background, #ffffff);
103
+ --motiongpu-color-accent: var(--color-accent, #ff6900);
104
+ --motiongpu-color-accent-secondary: var(--color-accent-secondary, #bd4d00);
105
+ --motiongpu-color-border: var(--color-border, rgba(107, 107, 107, 0.2));
106
+ --motiongpu-shadow-card: var(
107
+ --shadow-2xl,
108
+ 0px 1px 1px -0.5px rgba(0, 0, 0, 0.06),
109
+ 0px 3px 3px -1.5px rgba(0, 0, 0, 0.06),
110
+ 0px 6px 6px -3px rgba(0, 0, 0, 0.06),
111
+ 0px 12px 12px -6px rgba(0, 0, 0, 0.06),
112
+ 0px 24px 24px -12px rgba(0, 0, 0, 0.05),
113
+ 0px 48px 48px -24px rgba(0, 0, 0, 0.06)
114
+ );
115
+ --motiongpu-radius-md: var(--radius-md, 0.5rem);
116
+ --motiongpu-radius-lg: var(--radius-lg, 0.75rem);
117
+ --motiongpu-radius-xl: var(--radius-xl, 1rem);
118
+ --motiongpu-font-sans: var(
119
+ --font-sans,
120
+ 'Aeonik Pro',
121
+ 'Inter',
122
+ 'Segoe UI',
123
+ 'Helvetica Neue',
124
+ Arial,
125
+ sans-serif
126
+ );
127
+ --motiongpu-font-mono: var(
128
+ --font-mono,
129
+ 'Aeonik font-mono',
130
+ 'SFMono-Regular',
131
+ 'Menlo',
132
+ 'Consolas',
133
+ monospace
134
+ );
135
+ position: fixed;
136
+ inset: 0;
137
+ display: grid;
138
+ place-items: center;
139
+ padding: clamp(0.75rem, 1.4vw, 1.5rem);
140
+ background:
141
+ radial-gradient(125% 125% at 50% 0%, rgba(255, 105, 0, 0.12) 0%, rgba(255, 105, 0, 0) 56%),
142
+ rgba(12, 12, 14, 0.38);
143
+ backdrop-filter: blur(10px);
144
+ z-index: 2147483647;
145
+ font-family: var(--motiongpu-font-sans);
146
+ }
147
+
148
+ .motiongpu-error-dialog {
149
+ width: min(52rem, calc(100vw - 1.5rem));
150
+ max-height: min(84vh, 44rem);
151
+ overflow: auto;
152
+ margin: 0;
153
+ padding: 1.1rem;
154
+ border: 1px solid var(--motiongpu-color-border);
155
+ border-radius: var(--motiongpu-radius-xl);
156
+ max-width: calc(100vw - 1.5rem);
157
+ box-sizing: border-box;
158
+ font-size: 0.875rem;
159
+ font-weight: 300;
160
+ line-height: 1.45;
161
+ background: linear-gradient(
162
+ 180deg,
163
+ var(--motiongpu-color-card) 0%,
164
+ var(--motiongpu-color-background-muted) 100%
165
+ );
166
+ color: var(--motiongpu-color-foreground);
167
+ box-shadow: var(--motiongpu-shadow-card);
168
+ }
169
+
170
+ .motiongpu-error-header {
171
+ display: grid;
172
+ gap: 0.55rem;
173
+ padding-bottom: 0.9rem;
174
+ border-bottom: 1px solid var(--motiongpu-color-border);
175
+ }
176
+
177
+ .motiongpu-error-badge-wrap {
178
+ display: inline-flex;
179
+ align-items: center;
180
+ gap: 0.4rem;
181
+ width: fit-content;
182
+ padding: 0.18rem;
183
+ border-radius: 999px;
184
+ border: 1px solid var(--motiongpu-color-border);
185
+ background: var(--motiongpu-color-background-muted);
186
+ }
187
+
188
+ .motiongpu-error-phase {
189
+ display: inline-flex;
190
+ align-items: center;
191
+ margin: 0;
192
+ padding: 0.22rem 0.56rem;
193
+ border-radius: 999px;
194
+ font-size: 0.66rem;
195
+ letter-spacing: 0.08em;
196
+ line-height: 1;
197
+ font-weight: 500;
198
+ text-transform: uppercase;
199
+ color: var(--motiongpu-color-background);
200
+ background: linear-gradient(
201
+ 180deg,
202
+ var(--motiongpu-color-accent) 0%,
203
+ var(--motiongpu-color-accent-secondary) 100%
204
+ );
205
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.24);
206
+ }
207
+
208
+ .motiongpu-error-title {
209
+ margin: 0;
210
+ font-size: clamp(1.02rem, 1vw + 0.72rem, 1.32rem);
211
+ font-weight: 500;
212
+ line-height: 1.18;
213
+ letter-spacing: -0.02em;
214
+ text-wrap: balance;
215
+ color: var(--motiongpu-color-foreground);
216
+ }
217
+
218
+ .motiongpu-error-body {
219
+ display: grid;
220
+ gap: 0.62rem;
221
+ margin-top: 0.92rem;
222
+ }
223
+
224
+ .motiongpu-error-message {
225
+ margin: 0;
226
+ padding: 0.72rem 0.78rem;
227
+ border: 1px solid color-mix(in srgb, var(--motiongpu-color-accent) 28%, transparent);
228
+ border-radius: var(--motiongpu-radius-md);
229
+ background: color-mix(in srgb, var(--motiongpu-color-accent) 9%, var(--motiongpu-color-card));
230
+ font-size: 0.82rem;
231
+ line-height: 1.4;
232
+ font-weight: 300;
233
+ color: var(--motiongpu-color-foreground);
234
+ }
235
+
236
+ .motiongpu-error-hint {
237
+ margin: 0;
238
+ font-size: 0.82rem;
239
+ line-height: 1.45;
240
+ font-weight: 300;
241
+ color: var(--motiongpu-color-foreground-muted);
242
+ }
243
+
244
+ .motiongpu-error-sections {
245
+ display: grid;
246
+ gap: 0.62rem;
247
+ margin-top: 0.95rem;
248
+ }
249
+
250
+ .motiongpu-error-source {
251
+ display: grid;
252
+ gap: 0.48rem;
253
+ margin-top: 0.96rem;
254
+ }
255
+
256
+ .motiongpu-error-source-title {
257
+ margin: 0;
258
+ font-size: 0.8rem;
259
+ font-weight: 500;
260
+ line-height: 1.3;
261
+ letter-spacing: 0.045em;
262
+ text-transform: uppercase;
263
+ color: var(--motiongpu-color-foreground);
264
+ }
265
+
266
+ .motiongpu-error-source-frame {
267
+ border: 1px solid var(--motiongpu-color-border);
268
+ border-radius: var(--motiongpu-radius-lg);
269
+ overflow: hidden;
270
+ background: var(--motiongpu-color-background-muted);
271
+ }
272
+
273
+ .motiongpu-error-source-tabs {
274
+ display: flex;
275
+ align-items: stretch;
276
+ border-bottom: 1px solid var(--motiongpu-color-border);
277
+ background: var(--motiongpu-color-background);
278
+ }
279
+
280
+ .motiongpu-error-source-tab {
281
+ display: inline-flex;
282
+ align-items: center;
283
+ padding: 0.5rem 0.68rem;
284
+ font-size: 0.76rem;
285
+ font-weight: 300;
286
+ line-height: 1.2;
287
+ color: var(--motiongpu-color-foreground-muted);
288
+ border-right: 1px solid var(--motiongpu-color-border);
289
+ }
290
+
291
+ .motiongpu-error-source-tab-active {
292
+ color: var(--motiongpu-color-foreground);
293
+ background: var(--motiongpu-color-background-muted);
294
+ }
295
+
296
+ .motiongpu-error-source-tab-spacer {
297
+ flex: 1 1 auto;
298
+ }
299
+
300
+ .motiongpu-error-source-snippet {
301
+ display: grid;
302
+ background: var(--motiongpu-color-background-muted);
303
+ }
304
+
305
+ .motiongpu-error-source-row {
306
+ display: grid;
307
+ grid-template-columns: 2rem minmax(0, 1fr);
308
+ align-items: start;
309
+ gap: 0.42rem;
310
+ padding: 0.2rem 0.68rem;
311
+ }
312
+
313
+ .motiongpu-error-source-row-active {
314
+ background: color-mix(in srgb, var(--motiongpu-color-accent) 10%, transparent);
315
+ }
316
+
317
+ .motiongpu-error-source-line {
318
+ font-family: var(--motiongpu-font-mono);
319
+ font-size: 0.77rem;
320
+ font-weight: 300;
321
+ line-height: 1.3;
322
+ font-variant-numeric: tabular-nums;
323
+ font-feature-settings: 'tnum' 1;
324
+ border-right: 1px solid var(--motiongpu-color-border);
325
+ color: var(--motiongpu-color-foreground-muted);
326
+ text-align: left;
327
+ }
328
+
329
+ .motiongpu-error-source-code {
330
+ font-family: var(--motiongpu-font-mono);
331
+ font-size: 0.77rem;
332
+ font-weight: 350;
333
+ line-height: 1.3;
334
+ color: var(--motiongpu-color-foreground);
335
+ white-space: pre-wrap;
336
+ word-break: break-word;
337
+ }
338
+
339
+ .motiongpu-error-details {
340
+ border: 1px solid var(--motiongpu-color-border);
341
+ border-radius: var(--motiongpu-radius-lg);
342
+ overflow: hidden;
343
+ background: var(--motiongpu-color-background);
344
+ }
345
+
346
+ .motiongpu-error-details summary {
347
+ cursor: pointer;
348
+ padding: 0.56rem 0.68rem;
349
+ font-size: 0.7rem;
350
+ letter-spacing: 0.07em;
351
+ line-height: 1.2;
352
+ font-weight: 500;
353
+ text-transform: uppercase;
354
+ color: var(--motiongpu-color-foreground);
355
+ }
356
+
357
+ .motiongpu-error-details[open] summary {
358
+ border-bottom: 1px solid var(--motiongpu-color-border);
359
+ }
360
+
361
+ .motiongpu-error-details pre {
362
+ margin: 0;
363
+ padding: 0.62rem 0.68rem;
364
+ white-space: pre-wrap;
365
+ word-break: break-word;
366
+ overflow: auto;
367
+ background: var(--motiongpu-color-background-muted);
368
+ font-size: 0.74rem;
369
+ line-height: 1.4;
370
+ font-weight: 300;
371
+ color: var(--motiongpu-color-foreground);
372
+ font-family: var(--motiongpu-font-mono);
373
+ }
374
+
375
+ @media (max-width: 42rem) {
376
+ .motiongpu-error-overlay {
377
+ padding: 0.62rem;
378
+ }
379
+
380
+ .motiongpu-error-dialog {
381
+ padding: 0.85rem;
382
+ }
383
+
384
+ .motiongpu-error-title {
385
+ font-size: 1.02rem;
386
+ }
387
+ }
388
+
389
+ @media (prefers-reduced-motion: reduce) {
390
+ .motiongpu-error-overlay {
391
+ backdrop-filter: none;
392
+ }
393
+ }
394
+ </style>
@@ -0,0 +1,7 @@
1
+ import type { MotionGPUErrorReport } from './core/error-report';
2
+ interface Props {
3
+ report: MotionGPUErrorReport;
4
+ }
5
+ declare const MotionGPUErrorOverlay: import("svelte").Component<Props, {}, "">;
6
+ type MotionGPUErrorOverlay = ReturnType<typeof MotionGPUErrorOverlay>;
7
+ export default MotionGPUErrorOverlay;
@@ -0,0 +1,46 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ target?: string | HTMLElement | null;
6
+ children?: Snippet;
7
+ }
8
+
9
+ let { target = 'body', children }: Props = $props();
10
+
11
+ function resolveTargetElement(input: string | HTMLElement | null | undefined): HTMLElement {
12
+ return typeof input === 'string'
13
+ ? (document.querySelector<HTMLElement>(input) ?? document.body)
14
+ : (input ?? document.body);
15
+ }
16
+
17
+ const portal = (node: HTMLDivElement, initialTarget: string | HTMLElement | null) => {
18
+ let targetElement = resolveTargetElement(initialTarget);
19
+ targetElement.appendChild(node);
20
+
21
+ return {
22
+ update(nextTarget: string | HTMLElement | null) {
23
+ const nextTargetElement = resolveTargetElement(nextTarget);
24
+ if (nextTargetElement === targetElement) {
25
+ return;
26
+ }
27
+
28
+ if (node.parentNode === targetElement) {
29
+ targetElement.removeChild(node);
30
+ }
31
+
32
+ nextTargetElement.appendChild(node);
33
+ targetElement = nextTargetElement;
34
+ },
35
+ destroy() {
36
+ if (node.parentNode === targetElement) {
37
+ targetElement.removeChild(node);
38
+ }
39
+ }
40
+ };
41
+ };
42
+ </script>
43
+
44
+ <div use:portal={target}>
45
+ {@render children?.()}
46
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ target?: string | HTMLElement | null;
4
+ children?: Snippet;
5
+ }
6
+ declare const Portal: import("svelte").Component<Props, {}, "">;
7
+ type Portal = ReturnType<typeof Portal>;
8
+ export default Portal;
@@ -0,0 +1,44 @@
1
+ import type { FrameProfilingSnapshot, FrameRunTimings, FrameScheduleSnapshot, MotionGPUScheduler } from './motiongpu-context';
2
+ /**
3
+ * Named scheduler presets exposed from the advanced entrypoint.
4
+ */
5
+ export type SchedulerPreset = 'balanced' | 'debug' | 'performance';
6
+ /**
7
+ * Resolved scheduler timing configuration.
8
+ *
9
+ * Note: diagnostics and profiling currently share one internal toggle in the frame registry.
10
+ */
11
+ export interface SchedulerPresetConfig {
12
+ diagnosticsEnabled: boolean;
13
+ profilingEnabled: boolean;
14
+ profilingWindow: number;
15
+ }
16
+ /**
17
+ * Optional overrides applied on top of a named scheduler preset.
18
+ */
19
+ export interface ApplySchedulerPresetOptions {
20
+ diagnosticsEnabled?: boolean;
21
+ profilingEnabled?: boolean;
22
+ profilingWindow?: number;
23
+ }
24
+ /**
25
+ * Snapshot payload useful for scheduler diagnostics UIs and debug tooling.
26
+ */
27
+ export interface SchedulerDebugSnapshot {
28
+ diagnosticsEnabled: boolean;
29
+ profilingEnabled: boolean;
30
+ profilingWindow: number;
31
+ schedule: FrameScheduleSnapshot;
32
+ lastRunTimings: FrameRunTimings | null;
33
+ profilingSnapshot: FrameProfilingSnapshot | null;
34
+ }
35
+ /**
36
+ * Applies a named scheduler preset to the runtime scheduler instance.
37
+ *
38
+ * Returns resolved values after overrides for easy logging/telemetry.
39
+ */
40
+ export declare function applySchedulerPreset(scheduler: MotionGPUScheduler, preset: SchedulerPreset, options?: ApplySchedulerPresetOptions): SchedulerPresetConfig;
41
+ /**
42
+ * Captures an aggregate scheduler diagnostics snapshot.
43
+ */
44
+ export declare function captureSchedulerDebugSnapshot(scheduler: MotionGPUScheduler): SchedulerDebugSnapshot;
@@ -0,0 +1,58 @@
1
+ const PRESET_CONFIG = {
2
+ performance: {
3
+ diagnosticsEnabled: false,
4
+ profilingEnabled: false,
5
+ profilingWindow: 60
6
+ },
7
+ balanced: {
8
+ diagnosticsEnabled: true,
9
+ profilingEnabled: true,
10
+ profilingWindow: 120
11
+ },
12
+ debug: {
13
+ diagnosticsEnabled: true,
14
+ profilingEnabled: true,
15
+ profilingWindow: 240
16
+ }
17
+ };
18
+ function assertProfilingWindow(value) {
19
+ if (!Number.isFinite(value) || value <= 0) {
20
+ throw new Error('profilingWindow must be a finite number greater than 0');
21
+ }
22
+ return Math.floor(value);
23
+ }
24
+ /**
25
+ * Applies a named scheduler preset to the runtime scheduler instance.
26
+ *
27
+ * Returns resolved values after overrides for easy logging/telemetry.
28
+ */
29
+ export function applySchedulerPreset(scheduler, preset, options = {}) {
30
+ const base = PRESET_CONFIG[preset];
31
+ const diagnosticsEnabled = options.diagnosticsEnabled ?? base.diagnosticsEnabled;
32
+ const profilingEnabled = options.profilingEnabled ?? base.profilingEnabled;
33
+ if (diagnosticsEnabled !== profilingEnabled) {
34
+ throw new Error('MotionGPU scheduler currently shares diagnostics/profiling state; both values must match');
35
+ }
36
+ const profilingWindow = assertProfilingWindow(options.profilingWindow ?? base.profilingWindow);
37
+ scheduler.setProfilingWindow(profilingWindow);
38
+ scheduler.setDiagnosticsEnabled(diagnosticsEnabled);
39
+ scheduler.setProfilingEnabled(profilingEnabled);
40
+ return {
41
+ diagnosticsEnabled,
42
+ profilingEnabled,
43
+ profilingWindow
44
+ };
45
+ }
46
+ /**
47
+ * Captures an aggregate scheduler diagnostics snapshot.
48
+ */
49
+ export function captureSchedulerDebugSnapshot(scheduler) {
50
+ return {
51
+ diagnosticsEnabled: scheduler.getDiagnosticsEnabled(),
52
+ profilingEnabled: scheduler.getProfilingEnabled(),
53
+ profilingWindow: scheduler.getProfilingWindow(),
54
+ schedule: scheduler.getSchedule(),
55
+ lastRunTimings: scheduler.getLastRunTimings(),
56
+ profilingSnapshot: scheduler.getProfilingSnapshot()
57
+ };
58
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Advanced MotionGPU entrypoint.
3
+ *
4
+ * Includes power-user hooks and diagnostics-oriented types that are not part of the
5
+ * minimal root API surface.
6
+ */
7
+ export * from './index';
8
+ export { applySchedulerPreset, captureSchedulerDebugSnapshot } from './advanced-scheduler';
9
+ export { setMotionGPUUserContext, useMotionGPUUserContext } from './use-motiongpu-user-context';
10
+ export type { ApplySchedulerPresetOptions, SchedulerDebugSnapshot, SchedulerPreset, SchedulerPresetConfig } from './advanced-scheduler';
11
+ export type { MotionGPUUserContext, MotionGPUUserNamespace } from './motiongpu-context';
12
+ export type { FrameProfilingSnapshot, FrameKey, FrameTaskInvalidation, FrameTaskInvalidationToken, FrameRunTimings, FrameScheduleSnapshot, FrameStage, FrameStageCallback, FrameTimingStats, FrameTask } from './frame-context';
13
+ export type { SetMotionGPUUserContextOptions } from './use-motiongpu-user-context';
14
+ export type { RenderPassContext, RenderTarget, UniformLayout, UniformLayoutEntry } from './core/types';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Advanced MotionGPU entrypoint.
3
+ *
4
+ * Includes power-user hooks and diagnostics-oriented types that are not part of the
5
+ * minimal root API surface.
6
+ */
7
+ export * from './index';
8
+ export { applySchedulerPreset, captureSchedulerDebugSnapshot } from './advanced-scheduler';
9
+ export { setMotionGPUUserContext, useMotionGPUUserContext } from './use-motiongpu-user-context';
@@ -0,0 +1,40 @@
1
+ import type { MaterialSourceLocation } from './material-preprocess';
2
+ /**
3
+ * Source metadata for material declaration callsite.
4
+ */
5
+ export interface MaterialSourceMetadata {
6
+ component?: string;
7
+ file?: string;
8
+ line?: number;
9
+ column?: number;
10
+ functionName?: string;
11
+ }
12
+ /**
13
+ * One WGSL compiler diagnostic enriched with source-location metadata.
14
+ */
15
+ export interface ShaderCompilationDiagnostic {
16
+ generatedLine: number;
17
+ message: string;
18
+ linePos?: number;
19
+ lineLength?: number;
20
+ sourceLocation: MaterialSourceLocation | null;
21
+ }
22
+ /**
23
+ * Structured payload attached to WGSL compilation errors.
24
+ */
25
+ export interface ShaderCompilationDiagnosticsPayload {
26
+ kind: 'shader-compilation';
27
+ diagnostics: ShaderCompilationDiagnostic[];
28
+ fragmentSource: string;
29
+ includeSources: Record<string, string>;
30
+ defineBlockSource?: string;
31
+ materialSource: MaterialSourceMetadata | null;
32
+ }
33
+ /**
34
+ * Attaches structured diagnostics payload to an Error.
35
+ */
36
+ export declare function attachShaderCompilationDiagnostics(error: Error, payload: ShaderCompilationDiagnosticsPayload): Error;
37
+ /**
38
+ * Extracts structured diagnostics payload from unknown error value.
39
+ */
40
+ export declare function getShaderCompilationDiagnostics(error: unknown): ShaderCompilationDiagnosticsPayload | null;