@graphty/webgpu-graph-algorithms 0.5.1 → 0.6.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.
Files changed (243) hide show
  1. package/README.md +98 -52
  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 +5 -4
  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
@@ -1,12 +1,50 @@
1
1
  /**
2
- * The option and value helpers every force model's resolver and stats decoder share (PD-7): moved verbatim from
3
- * src/layouts/forceatlas2.ts (P3-T2) so the Fruchterman-Reingold and spring-electrical models of P5 neither copy
4
- * them nor import a sibling model. Layout zone; imports errors.ts only.
2
+ * The option and value helpers every force model's resolver and stats decoder share (P5 PD-7): moved verbatim
3
+ * from src/layouts/forceatlas2.ts (P3-T2) so the Fruchterman-Reingold and spring-electrical models of P5 neither
4
+ * copy them nor import a sibling model; and, since P4-T6, the K2 tier binding and dispatch the three models share
5
+ * (`bindAttraction` / `recordAttraction`, P4 PD-7), so every model's bind() / recordIteration() calls one function
6
+ * instead of holding its own copy. Layout zone.
5
7
  */
6
8
  import { WebGpuGraphError } from "../errors.js";
9
+ import { type DispatchPlan } from "../kernel/dispatch.js";
10
+ import { type BoundKernel, type Kernel } from "../kernel/kernel.js";
7
11
  import { type UniformValues } from "../kernel/struct-block.js";
12
+ import { type Binding } from "../types/memory.js";
13
+ import { type ModelResources } from "./force-simulation.js";
8
14
  /** An override record as the kernel layer takes it. */
9
15
  export type Overrides = Readonly<Record<string, number | boolean>>;
16
+ /** The K2 (`fa2-attraction`) dispatches of one iteration: `[kernel, bind group, plan]` in dispatch order TIER 2, TIER 1, TIER 0 (only the tiers whose row range is non-empty). */
17
+ export interface AttractionBound {
18
+ readonly kernels: readonly (readonly [Kernel, BoundKernel, DispatchPlan])[];
19
+ }
20
+ /** The group-1 / group-2 bindings of K2 every tier dispatch shares: `pos` (vec4f, mass in w), `force` (stride-3 f32) and the Fa2Params slot of the UniformRing. @public the bindings parameter of bindAttraction */
21
+ export interface AttractionBindings {
22
+ readonly pos: Binding;
23
+ readonly force: Binding;
24
+ readonly params: Binding;
25
+ }
26
+ /**
27
+ * Compiles (through the cache) and binds the `fa2-attraction` pipelines a load needs against the graph group and
28
+ * { pos, force, P } (P4 PD-7): TIER 0 always; TIER 1 when a row of degree 32..1023 exists (`[hiEnd, midEnd)` is
29
+ * non-empty); TIER 2 when a row of degree >= 1024 exists (`hiEnd > 0`). The dispatch plans are one workgroup per
30
+ * row for TIER 2, `WG / 32` rows per workgroup for TIER 1 and one row per thread for TIER 0, over each tier's row
31
+ * count (the K2 body reads its range from `Fa2Params.hiEnd` / `midEnd` / `tierStart` / `tierEnd`). The TIER 1 / 2
32
+ * pipelines compile on the first load that needs them (a one-time cost at that load); a model's `specs()` lists
33
+ * the TIER 0 spec only, because it has no `n` to know which tiers a load needs. A device whose workgroup size is
34
+ * below 32 cannot fold the mid tier: E_UNSUPPORTED { feature: "fa2-attraction.tiers" } when a permutation is bound.
35
+ * @param resources - the load's resources (core, tiers, weights, pipelines, caps)
36
+ * @param k2 - the K2 override record of the model (LINLOG / DISTRIBUTED / LAW plus USE_PERM / HAS_WEIGHTS; TIER is overwritten per dispatch)
37
+ * @param bindings - the group-1 / group-2 bindings shared by every tier
38
+ * @returns the bound dispatches in order TIER 2, 1, 0
39
+ */
40
+ export declare function bindAttraction(resources: ModelResources, k2: Overrides, bindings: AttractionBindings): Promise<AttractionBound>;
41
+ /**
42
+ * Records the K2 dispatches of one iteration in order TIER 2, TIER 1, TIER 0 with the iteration's params offset.
43
+ * @param pass - the open compute pass
44
+ * @param bound - what bindAttraction produced
45
+ * @param paramsOffset - the UniformRing byte offset of this iteration's Fa2Params
46
+ */
47
+ export declare function recordAttraction(pass: GPUComputePassEncoder, bound: AttractionBound, paramsOffset: number): void;
10
48
  /** Bytes of the stride-3 f32 force arrays per node. */
11
49
  export declare const FORCE_BYTES_PER_NODE = 12;
12
50
  /** The name of the model-owned FillParams buffer (a BufferSpec, reached through ModelResources.buffer). */
