@graphty/webgpu-graph-algorithms 0.5.1 → 0.6.1

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 (243) hide show
  1. package/README.md +459 -58
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{context-BR7fx3vR.js → context-BXqgCifx.js} +190 -40
  4. package/dist/chunks/context-BXqgCifx.js.map +1 -0
  5. package/dist/node.js +1 -1
  6. package/dist/src/algorithms/components.d.ts.map +1 -1
  7. package/dist/src/algorithms/components.js +12 -13
  8. package/dist/src/algorithms/components.js.map +1 -1
  9. package/dist/src/algorithms/degree.d.ts +6 -8
  10. package/dist/src/algorithms/degree.d.ts.map +1 -1
  11. package/dist/src/algorithms/degree.js +58 -35
  12. package/dist/src/algorithms/degree.js.map +1 -1
  13. package/dist/src/algorithms/pagerank.d.ts.map +1 -1
  14. package/dist/src/algorithms/pagerank.js +16 -14
  15. package/dist/src/algorithms/pagerank.js.map +1 -1
  16. package/dist/src/algorithms/power-iteration.d.ts +2 -2
  17. package/dist/src/algorithms/power-iteration.d.ts.map +1 -1
  18. package/dist/src/algorithms/power-iteration.js +17 -14
  19. package/dist/src/algorithms/power-iteration.js.map +1 -1
  20. package/dist/src/constants.d.ts +38 -8
  21. package/dist/src/constants.d.ts.map +1 -1
  22. package/dist/src/constants.js +38 -8
  23. package/dist/src/constants.js.map +1 -1
  24. package/dist/src/errors.d.ts +3 -2
  25. package/dist/src/errors.d.ts.map +1 -1
  26. package/dist/src/errors.js +2 -1
  27. package/dist/src/errors.js.map +1 -1
  28. package/dist/src/index.d.ts +6 -4
  29. package/dist/src/index.d.ts.map +1 -1
  30. package/dist/src/index.js +8 -3
  31. package/dist/src/index.js.map +1 -1
  32. package/dist/src/kernel/dispatch.d.ts +8 -3
  33. package/dist/src/kernel/dispatch.d.ts.map +1 -1
  34. package/dist/src/kernel/dispatch.js +18 -7
  35. package/dist/src/kernel/dispatch.js.map +1 -1
  36. package/dist/src/kernel/kernel.d.ts +30 -1
  37. package/dist/src/kernel/kernel.d.ts.map +1 -1
  38. package/dist/src/kernel/kernel.js +49 -5
  39. package/dist/src/kernel/kernel.js.map +1 -1
  40. package/dist/src/kernel/prelude.d.ts.map +1 -1
  41. package/dist/src/kernel/prelude.js +6 -1
  42. package/dist/src/kernel/prelude.js.map +1 -1
  43. package/dist/src/kernel/profiler.d.ts +15 -3
  44. package/dist/src/kernel/profiler.d.ts.map +1 -1
  45. package/dist/src/kernel/profiler.js +27 -4
  46. package/dist/src/kernel/profiler.js.map +1 -1
  47. package/dist/src/kernels.d.ts +17 -7
  48. package/dist/src/kernels.d.ts.map +1 -1
  49. package/dist/src/kernels.js +323 -16
  50. package/dist/src/kernels.js.map +1 -1
  51. package/dist/src/layouts/calibrate.d.ts +51 -0
  52. package/dist/src/layouts/calibrate.d.ts.map +1 -0
  53. package/dist/src/layouts/calibrate.js +172 -0
  54. package/dist/src/layouts/calibrate.js.map +1 -0
  55. package/dist/src/layouts/force-simulation.d.ts +39 -4
  56. package/dist/src/layouts/force-simulation.d.ts.map +1 -1
  57. package/dist/src/layouts/force-simulation.js +71 -19
  58. package/dist/src/layouts/force-simulation.js.map +1 -1
  59. package/dist/src/layouts/forceatlas2.d.ts +107 -36
  60. package/dist/src/layouts/forceatlas2.d.ts.map +1 -1
  61. package/dist/src/layouts/forceatlas2.js +296 -100
  62. package/dist/src/layouts/forceatlas2.js.map +1 -1
  63. package/dist/src/layouts/fruchterman-reingold.d.ts +73 -27
  64. package/dist/src/layouts/fruchterman-reingold.d.ts.map +1 -1
  65. package/dist/src/layouts/fruchterman-reingold.js +230 -70
  66. package/dist/src/layouts/fruchterman-reingold.js.map +1 -1
  67. package/dist/src/layouts/model-common.d.ts +41 -3
  68. package/dist/src/layouts/model-common.d.ts.map +1 -1
  69. package/dist/src/layouts/model-common.js +74 -3
  70. package/dist/src/layouts/model-common.js.map +1 -1
  71. package/dist/src/layouts/repulsion-grid.d.ts +152 -0
  72. package/dist/src/layouts/repulsion-grid.d.ts.map +1 -0
  73. package/dist/src/layouts/repulsion-grid.js +318 -0
  74. package/dist/src/layouts/repulsion-grid.js.map +1 -0
  75. package/dist/src/layouts/spring-electrical.d.ts +75 -30
  76. package/dist/src/layouts/spring-electrical.d.ts.map +1 -1
  77. package/dist/src/layouts/spring-electrical.js +231 -74
  78. package/dist/src/layouts/spring-electrical.js.map +1 -1
  79. package/dist/src/memory/residency.d.ts +6 -2
  80. package/dist/src/memory/residency.d.ts.map +1 -1
  81. package/dist/src/memory/residency.js +84 -14
  82. package/dist/src/memory/residency.js.map +1 -1
  83. package/dist/src/primitives/core-shape.d.ts +38 -2
  84. package/dist/src/primitives/core-shape.d.ts.map +1 -1
  85. package/dist/src/primitives/core-shape.js +71 -3
  86. package/dist/src/primitives/core-shape.js.map +1 -1
  87. package/dist/src/primitives/grid-pyramid.d.ts +71 -0
  88. package/dist/src/primitives/grid-pyramid.d.ts.map +1 -0
  89. package/dist/src/primitives/grid-pyramid.js +143 -0
  90. package/dist/src/primitives/grid-pyramid.js.map +1 -0
  91. package/dist/src/primitives/grid.d.ts +118 -0
  92. package/dist/src/primitives/grid.d.ts.map +1 -0
  93. package/dist/src/primitives/grid.js +225 -0
  94. package/dist/src/primitives/grid.js.map +1 -0
  95. package/dist/src/primitives/histogram.d.ts +67 -0
  96. package/dist/src/primitives/histogram.d.ts.map +1 -0
  97. package/dist/src/primitives/histogram.js +190 -0
  98. package/dist/src/primitives/histogram.js.map +1 -0
  99. package/dist/src/primitives/radix-sort.d.ts +75 -0
  100. package/dist/src/primitives/radix-sort.d.ts.map +1 -0
  101. package/dist/src/primitives/radix-sort.js +168 -0
  102. package/dist/src/primitives/radix-sort.js.map +1 -0
  103. package/dist/src/primitives/scan.d.ts +44 -0
  104. package/dist/src/primitives/scan.d.ts.map +1 -0
  105. package/dist/src/primitives/scan.js +151 -0
  106. package/dist/src/primitives/scan.js.map +1 -0
  107. package/dist/src/primitives/segmented-reduce.d.ts +25 -17
  108. package/dist/src/primitives/segmented-reduce.d.ts.map +1 -1
  109. package/dist/src/primitives/segmented-reduce.js +166 -47
  110. package/dist/src/primitives/segmented-reduce.js.map +1 -1
  111. package/dist/src/primitives/spmv.d.ts +18 -14
  112. package/dist/src/primitives/spmv.d.ts.map +1 -1
  113. package/dist/src/primitives/spmv.js +94 -58
  114. package/dist/src/primitives/spmv.js.map +1 -1
  115. package/dist/src/primitives/verify.d.ts +49 -0
  116. package/dist/src/primitives/verify.d.ts.map +1 -0
  117. package/dist/src/primitives/verify.js +229 -0
  118. package/dist/src/primitives/verify.js.map +1 -0
  119. package/dist/src/types/context.d.ts +53 -0
  120. package/dist/src/types/context.d.ts.map +1 -1
  121. package/dist/src/types/layout.d.ts +20 -0
  122. package/dist/src/types/layout.d.ts.map +1 -1
  123. package/dist/src/wgsl/counting-scatter.wgsl.d.ts +8 -0
  124. package/dist/src/wgsl/counting-scatter.wgsl.d.ts.map +1 -0
  125. package/dist/src/wgsl/counting-scatter.wgsl.js +17 -0
  126. package/dist/src/wgsl/counting-scatter.wgsl.js.map +1 -0
  127. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +23 -11
  128. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -1
  129. package/dist/src/wgsl/fa2-attraction.wgsl.js +98 -20
  130. package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -1
  131. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +6 -2
  132. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -1
  133. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +22 -1
  134. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -1
  135. package/dist/src/wgsl/grid-cell-key.wgsl.d.ts +8 -0
  136. package/dist/src/wgsl/grid-cell-key.wgsl.d.ts.map +1 -0
  137. package/dist/src/wgsl/grid-cell-key.wgsl.js +30 -0
  138. package/dist/src/wgsl/grid-cell-key.wgsl.js.map +1 -0
  139. package/dist/src/wgsl/grid-centroid-hub.wgsl.d.ts +8 -0
  140. package/dist/src/wgsl/grid-centroid-hub.wgsl.d.ts.map +1 -0
  141. package/dist/src/wgsl/grid-centroid-hub.wgsl.js +29 -0
  142. package/dist/src/wgsl/grid-centroid-hub.wgsl.js.map +1 -0
  143. package/dist/src/wgsl/grid-centroid.wgsl.d.ts +8 -0
  144. package/dist/src/wgsl/grid-centroid.wgsl.d.ts.map +1 -0
  145. package/dist/src/wgsl/grid-centroid.wgsl.js +29 -0
  146. package/dist/src/wgsl/grid-centroid.wgsl.js.map +1 -0
  147. package/dist/src/wgsl/grid-downsample.wgsl.d.ts +7 -0
  148. package/dist/src/wgsl/grid-downsample.wgsl.d.ts.map +1 -0
  149. package/dist/src/wgsl/grid-downsample.wgsl.js +28 -0
  150. package/dist/src/wgsl/grid-downsample.wgsl.js.map +1 -0
  151. package/dist/src/wgsl/grid-far-field.wgsl.d.ts +13 -0
  152. package/dist/src/wgsl/grid-far-field.wgsl.d.ts.map +1 -0
  153. package/dist/src/wgsl/grid-far-field.wgsl.js +98 -0
  154. package/dist/src/wgsl/grid-far-field.wgsl.js.map +1 -0
  155. package/dist/src/wgsl/grid-near-field.wgsl.d.ts +19 -0
  156. package/dist/src/wgsl/grid-near-field.wgsl.d.ts.map +1 -0
  157. package/dist/src/wgsl/grid-near-field.wgsl.js +129 -0
  158. package/dist/src/wgsl/grid-near-field.wgsl.js.map +1 -0
  159. package/dist/src/wgsl/histogram.wgsl.d.ts +7 -0
  160. package/dist/src/wgsl/histogram.wgsl.d.ts.map +1 -0
  161. package/dist/src/wgsl/histogram.wgsl.js +15 -0
  162. package/dist/src/wgsl/histogram.wgsl.js.map +1 -0
  163. package/dist/src/wgsl/indirect-finalize.wgsl.d.ts +8 -0
  164. package/dist/src/wgsl/indirect-finalize.wgsl.d.ts.map +1 -0
  165. package/dist/src/wgsl/indirect-finalize.wgsl.js +26 -0
  166. package/dist/src/wgsl/indirect-finalize.wgsl.js.map +1 -0
  167. package/dist/src/wgsl/radix-hist.wgsl.d.ts +9 -0
  168. package/dist/src/wgsl/radix-hist.wgsl.d.ts.map +1 -0
  169. package/dist/src/wgsl/radix-hist.wgsl.js +31 -0
  170. package/dist/src/wgsl/radix-hist.wgsl.js.map +1 -0
  171. package/dist/src/wgsl/radix-scatter.wgsl.d.ts +9 -0
  172. package/dist/src/wgsl/radix-scatter.wgsl.d.ts.map +1 -0
  173. package/dist/src/wgsl/radix-scatter.wgsl.js +40 -0
  174. package/dist/src/wgsl/radix-scatter.wgsl.js.map +1 -0
  175. package/dist/src/wgsl/scan-add.wgsl.d.ts +6 -0
  176. package/dist/src/wgsl/scan-add.wgsl.d.ts.map +1 -0
  177. package/dist/src/wgsl/scan-add.wgsl.js +14 -0
  178. package/dist/src/wgsl/scan-add.wgsl.js.map +1 -0
  179. package/dist/src/wgsl/scan-block.wgsl.d.ts +8 -0
  180. package/dist/src/wgsl/scan-block.wgsl.d.ts.map +1 -0
  181. package/dist/src/wgsl/scan-block.wgsl.js +30 -0
  182. package/dist/src/wgsl/scan-block.wgsl.js.map +1 -0
  183. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts +22 -8
  184. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts.map +1 -1
  185. package/dist/src/wgsl/segmented-reduce.wgsl.js +84 -15
  186. package/dist/src/wgsl/segmented-reduce.wgsl.js.map +1 -1
  187. package/dist/src/wgsl/spmv-pull.wgsl.d.ts +22 -11
  188. package/dist/src/wgsl/spmv-pull.wgsl.d.ts.map +1 -1
  189. package/dist/src/wgsl/spmv-pull.wgsl.js +110 -36
  190. package/dist/src/wgsl/spmv-pull.wgsl.js.map +1 -1
  191. package/dist/tsconfig.build.tsbuildinfo +1 -1
  192. package/dist/webgpu-graph-algorithms.js +3815 -1003
  193. package/dist/webgpu-graph-algorithms.js.map +1 -1
  194. package/package.json +9 -8
  195. package/src/algorithms/components.ts +12 -16
  196. package/src/algorithms/degree.ts +58 -43
  197. package/src/algorithms/pagerank.ts +20 -18
  198. package/src/algorithms/power-iteration.ts +19 -18
  199. package/src/constants.ts +38 -8
  200. package/src/errors.ts +3 -1
  201. package/src/index.ts +14 -4
  202. package/src/kernel/dispatch.ts +18 -7
  203. package/src/kernel/kernel.ts +59 -5
  204. package/src/kernel/prelude.ts +9 -0
  205. package/src/kernel/profiler.ts +28 -4
  206. package/src/kernels.ts +356 -18
  207. package/src/layouts/calibrate.ts +187 -0
  208. package/src/layouts/force-simulation.ts +91 -23
  209. package/src/layouts/forceatlas2.ts +331 -106
  210. package/src/layouts/fruchterman-reingold.ts +255 -74
  211. package/src/layouts/model-common.ts +98 -3
  212. package/src/layouts/repulsion-grid.ts +451 -0
  213. package/src/layouts/spring-electrical.ts +257 -78
  214. package/src/memory/residency.ts +126 -20
  215. package/src/primitives/core-shape.ts +91 -4
  216. package/src/primitives/grid-pyramid.ts +221 -0
  217. package/src/primitives/grid.ts +349 -0
  218. package/src/primitives/histogram.ts +273 -0
  219. package/src/primitives/radix-sort.ts +246 -0
  220. package/src/primitives/scan.ts +197 -0
  221. package/src/primitives/segmented-reduce.ts +214 -56
  222. package/src/primitives/spmv.ts +125 -65
  223. package/src/primitives/verify.ts +249 -0
  224. package/src/types/context.ts +56 -0
  225. package/src/types/layout.ts +22 -0
  226. package/src/wgsl/counting-scatter.wgsl.ts +16 -0
  227. package/src/wgsl/fa2-attraction.wgsl.ts +98 -20
  228. package/src/wgsl/fa2-stats-finalize.wgsl.ts +22 -1
  229. package/src/wgsl/grid-cell-key.wgsl.ts +29 -0
  230. package/src/wgsl/grid-centroid-hub.wgsl.ts +28 -0
  231. package/src/wgsl/grid-centroid.wgsl.ts +28 -0
  232. package/src/wgsl/grid-downsample.wgsl.ts +27 -0
  233. package/src/wgsl/grid-far-field.wgsl.ts +97 -0
  234. package/src/wgsl/grid-near-field.wgsl.ts +128 -0
  235. package/src/wgsl/histogram.wgsl.ts +14 -0
  236. package/src/wgsl/indirect-finalize.wgsl.ts +25 -0
  237. package/src/wgsl/radix-hist.wgsl.ts +30 -0
  238. package/src/wgsl/radix-scatter.wgsl.ts +39 -0
  239. package/src/wgsl/scan-add.wgsl.ts +13 -0
  240. package/src/wgsl/scan-block.wgsl.ts +29 -0
  241. package/src/wgsl/segmented-reduce.wgsl.ts +84 -15
  242. package/src/wgsl/spmv-pull.wgsl.ts +110 -36
  243. package/dist/chunks/context-BR7fx3vR.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calibrate.d.ts","sourceRoot":"","sources":["../../../src/layouts/calibrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIhF,wGAAwG;AACxG,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAAoC,CAAC;AAqFlF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAClC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACzC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACzC,MAAM,CAQR;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAgC1G"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * calibrateLayout (spec 2.2, 7.8, D26; contract 3.3): the layout-tier micro-benchmark a consumer runs ONCE, off the
