@graphty/webgpu-graph-algorithms 0.0.0 → 0.2.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 (269) hide show
  1. package/README.md +344 -23
  2. package/dist/browser.d.ts +1 -0
  3. package/dist/browser.js +32 -0
  4. package/dist/browser.js.map +1 -0
  5. package/dist/chunks/context-E6iKaeuJ.js +3136 -0
  6. package/dist/chunks/context-E6iKaeuJ.js.map +1 -0
  7. package/dist/node.d.ts +1 -0
  8. package/dist/node.js +131 -0
  9. package/dist/node.js.map +1 -0
  10. package/dist/src/accelerator.d.ts +26 -0
  11. package/dist/src/accelerator.d.ts.map +1 -0
  12. package/dist/src/accelerator.js +101 -0
  13. package/dist/src/accelerator.js.map +1 -0
  14. package/dist/src/algorithms/degree.d.ts +35 -0
  15. package/dist/src/algorithms/degree.d.ts.map +1 -0
  16. package/dist/src/algorithms/degree.js +119 -0
  17. package/dist/src/algorithms/degree.js.map +1 -0
  18. package/dist/src/browser/index.d.ts +23 -0
  19. package/dist/src/browser/index.d.ts.map +1 -0
  20. package/dist/src/browser/index.js +48 -0
  21. package/dist/src/browser/index.js.map +1 -0
  22. package/dist/src/constants.d.ts +92 -0
  23. package/dist/src/constants.d.ts.map +1 -0
  24. package/dist/src/constants.js +92 -0
  25. package/dist/src/constants.js.map +1 -0
  26. package/dist/src/context.d.ts +84 -0
  27. package/dist/src/context.d.ts.map +1 -0
  28. package/dist/src/context.js +304 -0
  29. package/dist/src/context.js.map +1 -0
  30. package/dist/src/device/acquire.d.ts +57 -0
  31. package/dist/src/device/acquire.d.ts.map +1 -0
  32. package/dist/src/device/acquire.js +232 -0
  33. package/dist/src/device/acquire.js.map +1 -0
  34. package/dist/src/device/caps.d.ts +43 -0
  35. package/dist/src/device/caps.d.ts.map +1 -0
  36. package/dist/src/device/caps.js +104 -0
  37. package/dist/src/device/caps.js.map +1 -0
  38. package/dist/src/device/error-scope.d.ts +75 -0
  39. package/dist/src/device/error-scope.d.ts.map +1 -0
  40. package/dist/src/device/error-scope.js +152 -0
  41. package/dist/src/device/error-scope.js.map +1 -0
  42. package/dist/src/device/lost.d.ts +51 -0
  43. package/dist/src/device/lost.d.ts.map +1 -0
  44. package/dist/src/device/lost.js +130 -0
  45. package/dist/src/device/lost.js.map +1 -0
  46. package/dist/src/device/webgpu-constants.d.ts +31 -0
  47. package/dist/src/device/webgpu-constants.d.ts.map +1 -0
  48. package/dist/src/device/webgpu-constants.js +31 -0
  49. package/dist/src/device/webgpu-constants.js.map +1 -0
  50. package/dist/src/errors.d.ts +56 -0
  51. package/dist/src/errors.d.ts.map +1 -0
  52. package/dist/src/errors.js +57 -0
  53. package/dist/src/errors.js.map +1 -0
  54. package/dist/src/index.d.ts +29 -0
  55. package/dist/src/index.d.ts.map +1 -0
  56. package/dist/src/index.js +27 -0
  57. package/dist/src/index.js.map +1 -0
  58. package/dist/src/kernel/batch.d.ts +116 -0
  59. package/dist/src/kernel/batch.d.ts.map +1 -0
  60. package/dist/src/kernel/batch.js +335 -0
  61. package/dist/src/kernel/batch.js.map +1 -0
  62. package/dist/src/kernel/dispatch.d.ts +59 -0
  63. package/dist/src/kernel/dispatch.d.ts.map +1 -0
  64. package/dist/src/kernel/dispatch.js +139 -0
  65. package/dist/src/kernel/dispatch.js.map +1 -0
  66. package/dist/src/kernel/kernel.d.ts +84 -0
  67. package/dist/src/kernel/kernel.d.ts.map +1 -0
  68. package/dist/src/kernel/kernel.js +239 -0
  69. package/dist/src/kernel/kernel.js.map +1 -0
  70. package/dist/src/kernel/pipeline-cache.d.ts +90 -0
  71. package/dist/src/kernel/pipeline-cache.d.ts.map +1 -0
  72. package/dist/src/kernel/pipeline-cache.js +251 -0
  73. package/dist/src/kernel/pipeline-cache.js.map +1 -0
  74. package/dist/src/kernel/prelude.d.ts +35 -0
  75. package/dist/src/kernel/prelude.d.ts.map +1 -0
  76. package/dist/src/kernel/prelude.js +211 -0
  77. package/dist/src/kernel/prelude.js.map +1 -0
  78. package/dist/src/kernel/profiler.d.ts +64 -0
  79. package/dist/src/kernel/profiler.d.ts.map +1 -0
  80. package/dist/src/kernel/profiler.js +120 -0
  81. package/dist/src/kernel/profiler.js.map +1 -0
  82. package/dist/src/kernel/struct-block.d.ts +122 -0
  83. package/dist/src/kernel/struct-block.d.ts.map +1 -0
  84. package/dist/src/kernel/struct-block.js +353 -0
  85. package/dist/src/kernel/struct-block.js.map +1 -0
  86. package/dist/src/kernel/uniform-ring.d.ts +70 -0
  87. package/dist/src/kernel/uniform-ring.d.ts.map +1 -0
  88. package/dist/src/kernel/uniform-ring.js +146 -0
  89. package/dist/src/kernel/uniform-ring.js.map +1 -0
  90. package/dist/src/kernel/wgsl.d.ts +88 -0
  91. package/dist/src/kernel/wgsl.d.ts.map +1 -0
  92. package/dist/src/kernel/wgsl.js +390 -0
  93. package/dist/src/kernel/wgsl.js.map +1 -0
  94. package/dist/src/kernels.d.ts +81 -0
  95. package/dist/src/kernels.d.ts.map +1 -0
  96. package/dist/src/kernels.js +417 -0
  97. package/dist/src/kernels.js.map +1 -0
  98. package/dist/src/layouts/force-simulation.d.ts +498 -0
  99. package/dist/src/layouts/force-simulation.d.ts.map +1 -0
  100. package/dist/src/layouts/force-simulation.js +1650 -0
  101. package/dist/src/layouts/force-simulation.js.map +1 -0
  102. package/dist/src/layouts/forceatlas2.d.ts +210 -0
  103. package/dist/src/layouts/forceatlas2.d.ts.map +1 -0
  104. package/dist/src/layouts/forceatlas2.js +759 -0
  105. package/dist/src/layouts/forceatlas2.js.map +1 -0
  106. package/dist/src/layouts/inputs.d.ts +40 -0
  107. package/dist/src/layouts/inputs.d.ts.map +1 -0
  108. package/dist/src/layouts/inputs.js +185 -0
  109. package/dist/src/layouts/inputs.js.map +1 -0
  110. package/dist/src/layouts/repulsion-exact.d.ts +85 -0
  111. package/dist/src/layouts/repulsion-exact.d.ts.map +1 -0
  112. package/dist/src/layouts/repulsion-exact.js +134 -0
  113. package/dist/src/layouts/repulsion-exact.js.map +1 -0
  114. package/dist/src/layouts/seed.d.ts +56 -0
  115. package/dist/src/layouts/seed.d.ts.map +1 -0
  116. package/dist/src/layouts/seed.js +173 -0
  117. package/dist/src/layouts/seed.js.map +1 -0
  118. package/dist/src/memory/buffer-pool.d.ts +73 -0
  119. package/dist/src/memory/buffer-pool.d.ts.map +1 -0
  120. package/dist/src/memory/buffer-pool.js +170 -0
  121. package/dist/src/memory/buffer-pool.js.map +1 -0
  122. package/dist/src/memory/lease.d.ts +53 -0
  123. package/dist/src/memory/lease.d.ts.map +1 -0
  124. package/dist/src/memory/lease.js +85 -0
  125. package/dist/src/memory/lease.js.map +1 -0
  126. package/dist/src/memory/readback.d.ts +143 -0
  127. package/dist/src/memory/readback.d.ts.map +1 -0
  128. package/dist/src/memory/readback.js +375 -0
  129. package/dist/src/memory/readback.js.map +1 -0
  130. package/dist/src/memory/residency.d.ts +83 -0
  131. package/dist/src/memory/residency.d.ts.map +1 -0
  132. package/dist/src/memory/residency.js +573 -0
  133. package/dist/src/memory/residency.js.map +1 -0
  134. package/dist/src/memory/upload-plan.d.ts +101 -0
  135. package/dist/src/memory/upload-plan.d.ts.map +1 -0
  136. package/dist/src/memory/upload-plan.js +265 -0
  137. package/dist/src/memory/upload-plan.js.map +1 -0
  138. package/dist/src/node/index.d.ts +64 -0
  139. package/dist/src/node/index.d.ts.map +1 -0
  140. package/dist/src/node/index.js +183 -0
  141. package/dist/src/node/index.js.map +1 -0
  142. package/dist/src/primitives/reduce.d.ts +57 -0
  143. package/dist/src/primitives/reduce.d.ts.map +1 -0
  144. package/dist/src/primitives/reduce.js +161 -0
  145. package/dist/src/primitives/reduce.js.map +1 -0
  146. package/dist/src/primitives/segmented-reduce.d.ts +38 -0
  147. package/dist/src/primitives/segmented-reduce.d.ts.map +1 -0
  148. package/dist/src/primitives/segmented-reduce.js +211 -0
  149. package/dist/src/primitives/segmented-reduce.js.map +1 -0
  150. package/dist/src/types/accelerator.d.ts +209 -0
  151. package/dist/src/types/accelerator.d.ts.map +1 -0
  152. package/dist/src/types/accelerator.js +8 -0
  153. package/dist/src/types/accelerator.js.map +1 -0
  154. package/dist/src/types/context.d.ts +114 -0
  155. package/dist/src/types/context.d.ts.map +1 -0
  156. package/dist/src/types/context.js +7 -0
  157. package/dist/src/types/context.js.map +1 -0
  158. package/dist/src/types/layout.d.ts +95 -0
  159. package/dist/src/types/layout.d.ts.map +1 -0
  160. package/dist/src/types/layout.js +6 -0
  161. package/dist/src/types/layout.js.map +1 -0
  162. package/dist/src/types/memory.d.ts +22 -0
  163. package/dist/src/types/memory.d.ts.map +1 -0
  164. package/dist/src/types/memory.js +7 -0
  165. package/dist/src/types/memory.js.map +1 -0
  166. package/dist/src/types/options.d.ts +78 -0
  167. package/dist/src/types/options.d.ts.map +1 -0
  168. package/dist/src/types/options.js +7 -0
  169. package/dist/src/types/options.js.map +1 -0
  170. package/dist/src/types/run.d.ts +13 -0
  171. package/dist/src/types/run.d.ts.map +1 -0
  172. package/dist/src/types/run.js +6 -0
  173. package/dist/src/types/run.js.map +1 -0
  174. package/dist/src/wgsl/degree.wgsl.d.ts +10 -0
  175. package/dist/src/wgsl/degree.wgsl.d.ts.map +1 -0
  176. package/dist/src/wgsl/degree.wgsl.js +25 -0
  177. package/dist/src/wgsl/degree.wgsl.js.map +1 -0
  178. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +12 -0
  179. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -0
  180. package/dist/src/wgsl/fa2-attraction.wgsl.js +37 -0
  181. package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -0
  182. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts +13 -0
  183. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts.map +1 -0
  184. package/dist/src/wgsl/fa2-integrate.wgsl.js +69 -0
  185. package/dist/src/wgsl/fa2-integrate.wgsl.js.map +1 -0
  186. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts +12 -0
  187. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts.map +1 -0
  188. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js +79 -0
  189. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js.map +1 -0
  190. package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts +15 -0
  191. package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts.map +1 -0
  192. package/dist/src/wgsl/fa2-speed-finalize.wgsl.js +54 -0
  193. package/dist/src/wgsl/fa2-speed-finalize.wgsl.js.map +1 -0
  194. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +14 -0
  195. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -0
  196. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +57 -0
  197. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -0
  198. package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts +11 -0
  199. package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts.map +1 -0
  200. package/dist/src/wgsl/fa2-to-scene.wgsl.js +19 -0
  201. package/dist/src/wgsl/fa2-to-scene.wgsl.js.map +1 -0
  202. package/dist/src/wgsl/fill.wgsl.d.ts +7 -0
  203. package/dist/src/wgsl/fill.wgsl.d.ts.map +1 -0
  204. package/dist/src/wgsl/fill.wgsl.js +14 -0
  205. package/dist/src/wgsl/fill.wgsl.js.map +1 -0
  206. package/dist/src/wgsl/reduce.wgsl.d.ts +10 -0
  207. package/dist/src/wgsl/reduce.wgsl.d.ts.map +1 -0
  208. package/dist/src/wgsl/reduce.wgsl.js +63 -0
  209. package/dist/src/wgsl/reduce.wgsl.js.map +1 -0
  210. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts +13 -0
  211. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts.map +1 -0
  212. package/dist/src/wgsl/segmented-reduce.wgsl.js +35 -0
  213. package/dist/src/wgsl/segmented-reduce.wgsl.js.map +1 -0
  214. package/dist/tsconfig.build.tsbuildinfo +1 -0
  215. package/dist/webgpu-graph-algorithms.d.ts +1 -0
  216. package/dist/webgpu-graph-algorithms.js +4454 -0
  217. package/dist/webgpu-graph-algorithms.js.map +1 -0
  218. package/package.json +108 -17
  219. package/src/accelerator.ts +117 -0
  220. package/src/algorithms/degree.ts +142 -0
  221. package/src/browser/index.ts +57 -0
  222. package/src/constants.ts +116 -0
  223. package/src/context.ts +399 -0
  224. package/src/device/acquire.ts +256 -0
  225. package/src/device/caps.ts +122 -0
  226. package/src/device/error-scope.ts +171 -0
  227. package/src/device/lost.ts +142 -0
  228. package/src/device/webgpu-constants.ts +44 -0
  229. package/src/errors.ts +94 -0
  230. package/src/index.ts +102 -0
  231. package/src/kernel/batch.ts +427 -0
  232. package/src/kernel/dispatch.ts +162 -0
  233. package/src/kernel/kernel.ts +311 -0
  234. package/src/kernel/pipeline-cache.ts +288 -0
  235. package/src/kernel/prelude.ts +229 -0
  236. package/src/kernel/profiler.ts +148 -0
  237. package/src/kernel/struct-block.ts +439 -0
  238. package/src/kernel/uniform-ring.ts +184 -0
  239. package/src/kernel/wgsl.ts +490 -0
  240. package/src/kernels.ts +511 -0
  241. package/src/layouts/force-simulation.ts +2111 -0
  242. package/src/layouts/forceatlas2.ts +942 -0
  243. package/src/layouts/inputs.ts +252 -0
  244. package/src/layouts/repulsion-exact.ts +183 -0
  245. package/src/layouts/seed.ts +198 -0
  246. package/src/memory/buffer-pool.ts +204 -0
  247. package/src/memory/lease.ts +93 -0
  248. package/src/memory/readback.ts +429 -0
  249. package/src/memory/residency.ts +753 -0
  250. package/src/memory/upload-plan.ts +350 -0
  251. package/src/node/index.ts +230 -0
  252. package/src/primitives/reduce.ts +233 -0
  253. package/src/primitives/segmented-reduce.ts +270 -0
  254. package/src/types/accelerator.ts +236 -0
  255. package/src/types/context.ts +135 -0
  256. package/src/types/layout.ts +103 -0
  257. package/src/types/memory.ts +23 -0
  258. package/src/types/options.ts +84 -0
  259. package/src/types/run.ts +13 -0
  260. package/src/wgsl/degree.wgsl.ts +24 -0
  261. package/src/wgsl/fa2-attraction.wgsl.ts +37 -0
  262. package/src/wgsl/fa2-integrate.wgsl.ts +69 -0
  263. package/src/wgsl/fa2-repulsion-exact.wgsl.ts +78 -0
  264. package/src/wgsl/fa2-speed-finalize.wgsl.ts +53 -0
  265. package/src/wgsl/fa2-stats-finalize.wgsl.ts +57 -0
  266. package/src/wgsl/fa2-to-scene.wgsl.ts +19 -0
  267. package/src/wgsl/fill.wgsl.ts +13 -0
  268. package/src/wgsl/reduce.wgsl.ts +62 -0
  269. package/src/wgsl/segmented-reduce.wgsl.ts +35 -0