@@ -1 +1 @@
1
- {"version":3,"file":"model-common.d.ts","sourceRoot":"","sources":["../../../src/layouts/model-common.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,uDAAuD;AACvD,MAAM,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;AAEnE,uDAAuD;AACvD,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,2GAA2G;AAC3G,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAK/C;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAcpD;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAM5F;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACtB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,EACjC,QAAQ,EAAE,MAAM,GACjB,MAAM,CAMR;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,SAAS,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAMhG;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAMxE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACtB,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,SAAS,EACpC,QAAQ,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAC5C,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CA2BnC;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CASjG;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAKpD;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMlE;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAM7E;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,GAAG,SAAS,CAMxE"}
1
+ {"version":3,"file":"model-common.d.ts","sourceRoot":"","sources":["../../../src/layouts/model-common.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,80 @@
1
1
  /**
2
- * The option and value helpers every force model's resolver and stats decoder share (PD-7): moved verbatim from
3
- * src/layouts/forceatlas2.ts (P3-T2) so the Fruchterman-Reingold and spring-electrical models of P5 neither copy
4
- * them nor import a sibling model. Layout zone; imports errors.ts only.
2
+ * The option and value helpers every force model's resolver and stats decoder share (P5 PD-7): moved verbatim
3
+ * from src/layouts/forceatlas2.ts (P3-T2) so the Fruchterman-Reingold and spring-electrical models of P5 neither
4
+ * copy them nor import a sibling model; and, since P4-T6, the K2 tier binding and dispatch the three models share
5
+ * (`bindAttraction` / `recordAttraction`, P4 PD-7), so every model's bind() / recordIteration() calls one function
6
+ * instead of holding its own copy. Layout zone.
5
7
  */
6
8
  import { WebGpuGraphError } from "../errors.js";
9
+ import { plan1d } from "../kernel/dispatch.js";
10
+ import { graphBindings, kernelSpec } from "../kernels.js";
11
+ import { MID_TIER_LANES } from "../primitives/core-shape.js";
12
+ /**
13
+ * Compiles (through the cache) and binds the `fa2-attraction` pipelines a load needs against the graph group and
14
+ * { pos, force, P } (P4 PD-7): TIER 0 always; TIER 1 when a row of degree 32..1023 exists (`[hiEnd, midEnd)` is
15
+ * non-empty); TIER 2 when a row of degree >= 1024 exists (`hiEnd > 0`). The dispatch plans are one workgroup per
16
+ * row for TIER 2, `WG / 32` rows per workgroup for TIER 1 and one row per thread for TIER 0, over each tier's row
17
+ * count (the K2 body reads its range from `Fa2Params.hiEnd` / `midEnd` / `tierStart` / `tierEnd`). The TIER 1 / 2
18
+ * pipelines compile on the first load that needs them (a one-time cost at that load); a model's `specs()` lists
19
+ * the TIER 0 spec only, because it has no `n` to know which tiers a load needs. A device whose workgroup size is
20
+ * below 32 cannot fold the mid tier: E_UNSUPPORTED { feature: "fa2-attraction.tiers" } when a permutation is bound.
21
+ * @param resources - the load's resources (core, tiers, weights, pipelines, caps)
22
+ * @param k2 - the K2 override record of the model (LINLOG / DISTRIBUTED / LAW plus USE_PERM / HAS_WEIGHTS; TIER is overwritten per dispatch)
23
+ * @param bindings - the group-1 / group-2 bindings shared by every tier
24
+ * @returns the bound dispatches in order TIER 2, 1, 0
25
+ */
26
+ export async function bindAttraction(resources, k2, bindings) {
27
+ const { n, core, perm, tiers, weights, pipelines, caps } = resources;
28
+ const so = tiers?.segmentOffsets;
29
+ const hiEnd = so?.[1] ?? 0;
30
+ const midEnd = so?.[2] ?? 0;
31
+ const ranges = [
32
+ { tier: 2, rows: hiEnd },
33
+ { tier: 1, rows: midEnd - hiEnd },
34
+ { tier: 0, rows: n - midEnd },
35
+ ];
36
+ const group = {
37
+ ...graphBindings(core, perm, weights),
38
+ pos: bindings.pos,
39
+ force: bindings.force,
40
+ P: bindings.params,
41
+ };
42
+ const kernels = [];
43
+ for (const { tier, rows } of ranges) {
44
+ if (tier !== 0 && rows <= 0) {
45
+ continue;
46
+ }
47
+ // sequential on purpose: PipelineCache.get compiles inside a validation scope, one stack per device
48
+ const kernel = await pipelines.kernel(kernelSpec("fa2-attraction", { ...k2, TIER: tier }));
49
+ const wg = kernel.workgroupSize;
50
+ if (tier !== 0 && wg < MID_TIER_LANES) {
51
+ throw new WebGpuGraphError("E_UNSUPPORTED", `fa2-attraction: the mid tier folds ${MID_TIER_LANES} lanes per row, more than the workgroup size ${wg}`, { feature: "fa2-attraction.tiers" });
52
+ }
53
+ if (rows <= 0) {
54
+ continue;
55
+ }
56
+ let rowsPerGroup = wg;
57
+ if (tier === 2) {
58
+ rowsPerGroup = 1;
59
+ }
60
+ else if (tier === 1) {
61
+ rowsPerGroup = wg / MID_TIER_LANES;
62
+ }
63
+ kernels.push([kernel, kernel.bind(group), plan1d(rows, rowsPerGroup, caps)]);
64
+ }
65
+ return { kernels };
66
+ }
67
+ /**
68
+ * Records the K2 dispatches of one iteration in order TIER 2, TIER 1, TIER 0 with the iteration's params offset.
69
+ * @param pass - the open compute pass
70
+ * @param bound - what bindAttraction produced
71
+ * @param paramsOffset - the UniformRing byte offset of this iteration's Fa2Params
72
+ */
73
+ export function recordAttraction(pass, bound, paramsOffset) {
74
+ for (const [kernel, group, plan] of bound.kernels) {
75
+ kernel.dispatch(pass, group, plan, [paramsOffset]);
76
+ }
77
+ }
7
78
  /** Bytes of the stride-3 f32 force arrays per node. */
8
79
  export const FORCE_BYTES_PER_NODE = 12;
9
80
  /** The name of the model-owned FillParams buffer (a BufferSpec, reached through ModelResources.buffer). */
@@ -1 +1 @@
1
- {"version":3,"file":"model-common.js","sourceRoot":"","sources":["../../../src/layouts/model-common.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAMhD,uDAAuD;AACvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,2GAA2G;AAC3G,MAAM,CAAC,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAE/C,4FAA4F;AAC5F,MAAM,WAAW,GAAG,UAAU,CAAC;AAE/B;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAc;IACxC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO,MAAM,CAAC;IAClB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvF,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,WAAW,EAAE,CAAC;QAC/B,OAAO,WAAW,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACrF,OAAO,IAAI,KAAK,CAAC,MAAM,UAAU,CAAC;IACtC,CAAC;IACD,OAAO,OAAO,KAAK,CAAC;AACxB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CAAC,QAAgB,EAAE,KAAc,EAAE,QAAgB;IACtE,OAAO,IAAI,gBAAgB,CAAC,oBAAoB,EAAE,GAAG,QAAQ,YAAY,QAAQ,SAAS,aAAa,CAAC,KAAK,CAAC,EAAE,EAAE;QAC9G,QAAQ;QACR,KAAK;QACL,QAAQ;KACX,CAAC,CAAC;AACP,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CACtB,IAAY,EACZ,KAAyB,EACzB,QAAgB,EAChB,KAAiC,EACjC,QAAgB;IAEhB,MAAM,KAAK,GAAY,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;IAC9D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,MAAM,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,KAA0B,EAAE,QAAiB;IACnF,MAAM,KAAK,GAAY,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;IAC9D,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,KAAwB,EAAE,QAAe;IAC7D,MAAM,KAAK,GAAY,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;IAC9D,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CACtB,KAAoC,EACpC,QAA2C;IAE3C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,QAAQ,CAAC;IACpB,CAAC;IACD,MAAM,QAAQ,GAAG,mCAAmC,CAAC;IACrD,MAAM,KAAK,GAAY,KAAK,CAAC;IAC7B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,CAAC;QACtE,MAAM,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACzB,IAAI,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,CAAC,GAAY,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAY,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAY,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,IACI,OAAO,CAAC,KAAK,QAAQ;QACrB,OAAO,CAAC,KAAK,QAAQ;QACrB,OAAO,CAAC,KAAK,QAAQ;QACrB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EACrB,CAAC;QACC,MAAM,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAgC,EAAE,QAAuB;IAC9E,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,QAAQ,CAAC;IACpB,CAAC;IACD,MAAM,KAAK,GAAY,KAAK,CAAC;IAC7B,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAC3E,MAAM,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,yBAAyB,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC3C,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAmB;IACxC,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAChB,OAAO,CAAC,CAAC;IACb,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,WAAW,CAAC;AACpD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,MAAqB,EAAE,IAAY;IACtD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,MAAqB,EAAE,IAAY;IACtD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,MAAM,CAAC,MAAiB,EAAE,QAAmB;IACzD,MAAM,GAAG,GAAqC,EAAE,CAAC;IACjD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"model-common.js","sourceRoot":"","sources":["../../../src/layouts/model-common.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * The grid-tier repulsion stage of the force models (spec 7.7, 7.4; P4-T10): G1-G3 through the T8 grid build, G4-G5
3
+ * through the T9 pyramid, then G6 (`grid-far-field`) and G7 (`grid-near-field`, K3's pair law and epilogue) over
4
+ * `plan1d(n)`, followed by K4 (`fa2-speed-finalize`) exactly as `RepulsionExact` records it. The named grid buffers
5
+ * are the model's `BufferSpec`s (`buffers()`, so `inspect(name)` reaches them); the anonymous scratch of the sort
6
+ * and the scan and the static params of the pyramid draw on ONE `Lease` of the context's pool taken at `create()`
7
+ * (the scan planner takes its block-sum levels at prepare time) and released by `dispose()` (PD-11, DEP-P4-D: a
8
+ * per-batch lease would rebuild the G2-G4 bind groups every batch; a model creates one stage per bind(), so a stage
9
+ * is bound once). The stage is the ONE class every model reaches the grid tier through (PD-22): the FR and
10
+ * spring-electrical models pass `LAW` 1 / 2 in their override set, which reaches G6's per-cell law and G7's pair law
11
+ * (P4-T13).
12
+ */
13
+ import { type PipelineCache } from "../kernel/pipeline-cache.js";
14
+ import { type WgslModuleSpec } from "../kernel/wgsl.js";
15
+ import { type BufferPool } from "../memory/buffer-pool.js";
16
+ import { type GridSpec } from "../primitives/grid.js";
17
+ import { type PlanCaps } from "../types/context.js";
18
+ import { type Binding } from "../types/memory.js";
19
+ import { type BufferSpec } from "./force-simulation.js";
20
+ import { type RepulsionExactOverrides, type RepulsionExactResources } from "./repulsion-exact.js";
21
+ /** The stage names the grid tier records, in dispatch order (the `upTo` vocabulary of recordRepulsion). */
22
+ declare const GRID_STAGES: readonly ["G1", "G2", "G3", "G4", "G5", "G6", "G7"];
23
+ /** A grid stage name. */
24
+ export type GridStage = (typeof GRID_STAGES)[number];
25
+ /**
26
+ * The buffers the grid-tier repulsion stage binds: the exact tier's plus the named grid buffers of `buffers()`. The
27
+ * parameter type of RepulsionGrid.bind (knip: exported for the signature, not imported by name).
28
+ * @public
29
+ */
30
+ export interface RepulsionGridResources extends RepulsionExactResources {
31
+ readonly cellKey: Binding;
32
+ readonly cellVal: Binding;
33
+ readonly sortedKey: Binding;
34
+ readonly sortedIdx: Binding;
35
+ readonly cellHist: Binding;
36
+ readonly cellStart: Binding;
37
+ readonly hubList: Binding;
38
+ readonly hubCounters: Binding;
39
+ readonly hubArgs: Binding;
40
+ readonly pyramid: Binding;
41
+ }
42
+ /**
43
+ * The override set G6 / G7 / K4 compile with: K3's three plus the repulsion law (0 FA2, 1 FR, 2 coulomb; P4-T13,
44
+ * PD-22).
45
+ * @public
46
+ */
47
+ export interface RepulsionGridOverrides extends RepulsionExactOverrides {
48
+ readonly LAW: 0 | 1 | 2;
49
+ }
50
+ /**
51
+ * What the stage needs of the context to build its scope: the pieces `ModelResources` carries. The parameter type
52
+ * of RepulsionGrid.create (knip: exported for the signature, not imported by name).
53
+ * @public
54
+ */
55
+ export interface RepulsionGridScope {
56
+ readonly device: GPUDevice;
57
+ readonly caps: PlanCaps;
58
+ readonly pipelines: PipelineCache;
59
+ readonly pool: BufferPool;
60
+ }
61
+ /** G1-G7 then K4 (spec 7.7, 7.4): the grid tier's repulsion stage. */
62
+ export declare class RepulsionGrid {
63
+ /** The overrides G6 / G7 / K4 were compiled with (a frozen copy of the argument of create()). */
64
+ readonly overrides: RepulsionGridOverrides;
65
+ /** The grid geometry the stage was prepared for. */
66
+ readonly spec: GridSpec;
67
+ private readonly caps;
68
+ private readonly workgroupSize;
69
+ private readonly box;
70
+ private readonly build;
71
+ private readonly pyramid;
72
+ private readonly far;
73
+ private readonly near;
74
+ private readonly speedFinalize;
75
+ private bound;
76
+ /**
77
+ * Holds the planners and kernels; create() is the only caller.
78
+ * @param scope - the context pieces
79
+ * @param workgroupSize - the device's workgroup size (every kernel compiles with it)
80
+ * @param overrides - the override set G6 / G7 / K4 were compiled with
81
+ * @param spec - the grid
82
+ * @param box - the lease box the scope's scratch() and params() read
83
+ * @param build - the T8 planner (G1-G3)
84
+ * @param pyramid - the T9 planner (G4-G5)
85
+ * @param kernels - G6 (`far`), G7 (`near`) and K4 (`speedFinalize`)
86
+ */
87
+ private constructor();
88
+ /**
89
+ * The model-owned buffers of the grid tier (spec 7.3; PD-11): `cellKey` / `cellVal` / `sortedKey` / `sortedIdx`
90
+ * 4n, `cellHist` / `cellStart` 4 (cells + 2) zeroed, `hubList` one word per possible hub cell, `hubArgs` one
91
+ * indirect slot, `pyramid` 16 B per pyramid cell zeroed. `hubCounters` (16 B, zeroed) is the MODEL's on every
92
+ * tier (PD-14: K1 binds it on the exact tier too). n = 0 reports one node's worth of bytes (spec 3.6).
93
+ * @param n - the node count
94
+ * @param spec - the grid
95
+ * @returns the specs
96
+ */
97
+ static buffers(n: number, spec: GridSpec): readonly BufferSpec[];
98
+ /**
99
+ * The module specs of the grid tier under an override set (for warm() and the compile matrix): the build's
100
+ * (G1, the sort path `spec.deterministic` selects, the histogram, the scan, the fill), the pyramid's (G4, the
101
+ * finalize, G4b, G5), G6, G7 and K4.
102
+ * @param overrides - the override set of the stage
103
+ * @param spec - the grid (only its `deterministic` flag matters: the pipeline key carries no geometry)
104
+ * @returns the specs
105
+ */
106
+ static specs(overrides: RepulsionGridOverrides, spec: GridSpec): readonly WgslModuleSpec[];
107
+ /**
108
+ * Compiles every kernel of the tier through the cache (sequentially: PipelineCache.get compiles inside a
109
+ * validation scope, one stack per device) over a scope whose scratch and params draw on the stage's lease.
110
+ * @param scope - the context pieces (device, caps, pipelines, pool)
111
+ * @param workgroupSize - the device's workgroup size
112
+ * @param overrides - the SWING_MODE / STRONG_GRAVITY / GRAVITY_CENTER / LAW set of this stage
113
+ * @param spec - the grid
114
+ * @returns the stage, ready for bind()
115
+ */
116
+ static create(scope: RepulsionGridScope, workgroupSize: number, overrides: RepulsionGridOverrides, spec: GridSpec): Promise<RepulsionGrid>;
117
+ /**
118
+ * Builds every bind group once per load(): the build's and the pyramid's bind() (which take their scratch and
119
+ * write their static params through the lease), then G6, G7 and K4 against the named buffers (the 3.10.1
120
+ * binding names). A second bind() takes fresh scratch from the same lease and the first bind()'s scratch stays
121
+ * held until dispose(): the one lease also holds the prepare-time allocations (the scan's block-sum levels), so
122
+ * it cannot be released on a rebind (the model creates one stage per bind(), so a rebind never happens).
123
+ * @param resources - the buffers of spec 7.3 plus the grid's
124
+ */
125
+ bind(resources: RepulsionGridResources): void;
126
+ /**
127
+ * Records G1..G7 for `n` nodes with the params slot's dynamic offset, stopping after `upTo` when given (spec 7.4
128
+ * grid sequence; the inspect() stage split, spec 11.9 item 2): G1-G3 through the build planner, G4-G5 through the
129
+ * pyramid planner, then G6 and G7 over plan1d(n).
130
+ * @param pass - the open compute pass of the batch
131
+ * @param n - the node count (in [1, the capacity of the grid buffers])
132
+ * @param paramsOffset - the dynamic offset of this iteration's Fa2Params slot in the uniform ring
133
+ * @param upTo - the last grid stage to record (default "G7")
134
+ */
135
+ recordRepulsion(pass: GPUComputePassEncoder, n: number, paramsOffset: number, upTo?: GridStage): void;
136
+ /**
137
+ * Records K4 only (one workgroup).
138
+ * @param pass - the open compute pass
139
+ * @param paramsOffset - the dynamic offset of the Fa2Params slot
140
+ */
141
+ recordSpeedFinalize(pass: GPUComputePassEncoder, paramsOffset: number): void;
142
+ /** Releases the lease (the sort and scan scratch, the static params) and drops the bind groups; idempotent. */
143
+ dispose(): void;
144
+ /**
145
+ * The bound groups, or E_NOT_LOADED when bind() has not run.
146
+ * @param method - the caller's name for the message
147
+ * @returns the bound groups
148
+ */
149
+ private requireBound;
150
+ }
151
+ export {};
152
+ //# sourceMappingURL=repulsion-grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repulsion-grid.d.ts","sourceRoot":"","sources":["../../../src/layouts/repulsion-grid.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,318 @@
1
+ /**
2
+ * The grid-tier repulsion stage of the force models (spec 7.7, 7.4; P4-T10): G1-G3 through the T8 grid build, G4-G5
3
+ * through the T9 pyramid, then G6 (`grid-far-field`) and G7 (`grid-near-field`, K3's pair law and epilogue) over
4
+ * `plan1d(n)`, followed by K4 (`fa2-speed-finalize`) exactly as `RepulsionExact` records it. The named grid buffers
5
+ * are the model's `BufferSpec`s (`buffers()`, so `inspect(name)` reaches them); the anonymous scratch of the sort
6
+ * and the scan and the static params of the pyramid draw on ONE `Lease` of the context's pool taken at `create()`
7
+ * (the scan planner takes its block-sum levels at prepare time) and released by `dispose()` (PD-11, DEP-P4-D: a
8
+ * per-batch lease would rebuild the G2-G4 bind groups every batch; a model creates one stage per bind(), so a stage
9
+ * is bound once). The stage is the ONE class every model reaches the grid tier through (PD-22): the FR and
10
+ * spring-electrical models pass `LAW` 1 / 2 in their override set, which reaches G6's per-cell law and G7's pair law
11
+ * (P4-T13).
12
+ */
13
+ import { GRID_HUB_CELL } from "../constants.js";
14
+ import { BufferUsage } from "../device/webgpu-constants.js";
15
+ import { WebGpuGraphError } from "../errors.js";
16
+ import { plan1d } from "../kernel/dispatch.js";
17
+ import { INDIRECT_ARGS_STRIDE } from "../kernel/kernel.js";
18
+ import { kernelSpec } from "../kernels.js";
19
+ import { gridPyramidBytes, prepareGridBuild, } from "../primitives/grid.js";
20
+ import { preparePyramid } from "../primitives/grid-pyramid.js";
21
+ /** The stage names the grid tier records, in dispatch order (the `upTo` vocabulary of recordRepulsion). */
22
+ const GRID_STAGES = ["G1", "G2", "G3", "G4", "G5", "G6", "G7"];
23
+ /** The storage usage of every grid buffer. */
24
+ const STORAGE_RW = BufferUsage.STORAGE | BufferUsage.COPY_SRC | BufferUsage.COPY_DST;
25
+ /**
26
+ * The stage's lease, or E_DISPOSED after dispose().
27
+ * @param box - the stage's lease box
28
+ * @returns the lease
29
+ */
30
+ function leaseOf(box) {
31
+ if (box.lease === null) {
32
+ throw new WebGpuGraphError("E_DISPOSED", "RepulsionGrid: the stage was disposed", { label: "RepulsionGrid" });
33
+ }
34
+ return box.lease;
35
+ }
36
+ /**
37
+ * A uniform buffer of the lease holding one written record of `block` (the pyramid's static params, PD-11).
38
+ * @param device - the device
39
+ * @param lease - the stage's lease
40
+ * @param block - the uniform block
41
+ * @param values - the values to write
42
+ * @returns the whole-buffer binding and a zero dynamic offset
43
+ */
44
+ function writeParams(device, lease, block, values) {
45
+ const buffer = lease.uniform(block.byteLength, `grid/${block.name}`);
46
+ const bytes = new ArrayBuffer(block.byteLength);
47
+ block.write(new DataView(bytes), values);
48
+ device.queue.writeBuffer(buffer, 0, bytes);
49
+ return { binding: { buffer, offset: 0, size: block.byteLength, window: null }, offset: 0 };
50
+ }
51
+ /**
52
+ * The G6 spec of an override set (the law alone).
53
+ * @param overrides - the override set of the stage
54
+ * @returns the spec
55
+ */
56
+ function farFieldSpec(overrides) {
57
+ return kernelSpec("grid-far-field", { LAW: overrides.LAW });
58
+ }
59
+ /**
60
+ * The G7 spec of an override set (K3's four).
61
+ * @param overrides - the override set of the stage
62
+ * @returns the spec
63
+ */
64
+ function nearFieldSpec(overrides) {
65
+ return kernelSpec("grid-near-field", {
66
+ SWING_MODE: overrides.SWING_MODE,
67
+ STRONG_GRAVITY: overrides.STRONG_GRAVITY,
68
+ GRAVITY_CENTER: overrides.GRAVITY_CENTER,
69
+ LAW: overrides.LAW,
70
+ });
71
+ }
72
+ /** G1-G7 then K4 (spec 7.7, 7.4): the grid tier's repulsion stage. */
73
+ export class RepulsionGrid {
74
+ /**
75
+ * Holds the planners and kernels; create() is the only caller.
76
+ * @param scope - the context pieces
77
+ * @param workgroupSize - the device's workgroup size (every kernel compiles with it)
78
+ * @param overrides - the override set G6 / G7 / K4 were compiled with
79
+ * @param spec - the grid
80
+ * @param box - the lease box the scope's scratch() and params() read
81
+ * @param build - the T8 planner (G1-G3)
82
+ * @param pyramid - the T9 planner (G4-G5)
83
+ * @param kernels - G6 (`far`), G7 (`near`) and K4 (`speedFinalize`)
84
+ */
85
+ constructor(scope, workgroupSize, overrides, spec, box, build, pyramid, kernels) {
86
+ this.bound = null;
87
+ this.caps = scope.caps;
88
+ this.box = box;
89
+ this.workgroupSize = workgroupSize;
90
+ this.overrides = Object.freeze({
91
+ SWING_MODE: overrides.SWING_MODE,
92
+ STRONG_GRAVITY: overrides.STRONG_GRAVITY,
93
+ GRAVITY_CENTER: overrides.GRAVITY_CENTER,
94
+ LAW: overrides.LAW,
95
+ });
96
+ this.spec = spec;
97
+ this.build = build;
98
+ this.pyramid = pyramid;
99
+ this.far = kernels.far;
100
+ this.near = kernels.near;
101
+ this.speedFinalize = kernels.speedFinalize;
102
+ }
103
+ /**
104
+ * The model-owned buffers of the grid tier (spec 7.3; PD-11): `cellKey` / `cellVal` / `sortedKey` / `sortedIdx`
105
+ * 4n, `cellHist` / `cellStart` 4 (cells + 2) zeroed, `hubList` one word per possible hub cell, `hubArgs` one
106
+ * indirect slot, `pyramid` 16 B per pyramid cell zeroed. `hubCounters` (16 B, zeroed) is the MODEL's on every
107
+ * tier (PD-14: K1 binds it on the exact tier too). n = 0 reports one node's worth of bytes (spec 3.6).
108
+ * @param n - the node count
109
+ * @param spec - the grid
110
+ * @returns the specs
111
+ */
112
+ static buffers(n, spec) {
113
+ const words = 4 * Math.max(1, n);
114
+ return [
115
+ { name: "cellKey", byteLength: words, usage: STORAGE_RW, zero: false },
116
+ { name: "cellVal", byteLength: words, usage: STORAGE_RW, zero: false },
117
+ { name: "sortedKey", byteLength: words, usage: STORAGE_RW, zero: false },
118
+ { name: "sortedIdx", byteLength: words, usage: STORAGE_RW, zero: false },
119
+ { name: "cellHist", byteLength: 4 * spec.histWords, usage: STORAGE_RW, zero: true },
120
+ { name: "cellStart", byteLength: 4 * spec.histWords, usage: STORAGE_RW, zero: true },
121
+ {
122
+ name: "hubList",
123
+ byteLength: 4 * Math.max(1, Math.ceil(n / GRID_HUB_CELL)),
124
+ usage: STORAGE_RW,
125
+ zero: false,
126
+ },
127
+ { name: "hubArgs", byteLength: INDIRECT_ARGS_STRIDE, usage: STORAGE_RW | BufferUsage.INDIRECT, zero: true },
128
+ { name: "pyramid", byteLength: gridPyramidBytes(spec), usage: STORAGE_RW, zero: true },
129
+ ];
130
+ }
131
+ /**
132
+ * The module specs of the grid tier under an override set (for warm() and the compile matrix): the build's
133
+ * (G1, the sort path `spec.deterministic` selects, the histogram, the scan, the fill), the pyramid's (G4, the
134
+ * finalize, G4b, G5), G6, G7 and K4.
135
+ * @param overrides - the override set of the stage
136
+ * @param spec - the grid (only its `deterministic` flag matters: the pipeline key carries no geometry)
137
+ * @returns the specs
138
+ */
139
+ static specs(overrides, spec) {
140
+ const sort = spec.deterministic
141
+ ? [kernelSpec("radix-hist"), kernelSpec("radix-scatter"), kernelSpec("scan-block"), kernelSpec("scan-add")]
142
+ : [kernelSpec("counting-scatter"), kernelSpec("scan-block"), kernelSpec("scan-add")];
143
+ return [
144
+ kernelSpec("grid-cell-key"),
145
+ ...sort,
146
+ kernelSpec("histogram"),
147
+ kernelSpec("fill"),
148
+ kernelSpec("grid-centroid"),
149
+ kernelSpec("indirect-finalize"),
150
+ kernelSpec("grid-centroid-hub"),
151
+ kernelSpec("grid-downsample"),
152
+ farFieldSpec(overrides),
153
+ nearFieldSpec(overrides),
154
+ kernelSpec("fa2-speed-finalize", { SWING_MODE: overrides.SWING_MODE }),
155
+ ];
156
+ }
157
+ /**
158
+ * Compiles every kernel of the tier through the cache (sequentially: PipelineCache.get compiles inside a
159
+ * validation scope, one stack per device) over a scope whose scratch and params draw on the stage's lease.
160
+ * @param scope - the context pieces (device, caps, pipelines, pool)
161
+ * @param workgroupSize - the device's workgroup size
162
+ * @param overrides - the SWING_MODE / STRONG_GRAVITY / GRAVITY_CENTER / LAW set of this stage
163
+ * @param spec - the grid
164
+ * @returns the stage, ready for bind()
165
+ */
166
+ static async create(scope, workgroupSize, overrides, spec) {
167
+ const box = { lease: scope.pool.lease() };
168
+ const reduceScope = {
169
+ device: scope.device,
170
+ caps: scope.caps,
171
+ pipelines: scope.pipelines,
172
+ pool: scope.pool,
173
+ workgroupSize,
174
+ scratch: (byteLength, label) => leaseOf(box).storage(byteLength, label),
175
+ params: (block, values) => writeParams(scope.device, leaseOf(box), block, values),
176
+ };
177
+ try {
178
+ const build = await prepareGridBuild(reduceScope, spec);
179
+ const pyramid = await preparePyramid(reduceScope, spec);
180
+ const far = await scope.pipelines.kernel(farFieldSpec(overrides));
181
+ const near = await scope.pipelines.kernel(nearFieldSpec(overrides));
182
+ const speedFinalize = await scope.pipelines.kernel(kernelSpec("fa2-speed-finalize", { SWING_MODE: overrides.SWING_MODE }));
183
+ return new RepulsionGrid(scope, workgroupSize, overrides, spec, box, build, pyramid, {
184
+ far,
185
+ near,
186
+ speedFinalize,
187
+ });
188
+ }
189
+ catch (error) {
190
+ leaseOf(box).release();
191
+ throw error;
192
+ }
193
+ }
194
+ /**
195
+ * Builds every bind group once per load(): the build's and the pyramid's bind() (which take their scratch and
196
+ * write their static params through the lease), then G6, G7 and K4 against the named buffers (the 3.10.1
197
+ * binding names). A second bind() takes fresh scratch from the same lease and the first bind()'s scratch stays
198
+ * held until dispose(): the one lease also holds the prepare-time allocations (the scan's block-sum levels), so
199
+ * it cannot be released on a rebind (the model creates one stage per bind(), so a rebind never happens).
200
+ * @param resources - the buffers of spec 7.3 plus the grid's
201
+ */
202
+ bind(resources) {
203
+ leaseOf(this.box);
204
+ const r = resources;
205
+ this.build.bind({
206
+ pos: r.pos,
207
+ state: r.state,
208
+ params: r.params,
209
+ cellKey: r.cellKey,
210
+ cellVal: r.cellVal,
211
+ sortedKey: r.sortedKey,
212
+ sortedIdx: r.sortedIdx,
213
+ cellHist: r.cellHist,
214
+ cellStart: r.cellStart,
215
+ });
216
+ this.pyramid.bind({
217
+ pos: r.pos,
218
+ params: r.params,
219
+ sortedIdx: r.sortedIdx,
220
+ cellStart: r.cellStart,
221
+ pyramid: r.pyramid,
222
+ hubList: r.hubList,
223
+ hubCounters: r.hubCounters,
224
+ hubArgs: r.hubArgs,
225
+ });
226
+ this.bound = {
227
+ far: this.far.bind({
228
+ pos: r.pos,
229
+ sortedIdx: r.sortedIdx,
230
+ pyramid: r.pyramid,
231
+ S: r.state,
232
+ force: r.force,
233
+ P: r.params,
234
+ }),
235
+ near: this.near.bind({
236
+ pos: r.pos,
237
+ sortedIdx: r.sortedIdx,
238
+ cellStart: r.cellStart,
239
+ S: r.state,
240
+ force: r.force,
241
+ oldForce: r.oldForce,
242
+ fixedMask: r.fixedMask,
243
+ partials: r.partials,
244
+ P: r.params,
245
+ }),
246
+ speedFinalize: this.speedFinalize.bind({ partials: r.partials, S: r.state, T: r.trace, P: r.params }),
247
+ };
248
+ }
249
+ /**
250
+ * Records G1..G7 for `n` nodes with the params slot's dynamic offset, stopping after `upTo` when given (spec 7.4
251
+ * grid sequence; the inspect() stage split, spec 11.9 item 2): G1-G3 through the build planner, G4-G5 through the
252
+ * pyramid planner, then G6 and G7 over plan1d(n).
253
+ * @param pass - the open compute pass of the batch
254
+ * @param n - the node count (in [1, the capacity of the grid buffers])
255
+ * @param paramsOffset - the dynamic offset of this iteration's Fa2Params slot in the uniform ring
256
+ * @param upTo - the last grid stage to record (default "G7")
257
+ */
258
+ recordRepulsion(pass, n, paramsOffset, upTo) {
259
+ const bound = this.requireBound("recordRepulsion");
260
+ const stop = GRID_STAGES.indexOf(upTo ?? "G7");
261
+ let buildStop = "G3";
262
+ if (stop === 0) {
263
+ buildStop = "G1";
264
+ }
265
+ else if (stop === 1) {
266
+ buildStop = "G2";
267
+ }
268
+ this.build.record(pass, n, paramsOffset, buildStop);
269
+ if (stop < 3) {
270
+ return;
271
+ }
272
+ this.pyramid.record(pass, paramsOffset, stop === 3 ? "G4" : "G5");
273
+ if (stop < 5) {
274
+ return;
275
+ }
276
+ const plan = plan1d(n, this.workgroupSize, this.caps);
277
+ this.far.dispatch(pass, bound.far, plan, [paramsOffset]);
278
+ if (stop < 6) {
279
+ return;
280
+ }
281
+ this.near.dispatch(pass, bound.near, plan, [paramsOffset]);
282
+ }
283
+ /**
284
+ * Records K4 only (one workgroup).
285
+ * @param pass - the open compute pass
286
+ * @param paramsOffset - the dynamic offset of the Fa2Params slot
287
+ */
288
+ recordSpeedFinalize(pass, paramsOffset) {
289
+ const bound = this.requireBound("recordSpeedFinalize");
290
+ const one = plan1d(this.speedFinalize.workgroupSize, this.speedFinalize.workgroupSize, this.caps);
291
+ this.speedFinalize.dispatch(pass, bound.speedFinalize, one, [paramsOffset]);
292
+ }
293
+ /** Releases the lease (the sort and scan scratch, the static params) and drops the bind groups; idempotent. */
294
+ dispose() {
295
+ if (this.box.lease !== null) {
296
+ this.box.lease.release();
297
+ this.box.lease = null;
298
+ }
299
+ for (const kernel of [this.far, this.near, this.speedFinalize]) {
300
+ kernel.invalidate();
301
+ }
302
+ this.bound = null;
303
+ }
304
+ /**
305
+ * The bound groups, or E_NOT_LOADED when bind() has not run.
306
+ * @param method - the caller's name for the message
307
+ * @returns the bound groups
308
+ */
309
+ requireBound(method) {
310
+ if (this.bound === null) {
311
+ throw new WebGpuGraphError("E_NOT_LOADED", `RepulsionGrid.${method}(): bind() has not been called for this stage`, {
312
+ state: "unbound",
313
+ });
314
+ }
315
+ return this.bound;
316
+ }
317
+ }
318
+ //# sourceMappingURL=repulsion-grid.js.map