3
+ * critical path, to measure the exact / grid crossover on the actual device. For every probed size it builds a seeded
4
+ * G(n, 10n) snapshot, runs ForceAtlas2 on the exact tier and on the grid tier -- one untimed `step(1)` after
5
+ * `load()` (which warms every pipeline through `PipelineCache.warm` of the model's specs, so the first timed step
6
+ * compiles nothing) and then TIMED_ITERATIONS timed `step(1)` calls whose `stats.msPerIteration` (the profiler's GPU
7
+ * time when "timestamp-query" was granted, else the batch wall time) are averaged -- and releases the probe.
8
+ *
9
+ * PLAN DECISION PD-23 (P4-T14): `src/` cannot import `test/helpers` or `benchmarks/`, so the probe graphs are built
10
+ * here from the package's own LCG (`Lcg`, seed.ts) with a fixed seed, and the spec 7.8 rule is re-implemented in
11
+ * `suggestedExactMaxNodes` below; its twin is `exactMaxNodesFromLadder` in benchmarks/layout-exact.bench.ts (the
12
+ * one copy the G3 / G4 records apply to the committed baselines), which test/layouts/calibrate.test.ts compares it
13
+ * with. The function reads `caps` for nothing: never `caps.software` (spec 7.8, Q-6), so on a software adapter it
14
+ * returns honest numbers a caller can compare in shape, never in value.
15
+ */
16
+ import { fromEdgeArrays } from "@graphty/graph-format";
17
+ import { WebGpuGraphError } from "../errors.js";
18
+ import { assertDeviceComputes } from "../primitives/verify.js";
19
+ import { createForceAtlas2 } from "./forceatlas2.js";
20
+ import { Lcg } from "./seed.js";
21
+ /** The default probe sizes (spec 2.2): the 8k-65k subset of the exact ladder of spec 7.8 / 10.4 T-4. */
22
+ export const CALIBRATE_SIZES = [8192, 16384, 32768, 65536];
23
+ /** The spec 7.8 per-iteration budget of the exact tier, milliseconds (the twin of EXACT_BUDGET_MS in benchmarks/layout-exact.bench.ts). */
24
+ const BUDGET_MS = 4;
25
+ /** Edges per node of every probe graph (E = 10n, the density of the exact ladder). */
26
+ const EDGES_PER_NODE = 10;
27
+ /** Timed iterations per size and tier (spec 2.2: "10 timed iterations"). */
28
+ const TIMED_ITERATIONS = 10;
29
+ /** The seed of every probe graph and of the simulation's own LCG. */
30
+ const SEED = 12345;
31
+ /**
32
+ * A seeded G(n, 10n) probe snapshot (self-loops and parallels allowed, unweighted, undirected).
33
+ * @param n - the node count
34
+ * @returns the snapshot
35
+ */
36
+ function probeSnapshot(n) {
37
+ const m = EDGES_PER_NODE * n;
38
+ const rng = new Lcg(SEED);
39
+ const src = new Uint32Array(m);
40
+ const dst = new Uint32Array(m);
41
+ for (let e = 0; e < m; e++) {
42
+ src[e] = Math.floor(rng.next() * n);
43
+ dst[e] = Math.floor(rng.next() * n);
44
+ }
45
+ return fromEdgeArrays({ directed: false, nodeCount: n, src, dst }, { label: `calibrate/${n}` });
46
+ }
47
+ /**
48
+ * The mean ms per iteration of one tier at one size: one untimed step after load(), then TIMED_ITERATIONS timed
49
+ * steps (reheat() before each so a settled simulation never short-circuits). With the profiler (a device that granted
50
+ * "timestamp-query") the sample is the GPU time of the iteration's passes, the quantity the spec 7.8 rule reads; without
51
+ * it the sample is the step's wall time, which also carries the JS submit and the 12n-byte readback -- a fixed cost of
52
+ * ~1-2 ms on a discrete card that is the same for either tier, so the wall ratio understates the grid tier's
53
+ * advantage at every size and the crossover it suggests is, if anything, too high.
54
+ * @param ctx - the context
55
+ * @param snapshot - the probe snapshot
56
+ * @param tier - the repulsion tier to force
57
+ * @returns milliseconds per iteration
58
+ */
59
+ async function probeTier(ctx, snapshot, tier) {
60
+ const n = snapshot.nodeCount;
61
+ const positions = new Float32Array(3 * n).fill(Number.NaN);
62
+ const sim = createForceAtlas2(ctx, {
63
+ dim: 2,
64
+ seed: SEED,
65
+ maxIter: 1000000,
66
+ iterationsPerStep: 1,
67
+ maxInFlight: 1,
68
+ repulsion: tier,
69
+ compat: "paper",
70
+ });
71
+ try {
72
+ sim.load(snapshot, positions);
73
+ await sim.step(1);
74
+ let total = 0;
75
+ for (let i = 0; i < TIMED_ITERATIONS; i++) {
76
+ sim.reheat();
77
+ const start = performance.now();
78
+ await sim.step(1);
79
+ const wall = performance.now() - start;
80
+ total += sim.stats.msPerIteration ?? wall;
81
+ }
82
+ return total / TIMED_ITERATIONS;
83
+ }
84
+ finally {
85
+ sim.dispose();
86
+ }
87
+ }
88
+ /**
89
+ * The largest power of two that is <= n (the twin of floorPow2 in benchmarks/layout-exact.bench.ts).
90
+ * @param n - a number >= 1
91
+ * @returns the largest power of two not above n
92
+ */
93
+ function floorPow2(n) {
94
+ let p = 1;
95
+ while (p * 2 <= n) {
96
+ p *= 2;
97
+ }
98
+ return p;
99
+ }
100
+ /**
101
+ * The spec 7.8 rule over the probed sizes (the twin of exactMaxNodesFromLadder(rows, budget, gridRows) in
102
+ * benchmarks/layout-exact.bench.ts, which test/layouts/calibrate.test.ts compares it with): the largest probed n with
103
+ * exactMs(n) <= BUDGET_MS and exactMs(n) <= gridMs(n), rounded down to a power of two.
104
+ *
105
+ * CONTRACT DECISION (the review of P4-T14; spec 2.2 is silent): when NO probed size satisfies the rule -- the grid
106
+ * tier faster than the exact tier at every probe (the RTX 4070 SUPER with the default sizes: the grid beats the exact
107
+ * tier from 4k up), or every probe over the budget -- the benchmark twin throws and hands the value to an owner
108
+ * decision (spec 10.4), which a library call cannot do. The answer here is then the largest power of two STRICTLY
109
+ * BELOW the smallest probe (1 when the smallest probe is 1): the exact tier runs at no probed size, the unprobed range
110
+ * below keeps the exact tier (whose cost falls with n^2 and is the oracle), and the value is distinguishable from a
111
+ * rule answer, which is never below floorPow2(min(sizes)). A caller that wants the crossover itself probes smaller
112
+ * sizes (the T-4 ladder from 1k); one that wants the exact tier nowhere passes `repulsion: "grid"`.
113
+ * @param sizes - the probed sizes (integers >= 1)
114
+ * @param exactMs - ms per iteration of the exact tier per size
115
+ * @param gridMs - ms per iteration of the grid tier per size
116
+ * @returns the suggested exactMaxNodes
117
+ */
118
+ export function suggestedExactMaxNodes(sizes, exactMs, gridMs) {
119
+ let best = 0;
120
+ for (const n of sizes) {
121
+ if (exactMs[n] <= BUDGET_MS && exactMs[n] <= gridMs[n] && n > best) {
122
+ best = n;
123
+ }
124
+ }
125
+ return floorPow2(best === 0 ? Math.max(1, Math.min(...sizes) - 1) : best);
126
+ }
127
+ /**
128
+ * Spec 2.2 calibrateLayout, verbatim: measures ms per iteration of the exact and the grid repulsion tier at every
129
+ * probed size on THIS device and suggests `exactMaxNodes` by the spec 7.8 rule (`suggestedExactMaxNodes` above, with
130
+ * its below-the-range answer when no probed size qualifies). Every probe graph is built here and released before the
131
+ * call returns; `firstCallMs` is the wall time of the whole call (pipeline compilation included the first time). The
132
+ * app passes `suggestedExactMaxNodes` through `createAccelerator(ctx, { layout: { exactMaxNodes } })`; the package
133
+ * never calls this implicitly and `"auto"` never depends on `caps.software`.
134
+ * @param ctx - the context (E_DISPOSED / E_DEVICE_LOST through assertReady)
135
+ * @param options - the probe sizes (positive integers; default CALIBRATE_SIZES)
136
+ * @returns the calibration record
137
+ */
138
+ export async function calibrateLayout(ctx, options) {
139
+ ctx.assertReady();
140
+ await assertDeviceComputes(ctx);
141
+ const sizes = options?.sizes ?? CALIBRATE_SIZES;
142
+ if (!Array.isArray(sizes) || sizes.length === 0 || !sizes.every((n) => Number.isInteger(n) && n >= 1)) {
143
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", "sizes must be a non-empty list of integers >= 1", {
144
+ argument: "sizes",
145
+ value: sizes,
146
+ expected: "a non-empty list of integers >= 1",
147
+ });
148
+ }
149
+ const start = performance.now();
150
+ const exactMsPerIter = {};
151
+ const gridMsPerIter = {};
152
+ for (const n of sizes) {
153
+ const snapshot = probeSnapshot(n);
154
+ try {
155
+ exactMsPerIter[n] = await probeTier(ctx, snapshot, "exact");
156
+ gridMsPerIter[n] = await probeTier(ctx, snapshot, "grid");
157
+ }
158
+ finally {
159
+ ctx.release(snapshot);
160
+ }
161
+ }
162
+ const largest = Math.max(...sizes);
163
+ const pairs = largest * (largest - 1);
164
+ return {
165
+ pairsPerSecond: (pairs / exactMsPerIter[largest]) * 1000,
166
+ exactMsPerIter,
167
+ gridMsPerIter,
168
+ suggestedExactMaxNodes: suggestedExactMaxNodes(sizes, exactMsPerIter, gridMsPerIter),
169
+ firstCallMs: performance.now() - start,
170
+ };
171
+ }
172
+ //# sourceMappingURL=calibrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calibrate.js","sourceRoot":"","sources":["../../../src/layouts/calibrate.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,9 @@ import { type PipelineCache } from "../kernel/pipeline-cache.js";
14
14
  import { type UniformBlock, type UniformValues } from "../kernel/struct-block.js";
