@motion-core/motion-gpu 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 +37 -11
- package/dist/advanced.d.ts +3 -11
- package/dist/advanced.js +3 -6
- package/dist/core/advanced.d.ts +6 -0
- package/dist/core/advanced.js +5 -0
- package/dist/core/current-value.d.ts +23 -0
- package/dist/core/current-value.js +36 -0
- package/dist/core/error-diagnostics.d.ts +15 -1
- package/dist/core/error-diagnostics.js +41 -1
- package/dist/core/error-report.d.ts +37 -0
- package/dist/core/error-report.js +62 -3
- package/dist/{frame-context.d.ts → core/frame-registry.d.ts} +3 -17
- package/dist/{frame-context.js → core/frame-registry.js} +2 -37
- package/dist/core/index.d.ts +19 -0
- package/dist/core/index.js +12 -0
- package/dist/core/material-preprocess.d.ts +1 -1
- package/dist/core/material-preprocess.js +1 -1
- package/dist/core/material.d.ts +4 -4
- package/dist/core/material.js +3 -3
- package/dist/core/recompile-policy.d.ts +1 -1
- package/dist/core/render-graph.d.ts +1 -1
- package/dist/core/render-targets.d.ts +1 -1
- package/dist/core/render-targets.js +1 -1
- package/dist/core/renderer.d.ts +11 -1
- package/dist/core/renderer.js +72 -10
- package/dist/core/runtime-loop.d.ts +34 -0
- package/dist/core/runtime-loop.js +365 -0
- package/dist/{advanced-scheduler.d.ts → core/scheduler-helpers.d.ts} +6 -2
- package/dist/core/shader.d.ts +2 -2
- package/dist/core/shader.js +1 -1
- package/dist/core/texture-loader.d.ts +1 -1
- package/dist/core/textures.d.ts +1 -1
- package/dist/core/textures.js +1 -1
- package/dist/core/types.d.ts +4 -0
- package/dist/core/uniforms.d.ts +1 -1
- package/dist/index.d.ts +3 -14
- package/dist/index.js +3 -8
- package/dist/passes/BlitPass.d.ts +6 -27
- package/dist/passes/BlitPass.js +10 -121
- package/dist/passes/CopyPass.d.ts +1 -1
- package/dist/passes/CopyPass.js +1 -1
- package/dist/passes/FullscreenPass.d.ts +37 -0
- package/dist/passes/FullscreenPass.js +131 -0
- package/dist/passes/ShaderPass.d.ts +6 -26
- package/dist/passes/ShaderPass.js +10 -121
- package/dist/passes/index.d.ts +3 -3
- package/dist/passes/index.js +3 -3
- package/dist/svelte/FragCanvas.svelte +263 -0
- package/dist/{FragCanvas.svelte.d.ts → svelte/FragCanvas.svelte.d.ts} +5 -3
- package/dist/{MotionGPUErrorOverlay.svelte → svelte/MotionGPUErrorOverlay.svelte} +11 -20
- package/dist/{MotionGPUErrorOverlay.svelte.d.ts → svelte/MotionGPUErrorOverlay.svelte.d.ts} +1 -1
- package/dist/svelte/advanced.d.ts +11 -0
- package/dist/svelte/advanced.js +6 -0
- package/dist/svelte/frame-context.d.ts +14 -0
- package/dist/svelte/frame-context.js +32 -0
- package/dist/svelte/index.d.ts +15 -0
- package/dist/svelte/index.js +9 -0
- package/dist/{motiongpu-context.d.ts → svelte/motiongpu-context.d.ts} +5 -7
- package/dist/{use-motiongpu-user-context.d.ts → svelte/use-motiongpu-user-context.d.ts} +2 -2
- package/dist/{use-motiongpu-user-context.js → svelte/use-motiongpu-user-context.js} +1 -1
- package/dist/{use-texture.d.ts → svelte/use-texture.d.ts} +7 -2
- package/dist/{use-texture.js → svelte/use-texture.js} +9 -3
- package/package.json +25 -5
- package/dist/FragCanvas.svelte +0 -511
- package/dist/current-writable.d.ts +0 -31
- package/dist/current-writable.js +0 -27
- /package/dist/{advanced-scheduler.js → core/scheduler-helpers.js} +0 -0
- /package/dist/{Portal.svelte → svelte/Portal.svelte} +0 -0
- /package/dist/{Portal.svelte.d.ts → svelte/Portal.svelte.d.ts} +0 -0
- /package/dist/{motiongpu-context.js → svelte/motiongpu-context.js} +0 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
import type { FragMaterial } from '../core/material';
|
|
5
|
+
import { createCurrentWritable as currentWritable } from '../core/current-value';
|
|
6
|
+
import { toMotionGPUErrorReport, type MotionGPUErrorReport } from '../core/error-report';
|
|
7
|
+
import MotionGPUErrorOverlay from './MotionGPUErrorOverlay.svelte';
|
|
8
|
+
import { createMotionGPURuntimeLoop } from '../core/runtime-loop';
|
|
9
|
+
import type {
|
|
10
|
+
FrameInvalidationToken,
|
|
11
|
+
OutputColorSpace,
|
|
12
|
+
RenderPass,
|
|
13
|
+
RenderMode,
|
|
14
|
+
RenderTargetDefinitionMap
|
|
15
|
+
} from '../core/types';
|
|
16
|
+
import { provideMotionGPUContext } from './motiongpu-context';
|
|
17
|
+
import { createFrameRegistry, provideFrameRegistry } from './frame-context';
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
material: FragMaterial;
|
|
21
|
+
renderTargets?: RenderTargetDefinitionMap;
|
|
22
|
+
passes?: RenderPass[];
|
|
23
|
+
clearColor?: [number, number, number, number];
|
|
24
|
+
outputColorSpace?: OutputColorSpace;
|
|
25
|
+
renderMode?: RenderMode;
|
|
26
|
+
autoRender?: boolean;
|
|
27
|
+
maxDelta?: number;
|
|
28
|
+
adapterOptions?: GPURequestAdapterOptions;
|
|
29
|
+
deviceDescriptor?: GPUDeviceDescriptor;
|
|
30
|
+
dpr?: number;
|
|
31
|
+
showErrorOverlay?: boolean;
|
|
32
|
+
errorRenderer?: Snippet<[MotionGPUErrorReport]>;
|
|
33
|
+
onError?: (report: MotionGPUErrorReport) => void;
|
|
34
|
+
errorHistoryLimit?: number;
|
|
35
|
+
onErrorHistory?: (history: MotionGPUErrorReport[]) => void;
|
|
36
|
+
class?: string;
|
|
37
|
+
style?: string;
|
|
38
|
+
children?: Snippet;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const initialDpr = typeof window === 'undefined' ? 1 : (window.devicePixelRatio ?? 1);
|
|
42
|
+
|
|
43
|
+
let {
|
|
44
|
+
material,
|
|
45
|
+
renderTargets = {},
|
|
46
|
+
passes = [],
|
|
47
|
+
clearColor = [0, 0, 0, 1],
|
|
48
|
+
outputColorSpace = 'srgb',
|
|
49
|
+
renderMode = 'always',
|
|
50
|
+
autoRender = true,
|
|
51
|
+
maxDelta = 0.1,
|
|
52
|
+
adapterOptions = undefined,
|
|
53
|
+
deviceDescriptor = undefined,
|
|
54
|
+
dpr = initialDpr,
|
|
55
|
+
showErrorOverlay = true,
|
|
56
|
+
errorRenderer = undefined,
|
|
57
|
+
onError = undefined,
|
|
58
|
+
errorHistoryLimit = 0,
|
|
59
|
+
onErrorHistory = undefined,
|
|
60
|
+
class: className = '',
|
|
61
|
+
style = '',
|
|
62
|
+
children
|
|
63
|
+
}: Props = $props();
|
|
64
|
+
|
|
65
|
+
let canvas: HTMLCanvasElement | undefined;
|
|
66
|
+
let errorReport = $state<MotionGPUErrorReport | null>(null);
|
|
67
|
+
let errorHistory = $state<MotionGPUErrorReport[]>([]);
|
|
68
|
+
|
|
69
|
+
const getNormalizedErrorHistoryLimit = (): number => {
|
|
70
|
+
if (!Number.isFinite(errorHistoryLimit) || errorHistoryLimit <= 0) {
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
73
|
+
return Math.floor(errorHistoryLimit);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const bindCanvas = (node: HTMLCanvasElement) => {
|
|
77
|
+
canvas = node;
|
|
78
|
+
return {
|
|
79
|
+
destroy: () => {
|
|
80
|
+
if (canvas === node) {
|
|
81
|
+
canvas = undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const registry = createFrameRegistry({ maxDelta: 0.1 });
|
|
88
|
+
provideFrameRegistry(registry);
|
|
89
|
+
let requestFrameSignal: (() => void) | null = null;
|
|
90
|
+
const requestFrame = (): void => {
|
|
91
|
+
requestFrameSignal?.();
|
|
92
|
+
};
|
|
93
|
+
const invalidateFrame = (token?: FrameInvalidationToken): void => {
|
|
94
|
+
registry.invalidate(token);
|
|
95
|
+
requestFrame();
|
|
96
|
+
};
|
|
97
|
+
const advanceFrame = (): void => {
|
|
98
|
+
registry.advance();
|
|
99
|
+
requestFrame();
|
|
100
|
+
};
|
|
101
|
+
const size = currentWritable({ width: 0, height: 0 });
|
|
102
|
+
const dprState = currentWritable(initialDpr, requestFrame);
|
|
103
|
+
const maxDeltaState = currentWritable<number>(0.1, (value) => {
|
|
104
|
+
registry.setMaxDelta(value);
|
|
105
|
+
requestFrame();
|
|
106
|
+
});
|
|
107
|
+
const renderModeState = currentWritable<RenderMode>('always', (value) => {
|
|
108
|
+
registry.setRenderMode(value);
|
|
109
|
+
requestFrame();
|
|
110
|
+
});
|
|
111
|
+
const autoRenderState = currentWritable<boolean>(true, (value) => {
|
|
112
|
+
registry.setAutoRender(value);
|
|
113
|
+
requestFrame();
|
|
114
|
+
});
|
|
115
|
+
const userState = currentWritable<Record<string | symbol, unknown>>({});
|
|
116
|
+
|
|
117
|
+
provideMotionGPUContext({
|
|
118
|
+
get canvas() {
|
|
119
|
+
return canvas;
|
|
120
|
+
},
|
|
121
|
+
size,
|
|
122
|
+
dpr: dprState,
|
|
123
|
+
maxDelta: maxDeltaState,
|
|
124
|
+
renderMode: renderModeState,
|
|
125
|
+
autoRender: autoRenderState,
|
|
126
|
+
user: userState,
|
|
127
|
+
invalidate: () => invalidateFrame(),
|
|
128
|
+
advance: advanceFrame,
|
|
129
|
+
scheduler: {
|
|
130
|
+
createStage: registry.createStage,
|
|
131
|
+
getStage: registry.getStage,
|
|
132
|
+
setDiagnosticsEnabled: registry.setDiagnosticsEnabled,
|
|
133
|
+
getDiagnosticsEnabled: registry.getDiagnosticsEnabled,
|
|
134
|
+
getLastRunTimings: registry.getLastRunTimings,
|
|
135
|
+
getSchedule: registry.getSchedule,
|
|
136
|
+
setProfilingEnabled: registry.setProfilingEnabled,
|
|
137
|
+
setProfilingWindow: registry.setProfilingWindow,
|
|
138
|
+
resetProfiling: registry.resetProfiling,
|
|
139
|
+
getProfilingEnabled: registry.getProfilingEnabled,
|
|
140
|
+
getProfilingWindow: registry.getProfilingWindow,
|
|
141
|
+
getProfilingSnapshot: registry.getProfilingSnapshot
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
$effect(() => {
|
|
146
|
+
renderModeState.set(renderMode);
|
|
147
|
+
requestFrame();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
$effect(() => {
|
|
151
|
+
autoRenderState.set(autoRender);
|
|
152
|
+
requestFrame();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
$effect(() => {
|
|
156
|
+
maxDeltaState.set(maxDelta);
|
|
157
|
+
requestFrame();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
$effect(() => {
|
|
161
|
+
dprState.set(dpr);
|
|
162
|
+
requestFrame();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
$effect(() => {
|
|
166
|
+
const limit = getNormalizedErrorHistoryLimit();
|
|
167
|
+
if (limit <= 0) {
|
|
168
|
+
if (errorHistory.length === 0) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
errorHistory = [];
|
|
172
|
+
onErrorHistory?.([]);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (errorHistory.length <= limit) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const trimmed = errorHistory.slice(errorHistory.length - limit);
|
|
181
|
+
errorHistory = trimmed;
|
|
182
|
+
onErrorHistory?.(trimmed);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
onMount(() => {
|
|
186
|
+
if (!canvas) {
|
|
187
|
+
const report = toMotionGPUErrorReport(
|
|
188
|
+
new Error('Canvas element is not available'),
|
|
189
|
+
'initialization'
|
|
190
|
+
);
|
|
191
|
+
errorReport = report;
|
|
192
|
+
const historyLimit = getNormalizedErrorHistoryLimit();
|
|
193
|
+
if (historyLimit > 0) {
|
|
194
|
+
const nextHistory = [report].slice(-historyLimit);
|
|
195
|
+
errorHistory = nextHistory;
|
|
196
|
+
onErrorHistory?.(nextHistory);
|
|
197
|
+
}
|
|
198
|
+
onError?.(report);
|
|
199
|
+
return () => registry.clear();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const runtimeLoop = createMotionGPURuntimeLoop({
|
|
203
|
+
canvas,
|
|
204
|
+
registry,
|
|
205
|
+
size,
|
|
206
|
+
dpr: dprState,
|
|
207
|
+
maxDelta: maxDeltaState,
|
|
208
|
+
getMaterial: () => material,
|
|
209
|
+
getRenderTargets: () => renderTargets,
|
|
210
|
+
getPasses: () => passes,
|
|
211
|
+
getClearColor: () => clearColor,
|
|
212
|
+
getOutputColorSpace: () => outputColorSpace,
|
|
213
|
+
getAdapterOptions: () => adapterOptions,
|
|
214
|
+
getDeviceDescriptor: () => deviceDescriptor,
|
|
215
|
+
getOnError: () => onError,
|
|
216
|
+
getErrorHistoryLimit: () => errorHistoryLimit,
|
|
217
|
+
getOnErrorHistory: () => onErrorHistory,
|
|
218
|
+
reportErrorHistory: (history) => {
|
|
219
|
+
errorHistory = history;
|
|
220
|
+
},
|
|
221
|
+
reportError: (report) => {
|
|
222
|
+
errorReport = report;
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
requestFrameSignal = runtimeLoop.requestFrame;
|
|
226
|
+
|
|
227
|
+
return () => {
|
|
228
|
+
requestFrameSignal = null;
|
|
229
|
+
runtimeLoop.destroy();
|
|
230
|
+
};
|
|
231
|
+
});
|
|
232
|
+
</script>
|
|
233
|
+
|
|
234
|
+
<div class="motiongpu-canvas-wrap">
|
|
235
|
+
<canvas use:bindCanvas class={className} {style}></canvas>
|
|
236
|
+
{#if showErrorOverlay && errorReport}
|
|
237
|
+
{#if errorRenderer}
|
|
238
|
+
{@render errorRenderer(errorReport)}
|
|
239
|
+
{:else}
|
|
240
|
+
<MotionGPUErrorOverlay report={errorReport} />
|
|
241
|
+
{/if}
|
|
242
|
+
{/if}
|
|
243
|
+
{@render children?.()}
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<style>
|
|
247
|
+
.motiongpu-canvas-wrap {
|
|
248
|
+
position: relative;
|
|
249
|
+
width: 100%;
|
|
250
|
+
height: 100%;
|
|
251
|
+
min-width: 0;
|
|
252
|
+
min-height: 0;
|
|
253
|
+
overflow: hidden;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
canvas {
|
|
257
|
+
position: absolute;
|
|
258
|
+
inset: 0;
|
|
259
|
+
display: block;
|
|
260
|
+
width: 100%;
|
|
261
|
+
height: 100%;
|
|
262
|
+
}
|
|
263
|
+
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
import {
|
|
3
|
-
import { type MotionGPUErrorReport } from '
|
|
4
|
-
import type { OutputColorSpace, RenderPass, RenderMode, RenderTargetDefinitionMap } from '
|
|
2
|
+
import type { FragMaterial } from '../core/material';
|
|
3
|
+
import { type MotionGPUErrorReport } from '../core/error-report';
|
|
4
|
+
import type { OutputColorSpace, RenderPass, RenderMode, RenderTargetDefinitionMap } from '../core/types';
|
|
5
5
|
interface Props {
|
|
6
6
|
material: FragMaterial;
|
|
7
7
|
renderTargets?: RenderTargetDefinitionMap;
|
|
@@ -17,6 +17,8 @@ interface Props {
|
|
|
17
17
|
showErrorOverlay?: boolean;
|
|
18
18
|
errorRenderer?: Snippet<[MotionGPUErrorReport]>;
|
|
19
19
|
onError?: (report: MotionGPUErrorReport) => void;
|
|
20
|
+
errorHistoryLimit?: number;
|
|
21
|
+
onErrorHistory?: (history: MotionGPUErrorReport[]) => void;
|
|
20
22
|
class?: string;
|
|
21
23
|
style?: string;
|
|
22
24
|
children?: Snippet;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { MotionGPUErrorReport } from '
|
|
2
|
+
import type { MotionGPUErrorReport } from '../core/error-report';
|
|
3
3
|
import Portal from './Portal.svelte';
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
@@ -53,9 +53,8 @@
|
|
|
53
53
|
class="motiongpu-error-source-tab motiongpu-error-source-tab-active"
|
|
54
54
|
role="tab"
|
|
55
55
|
aria-selected="true"
|
|
56
|
-
>{report.source.
|
|
57
|
-
|
|
58
|
-
{report.source.column}{/if})</span
|
|
56
|
+
>{report.source.location}{#if report.source.column}, col {report.source
|
|
57
|
+
.column}{/if}</span
|
|
59
58
|
>
|
|
60
59
|
<span class="motiongpu-error-source-tab-spacer" aria-hidden="true"></span>
|
|
61
60
|
</div>
|
|
@@ -117,21 +116,13 @@
|
|
|
117
116
|
--motiongpu-radius-xl: var(--radius-xl, 1rem);
|
|
118
117
|
--motiongpu-font-sans: var(
|
|
119
118
|
--font-sans,
|
|
120
|
-
'Aeonik Pro',
|
|
121
119
|
'Inter',
|
|
122
120
|
'Segoe UI',
|
|
123
121
|
'Helvetica Neue',
|
|
124
122
|
Arial,
|
|
125
123
|
sans-serif
|
|
126
124
|
);
|
|
127
|
-
--motiongpu-font-mono: var(
|
|
128
|
-
--font-mono,
|
|
129
|
-
'Aeonik font-mono',
|
|
130
|
-
'SFMono-Regular',
|
|
131
|
-
'Menlo',
|
|
132
|
-
'Consolas',
|
|
133
|
-
monospace
|
|
134
|
-
);
|
|
125
|
+
--motiongpu-font-mono: var(--font-mono, 'SFMono-Regular', 'Menlo', 'Consolas', monospace);
|
|
135
126
|
position: fixed;
|
|
136
127
|
inset: 0;
|
|
137
128
|
display: grid;
|
|
@@ -156,7 +147,7 @@
|
|
|
156
147
|
max-width: calc(100vw - 1.5rem);
|
|
157
148
|
box-sizing: border-box;
|
|
158
149
|
font-size: 0.875rem;
|
|
159
|
-
font-weight:
|
|
150
|
+
font-weight: 400;
|
|
160
151
|
line-height: 1.45;
|
|
161
152
|
background: linear-gradient(
|
|
162
153
|
180deg,
|
|
@@ -229,7 +220,7 @@
|
|
|
229
220
|
background: color-mix(in srgb, var(--motiongpu-color-accent) 9%, var(--motiongpu-color-card));
|
|
230
221
|
font-size: 0.82rem;
|
|
231
222
|
line-height: 1.4;
|
|
232
|
-
font-weight:
|
|
223
|
+
font-weight: 400;
|
|
233
224
|
color: var(--motiongpu-color-foreground);
|
|
234
225
|
}
|
|
235
226
|
|
|
@@ -237,7 +228,7 @@
|
|
|
237
228
|
margin: 0;
|
|
238
229
|
font-size: 0.82rem;
|
|
239
230
|
line-height: 1.45;
|
|
240
|
-
font-weight:
|
|
231
|
+
font-weight: 400;
|
|
241
232
|
color: var(--motiongpu-color-foreground-muted);
|
|
242
233
|
}
|
|
243
234
|
|
|
@@ -282,7 +273,7 @@
|
|
|
282
273
|
align-items: center;
|
|
283
274
|
padding: 0.5rem 0.68rem;
|
|
284
275
|
font-size: 0.76rem;
|
|
285
|
-
font-weight:
|
|
276
|
+
font-weight: 400;
|
|
286
277
|
line-height: 1.2;
|
|
287
278
|
color: var(--motiongpu-color-foreground-muted);
|
|
288
279
|
border-right: 1px solid var(--motiongpu-color-border);
|
|
@@ -317,7 +308,7 @@
|
|
|
317
308
|
.motiongpu-error-source-line {
|
|
318
309
|
font-family: var(--motiongpu-font-mono);
|
|
319
310
|
font-size: 0.77rem;
|
|
320
|
-
font-weight:
|
|
311
|
+
font-weight: 400;
|
|
321
312
|
line-height: 1.3;
|
|
322
313
|
font-variant-numeric: tabular-nums;
|
|
323
314
|
font-feature-settings: 'tnum' 1;
|
|
@@ -329,7 +320,7 @@
|
|
|
329
320
|
.motiongpu-error-source-code {
|
|
330
321
|
font-family: var(--motiongpu-font-mono);
|
|
331
322
|
font-size: 0.77rem;
|
|
332
|
-
font-weight:
|
|
323
|
+
font-weight: 400;
|
|
333
324
|
line-height: 1.3;
|
|
334
325
|
color: var(--motiongpu-color-foreground);
|
|
335
326
|
white-space: pre-wrap;
|
|
@@ -367,7 +358,7 @@
|
|
|
367
358
|
background: var(--motiongpu-color-background-muted);
|
|
368
359
|
font-size: 0.74rem;
|
|
369
360
|
line-height: 1.4;
|
|
370
|
-
font-weight:
|
|
361
|
+
font-weight: 400;
|
|
371
362
|
color: var(--motiongpu-color-foreground);
|
|
372
363
|
font-family: var(--motiongpu-font-mono);
|
|
373
364
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelte adapter advanced entrypoint for MotionGPU.
|
|
3
|
+
*/
|
|
4
|
+
export * from './index.js';
|
|
5
|
+
export { applySchedulerPreset, captureSchedulerDebugSnapshot } from '../core/scheduler-helpers.js';
|
|
6
|
+
export { setMotionGPUUserContext, useMotionGPUUserContext } from './use-motiongpu-user-context.js';
|
|
7
|
+
export type { ApplySchedulerPresetOptions, SchedulerDebugSnapshot, SchedulerPreset, SchedulerPresetConfig } from '../core/scheduler-helpers.js';
|
|
8
|
+
export type { MotionGPUUserContext, MotionGPUUserNamespace } from './motiongpu-context.js';
|
|
9
|
+
export type { FrameProfilingSnapshot, FrameKey, FrameTaskInvalidation, FrameTaskInvalidationToken, FrameRunTimings, FrameScheduleSnapshot, FrameStage, FrameStageCallback, FrameTimingStats, FrameTask } from '../core/frame-registry.js';
|
|
10
|
+
export type { SetMotionGPUUserContextOptions } from './use-motiongpu-user-context.js';
|
|
11
|
+
export type { RenderPassContext, RenderTarget, UniformLayout, UniformLayoutEntry } from '../core/types.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelte adapter advanced entrypoint for MotionGPU.
|
|
3
|
+
*/
|
|
4
|
+
export * from './index.js';
|
|
5
|
+
export { applySchedulerPreset, captureSchedulerDebugSnapshot } from '../core/scheduler-helpers.js';
|
|
6
|
+
export { setMotionGPUUserContext, useMotionGPUUserContext } from './use-motiongpu-user-context.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createFrameRegistry, type FrameCallback, type FrameKey, type FrameProfilingSnapshot, type FrameRegistry, type FrameRunTimings, type FrameScheduleSnapshot, type FrameStage, type FrameStageCallback, type FrameTask, type FrameTaskInvalidation, type FrameTaskInvalidationToken, type UseFrameOptions, type UseFrameResult } from '../core/frame-registry.js';
|
|
2
|
+
export { createFrameRegistry, type FrameCallback, type FrameKey, type FrameProfilingSnapshot, type FrameRegistry, type FrameRunTimings, type FrameScheduleSnapshot, type FrameStage, type FrameStageCallback, type FrameTask, type FrameTaskInvalidation, type FrameTaskInvalidationToken, type UseFrameOptions, type UseFrameResult };
|
|
3
|
+
/**
|
|
4
|
+
* Provides a frame registry through Svelte context.
|
|
5
|
+
*/
|
|
6
|
+
export declare function provideFrameRegistry(registry: FrameRegistry): void;
|
|
7
|
+
/**
|
|
8
|
+
* Registers a frame callback using an auto-generated task key.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useFrame(callback: FrameCallback, options?: UseFrameOptions): UseFrameResult;
|
|
11
|
+
/**
|
|
12
|
+
* Registers a frame callback with an explicit task key.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useFrame(key: FrameKey, callback: FrameCallback, options?: UseFrameOptions): UseFrameResult;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { getContext, onDestroy, setContext } from 'svelte';
|
|
2
|
+
import { createFrameRegistry } from '../core/frame-registry.js';
|
|
3
|
+
/**
|
|
4
|
+
* Svelte context key for the active frame registry.
|
|
5
|
+
*/
|
|
6
|
+
const FRAME_CONTEXT_KEY = Symbol('motiongpu.frame-context');
|
|
7
|
+
export { createFrameRegistry };
|
|
8
|
+
/**
|
|
9
|
+
* Provides a frame registry through Svelte context.
|
|
10
|
+
*/
|
|
11
|
+
export function provideFrameRegistry(registry) {
|
|
12
|
+
setContext(FRAME_CONTEXT_KEY, registry);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Registers a callback in the active frame registry and auto-unsubscribes on destroy.
|
|
16
|
+
*/
|
|
17
|
+
export function useFrame(keyOrCallback, callbackOrOptions, maybeOptions) {
|
|
18
|
+
const registry = getContext(FRAME_CONTEXT_KEY);
|
|
19
|
+
if (!registry) {
|
|
20
|
+
throw new Error('useFrame must be used inside <FragCanvas>');
|
|
21
|
+
}
|
|
22
|
+
const registration = typeof keyOrCallback === 'function'
|
|
23
|
+
? registry.register(keyOrCallback, callbackOrOptions)
|
|
24
|
+
: registry.register(keyOrCallback, callbackOrOptions, maybeOptions);
|
|
25
|
+
onDestroy(registration.unsubscribe);
|
|
26
|
+
return {
|
|
27
|
+
task: registration.task,
|
|
28
|
+
start: registration.start,
|
|
29
|
+
stop: registration.stop,
|
|
30
|
+
started: registration.started
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelte adapter entrypoint for MotionGPU.
|
|
3
|
+
*/
|
|
4
|
+
export { default as FragCanvas } from './FragCanvas.svelte';
|
|
5
|
+
export { defineMaterial } from '../core/material.js';
|
|
6
|
+
export { BlitPass, CopyPass, ShaderPass } from '../passes/index.js';
|
|
7
|
+
export { useMotionGPU } from './motiongpu-context.js';
|
|
8
|
+
export { useFrame } from './frame-context.js';
|
|
9
|
+
export { useTexture } from './use-texture.js';
|
|
10
|
+
export type { FrameInvalidationToken, FrameState, OutputColorSpace, RenderPass, RenderPassContext, RenderPassFlags, RenderPassInputSlot, RenderPassOutputSlot, RenderMode, RenderTarget, RenderTargetDefinition, RenderTargetDefinitionMap, TextureData, TextureDefinition, TextureDefinitionMap, TextureUpdateMode, TextureMap, TextureSource, TextureValue, TypedUniform, UniformMat4Value, UniformMap, UniformType, UniformValue } from '../core/types.js';
|
|
11
|
+
export type { LoadedTexture, TextureDecodeOptions, TextureLoadOptions } from '../core/texture-loader.js';
|
|
12
|
+
export type { FragMaterial, FragMaterialInput, MaterialIncludes, MaterialDefineValue, MaterialDefines, TypedMaterialDefineValue } from '../core/material.js';
|
|
13
|
+
export type { MotionGPUContext } from './motiongpu-context.js';
|
|
14
|
+
export type { UseFrameOptions, UseFrameResult } from './frame-context.js';
|
|
15
|
+
export type { TextureUrlInput, UseTextureResult } from './use-texture.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelte adapter entrypoint for MotionGPU.
|
|
3
|
+
*/
|
|
4
|
+
export { default as FragCanvas } from './FragCanvas.svelte';
|
|
5
|
+
export { defineMaterial } from '../core/material.js';
|
|
6
|
+
export { BlitPass, CopyPass, ShaderPass } from '../passes/index.js';
|
|
7
|
+
export { useMotionGPU } from './motiongpu-context.js';
|
|
8
|
+
export { useFrame } from './frame-context.js';
|
|
9
|
+
export { useTexture } from './use-texture.js';
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import type { RenderMode } from '
|
|
2
|
-
import type { CurrentReadable, CurrentWritable } from '
|
|
3
|
-
import type { FrameProfilingSnapshot,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
export type MotionGPUScheduler = Pick<FrameRegistry, 'createStage' | 'getStage' | 'setDiagnosticsEnabled' | 'getDiagnosticsEnabled' | 'getLastRunTimings' | 'getSchedule' | 'setProfilingEnabled' | 'setProfilingWindow' | 'resetProfiling' | 'getProfilingEnabled' | 'getProfilingWindow' | 'getProfilingSnapshot'>;
|
|
1
|
+
import type { RenderMode } from '../core/types.js';
|
|
2
|
+
import type { CurrentReadable, CurrentWritable } from '../core/current-value.js';
|
|
3
|
+
import type { FrameProfilingSnapshot, FrameRunTimings, FrameScheduleSnapshot } from '../core/frame-registry.js';
|
|
4
|
+
import type { MotionGPUScheduler as CoreMotionGPUScheduler } from '../core/scheduler-helpers.js';
|
|
5
|
+
export type MotionGPUScheduler = CoreMotionGPUScheduler;
|
|
8
6
|
export type { FrameProfilingSnapshot, FrameRunTimings, FrameScheduleSnapshot };
|
|
9
7
|
/**
|
|
10
8
|
* Namespace identifier for user-owned context entries.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { CurrentReadable } from '
|
|
2
|
-
import { type MotionGPUUserNamespace } from './motiongpu-context';
|
|
1
|
+
import type { CurrentReadable } from '../core/current-value.js';
|
|
2
|
+
import { type MotionGPUUserNamespace } from './motiongpu-context.js';
|
|
3
3
|
/**
|
|
4
4
|
* Internal shape of the user context store.
|
|
5
5
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { type LoadedTexture, type TextureLoadOptions } from '
|
|
1
|
+
import { type CurrentReadable } from '../core/current-value.js';
|
|
2
|
+
import { type LoadedTexture, type TextureLoadOptions } from '../core/texture-loader.js';
|
|
3
|
+
import { type MotionGPUErrorReport } from '../core/error-report.js';
|
|
3
4
|
/**
|
|
4
5
|
* Reactive state returned by {@link useTexture}.
|
|
5
6
|
*/
|
|
@@ -16,6 +17,10 @@ export interface UseTextureResult {
|
|
|
16
17
|
* Last loading error.
|
|
17
18
|
*/
|
|
18
19
|
error: CurrentReadable<Error | null>;
|
|
20
|
+
/**
|
|
21
|
+
* Last loading error normalized to MotionGPU diagnostics report shape.
|
|
22
|
+
*/
|
|
23
|
+
errorReport: CurrentReadable<MotionGPUErrorReport | null>;
|
|
19
24
|
/**
|
|
20
25
|
* Reloads all textures using current URL input.
|
|
21
26
|
*/
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { onDestroy } from 'svelte';
|
|
2
|
-
import { currentWritable } from '
|
|
3
|
-
import { isAbortError, loadTexturesFromUrls } from '
|
|
2
|
+
import { createCurrentWritable as currentWritable } from '../core/current-value.js';
|
|
3
|
+
import { isAbortError, loadTexturesFromUrls } from '../core/texture-loader.js';
|
|
4
|
+
import { toMotionGPUErrorReport } from '../core/error-report.js';
|
|
4
5
|
/**
|
|
5
6
|
* Normalizes unknown thrown values to an `Error` instance.
|
|
6
7
|
*/
|
|
@@ -60,6 +61,7 @@ export function useTexture(urlInput, options = {}) {
|
|
|
60
61
|
const textures = currentWritable(null);
|
|
61
62
|
const loading = currentWritable(true);
|
|
62
63
|
const error = currentWritable(null);
|
|
64
|
+
const errorReport = currentWritable(null);
|
|
63
65
|
let disposed = false;
|
|
64
66
|
let requestVersion = 0;
|
|
65
67
|
let activeController = null;
|
|
@@ -75,6 +77,7 @@ export function useTexture(urlInput, options = {}) {
|
|
|
75
77
|
activeController = controller;
|
|
76
78
|
loading.set(true);
|
|
77
79
|
error.set(null);
|
|
80
|
+
errorReport.set(null);
|
|
78
81
|
const previous = textures.current;
|
|
79
82
|
const mergedSignal = mergeAbortSignals(controller.signal, options.signal);
|
|
80
83
|
try {
|
|
@@ -98,7 +101,9 @@ export function useTexture(urlInput, options = {}) {
|
|
|
98
101
|
}
|
|
99
102
|
disposeTextures(previous);
|
|
100
103
|
textures.set(null);
|
|
101
|
-
|
|
104
|
+
const normalizedError = toError(nextError);
|
|
105
|
+
error.set(normalizedError);
|
|
106
|
+
errorReport.set(toMotionGPUErrorReport(normalizedError, 'initialization'));
|
|
102
107
|
}
|
|
103
108
|
finally {
|
|
104
109
|
if (!disposed && version === requestVersion) {
|
|
@@ -142,6 +147,7 @@ export function useTexture(urlInput, options = {}) {
|
|
|
142
147
|
textures,
|
|
143
148
|
loading,
|
|
144
149
|
error,
|
|
150
|
+
errorReport,
|
|
145
151
|
reload: load
|
|
146
152
|
};
|
|
147
153
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@motion-core/motion-gpu",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Framework-agnostic WebGPU runtime for fullscreen WGSL shaders with explicit Svelte adapter entrypoints.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svelte",
|
|
7
7
|
"svelte5",
|
|
@@ -26,18 +26,33 @@
|
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
28
|
"type": "module",
|
|
29
|
-
"svelte": "./dist/index.js",
|
|
30
29
|
"types": "./dist/index.d.ts",
|
|
31
30
|
"exports": {
|
|
32
31
|
".": {
|
|
33
32
|
"types": "./dist/index.d.ts",
|
|
34
|
-
"svelte": "./dist/index.js",
|
|
35
33
|
"default": "./dist/index.js"
|
|
36
34
|
},
|
|
37
35
|
"./advanced": {
|
|
38
36
|
"types": "./dist/advanced.d.ts",
|
|
39
|
-
"svelte": "./dist/advanced.js",
|
|
40
37
|
"default": "./dist/advanced.js"
|
|
38
|
+
},
|
|
39
|
+
"./svelte": {
|
|
40
|
+
"types": "./dist/svelte/index.d.ts",
|
|
41
|
+
"svelte": "./dist/svelte/index.js",
|
|
42
|
+
"default": "./dist/svelte/index.js"
|
|
43
|
+
},
|
|
44
|
+
"./svelte/advanced": {
|
|
45
|
+
"types": "./dist/svelte/advanced.d.ts",
|
|
46
|
+
"svelte": "./dist/svelte/advanced.js",
|
|
47
|
+
"default": "./dist/svelte/advanced.js"
|
|
48
|
+
},
|
|
49
|
+
"./core": {
|
|
50
|
+
"types": "./dist/core/index.d.ts",
|
|
51
|
+
"default": "./dist/core/index.js"
|
|
52
|
+
},
|
|
53
|
+
"./core/advanced": {
|
|
54
|
+
"types": "./dist/core/advanced.d.ts",
|
|
55
|
+
"default": "./dist/core/advanced.js"
|
|
41
56
|
}
|
|
42
57
|
},
|
|
43
58
|
"files": [
|
|
@@ -65,6 +80,11 @@
|
|
|
65
80
|
"peerDependencies": {
|
|
66
81
|
"svelte": "^5.0.0"
|
|
67
82
|
},
|
|
83
|
+
"peerDependenciesMeta": {
|
|
84
|
+
"svelte": {
|
|
85
|
+
"optional": true
|
|
86
|
+
}
|
|
87
|
+
},
|
|
68
88
|
"devDependencies": {
|
|
69
89
|
"@eslint/compat": "^2.0.2",
|
|
70
90
|
"@eslint/js": "^10.0.1",
|