@aardworx/wombat.rendering 0.19.18 → 0.19.20
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 +37 -3
- package/dist/window/loop.js.map +1 -1
- package/package.json +1 -1
- package/src/window/loop.ts +38 -3
|
@@ -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;AAyBpD,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,CA6FlB"}
|
package/dist/window/loop.js
CHANGED
|
@@ -22,12 +22,34 @@
|
|
|
22
22
|
//
|
|
23
23
|
// Returns a `stop()` to cancel the loop and clear the subscription.
|
|
24
24
|
import { AVal, transact } from "@aardworx/wombat.adaptive";
|
|
25
|
+
// ─── Benchmark toggles ─────────────────────────────────────────────────
|
|
26
|
+
//
|
|
27
|
+
// `globalThis.__wombatUncappedRenderLoop = true` (set BEFORE the loop
|
|
28
|
+
// starts) schedules frames via setTimeout(0) instead of
|
|
29
|
+
// requestAnimationFrame — no vsync clamp; with the standard
|
|
30
|
+
// `onSubmittedWorkDone` pacer the loop then runs at true GPU
|
|
31
|
+
// completion rate. The canvas still presents whatever frame is
|
|
32
|
+
// latest. When uncapped, `globalThis.__wombatFrameCount` increments
|
|
33
|
+
// AFTER each frame's pacer resolves (i.e. GPU work done), so a
|
|
34
|
+
// harness can serialize edit → frame-complete → next edit and read
|
|
35
|
+
// honest end-to-end frame costs.
|
|
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
|
+
}
|
|
42
|
+
function bumpFrameCount() {
|
|
43
|
+
const g = globalThis;
|
|
44
|
+
g.__wombatFrameCount = (g.__wombatFrameCount ?? 0) + 1;
|
|
45
|
+
}
|
|
25
46
|
export function runFrame(attachment, frame, opts = {}) {
|
|
26
47
|
let stopped = false;
|
|
27
48
|
let frameNo = 0;
|
|
28
49
|
let lastTime = performance.now();
|
|
29
50
|
let rafId = 0;
|
|
30
51
|
let pending = false;
|
|
52
|
+
const UNCAPPED = isUncapped();
|
|
31
53
|
// Wrap the frame callback in an AVal so the adaptive system tracks
|
|
32
54
|
// its dependency set. Each `force()` re-reads the inputs and runs
|
|
33
55
|
// the frame; subsequent input marks fire the marking callback.
|
|
@@ -50,6 +72,9 @@ export function runFrame(attachment, frame, opts = {}) {
|
|
|
50
72
|
const finalizeFrame = () => {
|
|
51
73
|
if (stopped)
|
|
52
74
|
return;
|
|
75
|
+
// pacer (GPU completion) has resolved by now — this frame is DONE
|
|
76
|
+
if (UNCAPPED)
|
|
77
|
+
bumpFrameCount();
|
|
53
78
|
if (opts.onAfterFrame !== undefined) {
|
|
54
79
|
transact(opts.onAfterFrame);
|
|
55
80
|
}
|
|
@@ -58,6 +83,15 @@ export function runFrame(attachment, frame, opts = {}) {
|
|
|
58
83
|
sub.dispose();
|
|
59
84
|
}
|
|
60
85
|
};
|
|
86
|
+
const schedule = (cb) => UNCAPPED
|
|
87
|
+
? setTimeout(cb, 0)
|
|
88
|
+
: requestAnimationFrame(cb);
|
|
89
|
+
const cancel = (h) => {
|
|
90
|
+
if (UNCAPPED)
|
|
91
|
+
clearTimeout(h);
|
|
92
|
+
else
|
|
93
|
+
cancelAnimationFrame(h);
|
|
94
|
+
};
|
|
61
95
|
const tick = () => {
|
|
62
96
|
if (stopped)
|
|
63
97
|
return;
|
|
@@ -87,16 +121,16 @@ export function runFrame(attachment, frame, opts = {}) {
|
|
|
87
121
|
if (pending || stopped)
|
|
88
122
|
return;
|
|
89
123
|
pending = true;
|
|
90
|
-
rafId =
|
|
124
|
+
rafId = schedule(tick);
|
|
91
125
|
});
|
|
92
126
|
// Initial render. Schedules subsequent frames only when adaptive
|
|
93
127
|
// marks reach `renderAval` (via the marking callback above).
|
|
94
128
|
pending = true;
|
|
95
|
-
rafId =
|
|
129
|
+
rafId = schedule(tick);
|
|
96
130
|
return {
|
|
97
131
|
stop() {
|
|
98
132
|
stopped = true;
|
|
99
|
-
|
|
133
|
+
cancel(rafId);
|
|
100
134
|
sub.dispose();
|
|
101
135
|
},
|
|
102
136
|
};
|
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;
|
|
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.20",
|
|
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
|
@@ -26,6 +26,29 @@ import type { aval, AdaptiveToken, IDisposable } from "@aardworx/wombat.adaptive
|
|
|
26
26
|
import { AVal, transact } from "@aardworx/wombat.adaptive";
|
|
27
27
|
import type { CanvasAttachment } from "./canvas.js";
|
|
28
28
|
|
|
29
|
+
// ─── Benchmark toggles ─────────────────────────────────────────────────
|
|
30
|
+
//
|
|
31
|
+
// `globalThis.__wombatUncappedRenderLoop = true` (set BEFORE the loop
|
|
32
|
+
// starts) schedules frames via setTimeout(0) instead of
|
|
33
|
+
// requestAnimationFrame — no vsync clamp; with the standard
|
|
34
|
+
// `onSubmittedWorkDone` pacer the loop then runs at true GPU
|
|
35
|
+
// completion rate. The canvas still presents whatever frame is
|
|
36
|
+
// latest. When uncapped, `globalThis.__wombatFrameCount` increments
|
|
37
|
+
// AFTER each frame's pacer resolves (i.e. GPU work done), so a
|
|
38
|
+
// harness can serialize edit → frame-complete → next edit and read
|
|
39
|
+
// honest end-to-end frame costs.
|
|
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)
|
|
44
|
+
.__wombatUncappedRenderLoop === true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function bumpFrameCount(): void {
|
|
48
|
+
const g = globalThis as Record<string, unknown> & typeof globalThis;
|
|
49
|
+
g.__wombatFrameCount = ((g.__wombatFrameCount as number | undefined) ?? 0) + 1;
|
|
50
|
+
}
|
|
51
|
+
|
|
29
52
|
export interface RunFrameOptions {
|
|
30
53
|
/** Stop after N frames. Useful for tests + finite animations. */
|
|
31
54
|
readonly maxFrames?: number;
|
|
@@ -73,6 +96,7 @@ export function runFrame(
|
|
|
73
96
|
let lastTime = performance.now();
|
|
74
97
|
let rafId = 0;
|
|
75
98
|
let pending = false;
|
|
99
|
+
const UNCAPPED = isUncapped();
|
|
76
100
|
|
|
77
101
|
// Wrap the frame callback in an AVal so the adaptive system tracks
|
|
78
102
|
// its dependency set. Each `force()` re-reads the inputs and runs
|
|
@@ -95,6 +119,8 @@ export function runFrame(
|
|
|
95
119
|
|
|
96
120
|
const finalizeFrame = (): void => {
|
|
97
121
|
if (stopped) return;
|
|
122
|
+
// pacer (GPU completion) has resolved by now — this frame is DONE
|
|
123
|
+
if (UNCAPPED) bumpFrameCount();
|
|
98
124
|
if (opts.onAfterFrame !== undefined) {
|
|
99
125
|
transact(opts.onAfterFrame);
|
|
100
126
|
}
|
|
@@ -104,6 +130,15 @@ export function runFrame(
|
|
|
104
130
|
}
|
|
105
131
|
};
|
|
106
132
|
|
|
133
|
+
const schedule = (cb: () => void): number =>
|
|
134
|
+
UNCAPPED
|
|
135
|
+
? (setTimeout(cb, 0) as unknown as number)
|
|
136
|
+
: requestAnimationFrame(cb);
|
|
137
|
+
const cancel = (h: number): void => {
|
|
138
|
+
if (UNCAPPED) clearTimeout(h);
|
|
139
|
+
else cancelAnimationFrame(h);
|
|
140
|
+
};
|
|
141
|
+
|
|
107
142
|
const tick = (): void => {
|
|
108
143
|
if (stopped) return;
|
|
109
144
|
pending = false;
|
|
@@ -133,18 +168,18 @@ export function runFrame(
|
|
|
133
168
|
}).addMarkingCallback(() => {
|
|
134
169
|
if (pending || stopped) return;
|
|
135
170
|
pending = true;
|
|
136
|
-
rafId =
|
|
171
|
+
rafId = schedule(tick);
|
|
137
172
|
});
|
|
138
173
|
|
|
139
174
|
// Initial render. Schedules subsequent frames only when adaptive
|
|
140
175
|
// marks reach `renderAval` (via the marking callback above).
|
|
141
176
|
pending = true;
|
|
142
|
-
rafId =
|
|
177
|
+
rafId = schedule(tick);
|
|
143
178
|
|
|
144
179
|
return {
|
|
145
180
|
stop() {
|
|
146
181
|
stopped = true;
|
|
147
|
-
|
|
182
|
+
cancel(rafId);
|
|
148
183
|
sub.dispose();
|
|
149
184
|
},
|
|
150
185
|
};
|