15
15
  import { UniformRing } from "../kernel/uniform-ring.js";
16
16
  import { type WgslModuleSpec } from "../kernel/wgsl.js";
17
+ import { type BufferPool } from "../memory/buffer-pool.js";
17
18
  import { type CoreBinding } from "../memory/residency.js";
19
+ import { type DegreeTiers } from "../primitives/core-shape.js";
18
20
  import { type PlanCaps } from "../types/context.js";
19
21
  import { type GpuLayoutSimulation, type LayoutStatsBase, type ResolvedLayoutTuning, type RunOptions } from "../types/layout.js";
20
22
  import { type Binding } from "../types/memory.js";
@@ -40,7 +42,14 @@ export interface ModelResources {
40
42
  readonly caps: PlanCaps;
41
43
  readonly pipelines: PipelineCache;
42
44
  readonly core: CoreBinding;
45
+ /** `tiers.perm`, or null when no row has degree >= 32 (P4 PD-7: the rowPtr dummy is bound and USE_PERM is false). */
43
46
  readonly perm: Binding | null;
47
+ /**
48
+ * The degree tiers of the snapshot's degreeOrder view (the perm binding and the CPU-side segment offsets
49
+ * [0, hiEnd, midEnd, lowEnd, n]), or null when no row has degree >= 32 -- then every K2 dispatch is the
50
+ * thread-per-row TIER 0 over node indices, as before P4.
51
+ */
52
+ readonly tiers: DegreeTiers | null;
44
53
  /**
45
54
  * The RESOLVED weights binding (model.inputs(): source "arcs" -> core.weights (null on an unweighted snapshot),
46
55
  * "column" -> the registered ArrayBinding's binding, "none" -> null); group 0 is built as
@@ -51,6 +60,8 @@ export interface ModelResources {
51
60
  readonly dim: 2 | 3;
52
61
  readonly tier: "exact" | "grid";
53
62
  readonly ring: UniformRing;
63
+ /** The context's buffer pool (the grid stage's lease of sort scratch draws on it, P4 PD-11). */
64
+ readonly pool: BufferPool;
54
65
  /** A shared or model-owned buffer by name: "positions", "scenePositions", "fixed", "partials", "state", "trace", plus every BufferSpec name. */
55
66
  buffer(name: string): Binding;
56
67
  }
