@zkmake/three-meter 0.9.2 → 0.11.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 CHANGED
@@ -142,18 +142,30 @@ second, like a hidden tab, are left out. Read them with `monitor.getFrameStats()
142
142
 
143
143
  ```ts
144
144
  monitor.getFrameStats();
145
- // { frames: 1000, lowFps: 97.6, p99Ms: 10.2, hitches: 3 }
145
+ // { frames: 1000, lowFps: 97.6, p99Ms: 10.2, hitches: 3, refreshHz: 120 }
146
146
  ```
147
147
 
148
+ ## Refresh rate and headroom
149
+
150
+ **Refresh** is the rate the loop runs at when it keeps up: the display's refresh rate, or the app's
151
+ own cap if it throttles itself. It comes from the fastest tenth of recent frames, with each interval
152
+ averaged against the next so a late frame and the early one after it don't read as a faster display,
153
+ then snapped to a common rate (60, 120, 144, …). It needs 60 frames.
154
+
155
+ **Headroom** is the spare time in each frame: the frame budget minus whichever of CPU and GPU took
156
+ longer. At 120 Hz with 3 ms of GPU work that's 5.3 ms. Below zero, frames miss the display's refresh,
157
+ and the row turns amber.
158
+
148
159
  ## Budgets
149
160
 
150
161
  A value past its budget turns amber in the full view and the compact HUD, and its tooltip names the
151
162
  budget. The FPS, CPU and GPU graphs draw the budget as a dashed line once the series reaches it; the
152
163
  scale never stretches to fit it, so a quiet graph keeps its detail.
153
164
 
154
- Timing budgets come from `targetFps` (60 by default): FPS at least 95% of it, 1% low at least half,
155
- CPU and GPU within one frame (16.7 ms), frame p99 within one and a half. Counts have no default,
156
- since what's reasonable depends on the scene. Set your own:
165
+ Timing budgets come from `targetFps`: FPS at least 95% of it, 1% low at least half, CPU and GPU
166
+ within one frame, frame p99 within one and a half, headroom at least zero. Leave `targetFps` out and
167
+ they follow the detected refresh rate, so a 120 Hz display gets 8.3 ms budgets (60 until it's
168
+ detected). Counts have no default, since what's reasonable depends on the scene. Set your own:
157
169
 
158
170
  ```ts
159
171
  mountPerfHud(monitor, { budgets: { targetFps: 120, calls: 500, triangles: 2_000_000 } });
@@ -166,7 +178,7 @@ hud.setBudgets({ gpu: null }); // null drops a default; false drops them all
166
178
 
167
179
  The HUD tells you there are 400 draw calls; **top costs** tells you which objects they come from.
168
180
  Tick it in the full view for the five biggest costs in the main render pass, grouped by **meshes** or
169
- **materials**, sorted by draw calls or triangles. Click a row to log its three objects to the
181
+ **materials**, sorted by draw calls or triangles. Click a row's name to log its three objects to the
170
182
  console.
171
183
 
172
184
  ```text
@@ -186,9 +198,18 @@ walks the scene only while open, twice a second.
186
198
 
187
199
  ```ts
188
200
  monitor.getSceneCost();
189
- // { calls: 309, triangles: 57548, meshes: [{ label: "tree", calls: 300, … }, …], materials: […] }
201
+ // { calls: 309, triangles: 57548, meshes: [{ key: "mesh:tree…", label: "tree", calls: 300, … }, …], materials: […] }
190
202
  ```
191
203
 
204
+ ### Test a cost by hiding it
205
+
206
+ Calls and triangles aren't time. The eye on each row hides its objects, every copy in the scene
207
+ including ones off screen, and the row then shows what that saved: GPU time averaged over 30 frames
208
+ before and after hiding (CPU time where there's no GPU timer), like `−4.3 ms GPU`. Hidden rows stay
209
+ listed so you can show them again. Everything comes back when you untick top costs or the HUD is
210
+ disposed, and objects that were already invisible stay that way. `monitor.getObjectsForKey(key)`
211
+ returns the same objects for a row's `key`.
212
+
192
213
  ## Bug reports
193
214
 
194
215
  The **report** row's copy button puts a Markdown snapshot on the clipboard: versions, backend, GPU,
@@ -196,9 +217,9 @@ the current metrics, the stutter stats, the top three meshes, the viewport and t
196
217
  `formatReport(monitor)` from `@zkmake/three-meter/ui` returns the same text.
197
218
 
198
219
  ```text
199
- three-meter v0.7.0 · three r186 · WebGL2 · Apple M4 Max
220
+ three-meter v0.10.0 · three r186 · WebGL2 · Apple M4 Max
200
221
  FPS 120 · 1% low 98 · p99 10.2 ms · hitches 3 / 1,000 frames