@@ -0,0 +1,101 @@
1
+ /**
2
+ * The pure upload planner of spec 4.2: from a snapshot's shape, the device limits and the core arrays a kernel
3
+ * needs, choose the one-buffer arena upload (the hot prefix, or the full arena when a cold segment is needed and
4
+ * fits), one buffer per array, or arc windows over the arc-indexed arrays. No GPU object is touched here:
5
+ * GraphResidency (./residency.ts) executes arena and perArray plans and P4 executes windowed plans (P1-P3 only
6
+ * plan them). Every byte length comes from counts and flags, so an identity permutation is never materialised
7
+ * (spec 4.1), and every arithmetic step uses `%` and Math.floor, never a bitwise operator: arc indices and byte
8
+ * offsets exceed 2^31 at the 10M / 100M tier (graph-format invariant I3, spec 4.2).
9
+ */
10
+ import { type CoreArrayName, type GraphSnapshot } from "@graphty/graph-format";
11
+ import { type PlanCaps, type PlanLimits } from "../types/context.js";
12
+ import { type ArcWindow } from "../types/memory.js";
13
+ /**
14
+ * Where one core array's bytes go: one or more buffers (split at window boundaries only when the array exceeds
15
+ * maxBufferSize). Exported with the plan union (contract 3.8): P4's windowed execution reads it; nothing at P1
16
+ * imports it by name.
17
+ * @public
18
+ */
19
+ export interface PlannedArray {
20
+ readonly name: CoreArrayName;
21
+ readonly byteLength: number;
22
+ readonly buffers: readonly {
23
+ readonly byteOffset: number;
24
+ readonly byteLength: number;
25
+ }[];
26
+ }
27
+ /**
28
+ * The arena path: ONE buffer of `bytes`, one writeBuffer, per-segment bindings at `segment.byteOffset - arena.byteOffset`.
29
+ * A member of the exported UploadPlan union (contract 3.8 exports the three plan shapes by name); nothing imports it
30
+ * by name, which knip 5.77 reports.
31
+ * @public
32
+ */
33
+ export interface ArenaPlan {
34
+ readonly kind: "arena";
35
+ readonly bytes: number;
36
+ readonly includesCold: boolean;
37
+ readonly segments: Readonly<Record<CoreArrayName, {
38
+ readonly offset: number;
39
+ readonly size: number;
40
+ } | null>>;
41
+ }
42
+ /**
43
+ * The per-array path: one buffer per needed array, whole-buffer bindings.
44
+ * A member of the exported UploadPlan union (contract 3.8 exports the three plan shapes by name); nothing imports it
45
+ * by name, which knip 5.77 reports.
46
+ * @public
47
+ */
48
+ export interface PerArrayPlan {
49
+ readonly kind: "perArray";
50
+ readonly arrays: readonly PlannedArray[];
51
+ }
52
+ /**
53
+ * The windowed path: per-array buffers plus the arc windows kernels iterate (P4 executes; P1-P3 only plan).
54
+ * A member of the exported UploadPlan union (contract 3.8 exports the three plan shapes by name); nothing imports it
55
+ * by name, which knip 5.77 reports.
56
+ * @public
57
+ */
58
+ export interface WindowedPlan {
59
+ readonly kind: "windowed";
60
+ readonly arrays: readonly PlannedArray[];
61
+ readonly windows: readonly ArcWindow[];
62
+ readonly arcsPerWindow: number;
63
+ }
64
+ /** One of the three plans. */
65
+ export type UploadPlan = ArenaPlan | PerArrayPlan | WindowedPlan;
66
+ /**
67
+ * The largest 64-aligned arc count one binding holds: floor(maxStorageBufferBindingSize / 4) rounded down to a
68
+ * multiple of ARC_WINDOW_ALIGN.
69
+ * @param limits - the device limits
70
+ * @returns the arcs per window (0 when the binding limit is below 256 bytes)
71
+ */
72
+ export declare function arcsPerWindowFor(limits: PlanLimits): number;
73
+ /**
74
+ * The window list for a rowPtr (pure; unit-tested with a synthetic rowPtr above 2^31 arcs): start = rowPtr[v0] -
75
+ * rowPtr[v0] % ARC_WINDOW_ALIGN, at most `arcsPerWindow` arcs per window, a row longer than a window split across
76
+ * windows. Whole rows first: a window ends at the last row boundary within `start + arcsPerWindow`; a row that does
77
+ * not fit a window opened at its own aligned start is split into aligned chunks whose `rowFirst === rowLast` is that
78
+ * row, and the next window continues the row at the chunk end. Every row belongs to a window (leading and trailing
79
+ * empty rows included); every window is placed in buffer 0 at offset 4 x start (planUpload re-places them when an
80
+ * array is split across buffers).
81
+ * @param rowPtr - nodeCount + 1 row offsets (rowPtr[nodeCount] === arcCount)
82
+ * @param arcCount - the arc count
83
+ * @param arcsPerWindow - a positive multiple of ARC_WINDOW_ALIGN
84
+ * @returns the windows in arc order (empty for arcCount 0)
85
+ */
86
+ export declare function planArcWindows(rowPtr: Uint32Array, arcCount: number, arcsPerWindow: number): ArcWindow[];
87
+ /**
88
+ * The pure planner of spec 4.2: arena (hot prefix unless `need` names a cold segment and the full arena fits) ->
89
+ * perArray -> windowed, in that order. `need` always contains "rowPtr" (it is added when absent); absent arrays
90
+ * (unweighted `weights`, identity permutations, zero-length arrays) are dropped; a snapshot with arcCount === 0
91
+ * plans rowPtr only. The arena path needs `bytes <= maxBufferSize` and every needed segment within both limits;
92
+ * ArenaPlan.segments lists every non-null segment inside the uploaded bytes (a needed cold segment outside them is
93
+ * null: the residency uploads it as its own buffer). The perArray path needs every needed array within both limits;
94
+ * otherwise the arc-indexed arrays are windowed (rowPtr and edgeToArc must fit, else E_TOO_LARGE).
95
+ * @param s - the snapshot (only arena, the counts, the flags and rowPtr are read)
96
+ * @param caps - the device capabilities (only `limits` is read)
97
+ * @param need - the core arrays the kernel binds
98
+ * @returns the plan
99
+ */
100
+ export declare function planUpload(s: GraphSnapshot, caps: PlanCaps, need: readonly CoreArrayName[]): UploadPlan;
101
+ //# sourceMappingURL=upload-plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-plan.d.ts","sourceRoot":"","sources":["../../../src/memory/upload-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI/E,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAQpD;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7F;AAED;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC,CAAC;CACjH;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;CAC5C;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAClC;AAED,8BAA8B;AAC9B,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,YAAY,CAAC;AAiFjE;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAE3D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,SAAS,EAAE,CA4CxG;AA6CD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,UAAU,CAsEvG"}
@@ -0,0 +1,265 @@
1
+ /**
2
+ * The pure upload planner of spec 4.2: from a snapshot's shape, the device limits and the core arrays a kernel
3
+ * needs, choose the one-buffer arena upload (the hot prefix, or the full arena when a cold segment is needed and
4
+ * fits), one buffer per array, or arc windows over the arc-indexed arrays. No GPU object is touched here:
5
+ * GraphResidency (./residency.ts) executes arena and perArray plans and P4 executes windowed plans (P1-P3 only
6
+ * plan them). Every byte length comes from counts and flags, so an identity permutation is never materialised
7
+ * (spec 4.1), and every arithmetic step uses `%` and Math.floor, never a bitwise operator: arc indices and byte
8
+ * offsets exceed 2^31 at the 10M / 100M tier (graph-format invariant I3, spec 4.2).
9
+ */
10
+ import { ARC_WINDOW_ALIGN } from "../constants.js";
11
+ import { WebGpuGraphError } from "../errors.js";
12
+ /** The five core arrays in arena (hot-to-cold) order. */
13
+ const CORE_ORDER = Object.freeze(["rowPtr", "colIdx", "weights", "arcToEdge", "edgeToArc"]);
14
+ /** The arc-indexed arrays: the only ones a window can cover (rowPtr is row-indexed, edgeToArc edge-indexed). */
15
+ const ARC_INDEXED = new Set(["colIdx", "weights", "arcToEdge"]);
16
+ /**
17
+ * Byte length of every core array from the counts and flags alone; 0 means absent (unweighted, an identity
18
+ * permutation, or zero length: spec 5.6 never binds a zero-length array). No array is read.
19
+ * @param s - the snapshot
20
+ * @returns the byte lengths keyed by core array name
21
+ */
22
+ function coreByteLengths(s) {
23
+ const arcs = s.arcCount;
24
+ const identity = s.flags.arcToEdgeIsIdentity;
25
+ return {
26
+ rowPtr: 4 * (s.nodeCount + 1),
27
+ colIdx: 4 * arcs,
28
+ weights: s.flags.weighted && arcs > 0 ? 4 * arcs : 0,
29
+ arcToEdge: !identity && arcs > 0 ? 4 * arcs : 0,
30
+ edgeToArc: !identity && s.edgeCount > 0 ? 4 * s.edgeCount : 0,
31
+ };
32
+ }
33
+ /**
34
+ * rowPtr always, then every requested PRESENT array, in arena order (absent names are dropped, never an error).
35
+ * @param need - the requested names
36
+ * @param lengths - the byte lengths of coreByteLengths
37
+ * @returns the names to plan
38
+ */
39
+ function neededNames(need, lengths) {
40
+ const wanted = new Set(need);
41
+ wanted.add("rowPtr");
42
+ return CORE_ORDER.filter((name) => wanted.has(name) && lengths[name] > 0);
43
+ }
44
+ /**
45
+ * Rounds an arc count down to a multiple of ARC_WINDOW_ALIGN with `%` (a bitwise `& ~63` breaks above 2^31).
46
+ * @param value - an arc count
47
+ * @returns the largest multiple of 64 not above it
48
+ */
49
+ function alignDown(value) {
50
+ return value - (value % ARC_WINDOW_ALIGN);
51
+ }
52
+ /**
53
+ * The E_TOO_LARGE error of spec 5.7 for a plan that cannot exist.
54
+ * @param needed - the bytes that do not fit
55
+ * @param limit - the limit they exceed
56
+ * @param path - "rowPtr" (no window can hold rowPtr) or "binding" (an edge-indexed array cannot be windowed)
57
+ * @returns the error to throw
58
+ */
59
+ function tooLarge(needed, limit, path) {
60
+ return new WebGpuGraphError("E_TOO_LARGE", `${path}: ${needed} bytes exceed the device limit of ${limit} bytes`, {
61
+ needed,
62
+ limit,
63
+ path,
64
+ algorithm: null,
65
+ });
66
+ }
67
+ /**
68
+ * The E_INVALID_ARGUMENT error of a bad planner input.
69
+ * @param argument - the argument name
70
+ * @param value - the value given
71
+ * @param expected - what was expected
72
+ * @returns the error to throw
73
+ */
74
+ function invalid(argument, value, expected) {
75
+ return new WebGpuGraphError("E_INVALID_ARGUMENT", `${argument}: expected ${expected}`, {
76
+ argument,
77
+ value,
78
+ expected,
79
+ });
80
+ }
81
+ /**
82
+ * The largest 64-aligned arc count one binding holds: floor(maxStorageBufferBindingSize / 4) rounded down to a
83
+ * multiple of ARC_WINDOW_ALIGN.
84
+ * @param limits - the device limits
85
+ * @returns the arcs per window (0 when the binding limit is below 256 bytes)
86
+ */
87
+ export function arcsPerWindowFor(limits) {
88
+ return alignDown(Math.floor(limits.maxStorageBufferBindingSize / 4));
89
+ }
90
+ /**
91
+ * The window list for a rowPtr (pure; unit-tested with a synthetic rowPtr above 2^31 arcs): start = rowPtr[v0] -
92
+ * rowPtr[v0] % ARC_WINDOW_ALIGN, at most `arcsPerWindow` arcs per window, a row longer than a window split across
93
+ * windows. Whole rows first: a window ends at the last row boundary within `start + arcsPerWindow`; a row that does
94
+ * not fit a window opened at its own aligned start is split into aligned chunks whose `rowFirst === rowLast` is that
95
+ * row, and the next window continues the row at the chunk end. Every row belongs to a window (leading and trailing
96
+ * empty rows included); every window is placed in buffer 0 at offset 4 x start (planUpload re-places them when an
97
+ * array is split across buffers).
98
+ * @param rowPtr - nodeCount + 1 row offsets (rowPtr[nodeCount] === arcCount)
99
+ * @param arcCount - the arc count
100
+ * @param arcsPerWindow - a positive multiple of ARC_WINDOW_ALIGN
101
+ * @returns the windows in arc order (empty for arcCount 0)
102
+ */
103
+ export function planArcWindows(rowPtr, arcCount, arcsPerWindow) {
104
+ if (rowPtr.length === 0) {
105
+ throw invalid("rowPtr", rowPtr.length, "nodeCount + 1 entries");
106
+ }
107
+ if (!Number.isInteger(arcsPerWindow) ||
108
+ arcsPerWindow < ARC_WINDOW_ALIGN ||
109
+ arcsPerWindow % ARC_WINDOW_ALIGN !== 0) {
110
+ throw invalid("arcsPerWindow", arcsPerWindow, `a positive multiple of ${ARC_WINDOW_ALIGN}`);
111
+ }
112
+ const n = rowPtr.length - 1;
113
+ if (rowPtr[n] !== arcCount) {
114
+ throw invalid("arcCount", arcCount, `rowPtr[${n}] === ${rowPtr[n]}`);
115
+ }
116
+ const windows = [];
117
+ if (arcCount === 0) {
118
+ return windows;
119
+ }
120
+ let pos = 0;
121
+ let v = 0;
122
+ let rowFirst = 0;
123
+ while (pos < arcCount) {
124
+ while (rowPtr[v + 1] <= pos) {
125
+ v++;
126
+ }
127
+ const start = alignDown(pos);
128
+ const limit = start + arcsPerWindow;
129
+ if (rowPtr[v + 1] > limit) {
130
+ windows.push({ start, end: limit, rowFirst, rowLast: v, bufferIndex: 0, offset: 4 * start });
131
+ pos = limit;
132
+ rowFirst = v;
133
+ }
134
+ else {
135
+ let u = v;
136
+ while (u + 1 < n && rowPtr[u + 2] <= limit) {
137
+ u++;
138
+ }
139
+ const end = rowPtr[u + 1];
140
+ windows.push({ start, end, rowFirst, rowLast: u, bufferIndex: 0, offset: 4 * start });
141
+ pos = end;
142
+ rowFirst = u + 1;
143
+ }
144
+ }
145
+ return windows;
146
+ }
147
+ /**
148
+ * Groups consecutive windows into buffers of at most `bufferLimit` bytes (spec 4.2: an array above maxBufferSize is
149
+ * split across buffers at window boundaries) and re-places every window with its buffer index and offset.
150
+ * @param windows - the windows of planArcWindows
151
+ * @param arcBytes - the byte length of one arc-indexed array
152
+ * @param bufferLimit - maxBufferSize
153
+ * @returns the buffer ranges shared by every arc-indexed array and the placed windows
154
+ */
155
+ function placeWindows(windows, arcBytes, bufferLimit) {
156
+ if (arcBytes <= bufferLimit) {
157
+ return { buffers: [{ byteOffset: 0, byteLength: arcBytes }], placed: [...windows] };
158
+ }
159
+ const buffers = [];
160
+ const placed = [];
161
+ let first = 0;
162
+ while (first < windows.length) {
163
+ let last = first;
164
+ while (last + 1 < windows.length && 4 * (windows[last + 1].end - windows[first].start) <= bufferLimit) {
165
+ last++;
166
+ }
167
+ const base = windows[first].start;
168
+ const bufferIndex = buffers.length;
169
+ buffers.push({ byteOffset: 4 * base, byteLength: 4 * (windows[last].end - base) });
170
+ for (let i = first; i <= last; i++) {
171
+ const w = windows[i];
172
+ placed.push({
173
+ start: w.start,
174
+ end: w.end,
175
+ rowFirst: w.rowFirst,
176
+ rowLast: w.rowLast,
177
+ bufferIndex,
178
+ offset: 4 * (w.start - base),
179
+ });
180
+ }
181
+ first = last + 1;
182
+ }
183
+ return { buffers, placed };
184
+ }
185
+ /**
186
+ * The pure planner of spec 4.2: arena (hot prefix unless `need` names a cold segment and the full arena fits) ->
187
+ * perArray -> windowed, in that order. `need` always contains "rowPtr" (it is added when absent); absent arrays
188
+ * (unweighted `weights`, identity permutations, zero-length arrays) are dropped; a snapshot with arcCount === 0
189
+ * plans rowPtr only. The arena path needs `bytes <= maxBufferSize` and every needed segment within both limits;
190
+ * ArenaPlan.segments lists every non-null segment inside the uploaded bytes (a needed cold segment outside them is
191
+ * null: the residency uploads it as its own buffer). The perArray path needs every needed array within both limits;
192
+ * otherwise the arc-indexed arrays are windowed (rowPtr and edgeToArc must fit, else E_TOO_LARGE).
193
+ * @param s - the snapshot (only arena, the counts, the flags and rowPtr are read)
194
+ * @param caps - the device capabilities (only `limits` is read)
195
+ * @param need - the core arrays the kernel binds
196
+ * @returns the plan
197
+ */
198
+ export function planUpload(s, caps, need) {
199
+ const { limits } = caps;
200
+ const binding = limits.maxStorageBufferBindingSize;
201
+ const bufferLimit = limits.maxBufferSize;
202
+ const fits = (bytes) => bytes <= binding && bytes <= bufferLimit;
203
+ const violated = (bytes) => (bytes > binding ? binding : bufferLimit);
204
+ const lengths = coreByteLengths(s);
205
+ const names = neededNames(need, lengths);
206
+ if (!fits(lengths.rowPtr)) {
207
+ throw tooLarge(lengths.rowPtr, violated(lengths.rowPtr), "rowPtr");
208
+ }
209
+ const { arena } = s;
210
+ if (arena !== null) {
211
+ const coldNeeded = names.some((name) => (name === "arcToEdge" || name === "edgeToArc") && arena.segments[name] !== null);
212
+ const includesCold = coldNeeded && arena.byteLength <= bufferLimit;
213
+ const bytes = includesCold ? arena.byteLength : arena.hotByteLength;
214
+ const bindable = names.every((name) => {
215
+ const segment = arena.segments[name];
216
+ return segment === null || fits(segment.byteLength);
217
+ });
218
+ if (bytes <= bufferLimit && bindable) {
219
+ const segmentOf = (name) => {
220
+ const segment = arena.segments[name];
221
+ if (segment === null) {
222
+ return null;
223
+ }
224
+ const offset = segment.byteOffset - arena.byteOffset;
225
+ return offset + segment.byteLength <= bytes ? { offset, size: segment.byteLength } : null;
226
+ };
227
+ return {
228
+ kind: "arena",
229
+ bytes,
230
+ includesCold,
231
+ segments: {
232
+ rowPtr: segmentOf("rowPtr"),
233
+ colIdx: segmentOf("colIdx"),
234
+ weights: segmentOf("weights"),
235
+ arcToEdge: segmentOf("arcToEdge"),
236
+ edgeToArc: segmentOf("edgeToArc"),
237
+ },
238
+ };
239
+ }
240
+ }
241
+ if (names.every((name) => fits(lengths[name]))) {
242
+ return {
243
+ kind: "perArray",
244
+ arrays: names.map((name) => ({
245
+ name,
246
+ byteLength: lengths[name],
247
+ buffers: [{ byteOffset: 0, byteLength: lengths[name] }],
248
+ })),
249
+ };
250
+ }
251
+ if (names.includes("edgeToArc") && !fits(lengths.edgeToArc)) {
252
+ throw tooLarge(lengths.edgeToArc, violated(lengths.edgeToArc), "binding");
253
+ }
254
+ const arcsPerWindow = Math.min(arcsPerWindowFor(limits), alignDown(Math.floor(bufferLimit / 4)));
255
+ if (arcsPerWindow < ARC_WINDOW_ALIGN) {
256
+ throw tooLarge(4 * ARC_WINDOW_ALIGN, binding, "binding");
257
+ }
258
+ const windows = planArcWindows(s.rowPtr, s.arcCount, arcsPerWindow);
259
+ const { buffers, placed } = placeWindows(windows, 4 * s.arcCount, bufferLimit);
260
+ const arrays = names.map((name) => ARC_INDEXED.has(name)
261
+ ? { name, byteLength: lengths[name], buffers }
262
+ : { name, byteLength: lengths[name], buffers: [{ byteOffset: 0, byteLength: lengths[name] }] });
263
+ return { kind: "windowed", arrays, windows: placed, arcsPerWindow };
264
+ }
265
+ //# sourceMappingURL=upload-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-plan.js","sourceRoot":"","sources":["../../../src/memory/upload-plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * The ./node entry (spec 2.1, 2.3, 3.4; contract 3.7): Dawn through the optional peer dependency `webgpu`. The
3
+ * ONLY file of the package that names the "webgpu" module, and only inside `await import("webgpu")` in a
4
+ * function body, so the root and browser bundles never carry the specifier (spec 2.5; test/build-output.test.ts,
5
+ * test/layers.test.ts). P0-T3 wrote createNodeGpu, dawnFlags and their types; P1-T1 adds createNodeGpuContext,
6
+ * probeNodeWebGpu and the `extends Omit<GpuContextOptions, ...>` clause of NodeGpuOptions.
7
+ *
8
+ * Rule of spec 2.5 item 5 (also in CLAUDE.md): "./node" is imported only by Node entry points and tests.
9
+ */
10
+ /// <reference types="@webgpu/types" preserve="true" />
11
+ import { GpuContext } from "../context.js";
12
+ import type { GpuContextOptions, ProbeResult } from "../types/context.js";
13
+ /** Options of the Node helpers (spec 3.4). */
14
+ export interface NodeGpuOptions extends Omit<GpuContextOptions, "gpu" | "adapter" | "device" | "runtime"> {
15
+ /** Dawn `adapter=<substring>`: a substring of the adapter name (`llvmpipe`, `4070`); an empty string is ignored; wins over `software`. */
16
+ readonly adapter?: string | undefined;
17
+ /** Dawn `backend=<name>`; `null` compiles pipelines and runs nothing (spec 5.1; the compile tests use it). */
18
+ readonly backend?: "vulkan" | "d3d12" | "d3d11" | "metal" | "opengl" | "opengles" | "null" | undefined;
19
+ /** Dawn toggles, emitted as `enable-dawn-features=a,b`. */
20
+ readonly dawnFeatures?: readonly string[] | undefined;
21
+ /** Shorthand for `adapter=llvmpipe` (Linux / Mesa specific, spec 2.3); ignored when `adapter` is given. */
22
+ readonly software?: boolean | undefined;
23
+ /** Install dawn.globals on globalThis (default true; spec 2.1 rule 2) so user code sees GPUBufferUsage and friends. */
24
+ readonly installGlobals?: boolean | undefined;
25
+ }
26
+ /** The Dawn GPU handle (spec 2.3): dispose() drops the reference so the process can exit. */
27
+ export interface NodeGpuHandle {
28
+ /** The GPU of `dawn.create(flags)`; reading it after dispose() throws E_DISPOSED. */
29
+ readonly gpu: GPU;
30
+ /** Drops the GPU reference; idempotent. */
31
+ dispose(): void;
32
+ }
33
+ /**
34
+ * The Dawn flag list a NodeGpuOptions maps to (exported for the tests and scripts/gpu-report.js):
35
+ * adapter=<s>, backend=<s>, enable-dawn-features=a,b, and software -> adapter=llvmpipe; an explicit non-empty
36
+ * `adapter` wins over `software`; an empty feature list emits nothing.
37
+ * @param options - the Node options, or undefined for no flags
38
+ * @returns the strings for dawn.create(), in the order adapter, backend, features
39
+ */
40
+ export declare function dawnFlags(options: NodeGpuOptions | undefined): string[];
41
+ /**
42
+ * import("webgpu"), install dawn.globals unless installGlobals === false, dawn.create(flags) (spec 2.3).
43
+ * @param options - adapter / backend / dawnFeatures / software / installGlobals (and the test seam)
44
+ * @returns the handle; `dispose()` drops the GPU reference so the process can exit
45
+ * @throws WebGpuGraphError E_NO_WEBGPU { reason, hint } when the module does not load (missing, or its glibc is too old), has no create(), or create(flags) throws
46
+ */
47
+ export declare function createNodeGpu(options?: NodeGpuOptions): Promise<NodeGpuHandle>;
48
+ /**
49
+ * createNodeGpu + GpuContext.create({ gpu, runtime: "node", ...options }); ctx.dispose() also disposes the
50
+ * handle, and a create() failure disposes it before rethrowing. The handle is dropped once `ctx.lost` has
51
+ * settled, never before: under webgpu@0.4.0 a GPU object collected while the device it created is still
52
+ * tearing down (its lost / work-done callbacks in flight) crashes or deadlocks the process (PLAN DECISION,
53
+ * P1-T1; measured with tmp/p1t1/gc-race2.mjs), and device.destroy() reports the loss right away.
54
+ * @param options - the Node options
55
+ * @returns the context
56
+ */
57
+ export declare function createNodeGpuContext(options?: NodeGpuOptions): Promise<GpuContext>;
58
+ /**
59
+ * createNodeGpu + GpuContext.probe + dispose; never throws (a load failure is { code: "E_NO_WEBGPU" }).
60
+ * @param options - the Node options
61
+ * @returns the probe result
62
+ */
63
+ export declare function probeNodeWebGpu(options?: NodeGpuOptions): Promise<ProbeResult>;
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/node/index.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAE1E,8CAA8C;AAC9C,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,iBAAiB,EAAE,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACrG,0IAA0I;IAC1I,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,8GAA8G;IAC9G,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;IACvG,2DAA2D;IAC3D,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACtD,2GAA2G;IAC3G,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,uHAAuH;IACvH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAMjD;AAED,6FAA6F;AAC7F,MAAM,WAAW,aAAa;IAC1B,qFAAqF;IACrF,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,2CAA2C;IAC3C,OAAO,IAAI,IAAI,CAAC;CACnB;AA4DD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,SAAS,GAAG,MAAM,EAAE,CAiBvE;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA4BpF;AAqBD;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAgBxF;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAgBpF"}
@@ -0,0 +1,183 @@
1
+ /// <reference types="@webgpu/types" preserve="true" />
2
+ /**
3
+ * The ./node entry (spec 2.1, 2.3, 3.4; contract 3.7): Dawn through the optional peer dependency `webgpu`. The
4
+ * ONLY file of the package that names the "webgpu" module, and only inside `await import("webgpu")` in a
5
+ * function body, so the root and browser bundles never carry the specifier (spec 2.5; test/build-output.test.ts,
6
+ * test/layers.test.ts). P0-T3 wrote createNodeGpu, dawnFlags and their types; P1-T1 adds createNodeGpuContext,
7
+ * probeNodeWebGpu and the `extends Omit<GpuContextOptions, ...>` clause of NodeGpuOptions.
8
+ *
9
+ * Rule of spec 2.5 item 5 (also in CLAUDE.md): "./node" is imported only by Node entry points and tests.
10
+ */
11
+ import { GpuContext } from "../context.js";
12
+ import { WebGpuGraphError } from "../errors.js";
13
+ /** The install hint of E_NO_WEBGPU (spec 2.5 item 4); P-ENV re-pins the version together with the devDependency. */
14
+ const INSTALL_HINT = "install the optional peer dependency webgpu@0.4.0";
15
+ /**
16
+ * Whether a loaded module is usable as Dawn.
17
+ * @param loaded - the module namespace
18
+ * @returns true when it has a create() function
19
+ */
20
+ function isDawnModule(loaded) {
21
+ return (typeof loaded === "object" && loaded !== null && typeof loaded.create === "function");
22
+ }
23
+ /**
24
+ * The message of a thrown value.
25
+ * @param err - what was caught
26
+ * @returns the Error message, or the value as a string
27
+ */
28
+ function messageOf(err) {
29
+ return err instanceof Error ? err.message : String(err);
30
+ }
31
+ /** The handle returned by createNodeGpu(): `gpu` is a getter so dispose() can drop the reference. */
32
+ class DawnHandle {
33
+ /**
34
+ * Wraps a GPU object.
35
+ * @param gpu - the object dawn.create() returned
36
+ */
37
+ constructor(gpu) {
38
+ this.ref = gpu;
39
+ }
40
+ /**
41
+ * The GPU object; E_DISPOSED after dispose().
42
+ * @returns the GPU object
43
+ */
44
+ get gpu() {
45
+ if (this.ref === null) {
46
+ throw new WebGpuGraphError("E_DISPOSED", "the Dawn GPU handle was disposed", { label: "NodeGpuHandle" });
47
+ }
48
+ return this.ref;
49
+ }
50
+ /** Drops the reference; idempotent. */
51
+ dispose() {
52
+ this.ref = null;
53
+ }
54
+ }
55
+ /**
56
+ * The Dawn flag list a NodeGpuOptions maps to (exported for the tests and scripts/gpu-report.js):
57
+ * adapter=<s>, backend=<s>, enable-dawn-features=a,b, and software -> adapter=llvmpipe; an explicit non-empty
58
+ * `adapter` wins over `software`; an empty feature list emits nothing.
59
+ * @param options - the Node options, or undefined for no flags
60
+ * @returns the strings for dawn.create(), in the order adapter, backend, features
61
+ */
62
+ export function dawnFlags(options) {
63
+ const flags = [];
64
+ if (options === undefined) {
65
+ return flags;
66
+ }
67
+ if (options.adapter !== undefined && options.adapter !== "") {
68
+ flags.push(`adapter=${options.adapter}`);
69
+ }
70
+ else if (options.software === true) {
71
+ flags.push("adapter=llvmpipe");
72
+ }
73
+ if (options.backend !== undefined) {
74
+ flags.push(`backend=${options.backend}`);
75
+ }
76
+ if (options.dawnFeatures !== undefined && options.dawnFeatures.length > 0) {
77
+ flags.push(`enable-dawn-features=${options.dawnFeatures.join(",")}`);
78
+ }
79
+ return flags;
80
+ }
81
+ /**
82
+ * import("webgpu"), install dawn.globals unless installGlobals === false, dawn.create(flags) (spec 2.3).
83
+ * @param options - adapter / backend / dawnFeatures / software / installGlobals (and the test seam)
84
+ * @returns the handle; `dispose()` drops the GPU reference so the process can exit
85
+ * @throws WebGpuGraphError E_NO_WEBGPU { reason, hint } when the module does not load (missing, or its glibc is too old), has no create(), or create(flags) throws
86
+ */
87
+ export async function createNodeGpu(options) {
88
+ const load = options?.loadModule ?? (() => import("webgpu"));
89
+ let loaded;
90
+ try {
91
+ loaded = await load();
92
+ }
93
+ catch (err) {
94
+ const reason = messageOf(err);
95
+ throw new WebGpuGraphError("E_NO_WEBGPU", `the webgpu (Dawn) native module did not load: ${reason}; ${INSTALL_HINT}`, { reason, hint: INSTALL_HINT });
96
+ }
97
+ if (!isDawnModule(loaded)) {
98
+ const reason = "the webgpu module exports no create() function";
99
+ throw new WebGpuGraphError("E_NO_WEBGPU", `${reason}; ${INSTALL_HINT}`, { reason, hint: INSTALL_HINT });
100
+ }
101
+ if (options?.installGlobals !== false && typeof loaded.globals === "object" && loaded.globals !== null) {
102
+ Object.assign(globalThis, loaded.globals);
103
+ }
104
+ let gpu;
105
+ try {
106
+ gpu = loaded.create(dawnFlags(options));
107
+ }
108
+ catch (err) {
109
+ const reason = `dawn.create() threw: ${messageOf(err)}`;
110
+ throw new WebGpuGraphError("E_NO_WEBGPU", `${reason}; ${INSTALL_HINT}`, { reason, hint: INSTALL_HINT });
111
+ }
112
+ return new DawnHandle(gpu);
113
+ }
114
+ /**
115
+ * The GpuContextOptions part of a NodeGpuOptions, copied key by key so the Node-only `adapter` string never
116
+ * reaches GpuContext.create as a GPUAdapter.
117
+ * @param options - the Node options
118
+ * @returns the context options without gpu / adapter / device / runtime
119
+ */
120
+ function contextOptionsOf(options) {
121
+ return {
122
+ powerPreference: options.powerPreference,
123
+ rejectSoftware: options.rejectSoftware,
124
+ limits: options.limits,
125
+ optionalFeatures: options.optionalFeatures,
126
+ requiredFeatures: options.requiredFeatures,
127
+ label: options.label,
128
+ onError: options.onError,
129
+ warnUnreleasedSnapshots: options.warnUnreleasedSnapshots,
130
+ };
131
+ }
132
+ /**
133
+ * createNodeGpu + GpuContext.create({ gpu, runtime: "node", ...options }); ctx.dispose() also disposes the
134
+ * handle, and a create() failure disposes it before rethrowing. The handle is dropped once `ctx.lost` has
135
+ * settled, never before: under webgpu@0.4.0 a GPU object collected while the device it created is still
136
+ * tearing down (its lost / work-done callbacks in flight) crashes or deadlocks the process (PLAN DECISION,
137
+ * P1-T1; measured with tmp/p1t1/gc-race2.mjs), and device.destroy() reports the loss right away.
138
+ * @param options - the Node options
139
+ * @returns the context
140
+ */
141
+ export async function createNodeGpuContext(options) {
142
+ const handle = await createNodeGpu(options);
143
+ let ctx;
144
+ try {
145
+ ctx = await GpuContext.create({ ...contextOptionsOf(options ?? {}), gpu: handle.gpu, runtime: "node" });
146
+ }
147
+ catch (err) {
148
+ handle.dispose();
149
+ throw err;
150
+ }
151
+ const { lost } = ctx;
152
+ ctx.attachDisposer(() => {
153
+ void lost.then(() => {
154
+ handle.dispose();
155
+ });
156
+ });
157
+ return ctx;
158
+ }
159
+ /**
160
+ * createNodeGpu + GpuContext.probe + dispose; never throws (a load failure is { code: "E_NO_WEBGPU" }).
161
+ * @param options - the Node options
162
+ * @returns the probe result
163
+ */
164
+ export async function probeNodeWebGpu(options) {
165
+ let handle;
166
+ try {
167
+ handle = await createNodeGpu(options);
168
+ }
169
+ catch (err) {
170
+ return { ok: false, code: "E_NO_WEBGPU", reason: messageOf(err), adapter: null, summary: null };
171
+ }
172
+ try {
173
+ return await GpuContext.probe({
174
+ gpu: handle.gpu,
175
+ powerPreference: options?.powerPreference ?? "high-performance",
176
+ rejectSoftware: options?.rejectSoftware,
177
+ });
178
+ }
179
+ finally {
180
+ handle.dispose();
181
+ }
182
+ }
183
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/node/index.ts"],"names":[],"mappings":"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"}