@@ -98,7 +109,17 @@ export interface ForceModel<Options, Stats extends LayoutStatsBase> {
98
109
  onReheat(state: StateWriter): void;
99
110
  onSetParams(patch: Partial<Options>, state: StateWriter): void;
100
111
  readStats(state: DataView, trace: DataView): Stats;
112
+ /** Releases what the model holds outside the simulation's buffers (the grid stage's lease, P4-T10); called by dispose() once every in-flight batch has settled. */
113
+ dispose?(): void;
101
114
  }
115
+ /**
116
+ * The repulsion tier of a node count under a tuning (PLAN DECISION 11; spec 7.8: `"auto"` by `n` alone). Exported
117
+ * so a model's `buffers(n, dim)` decides the tier by the same rule `load()` applies (P4 PD-18).
118
+ * @param tuning - the resolved tuning
119
+ * @param n - the node count
120
+ * @returns "exact" or "grid"
121
+ */
122
+ export declare function tierFor(tuning: ResolvedLayoutTuning, n: number): "exact" | "grid";
102
123
  /**
103
124
  * The shared layout state machine (spec 7.19): buffers, in-flight batches, readback, settle window, fixed mask,
104
125
  * setPosition overrides, trace, batch driver; consumes a ForceModel by composition.
@@ -146,6 +167,7 @@ export declare class ForceSimulation<Options extends CommonLayoutOptions & Simul
146
167
  private settledValue;
147
168
  private firstPending;
148
169
  private statsValue;
170
+ private lastPassTimingsValue;
149
171
  private lastSubmittedBatchIdValue;
150
172
  /** The id of the last batch submitted BEFORE the most recent reheat() (PLAN DECISION 21); 0 = none. */
151
173
  private reheatedAfterBatchId;
@@ -171,7 +193,7 @@ export declare class ForceSimulation<Options extends CommonLayoutOptions & Simul
171
193
  */
172
194
  get options(): Options;
173
195
  /**
174
- * The repulsion tier of the current load ("exact" until P4 lifts the grid tier).
196
+ * The repulsion tier of the current load (spec 7.8).
175
197
  * @returns the tier
176
198
  */
177
199
  get tier(): "exact" | "grid";
@@ -322,7 +344,10 @@ export declare class ForceSimulation<Options extends CommonLayoutOptions & Simul
322
344
  */
323
345
  private copyScene;
324
346
  /**
325
- * The batch's duration in milliseconds: the profiler's pass timings summed when present, else wall time.
347
+ * The batch's duration in milliseconds: the profiler's pass timings summed when present and complete, else wall
348
+ * time. The profiler budgets PROFILER_QUERY_SLOTS / 2 passes per batch; the grid tier records three passes per
349
+ * iteration (P4 PD-16), so a grid batch above (PROFILER_QUERY_SLOTS / 2 - 1) / 3 iterations is timed partially:
350
+ * its rows stay in `lastPassTimings` but the duration is the wall time, never the sum of a prefix.
326
351
  * @param record - the batch
327
352
  * @param bytes - its readback (the profiler's resolve lands in it)
328
353
  * @returns milliseconds
@@ -450,6 +475,7 @@ export declare class ForceSimulation<Options extends CommonLayoutOptions & Simul
450
475
  /**
451
476
  * The ModelResources of a load.
452
477
  * @param core - the core
478
+ * @param tiers - the degree tiers, or null when no row has degree >= 32
453
479
  * @param weights - the resolved weights binding
454
480
  * @param buffers - the buffers
455
481
  * @returns the resources
@@ -467,14 +493,23 @@ export declare class ForceSimulation<Options extends CommonLayoutOptions & Simul
467
493
  */