201
- CPU 0.2 ms · GPU 0.7 ms
222
+ CPU 0.2 ms · GPU 0.7 ms · refresh 120 Hz · headroom 7.6 ms
202
223
  Calls 1 · passes 1 · triangles 24,000 · lines 0 · points 0
203
224
  Geometries 1 · textures 1 · shaders 1
204
225
  Top: tree ×300 (300 calls, 9,600 tris) · house (6 calls, 12 tris) · dome (2 calls, 7,936 tris)
@@ -256,12 +277,35 @@ The resolved theme lands on `data-theme` of `.perf-hud` and `.perf-monitor`. To
256
277
  palette, override the `--perf-*` custom properties (`bg`, `fg`, `fg-dim`, `muted`, `row`,
257
278
  `border`, `accent`, `warn`, `shadow`) on those selectors. `warn` is the over-budget amber.
258
279
 
280
+ ## The dev-panel frame
281
+
282
+ The HUD's frame is `mountDevPanel` from `@zkmake/three-meter/ui`: the docked host, a card with a
283
+ brand label on top, and the drag / expand-compact / dim-on-leave discs. Other zkmake dev panels
284
+ (`@zkmake/three-textures`) mount through it too, so they all dock, wake, dim and theme the same way.
285
+ A tool of your own can use it:
286
+
287
+ ```ts
288
+ const panel = mountDevPanel({
289
+ brand: "my-tool",
290
+ label: "My tool",
291
+ content: myElement,
292
+ theme: new HudTheme("system"),
293
+ storageKey: "my-tool",
294
+ onToggle: () => myElement.classList.toggle("is-compact"),
295
+ });
296
+
297
+ panel.detail.textContent = "3 items"; // the brand row's right-hand slot
298
+ ```
299
+
300
+ The card is `.perf-hud__card`, holding `.perf-hud__brand` and your content (the HUD's is
301
+ `.perf-monitor`).
302
+
259
303
  ## Examples
260
304
 
261
- [`examples/site`](https://github.com/zkmake/three-kit/tree/main/examples/site) is what runs at [three-meter.pages.dev](https://three-meter.pages.dev/):
305
+ [`apps/three-meter-site`](https://github.com/zkmake/three-kit/tree/main/apps/three-meter-site) is what runs at [three-meter.pages.dev](https://three-meter.pages.dev/):
262
306
  one Vite app with both integrations of the same scene, swapped from the header.
263
- [`src/demos/vanilla.ts`](https://github.com/zkmake/three-kit/blob/main/examples/site/src/demos/vanilla.ts) is plain three with `mountPerfHud`;
264
- [`src/demos/r3f.tsx`](https://github.com/zkmake/three-kit/blob/main/examples/site/src/demos/r3f.tsx) is React Three Fiber with `PerfSampler` and
307
+ [`src/demos/vanilla.ts`](https://github.com/zkmake/three-kit/blob/main/apps/three-meter-site/src/demos/vanilla.ts) is plain three with `mountPerfHud`;
308
+ [`src/demos/r3f.tsx`](https://github.com/zkmake/three-kit/blob/main/apps/three-meter-site/src/demos/r3f.tsx) is React Three Fiber with `PerfSampler` and
265
309
  `PerfHud`. Both set a 250K triangle budget on top of the timing defaults. `?r3f` opens on Fiber,
266
310
  `?webgpu` uses `WebGPURenderer` in either, `?count=` scales the scene. The header's theme toggle sets the page theme and the HUD's `theme` layer together; the row
267
311
  inside the panel overrides the HUD alone. Run `bun run dev` inside it after a `bun install` at the repo root.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as GpuTiming, c as RenderBackend, d as Sample, f as SceneCost, i as FrameStats, l as RenderCounts, n as CostEntry, o as PerfRenderer, p as TimingMetric, r as Environment, s as PerformanceMonitorOptions, t as PerformanceMonitor, u as ResourceCounts } from "./performance-monitor-DgHxeQ2X.js";
1
+ import { a as GpuTiming, c as RenderBackend, d as Sample, f as SceneCost, i as FrameStats, l as RenderCounts, n as CostEntry, o as PerfRenderer, p as TimingMetric, r as Environment, s as PerformanceMonitorOptions, t as PerformanceMonitor, u as ResourceCounts } from "./performance-monitor-BoY_-GTt.js";
2
2
  //#region src/core/ring-buffer.d.ts
3
3
  /**
4
4
  * Fixed-capacity numeric ring buffer. Backs the per-frame timing history the
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as RingBuffer, t as PerformanceMonitor } from "./performance-monitor-DsBp13ts.js";
1
+ import { n as RingBuffer, t as PerformanceMonitor } from "./performance-monitor-BqnoiLEs.js";
2
2
  //#region src/core/wrap-animation-loop.ts
3
3
  /**
4
4
  * Wrap a `renderer.setAnimationLoop` callback so each tick is one frame: