@aardworx/wombat.rendering 0.19.19 → 0.19.21
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/dist/window/loop.d.ts.map +1 -1
- package/dist/window/loop.js +38 -6
- package/dist/window/loop.js.map +1 -1
- package/package.json +1 -1
- package/src/window/loop.ts +35 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/window/loop.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAQ,aAAa,EAAe,MAAM,2BAA2B,CAAC;AAElF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/window/loop.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAQ,aAAa,EAAe,MAAM,2BAA2B,CAAC;AAElF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAoDpD,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IACnC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;AAE5E,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,QAAQ,CACtB,UAAU,EAAE,gBAAgB,EAC5B,KAAK,EAAE,aAAa,EACpB,IAAI,GAAE,eAAoB,GACzB;IAAE,IAAI,IAAI,IAAI,CAAA;CAAE,CA2FlB"}
|
package/dist/window/loop.js
CHANGED
|
@@ -33,18 +33,52 @@ import { AVal, transact } from "@aardworx/wombat.adaptive";
|
|
|
33
33
|
// AFTER each frame's pacer resolves (i.e. GPU work done), so a
|
|
34
34
|
// harness can serialize edit → frame-complete → next edit and read
|
|
35
35
|
// honest end-to-end frame costs.
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
// Read at runFrame() start (NOT module load) — consumers set the flag
|
|
37
|
+
// from app code that runs after this module is imported.
|
|
38
|
+
function isUncapped() {
|
|
39
|
+
return globalThis
|
|
40
|
+
.__wombatUncappedRenderLoop === true;
|
|
41
|
+
}
|
|
38
42
|
function bumpFrameCount() {
|
|
39
43
|
const g = globalThis;
|
|
40
44
|
g.__wombatFrameCount = (g.__wombatFrameCount ?? 0) + 1;
|
|
41
45
|
}
|
|
46
|
+
// setTimeout(0) is useless for an uncapped loop: Chrome clamps nested
|
|
47
|
+
// timers to a 4 ms minimum after depth 5. MessageChannel.postMessage
|
|
48
|
+
// is the unthrottled macrotask primitive.
|
|
49
|
+
const immediateCbs = new Map();
|
|
50
|
+
let immediateNext = 1;
|
|
51
|
+
const immediateChannel = typeof MessageChannel !== "undefined" ? new MessageChannel() : null;
|
|
52
|
+
if (immediateChannel !== null) {
|
|
53
|
+
immediateChannel.port1.onmessage = (e) => {
|
|
54
|
+
const id = e.data;
|
|
55
|
+
const cb = immediateCbs.get(id);
|
|
56
|
+
immediateCbs.delete(id);
|
|
57
|
+
cb?.();
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function setImmediate2(cb) {
|
|
61
|
+
if (immediateChannel === null)
|
|
62
|
+
return setTimeout(cb, 0);
|
|
63
|
+
const id = immediateNext++;
|
|
64
|
+
immediateCbs.set(id, cb);
|
|
65
|
+
immediateChannel.port2.postMessage(id);
|
|
66
|
+
return id;
|
|
67
|
+
}
|
|
68
|
+
function clearImmediate2(id) {
|
|
69
|
+
if (immediateChannel === null) {
|
|
70
|
+
clearTimeout(id);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
immediateCbs.delete(id);
|
|
74
|
+
}
|
|
42
75
|
export function runFrame(attachment, frame, opts = {}) {
|
|
43
76
|
let stopped = false;
|
|
44
77
|
let frameNo = 0;
|
|
45
78
|
let lastTime = performance.now();
|
|
46
79
|
let rafId = 0;
|
|
47
80
|
let pending = false;
|
|
81
|
+
const UNCAPPED = isUncapped();
|
|
48
82
|
// Wrap the frame callback in an AVal so the adaptive system tracks
|
|
49
83
|
// its dependency set. Each `force()` re-reads the inputs and runs
|
|
50
84
|
// the frame; subsequent input marks fire the marking callback.
|
|
@@ -78,12 +112,10 @@ export function runFrame(attachment, frame, opts = {}) {
|
|
|
78
112
|
sub.dispose();
|
|
79
113
|
}
|
|
80
114
|
};
|
|
81
|
-
const schedule = (cb) => UNCAPPED
|
|
82
|
-
? setTimeout(cb, 0)
|
|
83
|
-
: requestAnimationFrame(cb);
|
|
115
|
+
const schedule = (cb) => UNCAPPED ? setImmediate2(cb) : requestAnimationFrame(cb);
|
|
84
116
|
const cancel = (h) => {
|
|
85
117
|
if (UNCAPPED)
|
|
86
|
-
|
|
118
|
+
clearImmediate2(h);
|
|
87
119
|
else
|
|
88
120
|
cancelAnimationFrame(h);
|
|
89
121
|
};
|
package/dist/window/loop.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/window/loop.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,iEAAiE;AACjE,gEAAgE;AAChE,oEAAoE;AACpE,gEAAgE;AAChE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAC1D,iCAAiC;AACjC,+DAA+D;AAC/D,6DAA6D;AAC7D,4DAA4D;AAC5D,iEAAiE;AACjE,iCAAiC;AACjC,6DAA6D;AAC7D,gEAAgE;AAChE,iEAAiE;AACjE,kEAAkE;AAClE,2CAA2C;AAC3C,gEAAgE;AAChE,wDAAwD;AACxD,EAAE;AACF,oEAAoE;AAGpE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAG3D,0EAA0E;AAC1E,EAAE;AACF,sEAAsE;AACtE,wDAAwD;AACxD,4DAA4D;AAC5D,6DAA6D;AAC7D,+DAA+D;AAC/D,oEAAoE;AACpE,+DAA+D;AAC/D,mEAAmE;AACnE,iCAAiC;AACjC,
|
|
1
|
+
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/window/loop.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aardworx/wombat.rendering",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.21",
|
|
4
4
|
"description": "WebGPU rendering layer for the Wombat TypeScript stack — RenderObject/RenderTask/runtime + window glue, port of Aardvark.Rendering's lower layers on top of WebGPU and wombat.shader.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "krauthaufen",
|
package/src/window/loop.ts
CHANGED
|
@@ -37,15 +37,45 @@ import type { CanvasAttachment } from "./canvas.js";
|
|
|
37
37
|
// AFTER each frame's pacer resolves (i.e. GPU work done), so a
|
|
38
38
|
// harness can serialize edit → frame-complete → next edit and read
|
|
39
39
|
// honest end-to-end frame costs.
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
// Read at runFrame() start (NOT module load) — consumers set the flag
|
|
41
|
+
// from app code that runs after this module is imported.
|
|
42
|
+
function isUncapped(): boolean {
|
|
43
|
+
return (globalThis as Record<string, unknown> & typeof globalThis)
|
|
42
44
|
.__wombatUncappedRenderLoop === true;
|
|
45
|
+
}
|
|
43
46
|
|
|
44
47
|
function bumpFrameCount(): void {
|
|
45
48
|
const g = globalThis as Record<string, unknown> & typeof globalThis;
|
|
46
49
|
g.__wombatFrameCount = ((g.__wombatFrameCount as number | undefined) ?? 0) + 1;
|
|
47
50
|
}
|
|
48
51
|
|
|
52
|
+
// setTimeout(0) is useless for an uncapped loop: Chrome clamps nested
|
|
53
|
+
// timers to a 4 ms minimum after depth 5. MessageChannel.postMessage
|
|
54
|
+
// is the unthrottled macrotask primitive.
|
|
55
|
+
const immediateCbs = new Map<number, () => void>();
|
|
56
|
+
let immediateNext = 1;
|
|
57
|
+
const immediateChannel: MessageChannel | null =
|
|
58
|
+
typeof MessageChannel !== "undefined" ? new MessageChannel() : null;
|
|
59
|
+
if (immediateChannel !== null) {
|
|
60
|
+
immediateChannel.port1.onmessage = (e: MessageEvent): void => {
|
|
61
|
+
const id = e.data as number;
|
|
62
|
+
const cb = immediateCbs.get(id);
|
|
63
|
+
immediateCbs.delete(id);
|
|
64
|
+
cb?.();
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function setImmediate2(cb: () => void): number {
|
|
68
|
+
if (immediateChannel === null) return setTimeout(cb, 0) as unknown as number;
|
|
69
|
+
const id = immediateNext++;
|
|
70
|
+
immediateCbs.set(id, cb);
|
|
71
|
+
immediateChannel.port2.postMessage(id);
|
|
72
|
+
return id;
|
|
73
|
+
}
|
|
74
|
+
function clearImmediate2(id: number): void {
|
|
75
|
+
if (immediateChannel === null) { clearTimeout(id); return; }
|
|
76
|
+
immediateCbs.delete(id);
|
|
77
|
+
}
|
|
78
|
+
|
|
49
79
|
export interface RunFrameOptions {
|
|
50
80
|
/** Stop after N frames. Useful for tests + finite animations. */
|
|
51
81
|
readonly maxFrames?: number;
|
|
@@ -93,6 +123,7 @@ export function runFrame(
|
|
|
93
123
|
let lastTime = performance.now();
|
|
94
124
|
let rafId = 0;
|
|
95
125
|
let pending = false;
|
|
126
|
+
const UNCAPPED = isUncapped();
|
|
96
127
|
|
|
97
128
|
// Wrap the frame callback in an AVal so the adaptive system tracks
|
|
98
129
|
// its dependency set. Each `force()` re-reads the inputs and runs
|
|
@@ -127,11 +158,9 @@ export function runFrame(
|
|
|
127
158
|
};
|
|
128
159
|
|
|
129
160
|
const schedule = (cb: () => void): number =>
|
|
130
|
-
UNCAPPED
|
|
131
|
-
? (setTimeout(cb, 0) as unknown as number)
|
|
132
|
-
: requestAnimationFrame(cb);
|
|
161
|
+
UNCAPPED ? setImmediate2(cb) : requestAnimationFrame(cb);
|
|
133
162
|
const cancel = (h: number): void => {
|
|
134
|
-
if (UNCAPPED)
|
|
163
|
+
if (UNCAPPED) clearImmediate2(h);
|
|
135
164
|
else cancelAnimationFrame(h);
|
|
136
165
|
};
|
|
137
166
|
|