468
494
  private startBind;
469
495
  /**
470
- * warm(model.specs()) then model.bind(); the await re-checks that the load is current before binding.
496
+ * assertDeviceComputes() then warm(model.specs()) then model.bind(); the await re-checks that the load is
497
+ * current before binding.
498
+ *
499
+ * The device self-check sits HERE rather than in submitBatch (its first home) because this promise is the one
500
+ * submitBatch already awaits before every batch: the check is therefore settled before the simulation can
501
+ * submit a single iteration, yet costs the frame loop nothing per batch. An extra await on the per-batch path
502
+ * moves the moment a submission becomes visible to a step() issued in the same tick, which is precisely what
503
+ * coalescing is measured on (test/layouts/frame-loop.test.ts, "a coalesced step() returns the same promise").
504
+ * A device that computes incorrectly rejects this promise, so the first step() rejects E_DEVICE_INCORRECT
505
+ * before any position is written; a check that could not RUN rejects with its own error, unchanged.
471
506
  * @param resources - the resources
472
507
  * @param overrides - the merged override set
473
508
  * @param generation - the generation the bind belongs to
474
509
  */
475
510
  private compileAndBind;
476
511
  /**
477
- * inspect(name): flush, read the named buffer back, Uint32Array for "fixed" and "trace", Float32Array otherwise.
512
+ * inspect(name): flush, read the named buffer back, Uint32Array for the u32 buffers (U32_BUFFER_NAMES), Float32Array otherwise.
478
513
  * @param name - a shared or BufferSpec name
479
514
  * @returns the words
480
515
  */
@@ -1 +1 @@
1
- {"version":3,"file":"force-simulation.d.ts","sourceRoot":"","sources":["../../../src/layouts/force-simulation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"force-simulation.d.ts","sourceRoot":"","sources":["../../../src/layouts/force-simulation.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,8 @@ import { hasErrorCode, WebGpuGraphError } from "../errors.js";
14
14
  import { CommandBatch } from "../kernel/batch.js";
15
15
  import { UniformRing } from "../kernel/uniform-ring.js";
16
16
  import { graphOverrides } from "../kernels.js";
17
+ import { degreeTiersOf } from "../primitives/core-shape.js";
18
+ import { assertDeviceComputes } from "../primitives/verify.js";
17
19
  import { seedPositions } from "./seed.js";
18
20
  // ============================================================ module-private helpers
19
21
  /** The shared params fields (name, width) every model params block must declare (PLAN DECISION 4). */
@@ -40,6 +42,20 @@ const SHARED_STATE_FIELDS = [
40
42
  ];
41
43
  /** The names of the shared buffers a BufferSpec may not reuse. */
42
44
  const SHARED_BUFFER_NAMES = ["positions", "scenePositions", "fixed", "partials", "state", "trace"];
45
+ /** The buffers inspect() returns as Uint32Array: the mask, the trace records and the grid tier's index / count arrays (P4). */
46
+ const U32_BUFFER_NAMES = new Set([
47
+ "fixed",
48
+ "trace",
49
+ "cellKey",
50
+ "cellVal",
51
+ "sortedKey",
52
+ "sortedIdx",
53
+ "cellHist",
54
+ "cellStart",
55
+ "hubList",
56
+ "hubCounters",
57
+ "hubArgs",
58
+ ]);
43
59
  /** The per-batch epilogue stage: iterations 0..k-2 stop after the stage that precedes it (PLAN DECISION 2). */
44
60
  const EPILOGUE_STAGE = "toScene";
45
61
  let simulationCounter = 0;
@@ -207,12 +223,13 @@ function centerOf(options) {
207
223
  return out;
208
224
  }
209
225
  /**
210
- * The repulsion tier of a node count under a tuning (PLAN DECISION 11).
226
+ * The repulsion tier of a node count under a tuning (PLAN DECISION 11; spec 7.8: `"auto"` by `n` alone). Exported
227
+ * so a model's `buffers(n, dim)` decides the tier by the same rule `load()` applies (P4 PD-18).
211
228
  * @param tuning - the resolved tuning
212
229
  * @param n - the node count
213
230
  * @returns "exact" or "grid"
214
231
  */
215
- function tierFor(tuning, n) {
232
+ export function tierFor(tuning, n) {
216
233
  if (tuning.repulsion === "exact") {
217
234
  return "exact";
218
235
  }
@@ -385,6 +402,7 @@ export class ForceSimulation {
385
402
  this.settledValue = false;
386
403
  this.firstPending = true;
387
404
  this.statsValue = null;
405
+ this.lastPassTimingsValue = null;
388
406
  this.lastSubmittedBatchIdValue = 0;
389
407
  /** The id of the last batch submitted BEFORE the most recent reheat() (PLAN DECISION 21); 0 = none. */
390
408
  this.reheatedAfterBatchId = 0;
@@ -450,12 +468,22 @@ export class ForceSimulation {
450
468
  return this.optionsValue;
451
469
  }
452
470
  /**
453
- * The repulsion tier of the current load ("exact" until P4 lifts the grid tier).
471
+ * The repulsion tier of the current load (spec 7.8).
454
472
  * @returns the tier
455
473
  */
456
474
  get tier() {
457
475
  return this.tierValue;
458
476
  }
477
+ /**
478
+ * The profiler's per-pass timings of the last landed batch (pass order; the grid tier's `fa2-k1` /
479
+ * `fa2-attraction` / `fa2-grid` / `fa2-to-scene` rows give T-7's attraction figure, P4 PD-16), or null before a
480
+ * batch landed or without `timestamp-query`.
481
+ * @internal
482
+ * @returns the timings
483
+ */
484
+ get lastPassTimings() {
485
+ return this.lastPassTimingsValue;
486
+ }
459
487
  /**
460
488
  * The generation counter bumped by every load() (stale readbacks are discarded).
461
489
  * @internal
@@ -577,12 +605,6 @@ export class ForceSimulation {
577
605
  const scale = scaleOf(this.optionsValue);
578
606
  const center = centerOf(this.optionsValue);
579
607
  const tier = tierFor(this.tuning, n);
580
- if (tier === "grid") {
581
- throw new WebGpuGraphError("E_UNSUPPORTED", `the grid repulsion tier lands at P4 (n = ${n}, exactMaxNodes = ${this.tuning.exactMaxNodes})`, {
582
- feature: "repulsion.grid",
583
- hint: 'pass repulsion: "exact" or raise exactMaxNodes',
584
- });
585
- }
586
608
  const positionsBytes = 16 * n;
587
609
  if (positionsBytes > this.ctx.caps.limits.maxBufferSize) {
588
610
  throw new WebGpuGraphError("E_TOO_LARGE", `${positionsBytes} bytes of positions exceed maxBufferSize`, {
@@ -593,6 +615,7 @@ export class ForceSimulation {
593
615
  });
594
616
  }
595
617
  let core = null;
618
+ let tiers = null;
596
619
  let inputs = null;
597
620
  if (n > 0) {
598
621
  core = this.ctx.residency.core(snapshot);
@@ -604,6 +627,11 @@ export class ForceSimulation {
604
627
  algorithm: this.model.kind,
605
628
  });
606
629
  }
630
+ // PD-7 (the 7.3 rule): the permutation is bound iff a row of degree >= 32 exists; the view is uploaded
631
+ // only then, so a low-degree snapshot compiles and runs the same pipelines as before P4
632
+ if (snapshot.degreeOrder().segmentOffsets[2] > 0) {
633
+ tiers = degreeTiersOf(this.ctx.residency.view(snapshot, "degreeOrder"));
634
+ }
607
635
  inputs = this.model.inputs(snapshot, this.optionsValue);
608
636
  if (inputs.mass.length !== n) {
609
637
  throw invalidArgument("nodeMass", inputs.mass.length, n, `the model resolved ${inputs.mass.length} masses for ${n} nodes`);
@@ -661,8 +689,11 @@ export class ForceSimulation {
661
689
  seedPositions(snapshot, positions, this.optionsValue.seed ?? null, this.dimValue, scale, center, range);
662
690
  this.uploadPositions(buffers, positions, inputs.mass);
663
691
  const weights = this.resolveWeightsBinding(snapshot, core, inputs.weights);
664
- const overrides = { ...this.model.overrides(this.optionsValue), ...graphOverrides(core, null, weights) };
665
- const resources = this.makeResources(core, weights, buffers);
692
+ const overrides = {
693
+ ...this.model.overrides(this.optionsValue),
694
+ ...graphOverrides(core, tiers?.perm ?? null, weights),
695
+ };
696
+ const resources = this.makeResources(core, tiers, weights, buffers);
666
697
  this.resources = resources;
667
698
  this.startBind(resources, overrides);
668
699
  this.settledValue = false;
@@ -885,7 +916,10 @@ export class ForceSimulation {
885
916
  this.center = center;
886
917
  const { resources, core } = this;
887
918
  if (this.stateValue === "loaded" && resources !== null && core !== null && before !== after) {
888
- const overrides = { ...this.model.overrides(next), ...graphOverrides(core, null, resources.weights) };
919
+ const overrides = {
920
+ ...this.model.overrides(next),
921
+ ...graphOverrides(core, resources.perm, resources.weights),
922
+ };
889
923
  this.startBind(resources, overrides);
890
924
  }
891
925
  this.model.onSetParams(patch, this.writer);
@@ -1088,7 +1122,10 @@ export class ForceSimulation {
1088
1122
  }
1089
1123
  }
1090
1124
  /**
1091
- * The batch's duration in milliseconds: the profiler's pass timings summed when present, else wall time.
1125
+ * The batch's duration in milliseconds: the profiler's pass timings summed when present and complete, else wall
1126
+ * time. The profiler budgets PROFILER_QUERY_SLOTS / 2 passes per batch; the grid tier records three passes per
1127
+ * iteration (P4 PD-16), so a grid batch above (PROFILER_QUERY_SLOTS / 2 - 1) / 3 iterations is timed partially:
1128
+ * its rows stay in `lastPassTimings` but the duration is the wall time, never the sum of a prefix.
1092
1129
  * @param record - the batch
1093
1130
  * @param bytes - its readback (the profiler's resolve lands in it)
1094
1131
  * @returns milliseconds
@@ -1097,7 +1134,8 @@ export class ForceSimulation {
1097
1134
  const { profiler } = this.ctx;
1098
1135
  if (profiler !== null && record.profile !== null) {
1099
1136
  const timings = profiler.timings(bytes, record.profile);
1100
- if (timings.length > 0) {
1137
+ this.lastPassTimingsValue = timings;
1138
+ if (timings.length > 0 && !profiler.partial(record.profile)) {
1101
1139
  let ns = 0;
1102
1140
  for (const timing of timings) {
1103
1141
  ns += timing.ns;
@@ -1493,23 +1531,26 @@ export class ForceSimulation {
1493
1531
  /**
1494
1532
  * The ModelResources of a load.
1495
1533
  * @param core - the core
1534
+ * @param tiers - the degree tiers, or null when no row has degree >= 32
1496
1535
  * @param weights - the resolved weights binding
1497
1536
  * @param buffers - the buffers
1498
1537
  * @returns the resources
1499
1538
  */
1500
- makeResources(core, weights, buffers) {
1539
+ makeResources(core, tiers, weights, buffers) {
1501
1540
  const { bindings } = buffers;
1502
1541
  return {
1503
1542
  device: this.ctx.device,
1504
1543
  caps: this.ctx.caps,
1505
1544
  pipelines: this.ctx.pipelines,
1506
1545
  core,
1507
- perm: null,
1546
+ perm: tiers?.perm ?? null,
1547
+ tiers,
1508
1548
  weights,
1509
1549
  n: this.n,
1510
1550
  dim: this.dimValue,
1511
1551
  tier: this.tierValue,
1512
1552
  ring: this.ring,
1553
+ pool: this.ctx.pool,
1513
1554
  buffer: (name) => {
1514
1555
  const binding = bindings.get(name);
1515
1556
  if (binding === undefined) {
@@ -1537,12 +1578,22 @@ export class ForceSimulation {
1537
1578
  this.ready = promise;
1538
1579
  }
1539
1580
  /**
1540
- * warm(model.specs()) then model.bind(); the await re-checks that the load is current before binding.
1581
+ * assertDeviceComputes() then warm(model.specs()) then model.bind(); the await re-checks that the load is
1582
+ * current before binding.
1583
+ *
1584
+ * The device self-check sits HERE rather than in submitBatch (its first home) because this promise is the one
1585
+ * submitBatch already awaits before every batch: the check is therefore settled before the simulation can
1586
+ * submit a single iteration, yet costs the frame loop nothing per batch. An extra await on the per-batch path
1587
+ * moves the moment a submission becomes visible to a step() issued in the same tick, which is precisely what
1588
+ * coalescing is measured on (test/layouts/frame-loop.test.ts, "a coalesced step() returns the same promise").
1589
+ * A device that computes incorrectly rejects this promise, so the first step() rejects E_DEVICE_INCORRECT
1590
+ * before any position is written; a check that could not RUN rejects with its own error, unchanged.
1541
1591
  * @param resources - the resources
1542
1592
  * @param overrides - the merged override set
1543
1593
  * @param generation - the generation the bind belongs to
1544
1594
  */
1545
1595
  async compileAndBind(resources, overrides, generation) {
1596
+ await assertDeviceComputes(this.ctx);
1546
1597
  const subgroups = this.ctx.caps.features.has("subgroups");
1547
1598
  await this.ctx.pipelines.warm(this.model.specs(overrides, subgroups));
1548
1599
  if (this.stateValue !== "loaded" || generation !== this.generationValue) {
@@ -1552,7 +1603,7 @@ export class ForceSimulation {
1552
1603
  }
1553
1604
  // ---------------------------------------------------------------- private: inspect and debug runs
1554
1605
  /**
1555
- * inspect(name): flush, read the named buffer back, Uint32Array for "fixed" and "trace", Float32Array otherwise.
1606
+ * inspect(name): flush, read the named buffer back, Uint32Array for the u32 buffers (U32_BUFFER_NAMES), Float32Array otherwise.
1556
1607
  * @param name - a shared or BufferSpec name
1557
1608
  * @returns the words
1558
1609
  */
@@ -1565,7 +1616,7 @@ export class ForceSimulation {
1565
1616
  }
1566
1617
  await this.flush();
1567
1618
  const bytes = await this.ctx.readback.read(binding.buffer, binding.size, undefined, binding.offset);
1568
- return name === "fixed" || name === "trace" ? new Uint32Array(bytes) : new Float32Array(bytes);
1619
+ return U32_BUFFER_NAMES.has(name) ? new Uint32Array(bytes) : new Float32Array(bytes);
1569
1620
  }
1570
1621
  /**
1571
1622
  * debugRunStages(upTo): one iteration truncated after a stage, submitted alone after flush(), awaited through
@@ -1633,6 +1684,7 @@ export class ForceSimulation {
1633
1684
  this.destroyBuffers();
1634
1685
  this.afterInFlight(() => {
1635
1686
  this.ring.destroy();
1687
+ this.model.dispose?.();
1636
1688
  });
1637
1689
  if (this.ctx.state === "ready") {
1638
1690
  this.ctx.pool.trim();