@graphty/webgpu-graph-algorithms 0.6.24 → 0.6.26

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 (64) hide show
  1. package/LICENSE +1 -1
  2. package/dist/browser.js +1 -1
  3. package/dist/chunks/{context-B40Z6lV_.js → context-BZY6SMsM.js} +41 -35
  4. package/dist/chunks/context-BZY6SMsM.js.map +1 -0
  5. package/dist/node.js +1 -1
  6. package/dist/src/algorithms/betweenness.d.ts +24 -9
  7. package/dist/src/algorithms/betweenness.d.ts.map +1 -1
  8. package/dist/src/algorithms/betweenness.js +105 -39
  9. package/dist/src/algorithms/betweenness.js.map +1 -1
  10. package/dist/src/constants.d.ts +11 -0
  11. package/dist/src/constants.d.ts.map +1 -1
  12. package/dist/src/constants.js +11 -0
  13. package/dist/src/constants.js.map +1 -1
  14. package/dist/src/kernel/prelude.d.ts.map +1 -1
  15. package/dist/src/kernel/prelude.js +4 -1
  16. package/dist/src/kernel/prelude.js.map +1 -1
  17. package/dist/src/kernels.d.ts +4 -4
  18. package/dist/src/kernels.d.ts.map +1 -1
  19. package/dist/src/kernels.js +43 -13
  20. package/dist/src/kernels.js.map +1 -1
  21. package/dist/src/layouts/seed.d.ts +3 -1
  22. package/dist/src/layouts/seed.d.ts.map +1 -1
  23. package/dist/src/layouts/seed.js +10 -1
  24. package/dist/src/layouts/seed.js.map +1 -1
  25. package/dist/src/types/betweenness.d.ts +5 -2
  26. package/dist/src/types/betweenness.d.ts.map +1 -1
  27. package/dist/src/wgsl/bc-backward.wgsl.d.ts +5 -2
  28. package/dist/src/wgsl/bc-backward.wgsl.d.ts.map +1 -1
  29. package/dist/src/wgsl/bc-backward.wgsl.js +12 -3
  30. package/dist/src/wgsl/bc-backward.wgsl.js.map +1 -1
  31. package/dist/src/wgsl/bc-count.wgsl.d.ts +22 -0
  32. package/dist/src/wgsl/bc-count.wgsl.d.ts.map +1 -0
  33. package/dist/src/wgsl/bc-count.wgsl.js +46 -0
  34. package/dist/src/wgsl/bc-count.wgsl.js.map +1 -0
  35. package/dist/src/wgsl/bc-edge-gather.wgsl.d.ts +3 -2
  36. package/dist/src/wgsl/bc-edge-gather.wgsl.d.ts.map +1 -1
  37. package/dist/src/wgsl/bc-edge-gather.wgsl.js +10 -2
  38. package/dist/src/wgsl/bc-edge-gather.wgsl.js.map +1 -1
  39. package/dist/src/wgsl/bc-finalize.wgsl.d.ts +4 -3
  40. package/dist/src/wgsl/bc-finalize.wgsl.d.ts.map +1 -1
  41. package/dist/src/wgsl/bc-finalize.wgsl.js +5 -3
  42. package/dist/src/wgsl/bc-finalize.wgsl.js.map +1 -1
  43. package/dist/src/wgsl/bc-forward-edge.wgsl.d.ts +2 -2
  44. package/dist/src/wgsl/bc-forward-edge.wgsl.js +2 -2
  45. package/dist/src/wgsl/bc-forward.wgsl.d.ts +4 -2
  46. package/dist/src/wgsl/bc-forward.wgsl.d.ts.map +1 -1
  47. package/dist/src/wgsl/bc-forward.wgsl.js +4 -2
  48. package/dist/src/wgsl/bc-forward.wgsl.js.map +1 -1
  49. package/dist/webgpu-graph-algorithms.js +176 -47
  50. package/dist/webgpu-graph-algorithms.js.map +1 -1
  51. package/package.json +3 -3
  52. package/src/algorithms/betweenness.ts +155 -48
  53. package/src/constants.ts +11 -0
  54. package/src/kernel/prelude.ts +4 -0
  55. package/src/kernels.ts +45 -13
  56. package/src/layouts/seed.ts +10 -1
  57. package/src/types/betweenness.ts +5 -2
  58. package/src/wgsl/bc-backward.wgsl.ts +12 -3
  59. package/src/wgsl/bc-count.wgsl.ts +45 -0
  60. package/src/wgsl/bc-edge-gather.wgsl.ts +10 -2
  61. package/src/wgsl/bc-finalize.wgsl.ts +5 -3
  62. package/src/wgsl/bc-forward-edge.wgsl.ts +2 -2
  63. package/src/wgsl/bc-forward.wgsl.ts +4 -2
  64. package/dist/chunks/context-B40Z6lV_.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-BZY6SMsM.js","sources":["../../src/constants.ts","../../src/errors.ts","../../src/device/acquire.ts","../../src/device/caps.ts","../../src/device/error-scope.ts","../../src/device/lost.ts","../../src/kernel/kernel.ts","../../src/device/webgpu-constants.ts","../../src/kernel/prelude.ts","../../src/kernel/wgsl.ts","../../src/kernel/pipeline-cache.ts","../../src/kernel/profiler.ts","../../src/memory/lease.ts","../../src/memory/buffer-pool.ts","../../src/memory/readback.ts","../../src/memory/upload-plan.ts","../../src/memory/residency.ts","../../src/context.ts"],"sourcesContent":["/**\n * Every numeric constant the package and the WGSL prelude share (spec 3.1, 3.5, 5.2, 7.8, 7.14, 7.17;\n * contract 3.2). The prelude (src/kernel/prelude.ts, P1-T3) interpolates these values and never retypes them\n * as literals (the literal grep of spec 3.5 enforces it); the planners read them; test/device/constants.test.ts\n * pins them. graph-format's INVALID_INDEX is imported by the prelude directly and is deliberately not copied.\n */\n\n/** Workgroup size of every 1D kernel; `WG = min(WORKGROUP_SIZE, caps.limits.maxComputeInvocationsPerWorkgroup)` at runtime (spec 5.1). */\nexport const WORKGROUP_SIZE = 256;\n/** The spec minimum of maxComputeWorkgroupsPerDimension; asserted equal to the device limit at create() (spec 2.2, 5.2). */\nexport const MAX_WORKGROUPS_PER_DIM = 65535;\n/** Items a 1D dispatch of WORKGROUP_SIZE covers: 65535 x 256 = 16,776,960, NOT 2^24 (design 10.6). */\nexport const MAX_1D_ITEMS = MAX_WORKGROUPS_PER_DIM * WORKGROUP_SIZE;\n/** The largest u32 (the `min` identity of the u32 reduce); interpolated into the prelude as `U32_MAX` so no body types the literal (contract 4.1). */\nexport const U32_MAX = 0xffffffff;\n/** The bins of one radix-sort pass, 2^8 (spec 6 row 6; P4 PD-5: 8 bits per pass); interpolated into the prelude as `RADIX_BINS` and `RADIX_DIGIT_MASK` (= bins - 1) so no body types the literal. */\nexport const RADIX_BINS = 256;\n/** Arc-window boundaries are multiples of 64 arcs = 256 bytes (design 10.6). */\nexport const ARC_WINDOW_ALIGN = 64;\n/** Storage-binding offset alignment the package always honours (spec 2.6): the graph-format arena is 256-aligned. */\nexport const STORAGE_ALIGN = 256;\n/** Stride of one UniformRing slot: minUniformBufferOffsetAlignment is 256 on every runtime the package targets (spec 5.3). */\nexport const UNIFORM_SLOT_BYTES = 256;\n/**\n * Exact-tier crossover default, re-fixed at G4 by the spec 7.8 rule in full (spec Q-6; docs/decisions/G3.md section 3\n * for the budget clause, docs/decisions/G4.md section 7 for the re-check): the largest rung of the T-4 ladder (1k / 4k /\n * 8k / 16k / 32k / 65k, E = 10n, 2D) with <= 4 ms per iteration AND not slower than the grid tier at the same n (the\n * `layout-grid` 2D rows: the shared rungs 32k / 65k and the re-check rungs 1k / 4k / 8k / 16k the group runs so every\n * exact rung has a grid row), rounded down to a power of two. Measured on the RTX 4070 SUPER under Dawn-node:\n * benchmarks/results/nvidia-lovelace-driver580.json, session 2026-09-21T06:15:17.027Z, the \"ms/iteration (profiler)\"\n * rows of layout-exact and the \"grid ms/iteration (profiler) ... 2D\" rows of layout-grid (the GPU time of the\n * iteration's passes at the card's working clock), exact / grid ms per iteration: 1k 0.102 / 0.290, 4k 0.262 / 0.188,\n * 8k 0.484 / 0.211, 16k 1.064 / 0.225, 32k 2.579 / 0.298, 65k 8.450 / 0.409. The grid tier's cost is a near-constant\n * ~0.19-0.3 ms floor (its sort, scan and pyramid passes) up to 32k, so the exact tier wins only at 1k and the rule's\n * answer is 1024 (32768 under the budget clause alone, the G3 value; 16384 was the P4-T14 draft's value, which only\n * evaluated the grid clause at 32k / 65k and was not a measurement). calibrateLayout's finer probe on the same card\n * (tmp/p4/t14-review/calibrate-defaults.log: exact 0.150 vs grid 0.190 ms at 2048) puts the true crossover between\n * 2k and 4k; the ladder has no 2k rung, and the design's basis (cosmos switches at 4,096) is within 0.07 ms per\n * iteration of the rule's value, so the choice among 1k / 2k / 4k is an accuracy preference (the exact tier is the\n * oracle), not a speed one. OWNER DECISION G4-D1 (docs/decisions/G4.md section 7, rows G4-D1 / G4-F9): the constant\n * KEEPS the G3 value 32768 while the accuracy work G4-F1 leaves is open -- G4-F1 (the grid tier's exact-vs-grid RMS\n * on the clumpy and degenerate fixtures) closed on 2026-09-21 by the owner's asserted / printed split, G4-F2 (the\n * unbiasedness item) the same day by its re-scope to the whole-field ratio, and the far field's accuracy on those\n * fixtures is the follow-up -- because \"auto\" is the default every consumer sees and the exact tier is the accurate\n * one; the rule's answer on the dev box (1024) is recorded, not shipped, until that work closes and the value is\n * re-fixed. A\n * consumer whose GPU differs (integrated, Apple, T4) passes its own value through\n * createAccelerator(ctx, { layout: { exactMaxNodes } }); calibrateLayout(ctx) measures it.\n */\nexport const EXACT_MAX_NODES = 32768;\n/** Default number of MAP_READ staging buffers in the Readback ring (spec 4.4). */\nexport const DEFAULT_STAGING_SLOTS = 3;\n/** Timestamp query-set size of the Profiler (spec 5.5: \"a query set of 256 slots\"; 2 slots per pass). */\nexport const PROFILER_QUERY_SLOTS = 256;\n/** Byte size above which createBuffer runs inside an \"out-of-memory\" error scope (spec 5.7). */\nexport const OOM_SCOPE_THRESHOLD_BYTES = 16 * 1024 * 1024;\n/** Idle buffers kept per (size class, usage) by the BufferPool (spec 4.4). */\nexport const POOL_MAX_IDLE_PER_CLASS = 4;\n/** Smallest power-of-two pool class (spec 4.4). */\nexport const POOL_MIN_CLASS_BYTES = 4 * 1024;\n/** Largest power-of-two pool class; above it the classes grow linearly (spec 4.4). */\nexport const POOL_MAX_POW2_CLASS_BYTES = 64 * 1024 * 1024;\n/** The linear step of the pool classes above the largest power of two (spec 4.4). */\nexport const POOL_LINEAR_STEP_BYTES = 16 * 1024 * 1024;\n/** Default `warnUnreleasedSnapshots` (spec 2.2, 4.1). */\nexport const DEFAULT_WARN_UNRELEASED_SNAPSHOTS = 2;\n/** CONTRACT DECISION: the largest `iterations` a single step() records (the trace region and the uniform ring are sized by it); larger values are E_INVALID_ARGUMENT. */\nexport const MAX_ITERATIONS_PER_STEP = 256;\n/** Bytes of one Fa2Trace record (spec 7.3: 32-byte records). */\nexport const TRACE_RECORD_BYTES = 32;\n/** CONTRACT DECISION: the state header is padded to 256 bytes so the trace region that follows it in the same buffer starts at a legal 256-aligned binding offset (spec 7.3 says \"128 + k x 32\"; 128 is not a legal storage offset). */\nexport const STATE_HEADER_BYTES = 256;\n/** Bytes of one per-workgroup partials record (spec 7.3: exactly 64 B). */\nexport const PARTIAL_BYTES = 64;\n/** ForceAtlas2 defaults (spec 7.14, 7.17, 7.19). */\nexport const FA2_DEFAULTS: Readonly<{\n maxIter: 100;\n jitterTolerance: 1;\n scalingRatio: 2;\n gravity: 1;\n strongGravity: false;\n distributedAction: false;\n linlog: false;\n dissuadeHubs: false;\n dim: 2;\n scale: 1;\n settleThreshold: 0.001;\n settleWindow: 10;\n iterationsPerStep: 1;\n maxInFlight: 2;\n}> = Object.freeze({\n maxIter: 100,\n jitterTolerance: 1,\n scalingRatio: 2,\n gravity: 1,\n strongGravity: false,\n distributedAction: false,\n linlog: false,\n dissuadeHubs: false,\n dim: 2,\n scale: 1,\n settleThreshold: 0.001,\n settleWindow: 10,\n iterationsPerStep: 1,\n maxInFlight: 2,\n});\n/** GPU-only layout tuning defaults (spec 7.14): repulsion \"auto\", exactMaxNodes EXACT_MAX_NODES, nearMax 64, deterministic true, gridMax2D 512, gridMax3D 128, extentFactor 6, compat \"paper\". */\nexport const LAYOUT_TUNING_DEFAULTS: Readonly<{\n repulsion: \"auto\";\n exactMaxNodes: number;\n nearMax: 64;\n deterministic: true;\n gridMax2D: 512;\n gridMax3D: 128;\n extentFactor: 6;\n compat: \"paper\";\n}> = Object.freeze({\n repulsion: \"auto\",\n exactMaxNodes: EXACT_MAX_NODES,\n nearMax: 64,\n deterministic: true,\n gridMax2D: 512,\n gridMax3D: 128,\n extentFactor: 6,\n compat: \"paper\",\n});\n/** The distance floor `max(d, 0.01)` of spec 7.2; interpolated into the prelude (contract 4.1). */\nexport const FA2_DISTANCE_FLOOR = 0.01;\n/** The square of FA2_DISTANCE_FLOOR. */\nexport const FA2_DISTANCE_FLOOR_SQ = 0.0001;\n/** The coincident threshold `d^2 < 1e-8` of spec 7.2. */\nexport const FA2_COINCIDENT_SQ = 1e-8;\n/**\n * The most WG-node tiles one K3 (`fa2-repulsion-exact`) dispatch sums per invocation (issue #87). llvmpipe runs at\n * most 65,535 loop iterations per shader invocation, counted over every loop together, and then quietly breaks\n * out of each loop; one tile costs WG + 2 of them (258 at WG 256), so a single pass lost every node past\n * j = 65,027. 128 tiles is 33,024 iterations, half the budget; a larger exact run records ceil(tiles / 128) passes.\n */\nexport const EXACT_TILES_PER_PASS = 128;\n/** Bits of Fa2Params.flags (contract 4.4). */\nexport const FA2_FLAG_FIRST = 1;\n/** Fa2Params.flags bit: the Fruchterman-Reingold temperature is the adaptive one in the state block, not the uniform's (the `cooling: \"adaptive\"` option). */\nexport const FA2_FLAG_ADAPTIVE = 2;\n/** The Fruchterman-Reingold loop's starting temperature (spec 7.20; `layout/src/simulation/fruchterman-reingold.ts:30`). */\nexport const FR_START_TEMPERATURE = 0.1;\n/** The reheat point of spec 7.20: the temperature index a reheat restarts at, as a fraction of `iterations`. */\nexport const FR_REHEAT_FRACTION = 0.7;\n/** Adaptive cooling (Yifan Hu 2005, section 3.2): the temperature is multiplied by this when the force energy rose, divided by it after FR_COOLING_PATIENCE consecutive falls. */\nexport const FR_COOLING_STEP = 0.9;\n/** Adaptive cooling: consecutive iterations of falling energy before the temperature grows. */\nexport const FR_COOLING_PATIENCE = 5;\n/** Adaptive cooling: the iteration budget when `iterations` is not given (the schedule no longer needs one; this is the cap on a run that never settles). */\nexport const FR_ADAPTIVE_MAX_ITERATIONS = 10_000;\n/** Fruchterman-Reingold defaults (spec 7.20, 9.3; the CPU simulation's, `layout/src/simulation/fruchterman-reingold.ts:32`): `k` null = `1 / sqrt(n)`. */\nexport const FR_DEFAULTS: Readonly<{\n k: null;\n iterations: 50;\n fixed: null;\n dim: 2;\n scale: 1;\n settleThreshold: 0.001;\n settleWindow: 10;\n iterationsPerStep: 1;\n maxInFlight: 2;\n cooling: \"linear\";\n}> = Object.freeze({\n k: null,\n iterations: 50,\n fixed: null,\n dim: 2,\n scale: 1,\n settleThreshold: 0.001,\n settleWindow: 10,\n iterationsPerStep: 1,\n maxInFlight: 2,\n cooling: \"linear\",\n});\n/**\n * Spring-electrical size scaling: when `gravity` or `springCoefficient` is left to its default, ngraph's constant is\n * multiplied by min(1, SE_SCALE_REFERENCE_NODES / n). ngraph's values were tuned for graphs of a few hundred nodes;\n * on tens of thousands the per-node forces are so large that every node moves at the unit speed clamp and the layout\n * never comes to rest (measured on the 58k-node Brightkite graph: 3,350 iterations to the settle rule with the\n * kinetic energy still at the clamp; a uniform 1/1000 factor settled in 1,000 with the energy decayed 25x).\n */\nexport const SE_SCALE_REFERENCE_NODES = 300;\n/** Spring-electrical defaults: ngraph.forcelayout 3.3.1's (`lib/createPhysicsSimulator.js:29,34,40,54,59`; spec 7.20), plus the shared simulation defaults. `gravity` is ngraph's Coulomb constant: negative repels. */\nexport const SE_DEFAULTS: Readonly<{\n springLength: 10;\n springCoefficient: 0.8;\n gravity: -12;\n dragCoefficient: 0.9;\n timeStep: 0.5;\n dim: 2;\n scale: 1;\n settleThreshold: 0.001;\n settleWindow: 10;\n iterationsPerStep: 1;\n maxInFlight: 2;\n}> = Object.freeze({\n springLength: 10,\n springCoefficient: 0.8,\n gravity: -12,\n dragCoefficient: 0.9,\n timeStep: 0.5,\n dim: 2,\n scale: 1,\n settleThreshold: 0.001,\n settleWindow: 10,\n iterationsPerStep: 1,\n maxInFlight: 2,\n});\n/**\n * The absolute settle floor of the shared settle rule (spec 7.17; issue #97): an iteration counts toward `settled` only\n * when its mean displacement is at most `settleThreshold x rmsRadius` AND at most this fraction of the model's length\n * unit -- `springLength` for spring-electrical (scaled by node count, see SETTLE_FLOOR_REFERENCE_NODES), `k` for\n * Fruchterman-Reingold. The relative rule alone reported a spring\n * layout settled while it still grew (6 % over 1,000 iterations at 10k nodes). ForceAtlas2 writes\n * `SETTLE_FLOOR_UNBOUNDED` instead: it does not drift after settling, and its per-iteration jitter grows with n, so any\n * fixed floor only delays or blocks its stop. The values are measured:\n * design/decisions/2026-09-24-settle-rule-has-an-absolute-floor.md.\n */\nexport const SETTLE_FLOOR_FRACTION: Readonly<{ springElectrical: number; fruchtermanReingold: number }> = Object.freeze(\n {\n springElectrical: 3e-3,\n fruchtermanReingold: 2e-3,\n },\n);\n/**\n * The node count at which the spring-electrical floor is exactly `SETTLE_FLOOR_FRACTION.springElectrical x\n * springLength`; at `n` nodes it is that times `(SETTLE_FLOOR_REFERENCE_NODES / n)^(1/4)`. A spring layout's rms radius\n * grows about as n^(1/4) in springLengths (3.4 at 150 nodes, 6.4 at 2,000, 10.4 at 10,000), so the relative half of the\n * rule loosens with size while the floor tightens with it: on a small graph the floor sits above the relative threshold\n * and the relative rule decides alone, as before issue #97; on a large one the floor binds, which is where the relative\n * rule let an expanding layout stop. A fixed floor bound the 150-node story graph too, where the grid tier's jitter sits\n * at the relative threshold, and nearly doubled its settle (427 -> 829 iterations on the RTX 4070 SUPER).\n */\nexport const SETTLE_FLOOR_REFERENCE_NODES = 2000;\n/** The settle floor that never binds: the largest finite f32, 0x1.fffffep+127 (ForceAtlas2's `settleFloor`, issue #97). */\nexport const SETTLE_FLOOR_UNBOUNDED = 2 ** 128 - 2 ** 104;\n/** The smallest finest grid side `G` (spec 7.7 geometry table: `clamp(nextPow2(2 n^(1/dim)), 8, gridMax)`; P4 PD-9). */\nexport const GRID_MIN_SIDE = 8;\n/** The coarsest pyramid level's side (spec 7.7: \"levels (coarsest 4 per axis)\", `levels = log2(G / 4) + 1`). */\nexport const GRID_COARSEST_SIDE = 4;\n/** A cell with more than this many entries is summed by a workgroup (G4b) instead of the thread-per-cell loop of G4 (spec 7.7 G4: `count > 1024`). */\nexport const GRID_HUB_CELL = 1024;\n/** The extent floor of spec 7.7: `cellSize = max(extent, 1e-6) / G`, so an all-coincident load never divides by zero. */\nexport const GRID_EXTENT_FLOOR = 1e-6;\n/** The bbox margin of spec 7.7: `bboxExtent` is the largest axis of `state.min / max` \"with a 1% margin\". */\nexport const GRID_BBOX_MARGIN = 1.01;\n/** The key width the grid always sorts with (P4 PD-5): three 8-bit passes cover the 19-bit 2D keys at G = 512 and the 22-bit 3D keys at G = 128, and an odd pass count leaves `sortedIdx` in the scratch pair. */\nexport const GRID_SORT_BITS = 24;\n/** Design 8.4 (P8 PD-7): traversal levels recorded per submit -- one four-byte readback per 32 BFS levels, SSSP rounds or closeness levels. */\nexport const MAX_LEVELS_PER_SUBMIT = 32;\n/** Design 8.4 and 6 row 8 (P8): a frontier at most this long runs the fused expand-contract kernel (Merrill's \"fleeting iterations\"); the default of the `fusedMax` uniform, which a test may set to 0 or `U32_MAX`. */\nexport const FUSED_FRONTIER_MAX = 4096;\n/** Design 8.4 (P8 PD-21): Beamer's beta -- switch back to top-down when `frontierCount * BEAMER_BETA < unvisitedCount` and the frontier is shrinking; alpha is derived from the graph, so it has no constant. */\nexport const BEAMER_BETA = 24;\n/** Design 8.4 (P8 PD-22): the near-far split `delta = SSSP_DELTA_FACTOR * avgWeight / avgDegree`, computed on the host from the weight vector the run uses. */\nexport const SSSP_DELTA_FACTOR = 32;\n/** The bit pattern of +Infinity, the unreached sentinel of `dist` (P8 PD-9); interpolated into the prelude as `F32_INF_BITS` so no body types the literal. */\nexport const F32_INF_BITS = 0x7f800000;\n/** Design 8.4 \"k planned from maxBufferSize and a 25% budget\": the share of `maxBufferSize` one betweenness source batch may hold. WebGPU exposes no device memory size, so this is a fraction of the largest buffer, not a memory measurement. */\nexport const BC_BATCH_BUDGET_FRACTION = 0.25;\n/** Design 10.1's betweenness column: the most sources one betweenness batch runs together. */\nexport const BC_MAX_BATCH = 64;\n/** Design 8.4 (McLaughlin-Bader): a betweenness batch runs the edge-parallel forward pass when the previous batch's level count is below `BC_EDGE_PARALLEL_GAMMA * log2(n)`. The design names the rule and no value; 2 is unmeasured and a benchmark run re-fixes it. */\nexport const BC_EDGE_PARALLEL_GAMMA = 2;\n/**\n * Betweenness path counts that wrapped u32 are recounted as f32, rescaled per depth by a power of two (`bc-count`):\n * when the largest count at one depth has a binary exponent above this cap, the next depth's counts are scaled down so\n * that largest count lands at 2^cap. A count then never exceeds 2^cap x 2 x (in-degree), below f32's 2^128 for any\n * in-degree a binding can hold (2^25), and the counts at one depth may span 2^(cap + 126) before the smallest leaves\n * f32's normal range, which is when the overflow flag rises (measured: a corner of a 235 x 235 grid, not of a 230 x 230\n * one). Powers of two scale without rounding, so the scores do not depend on the cap.\n */\nexport const BC_SIGMA_EXPONENT_CAP = 100;\n/** The most workgroups one `bc-count` dispatch launches (it grid-strides over the level): sized for the largest level, a dispatch of n x k lanes costs every level a mostly idle launch, which doubled a 100 x 100 grid's run on an RTX 4070 SUPER; 256 measured 1.3 s against 2.0 s there. */\nexport const BC_COUNT_MAX_GROUPS = 256;\n/** Backward-pass levels recorded per submit: each level is one dispatch with its own parameter record, so this bounds the uniform ring. */\nexport const BC_BACKWARD_LEVELS_PER_SUBMIT = 64;\n/**\n * Design 8.7: all-pairs shortest paths is a blocked Floyd-Warshall over `APSP_TILE x APSP_TILE` tiles. One tile of\n * f32 is 4 KiB of workgroup memory and a workgroup stages at most two (8 KiB), inside the 16 KiB\n * `maxComputeWorkgroupStorageSize` every WebGPU device reports. Interpolated into the prelude as `APSP_TILE`.\n */\nexport const APSP_TILE = 32;\n/**\n * The blocked sweep records `3 x ceil(n / APSP_TILE)` dispatches (543 at the 5,792-node ceiling of a 128 MiB binding,\n * 2,175 at a 2 GiB binding's 23,170, 3,072 at a 4 GiB binding's 32,767); above this many the driver splits the sweep\n * into further submits. No binding offered today reaches it, so every sweep is one submit; the cap only stops a\n * device with a binding above 4 GiB (`maxStorageBufferBindingSize` is a GPUSize64) from building one unbounded\n * command buffer.\n */\nexport const APSP_MAX_DISPATCHES_PER_SUBMIT = 4096;\n/**\n * Label propagation (design 8.6): passes recorded per submit, with ONE readback of the per-pass changed counts at the\n * end of the submit. A readback costs about 2 ms in Chromium whatever it carries, so at one readback per pass a\n * 10,000-node call spends more on synchronisation than the CPU spends on the whole algorithm\n * (design/decisions/2026-09-26-which-algorithms-earn-the-gpu.md: 101 passes x 2 ms, 0.79x); eight passes per\n * submit is the floor that decision sets. Even, so every submit holds as many descending as ascending passes of the\n * alternating direction rule.\n */\nexport const LABEL_PROP_PASSES_PER_SUBMIT = 8;\n/**\n * Boruvka's minimum spanning tree (design 8.5): rounds recorded per submit, with one readback of the counters block\n * per submit. Each readback is a device-to-host synchronisation that costs about 2 ms in Chromium, and at one per\n * round the syncs are 61 % of the 100,000-node call; four rounds per submit amortise them over O(log n) rounds, moving\n * the Chromium crossover from 6,000 to 4,600 nodes (design/decisions/2026-09-26-which-algorithms-earn-the-gpu.md).\n * `src/algorithms/mst.ts` reads it.\n */\nexport const BORUVKA_ROUNDS_PER_SUBMIT = 4;\n/**\n * The sign bit of an f32 bit pattern; interpolated into the prelude as `F32_SIGN_BIT` for `order_key`, the\n * order-preserving u32 key of an f32 that Boruvka's `atomicMin` over edge weights runs on (P11 PD-6).\n */\nexport const F32_SIGN_BIT = 0x80000000;\n/** The per-row group-by-key (design 8.6): a row of at most this many arcs is grouped by one thread in registers; a longer row by a workgroup over a global open-addressing region. */\nexport const GROUP_ROW_THREAD_MAX = 32;\n/** The largest row the thread tier accepts when a caller forces the tier: its pairwise scan is about d^2 / 2 loop steps, and llvmpipe stops every loop of an invocation after 65,535 steps in total. */\nexport const GROUP_ROW_THREAD_LIMIT = 128;\n/**\n * The most parallel arcs the simple symmetric graph build merges into one weighted arc. The merge sums each run of\n * parallel arcs in one invocation, and llvmpipe stops every loop of an invocation after 65,535 steps in total and\n * then quietly returns a short sum; a weighted build whose pair repeats more often is refused on every adapter.\n */\nexport const PARALLEL_MERGE_LIMIT = 65_000;\n/** The per-row group-by-key (design 8.6): the global open-addressing region of a workgroup-tier row holds this many slots per arc. */\nexport const GROUP_HASH_LOAD_FACTOR = 2;\n/** Triangle counting (design 8.5): intersect two oriented rows by merge, but binary-search each element of the shorter row into the longer when their lengths differ by more than this factor. */\nexport const TRIANGLE_BINARY_SEARCH_RATIO = 32;\n","/**\n * The error class and the closed code set of @graphty/webgpu-graph-algorithms (spec 3.3, 5.7; contract 3.1).\n *\n * Every condition the package detects itself is thrown as a WebGpuGraphError carrying a stable `code` and a\n * frozen shallow copy of the `details` the thrower supplied. Errors raised by @graphty/graph-format accessors\n * the package calls on the caller's behalf pass through unchanged (D12); PASSTHROUGH_FORMAT_CODES lists the\n * codes a public call may let escape. Constructors never throw. Messages are plain ASCII.\n *\n * `details` keys per code (contract 3.1, so tests can assert them): E_NO_WEBGPU { reason, hint };\n * E_NO_ADAPTER { reason }; E_NO_DEVICE { reason, adapter, limit?, requested?, available? } (reason \"consumed\" |\n * \"requestDevice\" | \"limit\" | \"feature\" | \"maxComputeWorkgroupsPerDimension\"); E_SOFTWARE_ONLY { adapter };\n * E_DEVICE_LOST { reason, message }; E_DEVICE_INCORRECT { check, where, expected, actual, poison, count, blocks,\n * workgroupSize, adapter, hint? }; E_DISPOSED { label }; E_VALIDATION { label, message, batchId? };\n * E_SHADER_COMPILE { id, stage: \"compose\" | \"compile\", slot?, messages? }; E_OUT_OF_MEMORY { requested, resident,\n * label }; E_TOO_LARGE { needed, limit, path, algorithm }; E_UNSUPPORTED { feature? | option?, hint? } (exactly\n * one of feature / option); E_INVALID_ARGUMENT { argument, value, expected? }; E_SNAPSHOT { reason, serial };\n * E_RELEASED { serial }; E_NOT_LOADED { state }; E_ABORTED { batchId? }.\n */\n\n/** Every condition the package detects itself carries one of these codes (spec 3.3). */\nexport type WebGpuGraphErrorCode =\n | \"E_NO_WEBGPU\"\n | \"E_NO_ADAPTER\"\n | \"E_NO_DEVICE\"\n | \"E_SOFTWARE_ONLY\"\n | \"E_DEVICE_LOST\"\n | \"E_DEVICE_INCORRECT\"\n | \"E_DISPOSED\"\n | \"E_VALIDATION\"\n | \"E_SHADER_COMPILE\"\n | \"E_OUT_OF_MEMORY\"\n | \"E_TOO_LARGE\"\n | \"E_UNSUPPORTED\"\n | \"E_INVALID_ARGUMENT\"\n | \"E_SNAPSHOT\"\n | \"E_RELEASED\"\n | \"E_NOT_LOADED\"\n | \"E_ABORTED\";\n\n/** The graph-format error codes a public call lets propagate unchanged (D12, spec 5.7): raised by accessors the package calls on the caller's behalf. */\nexport const PASSTHROUGH_FORMAT_CODES: readonly [\n \"E_GPU_INELIGIBLE\",\n \"E_UNKNOWN_NODE\",\n \"E_UNKNOWN_COLUMN\",\n \"E_COLUMN_LENGTH\",\n] = Object.freeze([\"E_GPU_INELIGIBLE\", \"E_UNKNOWN_NODE\", \"E_UNKNOWN_COLUMN\", \"E_COLUMN_LENGTH\"] as const);\n\nconst EMPTY_DETAILS: Readonly<Record<string, unknown>> = Object.freeze({});\n\n/** The one error class the package throws for conditions it detects itself: a stable `code` and frozen `details` (spec 3.3). */\nexport class WebGpuGraphError extends Error {\n /** The stable code. */\n readonly code: WebGpuGraphErrorCode;\n\n /** Frozen shallow copy of the details given to the constructor (`{}` when none). */\n readonly details: Readonly<Record<string, unknown>>;\n\n /** `name` is always \"WebGpuGraphError\". */\n override readonly name: \"WebGpuGraphError\";\n\n /**\n * Create a WebGpuGraphError.\n * @param code - the stable code the caller can branch on\n * @param message - a plain-ASCII human-readable message naming the offending label, limit or value\n * @param details - optional machine-readable context; copied shallowly and frozen\n */\n constructor(code: WebGpuGraphErrorCode, message: string, details?: Record<string, unknown>) {\n super(message);\n this.name = \"WebGpuGraphError\";\n this.code = code;\n this.details = details === undefined ? EMPTY_DETAILS : Object.freeze({ ...details });\n }\n}\n\n/**\n * Brand check that survives two package copies: `name === \"WebGpuGraphError\"` and a string `code`.\n * @param x - anything, typically a caught value\n * @returns true when `x` is structurally a WebGpuGraphError (instanceof is NOT required)\n */\nexport function isWebGpuGraphError(x: unknown): x is WebGpuGraphError {\n if (typeof x !== \"object\" || x === null) {\n return false;\n }\n const candidate = x as { readonly name?: unknown; readonly code?: unknown };\n return candidate.name === \"WebGpuGraphError\" && typeof candidate.code === \"string\";\n}\n\n/**\n * Brand check that survives two package copies: `code === x.code` for an `isWebGpuGraphError(x)`.\n * @param x - anything, typically a caught value\n * @param code - the code to test for\n * @returns true when `x` is a WebGpuGraphError carrying `code`\n */\nexport function hasErrorCode(x: unknown, code: WebGpuGraphErrorCode): boolean {\n return isWebGpuGraphError(x) && x.code === code;\n}\n","/**\n * Device acquisition (spec 2.2 steps 1-3, 2.6; contract 3.4): the adapter request, the software-adapter\n * test, the adapter summary, the requiredLimits / requiredFeatures builders and the device request. Nothing\n * above the device layer is constructed here (D26); src/context.ts sequences these calls. An adapter is\n * consumed by its first requestDevice (WebGPU 3.5.1; Dawn-node rejects the second call with\n * `OperationError: adapter is \"consumed\"`), so every device the package creates comes from a fresh adapter.\n */\n\nimport { WebGpuGraphError } from \"../errors.js\";\nimport type { AdapterInfoLike, AdapterSummary, LimitPolicy, RaisableLimit } from \"../types/context.js\";\n\n/** The six raisable limits in the order create() requests them (spec 2.2). */\nexport const RAISABLE_LIMITS: readonly RaisableLimit[] = Object.freeze([\n \"maxBufferSize\",\n \"maxStorageBufferBindingSize\",\n \"maxStorageBuffersPerShaderStage\",\n \"maxComputeWorkgroupStorageSize\",\n \"maxComputeInvocationsPerWorkgroup\",\n \"maxComputeWorkgroupSizeX\",\n]);\n\n/**\n * The WebGPU limit names summarizeAdapter reads (the GPUSupportedLimits members of @webgpu/types 0.1.72).\n * A fixed list because Chromium exposes the limits as prototype getters (Object.keys is empty) and Dawn-node as an\n * addon object; reading each name works identically on both, and a name the runtime lacks is simply absent.\n */\nconst LIMIT_NAMES: readonly string[] = [\n \"maxTextureDimension1D\",\n \"maxTextureDimension2D\",\n \"maxTextureDimension3D\",\n \"maxTextureArrayLayers\",\n \"maxBindGroups\",\n \"maxBindGroupsPlusVertexBuffers\",\n \"maxBindingsPerBindGroup\",\n \"maxDynamicUniformBuffersPerPipelineLayout\",\n \"maxDynamicStorageBuffersPerPipelineLayout\",\n \"maxSampledTexturesPerShaderStage\",\n \"maxSamplersPerShaderStage\",\n \"maxStorageBuffersPerShaderStage\",\n \"maxStorageBuffersInVertexStage\",\n \"maxStorageBuffersInFragmentStage\",\n \"maxStorageTexturesPerShaderStage\",\n \"maxStorageTexturesInVertexStage\",\n \"maxStorageTexturesInFragmentStage\",\n \"maxUniformBuffersPerShaderStage\",\n \"maxUniformBufferBindingSize\",\n \"maxStorageBufferBindingSize\",\n \"minUniformBufferOffsetAlignment\",\n \"minStorageBufferOffsetAlignment\",\n \"maxVertexBuffers\",\n \"maxBufferSize\",\n \"maxVertexAttributes\",\n \"maxVertexBufferArrayStride\",\n \"maxInterStageShaderVariables\",\n \"maxColorAttachments\",\n \"maxColorAttachmentBytesPerSample\",\n \"maxComputeWorkgroupStorageSize\",\n \"maxComputeInvocationsPerWorkgroup\",\n \"maxComputeWorkgroupSizeX\",\n \"maxComputeWorkgroupSizeY\",\n \"maxComputeWorkgroupSizeZ\",\n \"maxComputeWorkgroupsPerDimension\",\n \"maxImmediateSize\",\n];\n\n/** Adapters that created a device through requestDevice(): a second create({ adapter }) fails without a round trip. */\nconst consumedAdapters = new WeakSet<GPUAdapter>();\n\n/**\n * The message of a thrown value.\n * @param err - what was caught\n * @returns the Error message, or the value as a string\n */\nfunction messageOf(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Software adapter test (spec 2.2 step 2): architecture \"software\" (Dawn llvmpipe) or \"swiftshader\", or\n * isFallbackAdapter === true (Chromium); the ONE reader of these fields.\n * @param info - the adapter info (structural, so tests can fake it)\n * @returns true for a software adapter\n */\nexport function isSoftwareAdapter(info: AdapterInfoLike): boolean {\n // \"software\" = Dawn-node on llvmpipe, \"swiftshader\" = Chromium's fallback, \"warp\" = Dawn's D3D12 backend on\n // Microsoft's WARP rasterizer (the Windows host lane: vendor \"microsoft\", isFallbackAdapter absent under Dawn-node).\n return (\n info.architecture === \"software\" ||\n info.architecture === \"swiftshader\" ||\n info.architecture === \"warp\" ||\n info.isFallbackAdapter === true\n );\n}\n\n/**\n * The AdapterSummary of an adapter (info + features + limits); never requests a device.\n * @param adapter - an adapter (unused or not; only its info, features and limits are read)\n * @returns a frozen summary; `subgroupMinSize` / `subgroupMaxSize` are 0 when the info lacks them\n */\nexport function summarizeAdapter(adapter: GPUAdapter): AdapterSummary {\n const { info } = adapter;\n const source = adapter.limits as unknown as Readonly<Record<string, unknown>>;\n const limits: Record<string, number> = {};\n for (const name of LIMIT_NAMES) {\n const value = source[name];\n if (typeof value === \"number\") {\n limits[name] = value;\n }\n }\n return Object.freeze({\n vendor: info.vendor,\n architecture: info.architecture,\n device: info.device,\n description: info.description,\n software: isSoftwareAdapter(info),\n subgroupMinSize: info.subgroupMinSize ?? 0,\n subgroupMaxSize: info.subgroupMaxSize ?? 0,\n features: Object.freeze(Array.from(adapter.features).sort()),\n limits: Object.freeze(limits),\n });\n}\n\n/**\n * Step 1 of create(): requestAdapter with the power preference; null -> E_NO_ADAPTER.\n * @param gpu - navigator.gpu or the Dawn handle\n * @param powerPreference - honoured by browsers, ignored by Dawn-node (spec 2.6)\n * @returns an UNUSED adapter\n */\nexport async function requestAdapter(gpu: GPU, powerPreference: GPUPowerPreference): Promise<GPUAdapter> {\n let adapter: GPUAdapter | null;\n try {\n adapter = await gpu.requestAdapter({ powerPreference });\n } catch (err) {\n const reason = `requestAdapter() threw: ${messageOf(err)}`;\n throw new WebGpuGraphError(\"E_NO_ADAPTER\", reason, { reason });\n }\n if (adapter === null) {\n const reason = \"requestAdapter() returned null: no usable WebGPU adapter\";\n throw new WebGpuGraphError(\"E_NO_ADAPTER\", reason, { reason });\n }\n return adapter;\n}\n\n/**\n * Step 3 of create(): the requiredLimits record for a policy, clamped to the adapter; an explicit value\n * above the adapter -> E_NO_DEVICE { reason: \"limit\" } before any requestDevice call, so the failure is\n * diagnosable.\n * @param adapter - the adapter the device will come from\n * @param policy - \"default\" (nothing), \"raise\" (every raisable limit at the adapter's value) or explicit values\n * @returns the record to pass as requiredLimits\n */\nexport function buildRequiredLimits(adapter: GPUAdapter, policy: LimitPolicy): Record<string, number> {\n const limits: Record<string, number> = {};\n if (policy === \"default\") {\n return limits;\n }\n if (policy === \"raise\") {\n for (const name of RAISABLE_LIMITS) {\n limits[name] = adapter.limits[name];\n }\n return limits;\n }\n for (const name of RAISABLE_LIMITS) {\n const requested = policy[name];\n if (requested === undefined) {\n continue;\n }\n const available = adapter.limits[name];\n if (requested > available) {\n throw new WebGpuGraphError(\n \"E_NO_DEVICE\",\n `requested ${name} = ${requested} exceeds the adapter's ${available}`,\n { reason: \"limit\", adapter: summarizeAdapter(adapter), limit: name, requested, available },\n );\n }\n limits[name] = requested;\n }\n return limits;\n}\n\n/**\n * Step 3 of create(): the requiredFeatures list = required + (optional intersect adapter.features); a missing\n * required feature -> E_NO_DEVICE { reason: \"feature\", requested: <name> }.\n * @param adapter - the adapter the device will come from\n * @param required - features the caller cannot do without\n * @param optional - features requested only when the adapter has them\n * @returns the deduplicated list, required first\n */\nexport function buildRequiredFeatures(\n adapter: GPUAdapter,\n required: readonly GPUFeatureName[],\n optional: readonly GPUFeatureName[],\n): GPUFeatureName[] {\n const features: GPUFeatureName[] = [];\n for (const feature of required) {\n if (!adapter.features.has(feature)) {\n throw new WebGpuGraphError(\"E_NO_DEVICE\", `required feature \"${feature}\" is not supported by the adapter`, {\n reason: \"feature\",\n adapter: summarizeAdapter(adapter),\n requested: feature,\n });\n }\n if (!features.includes(feature)) {\n features.push(feature);\n }\n }\n for (const feature of optional) {\n if (adapter.features.has(feature) && !features.includes(feature)) {\n features.push(feature);\n }\n }\n return features;\n}\n\n/**\n * The E_NO_DEVICE of a consumed adapter; the runtime's text lives in the error message only (contract 3.1\n * documents `details` as { reason, adapter, limit?, requested?, available? }).\n * @param adapter - the adapter that already created a device\n * @param message - the runtime's rejection message when there was a round trip\n * @returns E_NO_DEVICE { reason: \"consumed\", adapter }\n */\nfunction consumedError(adapter: GPUAdapter, message: string): WebGpuGraphError {\n return new WebGpuGraphError(\n \"E_NO_DEVICE\",\n `the adapter already created a device (an adapter is consumed by one requestDevice, spec 2.2 step 1): ${message}`,\n { reason: \"consumed\", adapter: summarizeAdapter(adapter) },\n );\n}\n\n/**\n * Step 3 of create(): requestDevice; a rejection -> E_NO_DEVICE with the adapter summary (\"consumed\" when\n * the adapter already created a device, detected by the OperationError message or a prior-use record).\n * @param adapter - an UNUSED adapter\n * @param descriptor - requiredLimits, requiredFeatures and the label\n * @returns the device\n */\nexport async function requestDevice(adapter: GPUAdapter, descriptor: GPUDeviceDescriptor): Promise<GPUDevice> {\n if (consumedAdapters.has(adapter)) {\n throw consumedError(adapter, \"recorded by this package\");\n }\n let device: GPUDevice;\n try {\n device = await adapter.requestDevice(descriptor);\n } catch (err) {\n const message = messageOf(err);\n if (/consumed|already been used/i.test(message)) {\n throw consumedError(adapter, message);\n }\n throw new WebGpuGraphError(\"E_NO_DEVICE\", `requestDevice() rejected: ${message}`, {\n reason: \"requestDevice\",\n adapter: summarizeAdapter(adapter),\n });\n }\n consumedAdapters.add(adapter);\n return device;\n}\n","/**\n * Capability capture (spec 2.2 step 4, 3.3, 5.1, 5.2; contract 3.4): the GpuCaps record of a DEVICE (its\n * limits and features, never the adapter's), the zero-cost variant for an adopted device, the two planner\n * facts asserted at create(), and the workgroup size a device runs.\n */\n\nimport { MAX_WORKGROUPS_PER_DIM, WORKGROUP_SIZE } from \"../constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport type { AdapterInfoLike, GpuCaps, PlanCaps } from \"../types/context.js\";\nimport { isSoftwareAdapter } from \"./acquire.js\";\n\n/**\n * Step 4 of create(): the GpuCaps of a DEVICE (device.limits, never adapter.limits) with the adapter info\n * and the runtime tag. The subgroup sizes are the adapter's only when the device has the \"subgroups\"\n * feature, else 0 (spec 3.3).\n * @param device - the device the caps describe\n * @param info - the adapter's info (vendor, architecture, subgroup sizes)\n * @param runtime - the tag the creating entry sets (\"unknown\" for consumers of the core)\n * @param wgslFeatures - navigator.gpu.wgslLanguageFeatures or the Dawn equivalent (informational)\n * @returns the capability record\n */\nexport function captureCaps(\n device: GPUDevice,\n info: AdapterInfoLike,\n runtime: \"browser\" | \"node\" | \"unknown\",\n wgslFeatures: Iterable<string>,\n): GpuCaps {\n const features: ReadonlySet<string> = new Set(device.features);\n const subgroups = features.has(\"subgroups\");\n return {\n limits: device.limits,\n features,\n wgslFeatures: new Set(wgslFeatures),\n subgroupMinSize: subgroups ? (info.subgroupMinSize ?? 0) : 0,\n subgroupMaxSize: subgroups ? (info.subgroupMaxSize ?? 0) : 0,\n software: isSoftwareAdapter(info),\n runtime,\n vendor: info.vendor,\n architecture: info.architecture,\n device: info.device,\n description: info.description,\n };\n}\n\n/**\n * GpuContext.from(device, info?): caps from device.limits / device.features and the partial info given;\n * software false and runtime \"unknown\" unless given; the subgroup sizes are honoured only when the device\n * has the feature.\n * @param device - the adopted device\n * @param info - what the caller knows about the adapter, if anything\n * @returns the capability record\n */\nexport function capsFromDevice(device: GPUDevice, info: Partial<GpuCaps> | undefined): GpuCaps {\n const features: ReadonlySet<string> = new Set(device.features);\n const subgroups = features.has(\"subgroups\");\n return {\n limits: device.limits,\n features,\n wgslFeatures: info?.wgslFeatures ?? new Set<string>(),\n subgroupMinSize: subgroups ? (info?.subgroupMinSize ?? 0) : 0,\n subgroupMaxSize: subgroups ? (info?.subgroupMaxSize ?? 0) : 0,\n software: info?.software ?? false,\n runtime: info?.runtime ?? \"unknown\",\n vendor: info?.vendor ?? \"\",\n architecture: info?.architecture ?? \"\",\n device: info?.device ?? \"\",\n description: info?.description ?? \"\",\n };\n}\n\n/**\n * The workgroup size a device runs: min(WORKGROUP_SIZE, caps.limits.maxComputeInvocationsPerWorkgroup) rounded\n * down to a power of two (spec 5.1; the formula of contract 3.2 / 3.4). maxComputeWorkgroupSizeX is not a term:\n * every adapter supports its 256 default (WebGPU 3.6.2), so the result never exceeds it. Rounds down by doubling\n * (no bitwise operator).\n * @param caps - the capability record (a GpuCaps is a PlanCaps)\n * @returns the workgroup size\n */\nexport function workgroupSizeFor(caps: PlanCaps): number {\n const cap = Math.min(WORKGROUP_SIZE, caps.limits.maxComputeInvocationsPerWorkgroup);\n let size = 1;\n while (size * 2 <= cap) {\n size *= 2;\n }\n return size;\n}\n\n/**\n * Asserts the two facts the planners bake in: maxComputeWorkgroupsPerDimension === MAX_WORKGROUPS_PER_DIM\n * (the prelude's linear_id and plan1d / plan2d use the constant) and WG is a power of two >= 64 (spec 2.2,\n * 5.2). The limit is never requested, so a device reports the spec default whatever its adapter says.\n * @param caps - the capability record of the device\n */\nexport function assertPlanLimits(caps: GpuCaps): void {\n const perDim = caps.limits.maxComputeWorkgroupsPerDimension;\n if (perDim !== MAX_WORKGROUPS_PER_DIM) {\n throw new WebGpuGraphError(\n \"E_NO_DEVICE\",\n `maxComputeWorkgroupsPerDimension is ${perDim}; the dispatch planner and the WGSL prelude bake ${MAX_WORKGROUPS_PER_DIM}`,\n {\n reason: \"maxComputeWorkgroupsPerDimension\",\n adapter: null,\n requested: MAX_WORKGROUPS_PER_DIM,\n available: perDim,\n },\n );\n }\n const wg = workgroupSizeFor(caps);\n if (wg < 64) {\n throw new WebGpuGraphError(\n \"E_NO_DEVICE\",\n `the device allows a workgroup of ${wg} invocations; the kernels need a power of two >= 64`,\n {\n reason: \"limit\",\n adapter: null,\n limit: \"maxComputeInvocationsPerWorkgroup\",\n requested: 64,\n available: wg,\n },\n );\n }\n}\n","/**\n * Error scopes (spec 5.7; contract 3.4): a validation scope that turns a captured GPUValidationError into\n * E_VALIDATION { label, message }, the compilation-info formatter with body-relative line numbers, and the\n * AllocationTracker that wraps large createBuffer calls in an out-of-memory scope and keeps the resident-byte\n * bookkeeping the residency, the pool and the staging ring share (it is owned by the context).\n */\n\nimport { OOM_SCOPE_THRESHOLD_BYTES } from \"../constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\n\n/**\n * Runs `fn` inside pushErrorScope(\"validation\"); a captured error becomes E_VALIDATION { label, message }\n * thrown from the returned promise (spec 5.7). An error `fn` itself throws is rethrown unchanged after the\n * scope is popped, so the device's scope stack stays balanced.\n * @param device - the device\n * @param label - names the operation in the error (every object the package creates is labelled)\n * @param fn - the work; may return a promise\n * @returns the value of `fn`\n */\nexport async function withValidationScope<T>(device: GPUDevice, label: string, fn: () => Promise<T> | T): Promise<T> {\n device.pushErrorScope(\"validation\");\n let result: T;\n try {\n result = await fn();\n } catch (err) {\n await device.popErrorScope().catch(() => null);\n throw err;\n }\n const error = await device.popErrorScope();\n if (error !== null) {\n throw new WebGpuGraphError(\"E_VALIDATION\", `${label}: ${error.message}`, { label, message: error.message });\n }\n return result;\n}\n\n/**\n * Formats GPUCompilationInfo messages with line numbers relative to the kernel BODY: `preludeLines` (the\n * lines the composer emitted before the body) is subtracted, a message located inside those lines is\n * reported as `prelude:<line>`, and a message without a location (lineNum 0) carries no position (spec 5.1).\n * @param info - the compilation info of the shader module\n * @param preludeLines - the number of emitted lines before the body's first line\n * @returns one string per message: `<type> <line>:<column> <message>`\n */\nexport function formatCompilationInfo(info: GPUCompilationInfo, preludeLines: number): string[] {\n return info.messages.map((m) => {\n if (m.lineNum === 0) {\n return `${m.type} ${m.message}`;\n }\n const line = m.lineNum - preludeLines;\n if (line >= 1) {\n return `${m.type} ${line}:${m.linePos} ${m.message}`;\n }\n return `${m.type} prelude:${m.lineNum}:${m.linePos} ${m.message}`;\n });\n}\n\n/**\n * Creates buffers, wrapping sizes >= OOM_SCOPE_THRESHOLD_BYTES in an \"out-of-memory\" scope whose pop is\n * collected; `check()` surfaces the first OOM (spec 4.4, 5.7). Owned by the context, shared by the\n * residency and the pool.\n */\nexport class AllocationTracker {\n private readonly device: GPUDevice;\n private readonly threshold: number;\n private readonly live = new Map<GPUBuffer, number>();\n private residentBytes = 0;\n private pending: Promise<void>[] = [];\n private failure: WebGpuGraphError | null = null;\n private serial = 0;\n\n /**\n * Creates a tracker over one device.\n * @param device - the device buffers are created on\n * @param thresholdBytes - the byte size from which createBuffer runs inside an out-of-memory scope (default OOM_SCOPE_THRESHOLD_BYTES)\n */\n constructor(device: GPUDevice, thresholdBytes?: number) {\n this.device = device;\n this.threshold = thresholdBytes ?? OOM_SCOPE_THRESHOLD_BYTES;\n }\n\n /**\n * createBuffer with the scope rule; every buffer is labelled (an unlabelled descriptor becomes `buffer-<n>`).\n * @param descriptor - the buffer descriptor\n * @returns the buffer\n */\n createBuffer(descriptor: GPUBufferDescriptor): GPUBuffer {\n this.serial += 1;\n const label =\n descriptor.label === undefined || descriptor.label === \"\" ? `buffer-${this.serial}` : descriptor.label;\n const { size } = descriptor;\n const scoped = size >= this.threshold;\n if (scoped) {\n this.device.pushErrorScope(\"out-of-memory\");\n }\n const buffer = this.device.createBuffer({ ...descriptor, label });\n this.live.set(buffer, size);\n this.residentBytes += size;\n if (scoped) {\n const pop = this.device.popErrorScope().then(\n (error) => {\n if (error === null) {\n return;\n }\n if (this.live.has(buffer)) {\n this.live.delete(buffer);\n this.residentBytes -= size;\n }\n if (this.failure === null) {\n this.failure = new WebGpuGraphError(\n \"E_OUT_OF_MEMORY\",\n `out of memory creating \"${label}\" (${size} bytes, ${this.residentBytes} resident): ${error.message}`,\n { requested: size, resident: this.residentBytes, label },\n );\n }\n },\n () => undefined,\n );\n this.pending.push(pop);\n }\n return buffer;\n }\n\n /**\n * Destroys a buffer created here and decrements `resident`; a buffer the tracker does not know is destroyed\n * without touching the bookkeeping, so destroying twice is harmless.\n * @param buffer - the buffer to destroy\n */\n destroy(buffer: GPUBuffer): void {\n const size = this.live.get(buffer);\n if (size !== undefined) {\n this.live.delete(buffer);\n this.residentBytes -= size;\n }\n buffer.destroy();\n }\n\n /**\n * Awaits every outstanding scope pop; the first OOM -> E_OUT_OF_MEMORY { requested, resident, label }; later\n * calls after a failure throw the same error again until `reset()`.\n */\n async check(): Promise<void> {\n while (this.pending.length > 0) {\n const batch = this.pending.splice(0);\n await Promise.all(batch);\n }\n if (this.failure !== null) {\n throw this.failure;\n }\n }\n\n /** Forgets a recorded OOM after the caller released what it allocated. */\n reset(): void {\n this.failure = null;\n }\n\n /**\n * Bytes of live buffers created through this tracker.\n * @returns the resident byte count\n */\n get resident(): number {\n return this.residentBytes;\n }\n\n /**\n * Number of live buffers created through this tracker.\n * @returns the live buffer count\n */\n get liveBuffers(): number {\n return this.live.size;\n }\n}\n","/**\n * Device-loss and uncaptured-error plumbing (spec 5.7, 2.2 step 5; contract 3.4): the pending-error slot a\n * context throws from its next public call, the uncapturederror listener that routes each event to the\n * caller's sink or to the slot, the device.lost watcher and the E_DEVICE_LOST constructor. Nothing here\n * throws; errors are constructed and handed on.\n */\n\nimport { WebGpuGraphError } from \"../errors.js\";\n\n/** The context's pending-error slot (spec 5.7): the last uncaptured error not yet delivered; `take()` clears it. */\nexport class PendingErrorSlot {\n private readonly queue: WebGpuGraphError[] = [];\n\n /**\n * Stores an error; a second error before `take()` is kept as `details.next` of the first.\n * @param error - the error to hold until the next public call\n */\n set(error: WebGpuGraphError): void {\n this.queue.push(error);\n }\n\n /**\n * Returns and clears the pending error, or null. With several errors queued the FIRST is returned and\n * each later one is chained as `details.next` of its predecessor (a copy: `details` is frozen).\n * @returns the first pending error with the chain attached, or null\n */\n take(): WebGpuGraphError | null {\n if (this.queue.length === 0) {\n return null;\n }\n const errors = this.queue.splice(0);\n let chained: WebGpuGraphError | null = null;\n for (let i = errors.length - 1; i >= 0; i -= 1) {\n const error = errors[i];\n chained =\n chained === null\n ? error\n : new WebGpuGraphError(error.code, error.message, { ...error.details, next: chained });\n }\n return chained;\n }\n\n /**\n * True when an error is pending.\n * @returns whether `take()` would return an error\n */\n get pending(): boolean {\n return this.queue.length > 0;\n }\n}\n\n/**\n * The WebGpuGraphError for one uncaptured GPUError: E_OUT_OF_MEMORY for a GPUOutOfMemoryError (recognised\n * by its class name so no global is read, spec 2.1 rule 1), E_VALIDATION otherwise.\n * @param error - the event's error\n * @param label - the device label the error is attributed to\n * @returns the wrapped error\n */\nfunction uncapturedError(error: GPUError, label: string): WebGpuGraphError {\n const { message } = error;\n if (error.constructor.name === \"GPUOutOfMemoryError\") {\n // the documented shape is { requested, resident, label } (contract 3.1); the event names no size and the\n // sink tracks no residency, so both are 0 and the runtime's text lives in the message only\n return new WebGpuGraphError(\"E_OUT_OF_MEMORY\", `uncaptured out-of-memory error on \"${label}\": ${message}`, {\n requested: 0,\n resident: 0,\n label,\n });\n }\n return new WebGpuGraphError(\"E_VALIDATION\", `uncaptured validation error on \"${label}\": ${message}`, {\n label,\n message,\n });\n}\n\n/**\n * Installs the uncapturederror listener: each event becomes E_VALIDATION { label, message } (or\n * E_OUT_OF_MEMORY for GPUOutOfMemoryError) routed to `onError`, else stored in `slot`. Returns the\n * uninstaller. `label` is the device's label (the descriptor label create() gave it).\n * @param device - the device to listen on\n * @param slot - where errors go when no sink is given\n * @param onError - the caller's sink, or null\n * @returns a function that removes the listener\n */\nexport function installUncapturedErrorSink(\n device: GPUDevice,\n slot: PendingErrorSlot,\n onError: ((error: WebGpuGraphError) => void) | null,\n): () => void {\n let installed = true;\n const label = device.label ?? \"\";\n const listener = (event: GPUUncapturedErrorEvent): void => {\n if (!installed) {\n return;\n }\n const wrapped = uncapturedError(event.error, label);\n if (onError !== null) {\n onError(wrapped);\n } else {\n slot.set(wrapped);\n }\n };\n device.addEventListener(\"uncapturederror\", listener);\n return () => {\n installed = false;\n if (typeof device.removeEventListener === \"function\") {\n device.removeEventListener(\"uncapturederror\", listener);\n }\n };\n}\n\n/**\n * Chains device.lost into `onLost` exactly once; returns the promise the context exposes as `ctx.lost`.\n * @param device - the device whose loss is watched\n * @param onLost - called once with the lost info\n * @returns the lost info, after `onLost` ran\n */\nexport function watchDeviceLost(\n device: GPUDevice,\n onLost: (info: GPUDeviceLostInfo) => void,\n): Promise<GPUDeviceLostInfo> {\n let delivered = false;\n return device.lost.then((info) => {\n if (!delivered) {\n delivered = true;\n onLost(info);\n }\n return info;\n });\n}\n\n/**\n * The E_DEVICE_LOST error for a lost-info record.\n * @param info - the device.lost result\n * @returns E_DEVICE_LOST { reason, message }\n */\nexport function deviceLostError(info: GPUDeviceLostInfo): WebGpuGraphError {\n return new WebGpuGraphError(\"E_DEVICE_LOST\", `device lost (${info.reason}): ${info.message}`, {\n reason: info.reason,\n message: info.message,\n });\n}\n","/**\n * Kernel (spec 5.1; contract 3.9): a compiled pipeline bound to the binding list of its spec. `bind()` creates the\n * bind groups from a `Record<name, Binding>` keyed by the declared names and caches them by the identity of the\n * buffers, offsets and sizes (a layout's bind groups are created once per load(), not per iteration); `dispatch()`\n * records setPipeline / setBindGroup / dispatchWorkgroups and skips an empty plan (spec 5.6); `dispatchIndirect()`\n * (P4, spec 5.4) records the same prefix and a dispatchWorkgroupsIndirect over one 16-byte slot of an args buffer.\n */\n\nimport { STORAGE_ALIGN } from \"../constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type Binding } from \"../types/memory.js\";\nimport { type DispatchPlan } from \"./dispatch.js\";\nimport { type BindingDecl, type ComposedModule, type WgslModuleSpec } from \"./wgsl.js\";\n\n/** The resources of one bind(): one Binding per BindingDecl name; a uniform decl takes the ring's whole-buffer binding (the slot is chosen by the dynamic offset at dispatch). */\nexport type KernelBindings = Readonly<Record<string, Binding>>;\n/** A kernel with its bind groups created (spec 5.1: cached per set of buffers and offsets). */\nexport interface BoundKernel {\n readonly kernel: Kernel;\n readonly bindGroups: readonly GPUBindGroup[];\n /** Group indices whose bind group takes a dynamic offset (the uniform groups), in group order. */\n readonly dynamicGroups: readonly number[];\n}\n\n/** Bytes of one indirect args slot: (x, y, 1, count) as four u32 (spec 5.4; P4 PD-2). */\nexport const INDIRECT_ARGS_STRIDE = 16;\n\n/**\n * The most buffer sets one Kernel keeps bind groups for; binding one more forgets the least recently bound. A\n * Kernel lives as long as its context (the PipelineCache holds it), so an unbounded cache kept the bind groups --\n * and, on Dawn, the native memory behind them -- of every simulation and scratch lease ever bound, disposed or not\n * (issue #162). A caller keeps the BoundKernel it was given, so eviction only costs a later bind() of the same\n * buffers a new createBindGroup. One simulation binds at most a dozen sets per kernel (the scan's levels).\n * ponytail: a count bound, not a lifetime one; a per-buffer destroy hook would free a set as soon as its buffer goes.\n */\nexport const BIND_GROUP_CACHE_LIMIT = 32;\n\n/** Buffer identities for the bind-group cache key: every GPUBuffer seen by any Kernel gets one number, once. */\nconst bufferIds = new WeakMap<GPUBuffer, number>();\nlet nextBufferId = 1;\n\n/**\n * The identity number of a buffer.\n * @param buffer - the buffer\n * @returns its number\n */\nfunction bufferId(buffer: GPUBuffer): number {\n let id = bufferIds.get(buffer);\n if (id === undefined) {\n id = nextBufferId;\n nextBufferId += 1;\n bufferIds.set(buffer, id);\n }\n return id;\n}\n\n/**\n * True when two byte ranges intersect.\n * @param a - one binding\n * @param b - the other binding\n * @returns whether [a.offset, a.offset + a.size) and [b.offset, b.offset + b.size) overlap\n */\nfunction rangesIntersect(a: Binding, b: Binding): boolean {\n return a.offset < b.offset + b.size && b.offset < a.offset + a.size;\n}\n\n/** A compiled pipeline plus the binding list of its spec (spec 5.1). */\nexport class Kernel {\n /** The module spec the pipeline was compiled from (its bindings drive bind()). */\n readonly spec: WgslModuleSpec;\n /** The compiled compute pipeline. */\n readonly pipeline: GPUComputePipeline;\n /** The explicit bind group layouts, one per group index (an empty layout for an unused index). */\n readonly layouts: readonly GPUBindGroupLayout[];\n /** The workgroup size the pipeline was compiled with (the effective WG override). */\n readonly workgroupSize: number;\n /** The entry point name the pipeline was compiled with. */\n readonly entryPoint: string;\n private readonly device: GPUDevice;\n /** The declarations of each group in binding order (index = group). */\n private readonly groups: readonly (readonly BindingDecl[])[];\n /** The uniform-binding count of each group (the dynamic offsets a setBindGroup takes). */\n private readonly dynamicCounts: readonly number[];\n /** Cached bind groups by buffer identity + offset + size, least recently bound first (at most BIND_GROUP_CACHE_LIMIT). */\n private readonly cache = new Map<string, BoundKernel>();\n\n /**\n * Wraps a compiled pipeline.\n * @param device - the device the bind groups are created on\n * @param spec - the module\n * @param composed - the composed text (workgroup size and entry point)\n * @param pipeline - the compiled pipeline\n * @param layouts - the explicit bind-group layouts, one per group 0..maxGroup\n */\n constructor(\n device: GPUDevice,\n spec: WgslModuleSpec,\n composed: ComposedModule,\n pipeline: GPUComputePipeline,\n layouts: readonly GPUBindGroupLayout[],\n ) {\n this.device = device;\n this.spec = spec;\n this.pipeline = pipeline;\n this.layouts = layouts;\n this.workgroupSize = composed.overrides.WG as number;\n this.entryPoint = composed.entryPoint;\n const groups: BindingDecl[][] = layouts.map(() => []);\n for (const decl of spec.bindings) {\n groups[decl.group].push(decl);\n }\n for (const group of groups) {\n group.sort((a, b) => a.binding - b.binding);\n }\n this.groups = groups;\n this.dynamicCounts = groups.map((group) => group.filter((decl) => decl.kind === \"uniform\").length);\n }\n\n /**\n * Creates (or reuses, keyed by every buffer identity + offset + size) the bind groups, each labelled\n * `<spec.id>/<group>`; a missing or extra name is E_INVALID_ARGUMENT; two bindings of one call whose ranges\n * intersect on one buffer while either slot is `storage` (read_write) is E_INVALID_ARGUMENT\n * { argument: \"aliasing\" } (the host-side mirror of WebGPU's writable buffer-binding-aliasing rule, 3.10.1, so\n * the failure is synchronous and labelled). CONTRACT DECISION: bind() is synchronous, so a createBindGroup\n * validation error (a wrong-size uniform binding, a usage mismatch) is NOT thrown here -- it reaches the\n * pending-error slot as E_VALIDATION { label: \"<spec.id>/<group>\" } and is thrown by the batch's readback\n * (Dawn-node) or the next assertReady() (browser), spec 5.7. An empty bind group is created for every empty\n * layout index so setBindGroup is called for 0..maxGroup.\n * PLAN DECISION (verified on Dawn 0.4.0 / lavapipe): one buffer bound with two DIFFERENT access modes when one is\n * `storage` is also E_INVALID_ARGUMENT { argument: \"aliasing\", reason: \"usage\" } even with disjoint ranges, because\n * WebGPU's usage-scope rule rejects \"writable usage and another usage in the same synchronization scope\" per\n * BUFFER; two `storage` slots with disjoint ranges (the state header / trace pattern) are accepted; a zero-size\n * binding (never bind a zero-length buffer, spec 3.6) and an offset that is not a multiple of STORAGE_ALIGN = 256\n * (spec 2.6; Dawn: \"does not satisfy the minimum ... alignment (256)\") are E_INVALID_ARGUMENT.\n * @param resources - one Binding per declared name\n * @returns the bound kernel (the same object for the same buffers, offsets and sizes until invalidate())\n */\n bind(resources: KernelBindings): BoundKernel {\n const { id } = this.spec;\n const declared = new Map(this.spec.bindings.map((decl) => [decl.name, decl] as const));\n for (const name of Object.keys(resources)) {\n if (!declared.has(name)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${id}: no binding named \"${name}\"`, {\n argument: \"bindings\",\n value: name,\n expected: [...declared.keys()].join(\", \"),\n });\n }\n }\n const resolved: { readonly decl: BindingDecl; readonly binding: Binding }[] = [];\n for (const decl of this.spec.bindings) {\n const binding = resources[decl.name] as Binding | undefined;\n if (binding === undefined) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${id}: binding \"${decl.name}\" is missing`, {\n argument: \"bindings\",\n value: decl.name,\n expected: \"a Binding for every declared name\",\n });\n }\n if (!(Number.isInteger(binding.size) && binding.size > 0)) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${id}: binding \"${decl.name}\" has size ${binding.size}`,\n {\n argument: decl.name,\n value: binding.size,\n expected: \"size > 0 (a zero-length buffer is never bound)\",\n },\n );\n }\n if (!(Number.isInteger(binding.offset) && binding.offset >= 0 && binding.offset % STORAGE_ALIGN === 0)) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${id}: binding \"${decl.name}\" has offset ${binding.offset}`,\n {\n argument: decl.name,\n value: binding.offset,\n expected: `a multiple of ${STORAGE_ALIGN} (spec 2.6: the offset alignment the package always honours)`,\n },\n );\n }\n resolved.push({ decl, binding });\n }\n for (let i = 0; i < resolved.length; i++) {\n for (let j = i + 1; j < resolved.length; j++) {\n const a = resolved[i];\n const b = resolved[j];\n if (a.binding.buffer !== b.binding.buffer) {\n continue;\n }\n const writable = a.decl.kind === \"storage\" || b.decl.kind === \"storage\";\n if (!writable) {\n continue;\n }\n if (a.decl.kind !== b.decl.kind) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${id}: \"${a.decl.name}\" and \"${b.decl.name}\" bind one buffer with different access modes (writable usage next to another usage)`,\n {\n argument: \"aliasing\",\n value: [a.decl.name, b.decl.name],\n expected: \"one access mode per buffer when a slot is read_write\",\n reason: \"usage\",\n },\n );\n }\n if (rangesIntersect(a.binding, b.binding)) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${id}: \"${a.decl.name}\" and \"${b.decl.name}\" bind intersecting ranges of one read_write buffer`,\n {\n argument: \"aliasing\",\n value: [a.decl.name, b.decl.name],\n expected: \"disjoint ranges\",\n reason: \"range\",\n },\n );\n }\n }\n }\n const key = resolved\n .map(({ binding }) => `${bufferId(binding.buffer)}:${binding.offset}:${binding.size}`)\n .join(\"|\");\n const cached = this.cache.get(key);\n if (cached !== undefined) {\n // re-insert: the Map's insertion order is the recency order the eviction below reads\n this.cache.delete(key);\n this.cache.set(key, cached);\n return cached;\n }\n const byName = new Map(resolved.map(({ decl, binding }) => [decl.name, binding] as const));\n const bindGroups = this.layouts.map((layout, group) =>\n this.device.createBindGroup({\n label: `${id}/${group}`,\n layout,\n entries: this.groups[group].map((decl) => {\n const binding = byName.get(decl.name) as Binding;\n return {\n binding: decl.binding,\n resource: { buffer: binding.buffer, offset: binding.offset, size: binding.size },\n };\n }),\n }),\n );\n const dynamicGroups: number[] = [];\n this.dynamicCounts.forEach((count, group) => {\n if (count > 0) {\n dynamicGroups.push(group);\n }\n });\n const bound: BoundKernel = Object.freeze({\n kernel: this,\n bindGroups: Object.freeze(bindGroups),\n dynamicGroups: Object.freeze(dynamicGroups),\n });\n this.cache.set(key, bound);\n if (this.cache.size > BIND_GROUP_CACHE_LIMIT) {\n this.cache.delete(this.cache.keys().next().value as string);\n }\n return bound;\n }\n\n /**\n * setPipeline + setBindGroup for every group (dynamic offsets in dynamicGroups order) + dispatchWorkgroups(plan.x, plan.y, plan.z); a plan with x === 0 records nothing (spec 5.6).\n * PLAN DECISION: one dynamic offset per dynamic GROUP, replicated over every uniform binding of that group (every\n * P1-P3 kernel has exactly one params uniform per group); absent offsets mean 0; a BoundKernel of another kernel\n * or an offset list of the wrong length is E_INVALID_ARGUMENT.\n * PLAN DECISION: `dynamicOffsets?` is spelled `?: readonly number[]` rather than the contract's\n * `?: readonly number[] | undefined` because the root ESLint rule no-duplicate-type-constituents rejects the\n * explicit undefined on an optional parameter (the call signature is identical).\n * @param pass - the open compute pass\n * @param bound - a BoundKernel of THIS kernel\n * @param plan - the dispatch shape\n * @param dynamicOffsets - one byte offset per entry of bound.dynamicGroups\n */\n dispatch(\n pass: GPUComputePassEncoder,\n bound: BoundKernel,\n plan: DispatchPlan,\n dynamicOffsets?: readonly number[],\n ): void {\n this.check(bound, dynamicOffsets);\n if (plan.x === 0) {\n return;\n }\n this.setUp(pass, bound, dynamicOffsets);\n pass.dispatchWorkgroups(plan.x, plan.y, plan.z);\n }\n\n /**\n * setPipeline + the bind groups exactly as dispatch(), then dispatchWorkgroupsIndirect(args.buffer, args.offset +\n * INDIRECT_ARGS_STRIDE * slot) (spec 5.4): the (x, y, 1) of the slot were written by the indirect-finalize kernel\n * earlier in the same pass. A slot beyond the binding is E_INVALID_ARGUMENT.\n * @param pass - the open compute pass\n * @param bound - a BoundKernel of THIS kernel\n * @param args - the args buffer range (usage INDIRECT | STORAGE)\n * @param slot - the 16-byte slot index inside the range\n * @param dynamicOffsets - one byte offset per entry of bound.dynamicGroups\n */\n dispatchIndirect(\n pass: GPUComputePassEncoder,\n bound: BoundKernel,\n args: Binding,\n slot: number,\n dynamicOffsets?: readonly number[],\n ): void {\n this.check(bound, dynamicOffsets);\n if (!Number.isInteger(slot) || slot < 0 || (slot + 1) * INDIRECT_ARGS_STRIDE > args.size) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${this.spec.id}: args slot ${slot} is outside the binding`,\n {\n argument: \"slot\",\n value: slot,\n expected: `0 <= slot < ${Math.floor(args.size / INDIRECT_ARGS_STRIDE)}`,\n },\n );\n }\n this.setUp(pass, bound, dynamicOffsets);\n pass.dispatchWorkgroupsIndirect(args.buffer, args.offset + INDIRECT_ARGS_STRIDE * slot);\n }\n\n /**\n * The argument checks dispatch() and dispatchIndirect() share: a BoundKernel of another kernel or an offset list\n * of the wrong length is E_INVALID_ARGUMENT.\n * @param bound - the bound kernel\n * @param dynamicOffsets - the offsets, if any\n */\n private check(bound: BoundKernel, dynamicOffsets: readonly number[] | undefined): void {\n const { id } = this.spec;\n if (bound.kernel !== this) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${id}: the bound kernel belongs to \"${bound.kernel.spec.id}\"`,\n {\n argument: \"bound\",\n value: bound.kernel.spec.id,\n expected: id,\n },\n );\n }\n if (dynamicOffsets !== undefined && dynamicOffsets.length !== bound.dynamicGroups.length) {\n throw new WebGpuGraphError(\n \"E_INVALID_ARGUMENT\",\n `${id}: ${dynamicOffsets.length} dynamic offsets for ${bound.dynamicGroups.length} dynamic groups`,\n {\n argument: \"dynamicOffsets\",\n value: dynamicOffsets.length,\n expected: bound.dynamicGroups.length,\n },\n );\n }\n }\n\n /**\n * setPipeline + setBindGroup for every group (the dynamic offsets replicated over the uniform bindings of each\n * dynamic group), the prefix dispatch() and dispatchIndirect() share.\n * @param pass - the open compute pass\n * @param bound - a BoundKernel of this kernel\n * @param dynamicOffsets - one byte offset per entry of bound.dynamicGroups (absent = 0)\n */\n private setUp(\n pass: GPUComputePassEncoder,\n bound: BoundKernel,\n dynamicOffsets: readonly number[] | undefined,\n ): void {\n pass.setPipeline(this.pipeline);\n let next = 0;\n bound.bindGroups.forEach((bindGroup, group) => {\n const count = this.dynamicCounts[group];\n if (count > 0) {\n const offset = dynamicOffsets?.[next] ?? 0;\n next += 1;\n const offsets: number[] = [];\n for (let k = 0; k < count; k++) {\n offsets.push(offset);\n }\n pass.setBindGroup(group, bindGroup, offsets);\n } else {\n pass.setBindGroup(group, bindGroup);\n }\n });\n }\n\n /** Drops cached bind groups (a layout's buffers changed). */\n invalidate(): void {\n this.cache.clear();\n }\n}\n","/**\n * GPUBufferUsage / GPUMapMode / GPUShaderStage as numbers (spec 2.1 rule 1; contract 3.4): under Dawn-node the\n * global namespaces do not exist until `Object.assign(globalThis, dawn.globals)` has run, so the core never reads\n * them at module top level and keeps its own copies here. Each field names the WebGPU spec constant it mirrors;\n * test/device/constants.test.ts compares every field with the runtime globals so a drift is caught.\n */\n\n/** GPUBufferUsage bits as numbers so the core never reads the global at module top level (spec 2.1 rule 1). */\nexport const BufferUsage: Readonly<{\n MAP_READ: 0x0001;\n MAP_WRITE: 0x0002;\n COPY_SRC: 0x0004;\n COPY_DST: 0x0008;\n INDEX: 0x0010;\n VERTEX: 0x0020;\n UNIFORM: 0x0040;\n STORAGE: 0x0080;\n INDIRECT: 0x0100;\n QUERY_RESOLVE: 0x0200;\n}> = Object.freeze({\n MAP_READ: 0x0001, // GPUBufferUsage.MAP_READ\n MAP_WRITE: 0x0002, // GPUBufferUsage.MAP_WRITE\n COPY_SRC: 0x0004, // GPUBufferUsage.COPY_SRC\n COPY_DST: 0x0008, // GPUBufferUsage.COPY_DST\n INDEX: 0x0010, // GPUBufferUsage.INDEX\n VERTEX: 0x0020, // GPUBufferUsage.VERTEX\n UNIFORM: 0x0040, // GPUBufferUsage.UNIFORM\n STORAGE: 0x0080, // GPUBufferUsage.STORAGE\n INDIRECT: 0x0100, // GPUBufferUsage.INDIRECT\n QUERY_RESOLVE: 0x0200, // GPUBufferUsage.QUERY_RESOLVE\n});\n\n/** GPUMapMode bits. */\nexport const MapMode: Readonly<{ READ: 0x0001; WRITE: 0x0002 }> = Object.freeze({\n READ: 0x0001, // GPUMapMode.READ\n WRITE: 0x0002, // GPUMapMode.WRITE\n});\n\n/** GPUShaderStage bits. */\nexport const ShaderStage: Readonly<{ VERTEX: 0x1; FRAGMENT: 0x2; COMPUTE: 0x4 }> = Object.freeze({\n VERTEX: 0x1, // GPUShaderStage.VERTEX\n FRAGMENT: 0x2, // GPUShaderStage.FRAGMENT\n COMPUTE: 0x4, // GPUShaderStage.COMPUTE\n});\n","/**\n * The WGSL prelude every composed module receives first (contract 4.1), the two reduction-helper blocks the\n * composer splices for a body whose spec lists `needs: [\"subgroups\"]` (contract 4.3, D16), and the WGSL\n * reserved-word list the composer rejects identifiers from (contract 3.9).\n *\n * CONTRACT DECISION (3.9): this text lives in the kernel layer, not in `src/wgsl/`, because the composer must own\n * what it splices and `src/wgsl/` then holds kernel BODIES only. Every numeric constant is interpolated from\n * `constants.ts` and graph-format's `INVALID_INDEX`; the literal-grep test of spec 3.5 (`test/kernel/wgsl.test.ts`)\n * covers this file's template, so no u32 sentinel or workgroup-size literal is ever typed here.\n */\n\nimport { INVALID_INDEX } from \"@graphty/graph-format\";\n\nimport {\n APSP_TILE,\n BC_SIGMA_EXPONENT_CAP,\n EXACT_TILES_PER_PASS,\n F32_INF_BITS,\n F32_SIGN_BIT,\n FA2_COINCIDENT_SQ,\n FA2_DISTANCE_FLOOR,\n FA2_DISTANCE_FLOOR_SQ,\n FA2_FLAG_ADAPTIVE,\n FA2_FLAG_FIRST,\n FR_COOLING_PATIENCE,\n FR_COOLING_STEP,\n GRID_BBOX_MARGIN,\n GRID_EXTENT_FLOOR,\n GRID_HUB_CELL,\n GROUP_HASH_LOAD_FACTOR,\n MAX_WORKGROUPS_PER_DIM,\n RADIX_BINS,\n TRIANGLE_BINARY_SEARCH_RATIO,\n U32_MAX,\n WORKGROUP_SIZE,\n} from \"../constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\n\n/**\n * Formats a finite number as a WGSL f32 literal that always carries a decimal point or an exponent (`0.01`,\n * `1e-8`, `2.0`), so an integral value never becomes an abstract-int literal (contract 4.1).\n * @param value - the number to format\n * @returns the literal text\n */\nexport function wgslF32Literal(value: number): string {\n if (!Number.isFinite(value)) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `wgslF32Literal: ${value} is not a finite number`, {\n argument: \"value\",\n value,\n expected: \"a finite number\",\n });\n }\n const text = String(value);\n return /[.e]/.test(text) ? text : `${text}.0`;\n}\n\n/** The prelude text with the constants interpolated from constants.ts and graph-format's INVALID_INDEX (4.1). */\nexport const PRELUDE_WGSL: string = /* wgsl */ `// ---- prelude: constants, standard overrides, helpers (every module receives this text first)\nconst INVALID_INDEX: u32 = ${INVALID_INDEX}u;\nconst U32_MAX: u32 = ${U32_MAX}u;\nconst F32_INF_BITS: u32 = ${F32_INF_BITS}u;\nconst F32_SIGN_BIT: u32 = ${F32_SIGN_BIT}u;\nconst MAX_WORKGROUPS_PER_DIM: u32 = ${MAX_WORKGROUPS_PER_DIM}u;\nconst EXACT_TILES_PER_PASS: u32 = ${EXACT_TILES_PER_PASS}u;\nconst FA2_DIST_FLOOR: f32 = ${wgslF32Literal(FA2_DISTANCE_FLOOR)};\nconst FA2_DIST_FLOOR_SQ: f32 = ${wgslF32Literal(FA2_DISTANCE_FLOOR_SQ)};\nconst FA2_COINCIDENT_SQ: f32 = ${wgslF32Literal(FA2_COINCIDENT_SQ)};\nconst FA2_FLAG_FIRST: u32 = ${FA2_FLAG_FIRST}u;\nconst FA2_FLAG_ADAPTIVE: u32 = ${FA2_FLAG_ADAPTIVE}u;\nconst FR_COOLING_STEP: f32 = ${wgslF32Literal(FR_COOLING_STEP)};\nconst FR_COOLING_PATIENCE: u32 = ${FR_COOLING_PATIENCE}u;\nconst GRID_HUB_CELL: u32 = ${GRID_HUB_CELL}u;\nconst GRID_EXTENT_FLOOR: f32 = ${wgslF32Literal(GRID_EXTENT_FLOOR)};\nconst GRID_BBOX_MARGIN: f32 = ${wgslF32Literal(GRID_BBOX_MARGIN)};\nconst RADIX_BINS: u32 = ${RADIX_BINS}u;\nconst RADIX_DIGIT_MASK: u32 = ${RADIX_BINS - 1}u;\nconst APSP_TILE: u32 = ${APSP_TILE}u;\nconst GROUP_HASH_LOAD_FACTOR: u32 = ${GROUP_HASH_LOAD_FACTOR}u;\nconst TRIANGLE_BINARY_SEARCH_RATIO: u32 = ${TRIANGLE_BINARY_SEARCH_RATIO}u;\nconst BC_SIGMA_EXPONENT_CAP: i32 = ${BC_SIGMA_EXPONENT_CAP}i;\nconst F32_MAX: f32 = 0x1.fffffep+127;\noverride WG: u32 = ${WORKGROUP_SIZE}u;\noverride USE_PERM: bool = false;\noverride HAS_WEIGHTS: bool = false;\noverride SUBGROUP_MIN: u32 = 4u;\noverride SUBGROUP_MAX: u32 = 0u;\n\nfn linear_id(wid: vec3<u32>, lid: u32) -> u32 { return (wid.x + wid.y * MAX_WORKGROUPS_PER_DIM) * WG + lid; }\nfn group_id(wid: vec3<u32>) -> u32 { return wid.x + wid.y * MAX_WORKGROUPS_PER_DIM; }\n// betweenness: the power of two the counts of depth L + 1 are divided by, from the f32 bits of depth L's largest count\nfn sigma_shift(maxBits: u32) -> i32 { return max(0i, i32((maxBits >> 23u) & 0xffu) - 127i - BC_SIGMA_EXPONENT_CAP); }\nfn lowbias32(x0: u32) -> u32 {\n var x = x0;\n x = x ^ (x >> 16u);\n x = x * 0x7feb352du;\n x = x ^ (x >> 15u);\n x = x * 0x846ca68bu;\n x = x ^ (x >> 16u);\n return x;\n}\nfn mask_bit(w: u32, i: u32) -> bool { return ((w >> (i & 31u)) & 1u) == 1u; }\nfn unpack_u8(w: u32, i: u32) -> u32 { return (w >> (8u * (i & 3u))) & 0xFFu; }\nfn pair_hash(i: u32, j: u32) -> u32 { return lowbias32((min(i, j) * 0x9E3779B9u) ^ max(i, j)); }\nfn order_key(w: f32) -> u32 {\n let raw = bitcast<u32>(w);\n let bits = select(raw, 0u, raw == F32_SIGN_BIT);\n return select(bits | F32_SIGN_BIT, ~bits, (bits & F32_SIGN_BIT) != 0u);\n}\nfn hash_unit(h: u32) -> f32 { return f32(h >> 8u) * (1.0 / 16777216.0); }\nfn hash_dir(h: u32, dim: u32) -> vec3f {\n let phi = 6.283185307179586 * hash_unit(h);\n if (dim == 2u) { return vec3f(cos(phi), sin(phi), 0.0); }\n let z = 2.0 * hash_unit(lowbias32(h ^ 0x5bd1e995u)) - 1.0;\n let r = sqrt(max(0.0, 1.0 - z * z));\n return vec3f(r * cos(phi), r * sin(phi), z);\n}\nfn kick_dir(i: u32, j: u32, dim: u32) -> vec3f {\n let d = hash_dir(pair_hash(i, j), dim);\n return select(d, -d, i > j);\n}`;\n\n/** Line count of PRELUDE_WGSL (the compilation-info formatter subtracts it plus the emitted declarations). */\nexport const PRELUDE_LINES: number = PRELUDE_WGSL.split(\"\\n\").length;\n\n/** The workgroup-memory reduction helpers (the twin) (4.3), plus the workgroup-memory form of the P8 scan helper. */\nexport const REDUCE_HELPERS_WORKGROUP_WGSL: string = /* wgsl */ `var<workgroup> wg_scratch_v: array<vec4f, WG>;\nvar<workgroup> wg_scratch_u: array<u32, WG>;\nfn combine_v(a: vec4f, b: vec4f, op: u32) -> vec4f {\n if (op == 1u) { return min(a, b); }\n if (op == 2u) { return max(a, b); }\n return a + b;\n}\nfn combine_u(a: u32, b: u32, op: u32) -> u32 {\n if (op == 1u) { return min(a, b); }\n if (op == 2u) { return max(a, b); }\n return a + b;\n}\nfn wg_reduce_vec4(v: vec4f, lid: u32, op: u32) -> vec4f {\n workgroupBarrier();\n wg_scratch_v[lid] = v;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (lid < s) { wg_scratch_v[lid] = combine_v(wg_scratch_v[lid], wg_scratch_v[lid + s], op); }\n workgroupBarrier();\n }\n let total = wg_scratch_v[0];\n workgroupBarrier();\n return total;\n}\nfn wg_reduce_u32(v: u32, lid: u32, op: u32) -> u32 {\n workgroupBarrier();\n wg_scratch_u[lid] = v;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (lid < s) { wg_scratch_u[lid] = combine_u(wg_scratch_u[lid], wg_scratch_u[lid + s], op); }\n workgroupBarrier();\n }\n let total = wg_scratch_u[0];\n workgroupBarrier();\n return total;\n}\nfn wg_scan_u32(v: u32, lid: u32) -> u32 {\n workgroupBarrier();\n wg_scratch_u[lid] = v;\n workgroupBarrier();\n for (var s = 1u; s < WG; s = s * 2u) { // Hillis-Steele inclusive scan (scan-block's body); uniform: every lane runs every round\n var t = 0u;\n if (lid >= s) { t = wg_scratch_u[lid - s]; }\n workgroupBarrier();\n wg_scratch_u[lid] = wg_scratch_u[lid] + t;\n workgroupBarrier();\n }\n let inclusive = wg_scratch_u[lid];\n workgroupBarrier(); // the scratch is free for the next call\n return inclusive;\n}\nfn wg_reduce_f32(v: f32, lid: u32, op: u32) -> f32 { return wg_reduce_vec4(vec4f(v, 0.0, 0.0, 0.0), lid, op).x; }`;\n\n/** The subgroup reduction helpers, spliced only with `enable subgroups;` (4.3), plus the subgroup form of the P8 scan helper. */\nexport const REDUCE_HELPERS_SUBGROUP_WGSL: string = /* wgsl */ `override SG_SLOTS: u32 = (WG + SUBGROUP_MIN - 1u) / SUBGROUP_MIN; // one slot per subgroup; the count is largest when the compiler picks the SMALLEST size\nvar<workgroup> sg_counter: atomic<u32>;\nvar<workgroup> sg_val_v: array<vec4f, SG_SLOTS>;\nvar<workgroup> sg_val_u: array<u32, SG_SLOTS>;\nvar<workgroup> sg_key: array<u32, SG_SLOTS>;\nvar<workgroup> sg_sorted_v: array<vec4f, SG_SLOTS>;\nvar<workgroup> sg_sorted_u: array<u32, SG_SLOTS>;\nfn combine_v(a: vec4f, b: vec4f, op: u32) -> vec4f {\n if (op == 1u) { return min(a, b); }\n if (op == 2u) { return max(a, b); }\n return a + b;\n}\nfn combine_u(a: u32, b: u32, op: u32) -> u32 {\n if (op == 1u) { return min(a, b); }\n if (op == 2u) { return max(a, b); }\n return a + b;\n}\nfn wg_reduce_vec4(v: vec4f, lid: u32, op: u32) -> vec4f {\n workgroupBarrier();\n if (lid == 0u) { atomicStore(&sg_counter, 0u); }\n workgroupBarrier();\n let s_add = subgroupAdd(v);\n let s_min = subgroupMin(v);\n let s_max = subgroupMax(v);\n var partial = s_add;\n if (op == 1u) { partial = s_min; }\n if (op == 2u) { partial = s_max; }\n let key = subgroupMin(lid); // the smallest local id of this subgroup: a stable identity without @builtin(subgroup_id)\n var slot = 0u;\n if (subgroupElect()) { slot = atomicAdd(&sg_counter, 1u); } // D16: the elected lane takes a slot from the counter\n slot = subgroupBroadcast(slot, 0u); // and broadcasts it (lane 0 is the elected lane in uniform control flow)\n if (subgroupElect()) { sg_val_v[slot] = partial; sg_key[slot] = key; }\n workgroupBarrier();\n let count = atomicLoad(&sg_counter);\n if (lid < count) { // rank the slots by key so the final sum has a fixed order (11.9 item 4)\n let mine = sg_key[lid];\n var rank = 0u;\n for (var k = 0u; k < count; k = k + 1u) { if (sg_key[k] < mine) { rank = rank + 1u; } }\n sg_sorted_v[rank] = sg_val_v[lid];\n }\n workgroupBarrier();\n var total = sg_sorted_v[0];\n for (var k = 1u; k < count; k = k + 1u) { total = combine_v(total, sg_sorted_v[k], op); }\n workgroupBarrier();\n return total;\n}\nfn wg_reduce_u32(v: u32, lid: u32, op: u32) -> u32 {\n workgroupBarrier();\n if (lid == 0u) { atomicStore(&sg_counter, 0u); }\n workgroupBarrier();\n let s_add = subgroupAdd(v);\n let s_min = subgroupMin(v);\n let s_max = subgroupMax(v);\n var partial = s_add;\n if (op == 1u) { partial = s_min; }\n if (op == 2u) { partial = s_max; }\n let key = subgroupMin(lid);\n var slot = 0u;\n if (subgroupElect()) { slot = atomicAdd(&sg_counter, 1u); }\n slot = subgroupBroadcast(slot, 0u);\n if (subgroupElect()) { sg_val_u[slot] = partial; sg_key[slot] = key; }\n workgroupBarrier();\n let count = atomicLoad(&sg_counter);\n if (lid < count) {\n let mine = sg_key[lid];\n var rank = 0u;\n for (var k = 0u; k < count; k = k + 1u) { if (sg_key[k] < mine) { rank = rank + 1u; } }\n sg_sorted_u[rank] = sg_val_u[lid];\n }\n workgroupBarrier();\n var total = sg_sorted_u[0];\n for (var k = 1u; k < count; k = k + 1u) { total = combine_u(total, sg_sorted_u[k], op); }\n workgroupBarrier();\n return total;\n}\nfn wg_scan_u32(v: u32, lid: u32) -> u32 {\n workgroupBarrier();\n if (lid == 0u) { atomicStore(&sg_counter, 0u); }\n workgroupBarrier();\n let inSub = subgroupExclusiveAdd(v) + v; // the lane's inclusive sum within its subgroup\n let total = subgroupAdd(v);\n let key = subgroupMin(lid); // the subgroup's identity: its smallest local id (D16)\n var slot = 0u;\n if (subgroupElect()) { slot = atomicAdd(&sg_counter, 1u); }\n slot = subgroupBroadcast(slot, 0u);\n if (subgroupElect()) { sg_val_u[slot] = total; sg_key[slot] = key; }\n workgroupBarrier();\n let count = atomicLoad(&sg_counter);\n var carry = 0u; // the totals of every subgroup whose key is below this lane's: LANE order, whatever order the slots were taken in\n for (var k = 0u; k < count; k = k + 1u) { if (sg_key[k] < key) { carry = carry + sg_val_u[k]; } }\n workgroupBarrier(); // the slots are free for the next call\n return inSub + carry;\n}\nfn wg_reduce_f32(v: f32, lid: u32, op: u32) -> f32 { return wg_reduce_vec4(vec4f(v, 0.0, 0.0, 0.0), lid, op).x; }`;\n\n/** The helper function names a body may call when its spec lists needs: [\"subgroups\"]; `wg_scan_u32(v, lid)` is an INCLUSIVE prefix sum over the workgroup in lane order (P8-T1), bitwise the same in both forms. */\nexport const REDUCE_HELPER_NAMES = [\"wg_reduce_f32\", \"wg_reduce_u32\", \"wg_reduce_vec4\", \"wg_scan_u32\"] as const;\n\n/**\n * The WGSL reserved words of spec section 16.2 (the `_reserved` production), frozen; composeWgsl rejects a body or\n * snippet that uses one (3.9). PLAN DECISION: the list is the 146 words of the W3C Candidate Recommendation Draft\n * of 2026-08-31 (identical to the editor's draft of 2026-09-01); the contract's count of 147 predates the removal\n * of `binding_array`. `free`, `valid`, `tile`, `slot`, `key` and `count` are NOT reserved.\n */\nexport const WGSL_RESERVED_WORDS: readonly string[] = Object.freeze(\n `NULL Self abstract active alignas alignof as asm asm_fragment async attribute auto await become cast catch class\n co_await co_return co_yield coherent column_major common compile compile_fragment concept const_cast consteval\n constexpr constinit crate debugger decltype delete demote demote_to_helper do dynamic_cast enum explicit export\n extends extern external fallthrough filter final finally friend from fxgroup get goto groupshared highp impl\n implements import inline instanceof interface layout lowp macro macro_rules match mediump meta mod module move\n mut mutable namespace new nil noexcept noinline nointerpolation non_coherent noncoherent noperspective null\n nullptr of operator package packoffset partition pass patch pixelfragment precise precision premerge priv\n protected pub public readonly ref regardless register reinterpret_cast require resource restrict self set shared\n sizeof smooth snorm static static_assert static_cast std subroutine super target template this thread_local\n throw trait try type typedef typeid typename typeof union unless unorm unsafe unsized use using varying virtual\n volatile wgsl where with writeonly yield`\n .trim()\n .split(/\\s+/),\n);\n","/**\n * The WGSL composer (spec 3.5; contract 3.9, 4.2): ONE declaration per module (`WgslModuleSpec`) generates\n * everything the host and the shader must agree on -- the `@group / @binding` block, the `override` lines, the\n * struct texts, the explicit bind-group layouts and the bind() record keys -- by string concatenation in the fixed\n * order of contract 4.2. Every disagreement that would otherwise be a GPUPipelineError on the first device that\n * creates the variant is a compose-time `E_SHADER_COMPILE { stage: \"compose\" }` on every device.\n *\n * PLAN DECISION: this file imports `workgroupSizeFor` from `../device/caps.js` (one copy of the WG rule) and\n * `ShaderStage` from `../device/webgpu-constants.js` (spec 2.1 rule 1: the core never reads the `GPUShaderStage`\n * global at module top level); `../constants.js` is not imported because every constant the composer emits reaches\n * it through `./prelude.js`. The layer rule (contract 2.4: device < context < memory < kernel) allows both edges.\n */\n\nimport { workgroupSizeFor } from \"../device/caps.js\";\nimport { ShaderStage } from \"../device/webgpu-constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type PlanCaps } from \"../types/context.js\";\nimport {\n PRELUDE_WGSL,\n REDUCE_HELPER_NAMES,\n REDUCE_HELPERS_SUBGROUP_WGSL,\n REDUCE_HELPERS_WORKGROUP_WGSL,\n WGSL_RESERVED_WORDS,\n wgslF32Literal,\n} from \"./prelude.js\";\nimport { type UniformBlock } from \"./struct-block.js\";\n\n/** One storage or uniform binding of a module (spec 3.5). `wgslType` is the element / struct type text (\"array<u32>\", \"array<vec4f>\", \"Fa2State\"). */\nexport interface BindingDecl {\n readonly group: 0 | 1 | 2 | 3;\n readonly binding: number;\n readonly name: string;\n readonly kind: \"storage\" | \"storage-ro\" | \"uniform\";\n readonly wgslType: string;\n}\n/** One module-specific override (spec 3.5); the five standard ones (WG, USE_PERM, HAS_WEIGHTS, SUBGROUP_MIN, SUBGROUP_MAX) come from the prelude and are never listed here. */\nexport interface OverrideDecl {\n readonly name: string;\n readonly type: \"u32\" | \"bool\" | \"f32\";\n readonly default: number | boolean;\n}\n/** Spec 3.5 WgslModuleSpec, verbatim. `needs: [\"subgroups\"]` means \"this body calls a wg_reduce_* helper\": the composer splices the subgroup helper block when the device has the feature and the workgroup-memory twin otherwise. */\nexport interface WgslModuleSpec {\n readonly id: string;\n readonly body: string;\n readonly bindings: readonly BindingDecl[];\n readonly overrideDecls: readonly OverrideDecl[];\n readonly overrides: Readonly<Record<string, number | boolean>>;\n readonly needs: readonly \"subgroups\"[];\n readonly uniforms: readonly UniformBlock[];\n readonly snippets?: Readonly<Record<string, string>> | undefined;\n}\n/** The names the prelude declares as overrides; spec.overrides may set them without an OverrideDecl. */\nexport const STANDARD_OVERRIDES = [\"WG\", \"USE_PERM\", \"HAS_WEIGHTS\", \"SUBGROUP_MIN\", \"SUBGROUP_MAX\"] as const;\n/** What composeWgsl returns: the text, the body's first line in it (for compilation-info formatting), the effective overrides (WG, SUBGROUP_MIN, SUBGROUP_MAX filled) and the features to enable. */\nexport interface ComposedModule {\n readonly id: string;\n readonly code: string;\n readonly bodyLine: number;\n readonly overrides: Readonly<Record<string, number | boolean>>;\n /**\n * The subset of `overrides` the composed code REFERENCES outside its own declaration -- what the pipeline\n * descriptor's `constants` carries. WebKit (Safari) fails pipeline creation with \"Compute library failed\n * creation\" when a constant is supplied for an override the entry point never reads (HAS_WEIGHTS in `degree`,\n * TIER in the thread-per-row tiers); Dawn tolerates it. The cache key still uses `overrides` (contract 3.9).\n */\n readonly constants: Readonly<Record<string, number | boolean>>;\n readonly entryPoint: string;\n readonly subgroups: boolean;\n}\n\n/** The type of each standard override (the prelude's declarations). */\nconst STANDARD_OVERRIDE_TYPES: Readonly<Record<(typeof STANDARD_OVERRIDES)[number], OverrideDecl[\"type\"]>> =\n Object.freeze({\n WG: \"u32\",\n USE_PERM: \"bool\",\n HAS_WEIGHTS: \"bool\",\n SUBGROUP_MIN: \"u32\",\n SUBGROUP_MAX: \"u32\",\n });\n/** The only feature a body may need (spec 3.5). */\nconst KNOWN_NEEDS: readonly string[] = Object.freeze([\"subgroups\"]);\n/** The smallest legal subgroup size; the scratch of 4.3 is sized by the MINIMUM size. */\nconst SUBGROUP_FLOOR = 4;\n/** Builtin WGSL element types a binding may name without a struct declaration. */\nconst BUILTIN_TYPES: ReadonlySet<string> = new Set([\n \"u32\",\n \"i32\",\n \"f32\",\n \"f16\",\n \"bool\",\n \"vec2f\",\n \"vec3f\",\n \"vec4f\",\n \"vec2u\",\n \"vec3u\",\n \"vec4u\",\n \"vec2i\",\n \"vec3i\",\n \"vec4i\",\n \"vec2h\",\n \"vec3h\",\n \"vec4h\",\n]);\nconst TEMPLATED_BUILTIN = /^(vec[234]|mat[234]x[234]|atomic|array)</;\nconst IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;\n/** The `var<...>` form of each binding kind (contract 4.2). */\nconst ADDRESS_SPACE: Readonly<Record<BindingDecl[\"kind\"], string>> = Object.freeze({\n storage: \"var<storage, read_write>\",\n \"storage-ro\": \"var<storage, read>\",\n uniform: \"var<uniform>\",\n});\n/** The reserved words as a set (the frozen list stays the public form). */\nconst RESERVED: ReadonlySet<string> = new Set(WGSL_RESERVED_WORDS);\nconst MARKER = /\\/\\/@@([A-Za-z0-9_]+)@@/;\nconst IDENTIFIER_TOKENS = /(?<![A-Za-z0-9_])[A-Za-z_][A-Za-z0-9_]*/g;\nconst COMPUTE_ATTRIBUTE = /@compute\\b/g;\nconst ENTRY_FN = /\\bfn\\s+([A-Za-z_][A-Za-z0-9_]*)/;\n\n/**\n * The compose-time error of contract 3.9.\n * @param id - the module id\n * @param slot - what failed (`override:<key>`, `snippet:<key>`, `marker:<name>`, `body:<text>`, `binding:<name>`, `type:<name>`, `needs:<feature>`, `helper:<name>`, `reserved:<word>`, `entry`)\n * @param message - the human-readable reason\n * @returns the error (thrown by the caller)\n */\nfunction composeError(id: string, slot: string, message: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_SHADER_COMPILE\", `${id}: ${message}`, { id, stage: \"compose\", slot });\n}\n\n/**\n * Removes block and line comments so a word inside a comment is never taken for an identifier.\n * @param text - WGSL text\n * @returns the text without comments\n */\nfunction stripComments(text: string): string {\n return text.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/\\/\\/[^\\n]*/g, \"\");\n}\n\n/**\n * The struct a binding's element type names, or null for a builtin type.\n * @param wgslType - the binding's type text (\"array<u32>\", \"array<Fa2Partial>\", \"Fa2State\")\n * @returns the struct name or null\n */\nfunction structNameOf(wgslType: string): string | null {\n const trimmed = wgslType.trim();\n const inner = trimmed.startsWith(\"array<\")\n ? trimmed.slice(\"array<\".length).replace(/\\s*(,[^>]*)?>\\s*$/, \"\")\n : trimmed;\n if (BUILTIN_TYPES.has(inner) || TEMPLATED_BUILTIN.test(inner)) {\n return null;\n }\n return inner;\n}\n\n/**\n * Checks that an override value matches its declared type.\n * PLAN DECISION: a value of the wrong type (a number for a bool, a bool / negative / fractional for a u32) is a\n * compose-time `E_SHADER_COMPILE { slot: \"override:<name>\" }` instead of a GPUPipelineError on the first device.\n * @param id - the module id\n * @param name - the override name\n * @param type - the declared type\n * @param value - the value\n */\nfunction assertOverrideValue(id: string, name: string, type: OverrideDecl[\"type\"], value: number | boolean): void {\n const ok =\n type === \"bool\"\n ? typeof value === \"boolean\"\n : typeof value === \"number\" &&\n Number.isFinite(value) &&\n (type === \"f32\" || (Number.isInteger(value) && value >= 0));\n if (!ok) {\n throw composeError(id, `override:${name}`, `override ${name} (${type}) cannot take the value ${String(value)}`);\n }\n}\n\n/**\n * The WGSL literal of an override default (u32 literals carry the `u` suffix, f32 literals a decimal point, bools true / false).\n * @param decl - the override\n * @returns the literal text\n */\nfunction overrideLiteral(decl: OverrideDecl): string {\n if (decl.type === \"bool\") {\n return decl.default ? \"true\" : \"false\";\n }\n const value = decl.default as number;\n return decl.type === \"u32\" ? `${value}u` : wgslF32Literal(value);\n}\n\n/**\n * The `var<...>` declaration of one binding (contract 4.2).\n * @param decl - the binding\n * @returns the declaration line\n */\nfunction bindingLine(decl: BindingDecl): string {\n const space = ADDRESS_SPACE[decl.kind];\n return `@group(${decl.group}) @binding(${decl.binding}) ${space} ${decl.name}: ${decl.wgslType};`;\n}\n\n/**\n * The entry-point name of a body, or null when the body does not carry exactly one `@compute` attribute followed by `fn <name>`.\n * @param body - the kernel body\n * @returns the name or null\n */\nfunction findEntryPoint(body: string): string | null {\n const stripped = stripComments(body);\n const matches = [...stripped.matchAll(COMPUTE_ATTRIBUTE)];\n if (matches.length !== 1 || matches[0].index === undefined) {\n return null;\n }\n const fn = ENTRY_FN.exec(stripped.slice(matches[0].index));\n return fn === null ? null : fn[1];\n}\n\n/**\n * The entry-point name of a body: the identifier after `fn` on the line following `@compute` (every body has exactly one entry point).\n * PLAN DECISION: a body without exactly one `@compute` entry point is `E_SHADER_COMPILE { stage: \"compose\", slot: \"entry\" }`.\n * @param body - the kernel body\n * @returns the entry-point function name\n */\nexport function entryPointOf(body: string): string {\n const name = findEntryPoint(body);\n if (name === null) {\n throw new WebGpuGraphError(\n \"E_SHADER_COMPILE\",\n \"a body must carry exactly one @compute attribute followed by `fn <name>`\",\n {\n id: null,\n stage: \"compose\",\n slot: \"entry\",\n },\n );\n }\n return name;\n}\n\n/**\n * The bind-group-layout descriptors derived from spec.bindings: one per group 0..maxGroup (empty groups get an empty entry list); uniform decls carry hasDynamicOffset true (spec 5.1).\n * PLAN DECISION: a uniform decl whose struct is one of `spec.uniforms` also carries `minBindingSize = block.byteLength`,\n * so a wrong-size uniform binding fails at createBindGroup (synchronously, with the bind group's label in the message)\n * instead of at the first dispatch (verified on Dawn 0.4.0: without it the error names only the pipeline).\n * @param spec - the module\n * @returns the descriptors in group order\n */\nexport function bindGroupLayoutDescriptors(spec: WgslModuleSpec): GPUBindGroupLayoutDescriptor[] {\n const maxGroup = spec.bindings.reduce((acc, b) => Math.max(acc, b.group), -1);\n const blocks = new Map(spec.uniforms.map((block) => [block.name, block] as const));\n const descriptors: GPUBindGroupLayoutDescriptor[] = [];\n for (let group = 0; group <= maxGroup; group++) {\n const entries: GPUBindGroupLayoutEntry[] = spec.bindings\n .filter((b) => b.group === group)\n .sort((a, b) => a.binding - b.binding)\n .map((b) => {\n if (b.kind === \"uniform\") {\n const block = blocks.get(b.wgslType);\n const buffer: GPUBufferBindingLayout = { type: \"uniform\", hasDynamicOffset: true };\n if (block !== undefined) {\n buffer.minBindingSize = block.byteLength;\n }\n return { binding: b.binding, visibility: ShaderStage.COMPUTE, buffer };\n }\n return {\n binding: b.binding,\n visibility: ShaderStage.COMPUTE,\n buffer: { type: b.kind === \"storage\" ? \"storage\" : \"read-only-storage\" },\n };\n });\n descriptors.push({ entries });\n }\n return descriptors;\n}\n\n/**\n * The names of the bindings of one group in binding order.\n * @param spec - the module\n * @param group - the group index\n * @returns the names\n */\nexport function bindingNames(spec: WgslModuleSpec, group: number): readonly string[] {\n return spec.bindings\n .filter((b) => b.group === group)\n .sort((a, b) => a.binding - b.binding)\n .map((b) => b.name);\n}\n\n/**\n * Validates `spec.needs`, `spec.overrideDecls`, `spec.overrides` and `spec.bindings` (contract 3.9's compose-time checks).\n * PLAN DECISION: an `overrideDecls` entry that redeclares a standard override, repeats a name or names a reserved\n * word is `E_SHADER_COMPILE { slot: \"override:<name>\" }` (otherwise a duplicate-declaration error on the first device).\n * @param spec - the module\n */\nfunction validateDeclarations(spec: WgslModuleSpec): void {\n const { id } = spec;\n for (const need of spec.needs) {\n if (!KNOWN_NEEDS.includes(need)) {\n throw composeError(id, `needs:${need}`, `unknown feature \"${need}\" in needs`);\n }\n }\n const declared = new Map<string, OverrideDecl[\"type\"]>();\n for (const decl of spec.overrideDecls) {\n if (!IDENTIFIER.test(decl.name) || RESERVED.has(decl.name)) {\n throw composeError(id, `override:${decl.name}`, `override name \"${decl.name}\" is not a usable identifier`);\n }\n if ((STANDARD_OVERRIDES as readonly string[]).includes(decl.name) || declared.has(decl.name)) {\n throw composeError(\n id,\n `override:${decl.name}`,\n `override \"${decl.name}\" is declared twice (the prelude declares the standard ones)`,\n );\n }\n assertOverrideValue(id, decl.name, decl.type, decl.default);\n declared.set(decl.name, decl.type);\n }\n for (const [key, value] of Object.entries(spec.overrides)) {\n const standard = (STANDARD_OVERRIDE_TYPES as Readonly<Record<string, OverrideDecl[\"type\"] | undefined>>)[key];\n const type = standard ?? declared.get(key);\n if (type === undefined) {\n throw composeError(\n id,\n `override:${key}`,\n `override \"${key}\" is neither a standard override nor declared in overrideDecls`,\n );\n }\n assertOverrideValue(id, key, type, value);\n }\n const slots = new Set<string>();\n const names = new Set<string>();\n const blocks = new Set(spec.uniforms.map((block) => block.name));\n for (const b of spec.bindings) {\n if (!IDENTIFIER.test(b.name) || RESERVED.has(b.name)) {\n throw composeError(id, `binding:${b.name}`, `binding name \"${b.name}\" is not a usable identifier`);\n }\n const slot = `${b.group}.${b.binding}`;\n if (slots.has(slot)) {\n throw composeError(id, `binding:${b.name}`, `two bindings share group ${b.group} binding ${b.binding}`);\n }\n if (names.has(b.name)) {\n throw composeError(id, `binding:${b.name}`, `two bindings share the name \"${b.name}\"`);\n }\n slots.add(slot);\n names.add(b.name);\n const struct = structNameOf(b.wgslType);\n if (struct !== null && !blocks.has(struct)) {\n throw composeError(\n id,\n `type:${struct}`,\n `binding \"${b.name}\" names struct \"${struct}\" but no block in spec.uniforms declares it`,\n );\n }\n }\n}\n\n/**\n * Substitutes the snippets into the body (every `//@@NAME@@` marker replaced by `spec.snippets[NAME]`) and checks the markers.\n * @param spec - the module\n * @returns the substituted body\n */\nfunction substituteSnippets(spec: WgslModuleSpec): string {\n const { id } = spec;\n let { body } = spec;\n for (const [key, snippet] of Object.entries(spec.snippets ?? {})) {\n const marker = `//@@${key}@@`;\n if (!body.includes(marker)) {\n throw composeError(id, `snippet:${key}`, `snippet \"${key}\" has no ${marker} marker in the body`);\n }\n body = body.split(marker).join(snippet);\n }\n const left = MARKER.exec(body);\n if (left !== null) {\n throw composeError(id, `marker:${left[1]}`, `marker //@@${left[1]}@@ is not filled by any snippet`);\n }\n return body;\n}\n\n/**\n * The textual checks on the substituted body: no `@group(`, no `override `, no reserved identifier, no helper call without `needs`.\n * PLAN DECISION: a body calling a `wg_reduce_*` helper without `needs: [\"subgroups\"]` is\n * `E_SHADER_COMPILE { slot: \"helper:<name>\" }` (otherwise an unresolved identifier on the first device).\n * @param spec - the module\n * @param body - the substituted body\n */\nfunction validateBody(spec: WgslModuleSpec, body: string): void {\n const { id } = spec;\n for (const forbidden of [\"@group(\", \"override \"]) {\n if (body.includes(forbidden)) {\n throw composeError(\n id,\n `body:${forbidden}`,\n `a body must not contain \"${forbidden}\" (the composer emits those lines)`,\n );\n }\n }\n const stripped = stripComments(body);\n const helpers = REDUCE_HELPER_NAMES as readonly string[];\n for (const match of stripped.matchAll(IDENTIFIER_TOKENS)) {\n const word = match[0];\n if (RESERVED.has(word)) {\n throw composeError(\n id,\n `reserved:${word}`,\n `\"${word}\" is a WGSL reserved word (spec 16.2) and cannot be an identifier`,\n );\n }\n if (helpers.includes(word) && !spec.needs.includes(\"subgroups\")) {\n throw composeError(id, `helper:${word}`, `the body calls ${word} but spec.needs does not list \"subgroups\"`);\n }\n }\n}\n\n/**\n * String concatenation of spec 3.5: prelude (constants, standard overrides, helpers), module overrides, struct texts, the bind declarations, then the body with snippets substituted (4.2 gives the exact emitted format).\n * @param spec - the module\n * @param caps - the device capabilities (WG, the subgroup sizes and the feature set)\n * @returns the composed module\n */\nexport function composeWgsl(spec: WgslModuleSpec, caps: PlanCaps): ComposedModule {\n validateDeclarations(spec);\n const entryPoint = findEntryPoint(spec.body);\n if (entryPoint === null) {\n throw composeError(\n spec.id,\n \"entry\",\n \"a body must carry exactly one @compute attribute followed by `fn <name>`\",\n );\n }\n const body = substituteSnippets(spec);\n validateBody(spec, body);\n const wantsHelpers = spec.needs.includes(\"subgroups\");\n const subgroups = wantsHelpers && caps.features.has(\"subgroups\");\n const overrides: Record<string, number | boolean> = { ...spec.overrides };\n if (overrides.WG === undefined) {\n overrides.WG = workgroupSizeFor(caps);\n }\n if (subgroups) {\n overrides.SUBGROUP_MAX = caps.subgroupMaxSize;\n overrides.SUBGROUP_MIN = Math.max(SUBGROUP_FLOOR, caps.subgroupMinSize);\n }\n const parts: string[] = [];\n if (subgroups) {\n parts.push(\"enable subgroups;\");\n }\n parts.push(PRELUDE_WGSL);\n for (const decl of spec.overrideDecls) {\n parts.push(`override ${decl.name}: ${decl.type} = ${overrideLiteral(decl)};`);\n }\n for (const block of spec.uniforms) {\n parts.push(block.wgsl);\n }\n if (wantsHelpers) {\n parts.push(subgroups ? REDUCE_HELPERS_SUBGROUP_WGSL : REDUCE_HELPERS_WORKGROUP_WGSL);\n }\n for (const decl of spec.bindings) {\n parts.push(bindingLine(decl));\n }\n const head = parts.join(\"\\n\");\n const code = `${head}\\n${body}`;\n return Object.freeze({\n id: spec.id,\n code,\n bodyLine: head.split(\"\\n\").length + 1,\n overrides: Object.freeze(overrides),\n constants: Object.freeze(referencedOverrides(code, overrides)),\n entryPoint,\n subgroups,\n });\n}\n\n/**\n * The overrides whose names occur in the code outside comments and outside their own `override` declaration lines\n * (the constants a pipeline may carry on every backend, see ComposedModule.constants).\n * @param code - the composed module text\n * @param overrides - the effective override values\n * @returns the referenced subset, in the same order\n */\nfunction referencedOverrides(\n code: string,\n overrides: Readonly<Record<string, number | boolean>>,\n): Record<string, number | boolean> {\n const stripped = code\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \")\n .replace(/\\/\\/[^\\n]*/g, \" \")\n .replace(/^\\s*override\\s+\\w+\\s*:[^\\n]*$/gm, \" \");\n const referenced: Record<string, number | boolean> = {};\n for (const [name, value] of Object.entries(overrides)) {\n if (new RegExp(`\\\\b${name}\\\\b`).test(stripped)) {\n referenced[name] = value;\n }\n }\n return referenced;\n}\n","/**\n * PipelineCache (spec 5.1; contract 3.9): compile-once compute pipelines keyed by\n * `(id, overrides, needs present on the device, snippets)` with EXPLICIT bind-group layouts derived from\n * `spec.bindings` (never `layout: \"auto\"`, so one layout serves every dummy-binding variant and bind groups are\n * reused across variants). A WGSL error is `E_SHADER_COMPILE { stage: \"compile\", messages, lines }` with\n * body-relative line numbers; a pipeline error that is not a compilation message (an oversized workgroup, an\n * invalid layout) is `E_VALIDATION`.\n */\n\nimport { formatCompilationInfo } from \"../device/error-scope.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type PlanCaps } from \"../types/context.js\";\nimport { Kernel } from \"./kernel.js\";\nimport { bindGroupLayoutDescriptors, type ComposedModule, composeWgsl, type WgslModuleSpec } from \"./wgsl.js\";\n\n/** One cached entry: the pipeline, its layouts and the Kernel built on them. */\ninterface CacheEntry {\n readonly key: string;\n readonly composed: ComposedModule;\n readonly pipeline: GPUComputePipeline;\n readonly layouts: readonly GPUBindGroupLayout[];\n readonly kernel: Kernel;\n}\n\n/**\n * JSON with the keys of every (nested) object sorted, so two override records with the same content give one key.\n * @param value - a JSON-compatible value\n * @returns the canonical text\n */\nfunction stableJson(value: unknown): string {\n if (Array.isArray(value)) {\n return `[${value.map((item: unknown) => stableJson(item)).join(\",\")}]`;\n }\n if (typeof value === \"object\" && value !== null) {\n const record = value as Record<string, unknown>;\n const keys = Object.keys(record).sort();\n return `{${keys.map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`).join(\",\")}}`;\n }\n return JSON.stringify(value);\n}\n\n/**\n * FNV-1a (32-bit) of a text as 8 hex digits; \"0\" for an absent or empty snippet record. Hashes text, never an arc\n * index or a byte offset, so the bitwise operators are within the house rule.\n * @param snippets - the snippet record\n * @returns the hash text\n */\nfunction hashSnippets(snippets: Readonly<Record<string, string>> | undefined): string {\n if (snippets === undefined || Object.keys(snippets).length === 0) {\n return \"0\";\n }\n const text = stableJson(snippets);\n let hash = 0x811c9dc5;\n for (let i = 0; i < text.length; i++) {\n hash ^= text.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193) >>> 0;\n }\n return hash.toString(16).padStart(8, \"0\");\n}\n\n/**\n * The cache key of a spec on a device (pure; PLAN DECISION: exported so the override-matrix helper of P2-T2 can\n * compute keys without a device): `id + \"|\" + stableJson(overrides) + \"|\" + needs.filter(present).join(\",\") + \"|\" + hash(snippets)`.\n * @param spec - the module\n * @param caps - the device capabilities (the feature set decides which needs are present)\n * @returns the key\n */\nexport function pipelineKey(spec: WgslModuleSpec, caps: PlanCaps): string {\n const present = spec.needs.filter((need) => caps.features.has(need)).join(\",\");\n return `${spec.id}|${stableJson(spec.overrides)}|${present}|${hashSnippets(spec.snippets)}`;\n}\n\n/**\n * The message of an unknown error value.\n * @param err - the thrown value\n * @returns its message text\n */\nfunction messageOf(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/** Compile-once pipelines keyed by (id, overrides, needs present on the device, snippets) with explicit bind-group layouts (spec 5.1). */\nexport class PipelineCache {\n private readonly device: GPUDevice;\n private readonly caps: PlanCaps;\n /** In-flight and finished compiles by key (a promise, so two concurrent get() calls share one compile). */\n private readonly pending = new Map<string, Promise<CacheEntry>>();\n /** Finished compiles by key. */\n private readonly entries = new Map<string, CacheEntry>();\n /** Keys in the order their compiles were started (a failed compile is removed again). */\n private readonly order: string[] = [];\n private disposed = false;\n\n /**\n * Builds a cache over a device.\n * @param device - the device pipelines are created on\n * @param caps - its capabilities (WG, subgroup sizes, features)\n */\n constructor(device: GPUDevice, caps: PlanCaps) {\n this.device = device;\n this.caps = caps;\n }\n\n /**\n * The cache key of a spec on this device: `id + \"|\" + stableJson(overrides) + \"|\" + needs.filter(present).join(\",\") + \"|\" + hash(snippets)`.\n * @param spec - the module\n * @returns the key\n */\n key(spec: WgslModuleSpec): string {\n return pipelineKey(spec, this.caps);\n }\n\n /**\n * createComputePipelineAsync inside a validation scope with the layouts derived from spec.bindings; compilation messages become E_SHADER_COMPILE { id, stage: \"compile\", messages } with body-relative lines.\n * @param spec - the module\n * @returns the pipeline (the same object for the same key)\n */\n async get(spec: WgslModuleSpec): Promise<GPUComputePipeline> {\n return (await this.entry(spec)).pipeline;\n }\n\n /**\n * The Kernel (pipeline + layouts + binding names) for a spec; cached with the pipeline.\n * @param spec - the module\n * @returns the kernel (the same object for the same key)\n */\n async kernel(spec: WgslModuleSpec): Promise<Kernel> {\n return (await this.entry(spec)).kernel;\n }\n\n /**\n * Compiles every spec not yet cached (load() calls it so the first step() does not compile).\n * @param specs - the modules\n */\n async warm(specs: readonly WgslModuleSpec[]): Promise<void> {\n await Promise.all(specs.map((spec) => this.entry(spec)));\n }\n\n /**\n * Number of cached pipelines.\n * @returns the count of finished compiles\n */\n get size(): number {\n return this.entries.size;\n }\n\n /**\n * Every key created so far, in creation order (the override-matrix coverage test reads it).\n * PLAN DECISION: keys are listed in compile-START order and only those whose compile finished (warm() compiles\n * concurrently, so completion order is not deterministic; a failed compile is removed).\n * @returns the keys\n * @internal\n */\n keys(): readonly string[] {\n return this.order.filter((key) => this.entries.has(key));\n }\n\n /**\n * The bind-group layouts of a cached kernel by key.\n * @param key - a key from keys()\n * @returns the layouts, or null when the key is not cached\n * @internal\n */\n layoutsOf(key: string): readonly GPUBindGroupLayout[] | null {\n return this.entries.get(key)?.layouts ?? null;\n }\n\n /**\n * PLAN DECISION: forgets every pipeline and refuses further compiles with E_DISPOSED (the context's dispose()\n * may call it; a GPUComputePipeline has no destroy(), so the objects are simply released).\n */\n dispose(): void {\n this.disposed = true;\n this.pending.clear();\n this.entries.clear();\n this.order.length = 0;\n }\n\n /**\n * The cached entry of a spec, compiling it once per key.\n * @param spec - the module\n * @returns the entry\n */\n private entry(spec: WgslModuleSpec): Promise<CacheEntry> {\n if (this.disposed) {\n return Promise.reject(\n new WebGpuGraphError(\"E_DISPOSED\", \"PipelineCache: disposed\", { label: \"PipelineCache\" }),\n );\n }\n const key = this.key(spec);\n const inFlight = this.pending.get(key);\n if (inFlight !== undefined) {\n return inFlight;\n }\n this.order.push(key);\n const compile = this.compile(spec, key).then(\n (entry) => {\n if (!this.disposed) {\n this.entries.set(key, entry);\n }\n return entry;\n },\n (err: unknown) => {\n this.pending.delete(key);\n const at = this.order.indexOf(key);\n if (at >= 0) {\n this.order.splice(at, 1);\n }\n throw err;\n },\n );\n this.pending.set(key, compile);\n return compile;\n }\n\n /**\n * One compile: compose, create the shader module inside a synchronous push / pop validation pair (so concurrent\n * compiles never interleave scopes), check the compilation info, create the layouts and the pipeline.\n * PLAN DECISION: `E_SHADER_COMPILE` at stage \"compile\" also carries `lines` (the body-relative 1-based line of every\n * error message, from `composed.bodyLine`) next to the contract's `messages`; a `createComputePipelineAsync`\n * rejection (a GPUPipelineError, which pushes nothing into a validation scope on Dawn 0.4.0) is\n * `E_VALIDATION { label: \"<id>|pipeline\", message }`; bool overrides travel as the pipeline constants 1 / 0\n * because dawn.node's WebIDL layer rejects a boolean constant.\n * @param spec - the module\n * @param key - its key (the pipeline label)\n * @returns the entry\n */\n private async compile(spec: WgslModuleSpec, key: string): Promise<CacheEntry> {\n const composed = composeWgsl(spec, this.caps);\n const { device } = this;\n const label = `${spec.id}|pipeline`;\n device.pushErrorScope(\"validation\");\n const module = device.createShaderModule({ code: composed.code, label: spec.id });\n const layouts = bindGroupLayoutDescriptors(spec).map((descriptor, group) =>\n device.createBindGroupLayout({ ...descriptor, label: `${spec.id}/layout${group}` }),\n );\n const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: layouts, label: `${spec.id}|layout` });\n const popped = device.popErrorScope();\n const info = await module.getCompilationInfo();\n const scopeError = await popped;\n const errors = info.messages.filter((message) => message.type === \"error\");\n if (errors.length > 0) {\n const preludeLines = composed.bodyLine - 1;\n throw new WebGpuGraphError(\n \"E_SHADER_COMPILE\",\n `${spec.id}: WGSL compilation failed (${errors.length} error(s))`,\n {\n id: spec.id,\n stage: \"compile\",\n messages: formatCompilationInfo(info, preludeLines),\n lines: errors.map((message) => message.lineNum - preludeLines),\n },\n );\n }\n if (scopeError !== null) {\n throw new WebGpuGraphError(\"E_VALIDATION\", `${spec.id}: ${scopeError.message}`, {\n label,\n message: scopeError.message,\n });\n }\n // dawn.node's WebIDL layer rejects a boolean pipeline constant (\"value is not a number\"), so bools travel as 1 / 0;\n // only the REFERENCED overrides are supplied (composed.constants): WebKit rejects a constant for an unread override\n const constants: Record<string, number> = {};\n for (const [name, value] of Object.entries(composed.constants)) {\n if (typeof value === \"boolean\") {\n constants[name] = value ? 1 : 0;\n } else {\n constants[name] = value;\n }\n }\n let pipeline: GPUComputePipeline;\n try {\n pipeline = await device.createComputePipelineAsync({\n label: key,\n layout: pipelineLayout,\n compute: { module, entryPoint: composed.entryPoint, constants },\n });\n } catch (err: unknown) {\n const message = messageOf(err);\n throw new WebGpuGraphError(\"E_VALIDATION\", `${spec.id}: pipeline creation failed: ${message}`, {\n label,\n message,\n });\n }\n const kernel = new Kernel(device, spec, composed, pipeline, layouts);\n return { key, composed, pipeline, layouts, kernel };\n }\n}\n","/**\n * Timestamp profiling of spec 5.5: when \"timestamp-query\" was granted the context owns a Profiler\n * whose query set (PROFILER_QUERY_SLOTS slots, two per pass) is written by the timestampWrites of\n * every CommandBatch pass; `resolveInto(batch)` records the resolve plus a copy into the batch's\n * staging slot and `timings(bytes, request)` decodes `{ label, ns }` per pass from the batch's\n * readback bytes. Chromium quantises timestamps to 100 us (`quantised: true`); Dawn-node reports\n * 1,024 ns ticks (spec 2.6). The profiler never throws: a full query set drops the timings of the\n * passes past the budget and marks the batch's request `partial(request)` so a caller summing the\n * rows into a duration falls back to wall time; a device without the feature disables it. Slot\n * pairs are handed out in order and the cursor restarts at 0\n * after every resolve: queue order guarantees the resolve of batch A reads its slots before batch B\n * overwrites them, and one resolve buffer suffices for the same reason.\n */\n\nimport { PROFILER_QUERY_SLOTS } from \"../constants.js\";\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport type { CommandBatch, ReadbackRequest } from \"./batch.js\";\n\n/** One resolved pass timing. */\nexport interface PassTiming {\n readonly label: string;\n readonly ns: number;\n}\n\n/** A pass whose begin / end slots were handed out and not yet resolved. */\ninterface PendingPass {\n readonly label: string;\n readonly begin: number;\n}\n\n/** Timestamp profiling when \"timestamp-query\" was granted (spec 5.5). */\nexport class Profiler {\n /** True when the feature was granted and a query set exists. */\n readonly enabled: boolean;\n /** True in browsers (100 us quantisation), false under Dawn-node (spec 2.6). */\n readonly quantised: boolean;\n private readonly slots: number;\n private readonly querySet: GPUQuerySet | null;\n private readonly resolveBuffer: GPUBuffer | null;\n private readonly labels = new WeakMap<ReadbackRequest, readonly string[]>();\n private readonly partialRequests = new WeakSet<ReadbackRequest>();\n private pending: PendingPass[] = [];\n private cursor = 0;\n private refused = 0;\n private destroyed = false;\n\n /**\n * Creates the query set and the resolve buffer when usable; `slots` defaults to PROFILER_QUERY_SLOTS = 256\n * (spec 5.5); 2 query slots per pass. `enabled` is also false when the device lacks \"timestamp-query\" or\n * `slots < 2`, so no caller can make the profiler raise a validation error.\n * @param device - the device the query set is created on\n * @param enabled - whether the caller wants profiling (the context passes `features.has(\"timestamp-query\")`)\n * @param quantised - true in browsers\n * @param slots - query slots, two per pass (default PROFILER_QUERY_SLOTS)\n */\n constructor(device: GPUDevice, enabled: boolean, quantised: boolean, slots?: number) {\n const count = slots ?? PROFILER_QUERY_SLOTS;\n this.quantised = quantised;\n this.slots = count;\n const usable = enabled && count >= 2 && device.features.has(\"timestamp-query\");\n this.enabled = usable;\n if (usable) {\n this.querySet = device.createQuerySet({ label: \"profiler/timestamps\", type: \"timestamp\", count });\n this.resolveBuffer = device.createBuffer({\n label: \"profiler/resolve\",\n size: count * 8,\n usage: BufferUsage.QUERY_RESOLVE | BufferUsage.COPY_SRC,\n });\n } else {\n this.querySet = null;\n this.resolveBuffer = null;\n }\n }\n\n /**\n * The timestampWrites descriptor for a new pass, or undefined when disabled / out of slots. A pass refused for\n * want of slots is counted, and the next `resolveInto()` marks its request partial.\n * @param label - the pass name reported by `timings()`\n * @returns the descriptor a CommandBatch puts on beginComputePass, or undefined\n */\n beginPass(label: string): GPUComputePassTimestampWrites | undefined {\n if (this.querySet === null || this.destroyed) {\n return undefined;\n }\n if (this.cursor + 2 > this.slots) {\n this.refused++;\n return undefined;\n }\n const begin = this.cursor;\n this.cursor += 2;\n this.pending.push({ label, begin });\n return { querySet: this.querySet, beginningOfPassWriteIndex: begin, endOfPassWriteIndex: begin + 1 };\n }\n\n /**\n * Records the resolve + copy into the batch's staging slot; returns the request's byte range, or null when\n * nothing was written (disabled, destroyed, or no pass begun since the last resolve).\n * @param batch - the batch whose passes were timed (it must still be open)\n * @returns the readback request `timings()` decodes, or null\n */\n resolveInto(batch: CommandBatch): ReadbackRequest | null {\n if (this.querySet === null || this.resolveBuffer === null || this.destroyed || this.pending.length === 0) {\n return null;\n }\n const count = this.cursor;\n batch.resolveQuerySet(this.querySet, 0, count, this.resolveBuffer);\n const request = batch.readback(this.resolveBuffer, 0, count * 8);\n this.labels.set(\n request,\n this.pending.map((pass) => pass.label),\n );\n if (this.refused > 0) {\n this.partialRequests.add(request);\n }\n this.pending = [];\n this.cursor = 0;\n this.refused = 0;\n return request;\n }\n\n /**\n * Whether a pass of the batch was refused a slot pair, so `timings()` covers only its first slots / 2 passes\n * and their sum is not the batch's duration.\n * @param request - the request `resolveInto()` returned\n * @returns true when at least one pass of that batch went untimed\n */\n partial(request: ReadbackRequest): boolean {\n return this.partialRequests.has(request);\n }\n\n /**\n * Decodes the timings of a batch from its readback bytes.\n * @param bytes - the resolved readback of the batch\n * @param request - the request `resolveInto()` returned for it\n * @returns one timing per pass in pass order (empty for a request this profiler did not create)\n */\n timings(bytes: ArrayBuffer, request: ReadbackRequest): readonly PassTiming[] {\n const labels = this.labels.get(request);\n if (labels === undefined) {\n return [];\n }\n const view = new DataView(bytes);\n const out: PassTiming[] = [];\n for (let i = 0; i < labels.length; i++) {\n const at = request.offset + i * 16;\n if (at + 16 > bytes.byteLength) {\n break;\n }\n const begin = view.getBigUint64(at, true);\n const end = view.getBigUint64(at + 8, true);\n out.push({ label: labels[i], ns: Number(end - begin) });\n }\n return out;\n }\n\n /** Destroys the query set and the resolve buffer; idempotent. */\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.destroyed = true;\n this.pending = [];\n this.cursor = 0;\n this.refused = 0;\n if (this.querySet !== null) {\n this.querySet.destroy();\n }\n if (this.resolveBuffer !== null) {\n this.resolveBuffer.destroy();\n }\n }\n}\n","/**\n * The Lease scope object of spec 4.4: every buffer an algorithm acquires through it goes back to the\n * BufferPool in ONE `release()` call placed in the algorithm's `finally` block, so scratch never\n * outlives the call that took it (a `try / finally`, not `Symbol.dispose`, until the monorepo's\n * TypeScript target supports `using`). Persistent buffers (layout state) are owned by the simulation\n * object instead and freed by its `dispose()`.\n */\n\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport { hasErrorCode, WebGpuGraphError } from \"../errors.js\";\nimport type { BufferPool } from \"./buffer-pool.js\";\n\n/** Scope object algorithms use: every buffer acquired through it is released by `release()` in a finally block (spec 4.4). */\nexport class Lease {\n private readonly pool: BufferPool;\n private readonly buffers = new Set<GPUBuffer>();\n private released = false;\n\n /**\n * Creates a lease over a pool; `pool.lease()` is the usual way to get one.\n * @param pool - the pool every acquisition of this lease goes through\n */\n constructor(pool: BufferPool) {\n this.pool = pool;\n }\n\n /**\n * pool.acquire(byteLength, STORAGE | COPY_SRC | COPY_DST, label).\n * @param byteLength - bytes needed; the pool rounds up to its size class\n * @param label - the buffer label\n * @returns the buffer, returned to the pool by `release()`\n */\n storage(byteLength: number, label: string): GPUBuffer {\n return this.acquire(byteLength, BufferUsage.STORAGE | BufferUsage.COPY_SRC | BufferUsage.COPY_DST, label);\n }\n\n /**\n * pool.acquire(byteLength, UNIFORM | COPY_DST, label).\n * @param byteLength - bytes needed; the pool rounds up to its size class\n * @param label - the buffer label\n * @returns the buffer, returned to the pool by `release()`\n */\n uniform(byteLength: number, label: string): GPUBuffer {\n return this.acquire(byteLength, BufferUsage.UNIFORM | BufferUsage.COPY_DST, label);\n }\n\n /**\n * pool.acquire with explicit usage.\n * @param byteLength - bytes needed; the pool rounds up to its size class\n * @param usage - the GPUBufferUsage bits\n * @param label - the buffer label\n * @returns the buffer, returned to the pool by `release()`\n */\n acquire(byteLength: number, usage: number, label: string): GPUBuffer {\n if (this.released) {\n throw new WebGpuGraphError(\"E_DISPOSED\", `lease already released: cannot acquire \"${label}\"`, { label });\n }\n const buffer = this.pool.acquire(byteLength, usage, label);\n this.buffers.add(buffer);\n return buffer;\n }\n\n /**\n * Releases every buffer acquired through this lease; idempotent. A pool that `ctx.dispose()` already\n * destroyed has nothing left to take back, so its E_DISPOSED is swallowed here: the lease sits in a\n * `finally` block and must never mask the error that unwound the algorithm.\n */\n release(): void {\n if (this.released) {\n return;\n }\n this.released = true;\n const owned = [...this.buffers];\n this.buffers.clear();\n for (const buffer of owned) {\n try {\n this.pool.release(buffer);\n } catch (error) {\n if (!hasErrorCode(error, \"E_DISPOSED\")) {\n throw error;\n }\n }\n }\n }\n\n /**\n * Live buffers of this lease.\n * @returns the number of buffers acquired through the lease and not yet released\n */\n get count(): number {\n return this.buffers.size;\n }\n}\n","/**\n * Size-class pool of GPUBuffers by usage (spec 4.4): a request rounds up to a class (powers of two from 4 KiB to\n * 64 MiB, then 16 MiB steps), an idle buffer of that (class, usage) is reused, otherwise one is created through the\n * context's AllocationTracker (so the OOM scope of spec 5.7 and the resident accounting are shared with the\n * residency); `release` keeps at most maxIdlePerClass idle buffers per (class, usage); `trim` destroys the idle\n * ones (ctx.release and layouts on dispose); `destroyAll` everything (ctx.dispose). The Lease scope object arrives\n * with P2-T1 (`lease()`, PLAN DECISION 1). Classes above maxBufferSize are never created: a request that fits the\n * device but whose class overshoots gets the capped class (PLAN DECISION 14).\n */\n\nimport {\n POOL_LINEAR_STEP_BYTES,\n POOL_MAX_IDLE_PER_CLASS,\n POOL_MAX_POW2_CLASS_BYTES,\n POOL_MIN_CLASS_BYTES,\n} from \"../constants.js\";\nimport { type AllocationTracker } from \"../device/error-scope.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { Lease } from \"./lease.js\";\n\n/** What the pool remembers about a live buffer. */\ninterface LiveEntry {\n readonly sizeClass: number;\n readonly usage: number;\n}\n\n/**\n * The idle-list key of a (class, usage) pair.\n * @param sizeClass - the class in bytes\n * @param usage - the GPUBufferUsage flags\n * @returns the map key\n */\nfunction classKey(sizeClass: number, usage: number): string {\n return `${sizeClass}:${usage}`;\n}\n\n/** Size-class pool of GPUBuffers by usage (spec 4.4). */\nexport class BufferPool {\n private readonly allocator: AllocationTracker;\n private readonly maxBufferSize: number;\n private readonly maxIdlePerClass: number;\n private readonly idle = new Map<string, GPUBuffer[]>();\n private readonly live = new Map<GPUBuffer, LiveEntry>();\n private liveBytesValue = 0;\n private idleBytesValue = 0;\n private disposed = false;\n\n /**\n * Creates an empty pool.\n * @param _device - the device (buffers are created through the allocator, which owns it; the parameter keeps\n * the contract's constructor shape)\n * @param allocator - the context's OOM-scoped allocator\n * @param maxBufferSize - the device's maxBufferSize (classes above it are never created)\n * @param options - pool options\n * @param options.maxIdlePerClass - idle buffers kept per (class, usage); default POOL_MAX_IDLE_PER_CLASS\n */\n constructor(\n _device: GPUDevice,\n allocator: AllocationTracker,\n maxBufferSize: number,\n options?: { readonly maxIdlePerClass?: number | undefined },\n ) {\n this.allocator = allocator;\n this.maxBufferSize = maxBufferSize - (maxBufferSize % 4);\n this.maxIdlePerClass = options?.maxIdlePerClass ?? POOL_MAX_IDLE_PER_CLASS;\n }\n\n /**\n * The size class a byte length rounds up to: powers of two from 4 KiB to 64 MiB, then 16 MiB steps (pure).\n * @param byteLength - a positive integer\n * @returns the class in bytes\n */\n static sizeClass(byteLength: number): number {\n if (!Number.isInteger(byteLength) || byteLength <= 0) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", \"byteLength: expected a positive integer\", {\n argument: \"byteLength\",\n value: byteLength,\n expected: \"a positive integer\",\n });\n }\n if (byteLength > POOL_MAX_POW2_CLASS_BYTES) {\n return Math.ceil(byteLength / POOL_LINEAR_STEP_BYTES) * POOL_LINEAR_STEP_BYTES;\n }\n let sizeClass = POOL_MIN_CLASS_BYTES;\n while (sizeClass < byteLength) {\n sizeClass *= 2;\n }\n return sizeClass;\n }\n\n /**\n * Acquires a buffer of at least byteLength (an idle one of the class and usage, else a new one through the\n * allocator); E_TOO_LARGE above maxBufferSize.\n * @param byteLength - the bytes needed\n * @param usage - the GPUBufferUsage flags\n * @param label - the buffer label (a reused buffer is relabelled)\n * @returns a buffer of the class size\n */\n acquire(byteLength: number, usage: number, label: string): GPUBuffer {\n if (this.disposed) {\n throw new WebGpuGraphError(\"E_DISPOSED\", \"the buffer pool was disposed\", { label: \"pool\" });\n }\n const rounded = BufferPool.sizeClass(byteLength);\n if (byteLength > this.maxBufferSize) {\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n `pool: ${byteLength} bytes exceed the device maxBufferSize of ${this.maxBufferSize} bytes`,\n { needed: byteLength, limit: this.maxBufferSize, path: \"pool\", algorithm: null },\n );\n }\n const sizeClass = Math.min(rounded, this.maxBufferSize);\n const key = classKey(sizeClass, usage);\n const idle = this.idle.get(key);\n let buffer = idle?.pop();\n if (buffer === undefined) {\n buffer = this.allocator.createBuffer({ label, size: sizeClass, usage });\n } else {\n this.idleBytesValue -= sizeClass;\n buffer.label = label;\n }\n this.live.set(buffer, { sizeClass, usage });\n this.liveBytesValue += sizeClass;\n return buffer;\n }\n\n /**\n * Returns a buffer to its class; destroys it when the class already holds maxIdlePerClass idle buffers. A no-op\n * after destroyAll() (so a `finally` never masks the original error).\n * @param buffer - a buffer acquired from this pool and not yet released\n */\n release(buffer: GPUBuffer): void {\n if (this.disposed) {\n return;\n }\n const entry = this.live.get(buffer);\n if (entry === undefined) {\n throw new WebGpuGraphError(\"E_INVALID_ARGUMENT\", \"buffer: not a live buffer of this pool\", {\n argument: \"buffer\",\n value: buffer.label,\n expected: \"a buffer acquired from this pool and not yet released\",\n });\n }\n this.live.delete(buffer);\n this.liveBytesValue -= entry.sizeClass;\n const key = classKey(entry.sizeClass, entry.usage);\n let idle = this.idle.get(key);\n if (idle === undefined) {\n idle = [];\n this.idle.set(key, idle);\n }\n if (idle.length >= this.maxIdlePerClass) {\n this.allocator.destroy(buffer);\n return;\n }\n idle.push(buffer);\n this.idleBytesValue += entry.sizeClass;\n }\n\n /** Destroys every idle buffer. */\n trim(): void {\n for (const buffers of this.idle.values()) {\n for (const buffer of buffers) {\n this.allocator.destroy(buffer);\n }\n }\n this.idle.clear();\n this.idleBytesValue = 0;\n }\n\n /** Destroys everything, idle and live (ctx.dispose()); idempotent. @internal */\n destroyAll(): void {\n this.trim();\n for (const buffer of this.live.keys()) {\n this.allocator.destroy(buffer);\n }\n this.live.clear();\n this.liveBytesValue = 0;\n this.disposed = true;\n }\n\n /**\n * A scope object that releases everything acquired through it (spec 4.4, P2).\n * @returns a fresh lease over this pool\n */\n lease(): Lease {\n return new Lease(this);\n }\n\n /**\n * Bytes of buffers acquired and not yet released (class sizes).\n * @returns the live byte count\n */\n get liveBytes(): number {\n return this.liveBytesValue;\n }\n\n /**\n * Bytes of idle buffers (class sizes).\n * @returns the idle byte count\n */\n get idleBytes(): number {\n return this.idleBytesValue;\n }\n}\n","/**\n * The staging ring of spec 4.4: a ring of MAP_READ | COPY_DST buffers (default DEFAULT_STAGING_SLOTS slots of 4 MiB,\n * PLAN DECISION 15) through which every readback of the package flows. `read()` copies with its own encoder and\n * submit, awaits mapAsync, copies out of the mapped range BEFORE unmap (the range is detached at unmap, design 10.7)\n * and never polls onSubmittedWorkDone; requests above the slot size are chunked. Ownership is one-directional: the\n * ring owns its buffers; a CommandBatch (P2) BORROWS one slot through borrowSlot, maps it through mapSlot and always\n * returns it through returnSlot, which unmaps it. Slots at or above OOM_SCOPE_THRESHOLD_BYTES are created through the\n * AllocationTracker (the out-of-memory scope of spec 5.7), the default-size ones directly on the device, so the\n * allocator counts residency and pool buffers only. A mapAsync rejection is E_DEVICE_LOST (or E_DISPOSED after\n * destroyAll).\n *\n * The one invariant every path keeps: a staging buffer whose mapAsync is PENDING is never unmapped and never\n * destroyed. dawn-node 0.4.0 settles the pending promise synchronously on unmap() / destroy() and settles it a\n * second time when Dawn's map callback arrives (a SIGSEGV in AsyncRunner::Reject); on the Vulkan backends the\n * callback has already run inside device.destroy(), on Dawn's Metal backend it arrives after the device-lost\n * fan-out, which is where the macOS host lane lost its vitest worker (CLAUDE.md \"Verified Platform Facts\"). The\n * ring therefore tracks every map on its slots (mapPending) and defers an unmap, a return or a destroy that\n * arrives during one to the moment the map settles.\n */\n\nimport { DEFAULT_STAGING_SLOTS, OOM_SCOPE_THRESHOLD_BYTES } from \"../constants.js\";\nimport { type AllocationTracker } from \"../device/error-scope.js\";\nimport { BufferUsage, MapMode } from \"../device/webgpu-constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\n\n/** Default capacity of one staging slot (PLAN DECISION 15). */\nconst DEFAULT_SLOT_BYTES = 4 * 1024 * 1024;\n\n/** Every staging buffer is MAP_READ | COPY_DST. */\nconst STAGING_USAGE = BufferUsage.MAP_READ | BufferUsage.COPY_DST;\n\n/** Grown slots are sized in 256-byte steps. */\nconst SLOT_GRANULE = 256;\n\n/**\n * One MAP_READ | COPY_DST staging buffer of the ring. Exported for the borrowers of borrowSlot / returnSlot\n * (contract 3.8): P2-T1's CommandBatch imports it as a type; nothing at P1 imports it by name.\n * @public\n */\nexport interface StagingSlot {\n readonly index: number;\n readonly buffer: GPUBuffer;\n readonly capacity: number;\n}\n\n/** The ring's bookkeeping of one slot. */\ninterface SlotEntry {\n readonly slot: StagingSlot;\n borrowed: boolean;\n /** True between a successful mapAsync through the ring and the unmap of returnSlot (a fallback when mapState is absent). */\n mapped: boolean;\n /** True while a mapAsync through the ring (read() or mapSlot) is pending: returnSlot and destroyAll defer to the settle. */\n mapPending: boolean;\n /** True when returnSlot ran during a pending map: the settle finishes the return. */\n returnRequested: boolean;\n /** True when the buffer was created through the allocator (and is destroyed through it). */\n readonly tracked: boolean;\n}\n\n/**\n * Whether an ArrayBuffer-like is a SharedArrayBuffer (checked by tag so the global need not exist).\n * @param buffer - the buffer to test\n * @returns true for a SharedArrayBuffer\n */\nfunction isSharedBuffer(buffer: ArrayBufferLike): boolean {\n return Object.prototype.toString.call(buffer) === \"[object SharedArrayBuffer]\";\n}\n\n/**\n * The E_INVALID_ARGUMENT error of a bad readback argument.\n * @param argument - the argument name\n * @param value - the value given\n * @param expected - what was expected\n * @returns the error to throw\n */\nfunction invalid(argument: string, value: unknown, expected: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${argument}: expected ${expected}`, {\n argument,\n value,\n expected,\n });\n}\n\n/** The staging ring (spec 4.4): default 3 slots; grows when every slot is busy; always unmaps and destroys its own buffers. */\nexport class Readback {\n private readonly device: GPUDevice;\n private readonly allocator: AllocationTracker;\n private readonly slotBytes: number;\n private readonly ring: SlotEntry[] = [];\n private disposed = false;\n\n /**\n * Creates the ring with `slots` slots of `slotBytes` each.\n * @param device - the device the copies run on\n * @param allocator - the context's OOM-scoped allocator (used for slots at or above OOM_SCOPE_THRESHOLD_BYTES)\n * @param options - ring options\n * @param options.slots - slots created up front; default DEFAULT_STAGING_SLOTS\n * @param options.slotBytes - capacity of each slot and the chunk size of read(); default 4 MiB; a positive multiple of 4\n */\n constructor(\n device: GPUDevice,\n allocator: AllocationTracker,\n options?: { readonly slots?: number | undefined; readonly slotBytes?: number | undefined },\n ) {\n const slotBytes = options?.slotBytes ?? DEFAULT_SLOT_BYTES;\n if (!Number.isInteger(slotBytes) || slotBytes <= 0 || slotBytes % 4 !== 0) {\n throw invalid(\"slotBytes\", slotBytes, \"a positive multiple of 4\");\n }\n const slots = options?.slots ?? DEFAULT_STAGING_SLOTS;\n if (!Number.isInteger(slots) || slots < 0) {\n throw invalid(\"slots\", slots, \"a non-negative integer\");\n }\n this.device = device;\n this.allocator = allocator;\n this.slotBytes = slotBytes;\n for (let i = 0; i < slots; i++) {\n this.addSlot(slotBytes);\n }\n }\n\n /**\n * Copies `byteLength` bytes from `src` at `srcOffset` (own encoder, own submit), maps, copies out BEFORE unmap;\n * resolves the bytes (a fresh ArrayBuffer, or `dest.buffer` after `dest.set` when given). Requests above the slot\n * size are chunked.\n * @param src - a COPY_SRC buffer\n * @param byteLength - bytes to read (a positive multiple of 4, within src)\n * @param dest - an optional destination view of at least byteLength bytes over a plain ArrayBuffer\n * @param srcOffset - the byte offset in src (default 0; a multiple of 4)\n * @returns the bytes read\n */\n async read(src: GPUBuffer, byteLength: number, dest?: ArrayBufferView, srcOffset?: number): Promise<ArrayBuffer> {\n this.assertLive();\n const offset = srcOffset ?? 0;\n if (!Number.isInteger(byteLength) || byteLength <= 0 || byteLength % 4 !== 0) {\n throw invalid(\"byteLength\", byteLength, \"a positive multiple of 4\");\n }\n if (!Number.isInteger(offset) || offset < 0 || offset % 4 !== 0) {\n throw invalid(\"srcOffset\", offset, \"a non-negative multiple of 4\");\n }\n if (offset + byteLength > src.size) {\n throw invalid(\"byteLength\", byteLength, `srcOffset + byteLength <= src.size (${src.size})`);\n }\n if ((src.usage & BufferUsage.COPY_SRC) === 0) {\n throw invalid(\"src\", src.label, \"a buffer with COPY_SRC usage\");\n }\n let out: ArrayBuffer;\n let outBytes: Uint8Array;\n if (dest === undefined) {\n out = new ArrayBuffer(byteLength);\n outBytes = new Uint8Array(out);\n } else {\n if (isSharedBuffer(dest.buffer)) {\n throw invalid(\"dest\", \"SharedArrayBuffer\", \"a view over a plain ArrayBuffer\");\n }\n if (dest.byteLength < byteLength) {\n throw invalid(\"dest\", dest.byteLength, `at least ${byteLength} bytes`);\n }\n out = dest.buffer as ArrayBuffer;\n outBytes = new Uint8Array(out, dest.byteOffset, byteLength);\n }\n let done = 0;\n while (done < byteLength) {\n const chunk = Math.min(this.slotBytes, byteLength - done);\n const slot = this.borrowSlot(chunk);\n const entry = this.ring[slot.index];\n try {\n const encoder = this.device.createCommandEncoder({ label: \"readback\" });\n encoder.copyBufferToBuffer(src, offset + done, slot.buffer, 0, chunk);\n this.device.queue.submit([encoder.finish()]);\n await this.map(entry, chunk);\n outBytes.set(new Uint8Array(slot.buffer.getMappedRange(0, chunk)), done);\n } finally {\n this.returnSlot(slot);\n }\n done += chunk;\n }\n return out;\n }\n\n /**\n * Reads one u32 counter through the same ring.\n * @param src - a COPY_SRC buffer\n * @param byteOffset - the counter's byte offset (a multiple of 4)\n * @returns the counter value\n */\n async readU32(src: GPUBuffer, byteOffset: number): Promise<number> {\n const bytes = await this.read(src, 4, undefined, byteOffset);\n return new Uint32Array(bytes)[0];\n }\n\n /**\n * Borrows an unmapped slot of at least byteLength (grows the ring when none is free); the borrower ALWAYS\n * returns it (spec 4.4).\n * @param byteLength - the bytes the borrower will copy into the slot\n * @returns the slot\n */\n borrowSlot(byteLength: number): StagingSlot {\n this.assertLive();\n if (!Number.isInteger(byteLength) || byteLength <= 0) {\n throw invalid(\"byteLength\", byteLength, \"a positive integer\");\n }\n // a free slot is unmapped by construction: returnSlot unmaps, and only a borrower maps\n for (const entry of this.ring) {\n if (!entry.borrowed && entry.slot.capacity >= byteLength) {\n entry.borrowed = true;\n return entry.slot;\n }\n }\n const capacity = Math.max(this.slotBytes, Math.ceil(byteLength / SLOT_GRANULE) * SLOT_GRANULE);\n const entry = this.addSlot(capacity);\n entry.borrowed = true;\n return entry.slot;\n }\n\n /**\n * mapAsync(READ) on a borrowed slot, tracked by the ring: the slot counts as borrowed, and is neither unmapped\n * nor destroyed, until the map settles (see the file comment). Returns the runtime's own promise, untranslated:\n * the borrower classifies a rejection (a CommandBatch races it against device loss, spec 5.7).\n * @param slot - a slot borrowed from this ring and not yet returned\n * @param byteLength - the bytes to map from offset 0\n * @returns the mapAsync promise\n */\n mapSlot(slot: StagingSlot, byteLength: number): Promise<void> {\n this.assertLive();\n const entry = this.borrowedEntry(slot);\n if (entry.mapPending || entry.mapped) {\n throw invalid(\"slot\", slot.index, \"a borrowed slot that is not mapped and has no map pending\");\n }\n return this.track(entry, slot.buffer.mapAsync(MapMode.READ, 0, byteLength));\n }\n\n /**\n * Returns a borrowed slot (unmapping it if mapped). A slot whose map through the ring is still pending stays\n * borrowed until the map settles, when the ring unmaps and returns it; a borrower that maps a slot itself must\n * unmap it before returning it (spec 4.4; `mapState` decides when the runtime exposes it, otherwise the ring's\n * own record does). A no-op after destroyAll() (the ring is gone; a borrower's finally must never mask the\n * E_DISPOSED / E_DEVICE_LOST of the read it was serving).\n * @param slot - a slot borrowed from this ring and not yet returned\n */\n returnSlot(slot: StagingSlot): void {\n if (this.disposed) {\n return;\n }\n const entry = this.borrowedEntry(slot);\n if (entry.mapPending) {\n entry.returnRequested = true;\n return;\n }\n this.finishReturn(entry);\n }\n\n /**\n * The entry of a slot borrowed from this ring and not yet returned.\n * @param slot - the slot\n * @returns its entry\n */\n private borrowedEntry(slot: StagingSlot): SlotEntry {\n const entry = this.ring[slot.index];\n if (entry === undefined || entry.slot !== slot || !entry.borrowed) {\n throw invalid(\"slot\", slot.index, \"a slot borrowed from this ring and not yet returned\");\n }\n return entry;\n }\n\n /**\n * Unmaps a returned slot when it is mapped and frees it.\n * @param entry - the slot's entry (no map pending)\n */\n private finishReturn(entry: SlotEntry): void {\n const state: string | undefined = entry.slot.buffer.mapState;\n const mapped = state === undefined ? entry.mapped : state !== \"unmapped\";\n if (mapped) {\n entry.slot.buffer.unmap();\n }\n entry.mapped = false;\n entry.borrowed = false;\n entry.returnRequested = false;\n }\n\n /**\n * Tracks one mapAsync on a slot: mapPending until it settles, then the deferred work -- the destruction\n * destroyAll() left to the settle, or the return returnSlot() left to it. The handler is attached before the\n * promise is handed out, so it runs before any borrower's continuation.\n * @param entry - the slot's entry\n * @param pending - the runtime's mapAsync promise\n * @returns the same promise\n */\n private track(entry: SlotEntry, pending: Promise<void>): Promise<void> {\n entry.mapPending = true;\n const settle = (mapped: boolean): void => {\n entry.mapPending = false;\n entry.mapped = mapped;\n if (this.disposed) {\n if (mapped) {\n entry.slot.buffer.unmap();\n }\n this.destroySlot(entry);\n entry.mapped = false;\n return;\n }\n if (entry.returnRequested) {\n this.finishReturn(entry);\n }\n };\n void pending.then(\n () => {\n settle(true);\n },\n () => {\n settle(false);\n },\n );\n return pending;\n }\n\n /**\n * Number of slots (grows).\n * @returns the slot count\n */\n get slots(): number {\n return this.ring.length;\n }\n\n /**\n * Slots currently borrowed.\n * @returns the borrowed count\n */\n get borrowed(): number {\n let count = 0;\n for (const entry of this.ring) {\n if (entry.borrowed) {\n count++;\n }\n }\n return count;\n }\n\n /**\n * Destroys every staging buffer (ctx.dispose()); idempotent. A slot whose mapAsync is still pending is NOT\n * destroyed here (the file comment: dawn-node 0.4.0 settles the promise twice); its destruction is deferred to\n * the moment the map settles (track()), where a pending read() still rejects with E_DISPOSED as the contract\n * promises.\n * @internal\n */\n destroyAll(): void {\n for (const entry of this.ring) {\n if (entry.mapPending) {\n continue;\n }\n this.destroySlot(entry);\n }\n this.ring.length = 0;\n this.disposed = true;\n }\n\n /**\n * Destroys one slot's buffer through the allocator when it was created there.\n * @param entry - the slot\n */\n private destroySlot(entry: SlotEntry): void {\n if (entry.tracked) {\n this.allocator.destroy(entry.slot.buffer);\n } else {\n entry.slot.buffer.destroy();\n }\n }\n\n /**\n * Creates one slot at the end of the ring.\n * @param capacity - the slot's byte capacity\n * @returns the new entry\n */\n private addSlot(capacity: number): SlotEntry {\n const index = this.ring.length;\n const descriptor: GPUBufferDescriptor = {\n label: `readback:slot:${index}`,\n size: capacity,\n usage: STAGING_USAGE,\n };\n const tracked = capacity >= OOM_SCOPE_THRESHOLD_BYTES;\n const buffer = tracked ? this.allocator.createBuffer(descriptor) : this.device.createBuffer(descriptor);\n const entry: SlotEntry = {\n slot: Object.freeze({ index, buffer, capacity }),\n borrowed: false,\n mapped: false,\n mapPending: false,\n returnRequested: false,\n tracked,\n };\n this.ring.push(entry);\n return entry;\n }\n\n /**\n * mapAsync(READ) on a slot for read(); a rejection becomes E_DISPOSED (after destroyAll) or E_DEVICE_LOST.\n * @param entry - the ring entry of the borrowed slot\n * @param byteLength - the bytes to map\n */\n private async map(entry: SlotEntry, byteLength: number): Promise<void> {\n let mapped = false;\n let failure: unknown = null;\n try {\n await this.track(entry, entry.slot.buffer.mapAsync(MapMode.READ, 0, byteLength));\n mapped = true;\n } catch (err: unknown) {\n failure = err;\n }\n if (this.disposed) {\n // destroyAll() ran while the map was pending: track() finished the deferred destruction just before this\n throw new WebGpuGraphError(\"E_DISPOSED\", \"the readback ring was disposed while a read was pending\", {\n label: \"readback\",\n });\n }\n if (!mapped) {\n const message = failure instanceof Error ? failure.message : String(failure);\n throw new WebGpuGraphError(\"E_DEVICE_LOST\", `mapAsync rejected: ${message}`, {\n reason: \"mapAsync\",\n message,\n });\n }\n }\n\n /** Throws E_DISPOSED after destroyAll(). */\n private assertLive(): void {\n if (this.disposed) {\n throw new WebGpuGraphError(\"E_DISPOSED\", \"the readback ring was disposed\", { label: \"readback\" });\n }\n }\n}\n","/**\n * The pure upload planner of spec 4.2: from a snapshot's shape, the device limits and the core arrays a kernel\n * needs, choose the one-buffer arena upload (the hot prefix, or the full arena when a cold segment is needed and\n * fits), one buffer per array, or arc windows over the arc-indexed arrays. No GPU object is touched here:\n * GraphResidency (./residency.ts) executes arena and perArray plans and P4 executes windowed plans (P1-P3 only\n * plan them). Every byte length comes from counts and flags, so an identity permutation is never materialised\n * (spec 4.1), and every arithmetic step uses `%` and Math.floor, never a bitwise operator: arc indices and byte\n * offsets exceed 2^31 at the 10M / 100M tier (graph-format invariant I3, spec 4.2).\n */\n\nimport { type CoreArrayName, type GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { ARC_WINDOW_ALIGN } from \"../constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type PlanCaps, type PlanLimits } from \"../types/context.js\";\nimport { type ArcWindow } from \"../types/memory.js\";\n\n/** The five core arrays in arena (hot-to-cold) order. */\nconst CORE_ORDER: readonly CoreArrayName[] = Object.freeze([\"rowPtr\", \"colIdx\", \"weights\", \"arcToEdge\", \"edgeToArc\"]);\n\n/** The arc-indexed arrays: the only ones a window can cover (rowPtr is row-indexed, edgeToArc edge-indexed). */\nconst ARC_INDEXED: ReadonlySet<CoreArrayName> = new Set<CoreArrayName>([\"colIdx\", \"weights\", \"arcToEdge\"]);\n\n/**\n * Where one core array's bytes go: one or more buffers (split at window boundaries only when the array exceeds\n * maxBufferSize). Exported with the plan union (contract 3.8): P4's windowed execution reads it; nothing at P1\n * imports it by name.\n * @public\n */\nexport interface PlannedArray {\n readonly name: CoreArrayName;\n readonly byteLength: number;\n readonly buffers: readonly { readonly byteOffset: number; readonly byteLength: number }[];\n}\n\n/**\n * The arena path: ONE buffer of `bytes`, one writeBuffer, per-segment bindings at `segment.byteOffset - arena.byteOffset`.\n * A member of the exported UploadPlan union (contract 3.8 exports the three plan shapes by name); nothing imports it\n * by name, which knip 5.77 reports.\n * @public\n */\nexport interface ArenaPlan {\n readonly kind: \"arena\";\n readonly bytes: number;\n readonly includesCold: boolean;\n readonly segments: Readonly<Record<CoreArrayName, { readonly offset: number; readonly size: number } | null>>;\n}\n\n/**\n * The per-array path: one buffer per needed array, whole-buffer bindings.\n * A member of the exported UploadPlan union (contract 3.8 exports the three plan shapes by name); nothing imports it\n * by name, which knip 5.77 reports.\n * @public\n */\nexport interface PerArrayPlan {\n readonly kind: \"perArray\";\n readonly arrays: readonly PlannedArray[];\n}\n\n/**\n * The windowed path: per-array buffers plus the arc windows kernels iterate (P4 executes; P1-P3 only plan).\n * A member of the exported UploadPlan union (contract 3.8 exports the three plan shapes by name); nothing imports it\n * by name, which knip 5.77 reports.\n * @public\n */\nexport interface WindowedPlan {\n readonly kind: \"windowed\";\n readonly arrays: readonly PlannedArray[];\n readonly windows: readonly ArcWindow[];\n readonly arcsPerWindow: number;\n}\n\n/** One of the three plans. */\nexport type UploadPlan = ArenaPlan | PerArrayPlan | WindowedPlan;\n\n/** One buffer range of a PlannedArray. */\ninterface BufferRange {\n readonly byteOffset: number;\n readonly byteLength: number;\n}\n\n/**\n * Byte length of every core array from the counts and flags alone; 0 means absent (unweighted, an identity\n * permutation, or zero length: spec 5.6 never binds a zero-length array). No array is read.\n * @param s - the snapshot\n * @returns the byte lengths keyed by core array name\n */\nfunction coreByteLengths(s: GraphSnapshot): Readonly<Record<CoreArrayName, number>> {\n const arcs = s.arcCount;\n const identity = s.flags.arcToEdgeIsIdentity;\n return {\n rowPtr: 4 * (s.nodeCount + 1),\n colIdx: 4 * arcs,\n weights: s.flags.weighted && arcs > 0 ? 4 * arcs : 0,\n arcToEdge: !identity && arcs > 0 ? 4 * arcs : 0,\n edgeToArc: !identity && s.edgeCount > 0 ? 4 * s.edgeCount : 0,\n };\n}\n\n/**\n * rowPtr always, then every requested PRESENT array, in arena order (absent names are dropped, never an error).\n * @param need - the requested names\n * @param lengths - the byte lengths of coreByteLengths\n * @returns the names to plan\n */\nfunction neededNames(\n need: readonly CoreArrayName[],\n lengths: Readonly<Record<CoreArrayName, number>>,\n): CoreArrayName[] {\n const wanted = new Set<CoreArrayName>(need);\n wanted.add(\"rowPtr\");\n return CORE_ORDER.filter((name) => wanted.has(name) && lengths[name] > 0);\n}\n\n/**\n * Rounds an arc count down to a multiple of ARC_WINDOW_ALIGN with `%` (a bitwise `& ~63` breaks above 2^31).\n * @param value - an arc count\n * @returns the largest multiple of 64 not above it\n */\nfunction alignDown(value: number): number {\n return value - (value % ARC_WINDOW_ALIGN);\n}\n\n/**\n * The E_TOO_LARGE error of spec 5.7 for a plan that cannot exist.\n * @param needed - the bytes that do not fit\n * @param limit - the limit they exceed\n * @param path - \"rowPtr\" (no window can hold rowPtr) or \"binding\" (an edge-indexed array cannot be windowed)\n * @returns the error to throw\n */\nfunction tooLarge(needed: number, limit: number, path: \"rowPtr\" | \"binding\"): WebGpuGraphError {\n return new WebGpuGraphError(\"E_TOO_LARGE\", `${path}: ${needed} bytes exceed the device limit of ${limit} bytes`, {\n needed,\n limit,\n path,\n algorithm: null,\n });\n}\n\n/**\n * The E_INVALID_ARGUMENT error of a bad planner input.\n * @param argument - the argument name\n * @param value - the value given\n * @param expected - what was expected\n * @returns the error to throw\n */\nfunction invalid(argument: string, value: unknown, expected: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${argument}: expected ${expected}`, {\n argument,\n value,\n expected,\n });\n}\n\n/**\n * The largest 64-aligned arc count one binding holds: floor(maxStorageBufferBindingSize / 4) rounded down to a\n * multiple of ARC_WINDOW_ALIGN.\n * @param limits - the device limits\n * @returns the arcs per window (0 when the binding limit is below 256 bytes)\n */\nexport function arcsPerWindowFor(limits: PlanLimits): number {\n return alignDown(Math.floor(limits.maxStorageBufferBindingSize / 4));\n}\n\n/**\n * The window list for a rowPtr (pure; unit-tested with a synthetic rowPtr above 2^31 arcs): start = rowPtr[v0] -\n * rowPtr[v0] % ARC_WINDOW_ALIGN, at most `arcsPerWindow` arcs per window, a row longer than a window split across\n * windows. Whole rows first: a window ends at the last row boundary within `start + arcsPerWindow`; a row that does\n * not fit a window opened at its own aligned start is split into aligned chunks whose `rowFirst === rowLast` is that\n * row, and the next window continues the row at the chunk end. Every row belongs to a window (leading and trailing\n * empty rows included); every window is placed in buffer 0 at offset 4 x start (planUpload re-places them when an\n * array is split across buffers).\n * @param rowPtr - nodeCount + 1 row offsets (rowPtr[nodeCount] === arcCount)\n * @param arcCount - the arc count\n * @param arcsPerWindow - a positive multiple of ARC_WINDOW_ALIGN\n * @returns the windows in arc order (empty for arcCount 0)\n */\nexport function planArcWindows(rowPtr: Uint32Array, arcCount: number, arcsPerWindow: number): ArcWindow[] {\n if (rowPtr.length === 0) {\n throw invalid(\"rowPtr\", rowPtr.length, \"nodeCount + 1 entries\");\n }\n if (\n !Number.isInteger(arcsPerWindow) ||\n arcsPerWindow < ARC_WINDOW_ALIGN ||\n arcsPerWindow % ARC_WINDOW_ALIGN !== 0\n ) {\n throw invalid(\"arcsPerWindow\", arcsPerWindow, `a positive multiple of ${ARC_WINDOW_ALIGN}`);\n }\n const n = rowPtr.length - 1;\n if (rowPtr[n] !== arcCount) {\n throw invalid(\"arcCount\", arcCount, `rowPtr[${n}] === ${rowPtr[n]}`);\n }\n const windows: ArcWindow[] = [];\n if (arcCount === 0) {\n return windows;\n }\n let pos = 0;\n let v = 0;\n let rowFirst = 0;\n while (pos < arcCount) {\n while (rowPtr[v + 1] <= pos) {\n v++;\n }\n const start = alignDown(pos);\n const limit = start + arcsPerWindow;\n if (rowPtr[v + 1] > limit) {\n windows.push({ start, end: limit, rowFirst, rowLast: v, bufferIndex: 0, offset: 4 * start });\n pos = limit;\n rowFirst = v;\n } else {\n let u = v;\n while (u + 1 < n && rowPtr[u + 2] <= limit) {\n u++;\n }\n const end = rowPtr[u + 1];\n windows.push({ start, end, rowFirst, rowLast: u, bufferIndex: 0, offset: 4 * start });\n pos = end;\n rowFirst = u + 1;\n }\n }\n return windows;\n}\n\n/**\n * Groups consecutive windows into buffers of at most `bufferLimit` bytes (spec 4.2: an array above maxBufferSize is\n * split across buffers at window boundaries) and re-places every window with its buffer index and offset.\n * @param windows - the windows of planArcWindows\n * @param arcBytes - the byte length of one arc-indexed array\n * @param bufferLimit - maxBufferSize\n * @returns the buffer ranges shared by every arc-indexed array and the placed windows\n */\nfunction placeWindows(\n windows: readonly ArcWindow[],\n arcBytes: number,\n bufferLimit: number,\n): { readonly buffers: BufferRange[]; readonly placed: ArcWindow[] } {\n if (arcBytes <= bufferLimit) {\n return { buffers: [{ byteOffset: 0, byteLength: arcBytes }], placed: [...windows] };\n }\n const buffers: BufferRange[] = [];\n const placed: ArcWindow[] = [];\n let first = 0;\n while (first < windows.length) {\n let last = first;\n while (last + 1 < windows.length && 4 * (windows[last + 1].end - windows[first].start) <= bufferLimit) {\n last++;\n }\n const base = windows[first].start;\n const bufferIndex = buffers.length;\n buffers.push({ byteOffset: 4 * base, byteLength: 4 * (windows[last].end - base) });\n for (let i = first; i <= last; i++) {\n const w = windows[i];\n placed.push({\n start: w.start,\n end: w.end,\n rowFirst: w.rowFirst,\n rowLast: w.rowLast,\n bufferIndex,\n offset: 4 * (w.start - base),\n });\n }\n first = last + 1;\n }\n return { buffers, placed };\n}\n\n/**\n * The pure planner of spec 4.2: arena (hot prefix unless `need` names a cold segment and the full arena fits) ->\n * perArray -> windowed, in that order. `need` always contains \"rowPtr\" (it is added when absent); absent arrays\n * (unweighted `weights`, identity permutations, zero-length arrays) are dropped; a snapshot with arcCount === 0\n * plans rowPtr only. The arena path needs `bytes <= maxBufferSize` and every needed segment within both limits;\n * ArenaPlan.segments lists every non-null segment inside the uploaded bytes (a needed cold segment outside them is\n * null: the residency uploads it as its own buffer). The perArray path needs every needed array within both limits;\n * otherwise the arc-indexed arrays are windowed (rowPtr and edgeToArc must fit, else E_TOO_LARGE).\n * @param s - the snapshot (only arena, the counts, the flags and rowPtr are read)\n * @param caps - the device capabilities (only `limits` is read)\n * @param need - the core arrays the kernel binds\n * @returns the plan\n */\nexport function planUpload(s: GraphSnapshot, caps: PlanCaps, need: readonly CoreArrayName[]): UploadPlan {\n const { limits } = caps;\n const binding = limits.maxStorageBufferBindingSize;\n const bufferLimit = limits.maxBufferSize;\n const fits = (bytes: number): boolean => bytes <= binding && bytes <= bufferLimit;\n const violated = (bytes: number): number => (bytes > binding ? binding : bufferLimit);\n const lengths = coreByteLengths(s);\n const names = neededNames(need, lengths);\n if (!fits(lengths.rowPtr)) {\n throw tooLarge(lengths.rowPtr, violated(lengths.rowPtr), \"rowPtr\");\n }\n const { arena } = s;\n if (arena !== null) {\n const coldNeeded = names.some(\n (name) => (name === \"arcToEdge\" || name === \"edgeToArc\") && arena.segments[name] !== null,\n );\n const includesCold = coldNeeded && arena.byteLength <= bufferLimit;\n const bytes = includesCold ? arena.byteLength : arena.hotByteLength;\n const bindable = names.every((name) => {\n const segment = arena.segments[name];\n return segment === null || fits(segment.byteLength);\n });\n if (bytes <= bufferLimit && bindable) {\n const segmentOf = (name: CoreArrayName): { readonly offset: number; readonly size: number } | null => {\n const segment = arena.segments[name];\n if (segment === null) {\n return null;\n }\n const offset = segment.byteOffset - arena.byteOffset;\n return offset + segment.byteLength <= bytes ? { offset, size: segment.byteLength } : null;\n };\n return {\n kind: \"arena\",\n bytes,\n includesCold,\n segments: {\n rowPtr: segmentOf(\"rowPtr\"),\n colIdx: segmentOf(\"colIdx\"),\n weights: segmentOf(\"weights\"),\n arcToEdge: segmentOf(\"arcToEdge\"),\n edgeToArc: segmentOf(\"edgeToArc\"),\n },\n };\n }\n }\n if (names.every((name) => fits(lengths[name]))) {\n return {\n kind: \"perArray\",\n arrays: names.map((name) => ({\n name,\n byteLength: lengths[name],\n buffers: [{ byteOffset: 0, byteLength: lengths[name] }],\n })),\n };\n }\n if (names.includes(\"edgeToArc\") && !fits(lengths.edgeToArc)) {\n throw tooLarge(lengths.edgeToArc, violated(lengths.edgeToArc), \"binding\");\n }\n const arcsPerWindow = Math.min(arcsPerWindowFor(limits), alignDown(Math.floor(bufferLimit / 4)));\n if (arcsPerWindow < ARC_WINDOW_ALIGN) {\n throw tooLarge(4 * ARC_WINDOW_ALIGN, binding, \"binding\");\n }\n const windows = planArcWindows(s.rowPtr, s.arcCount, arcsPerWindow);\n const { buffers, placed } = placeWindows(windows, 4 * s.arcCount, bufferLimit);\n const arrays: PlannedArray[] = names.map((name) =>\n ARC_INDEXED.has(name)\n ? { name, byteLength: lengths[name], buffers }\n : { name, byteLength: lengths[name], buffers: [{ byteOffset: 0, byteLength: lengths[name] }] },\n );\n return { kind: \"windowed\", arrays, windows: placed, arcsPerWindow };\n}\n","/**\n * The upload cache of spec 4.1 / 4.3 / 4.5: every core array, view array, column and ad hoc array a kernel binds\n * lives on the device exactly once per snapshot core, keyed on the typed-array object (or the Column object for\n * columns, PLAN DECISION 8), recorded per serial so `release(snapshot)` destroys every buffer of a snapshot and its\n * withColumns() siblings, and tombstoned so a live user learns of the release through `isReleased` (spec 4.5).\n * Uploads follow the pure planner of ./upload-plan.ts: the arena path writes ONE buffer with ONE writeBuffer of the\n * hot prefix (or the full arena when a cold segment is needed and fits) and binds segments at\n * `segment.byteOffset - arena.byteOffset`; the perArray path writes one buffer per array; the windowed path (P4-T7,\n * PD-8) writes one buffer per PlannedArray range of every arc-indexed array and binds window 0 as the default\n * colIdx / weights, the whole window list and the per-array buffers riding on the CoreBinding for the row-walking\n * primitives to bind per window. Identity permutations are never materialised: presence is\n * decided from counts and flags, and the arcToEdge / edgeToArc getters are read only when a segment exists. Nothing\n * is freed by garbage collection; the once-only warning above warnUnreleasedSnapshots names the missing release.\n */\n\nimport {\n type AttributeTable,\n type Column,\n type CoreArrayName,\n type GpuEligibility,\n type GraphSnapshot,\n type TypedArrayData,\n} from \"@graphty/graph-format\";\n\nimport { STORAGE_ALIGN } from \"../constants.js\";\nimport { type AllocationTracker } from \"../device/error-scope.js\";\nimport { BufferUsage } from \"../device/webgpu-constants.js\";\nimport { WebGpuGraphError } from \"../errors.js\";\nimport { type PlanCaps } from \"../types/context.js\";\nimport { type ArcWindow, type Binding } from \"../types/memory.js\";\nimport { planUpload } from \"./upload-plan.js\";\n\n/** The core arrays a kernel binds by default (spec 4.1); the cold segments are named explicitly by the caller. */\nconst DEFAULT_NEED: readonly CoreArrayName[] = Object.freeze([\"rowPtr\", \"colIdx\", \"weights\"]);\n\n/** The five core arrays in arena (hot-to-cold) order. */\nconst CORE_ORDER: readonly CoreArrayName[] = Object.freeze([\"rowPtr\", \"colIdx\", \"weights\", \"arcToEdge\", \"edgeToArc\"]);\n\n/** The arc-indexed core arrays: the ones a windowed plan splits into window buffers (upload-plan.ts ARC_INDEXED). */\nconst ARC_INDEXED: readonly (\"colIdx\" | \"weights\" | \"arcToEdge\")[] = Object.freeze([\"colIdx\", \"weights\", \"arcToEdge\"]);\n\n/** Every resident buffer is bound by kernels, filled by writeBuffer and readable back (tests, readbacks of state). */\nconst RESIDENT_USAGE = BufferUsage.STORAGE | BufferUsage.COPY_DST | BufferUsage.COPY_SRC;\n\n/**\n * The core arrays of a snapshot on the device (spec 4.1); a null member is absent (zero-length, unweighted or an\n * identity permutation) and is bound as a dummy by the kernel layer (3.9). `Binding` itself is declared in\n * src/types/memory.ts (3.3). Exported by contract 3.8: P1-T4's graphBindings / graphOverrides and every later\n * kernel driver take it; nothing at P1-T2 imports it by name.\n * @public\n */\nexport interface CoreBinding {\n readonly serial: number;\n readonly plan: \"arena\" | \"perArray\" | \"windowed\";\n readonly rowPtr: Binding;\n readonly colIdx: Binding | null;\n readonly weights: Binding | null;\n readonly arcToEdge: Binding | null;\n readonly edgeToArc: Binding | null;\n readonly windows: readonly ArcWindow[] | null;\n /** The buffers each arc-indexed array was split into by the windowed plan (indexed by ArcWindow.bufferIndex; an absent array has none); non-null iff `plan === \"windowed\"`. */\n readonly arcBuffers: Readonly<Record<\"colIdx\" | \"weights\" | \"arcToEdge\", readonly GPUBuffer[]>> | null;\n readonly hasWeights: boolean;\n}\n\n/**\n * A view's arrays on the device plus the CPU-side scalars (degreeOrder's segmentOffsets) (spec 4.3). Exported by\n * contract 3.8: the degreeOrder permutation of P4's kernels is a ViewBinding; nothing at P1-T2 imports it by name.\n * @public\n */\nexport interface ViewBinding {\n readonly view:\n | \"reverse\"\n | \"coo\"\n | \"edgeList\"\n | \"outDegree\"\n | \"inDegree\"\n | \"degreeOrder\"\n | \"reverseDegreeOrder\"\n | \"mate\";\n readonly bindings: Readonly<Record<string, Binding>>;\n readonly scalars: Readonly<Record<string, readonly number[]>>;\n}\n\n/**\n * A column's gpuView() on the device (spec 4.3). Exported by contract 3.8: P3's layout inputs register columns\n * through it; nothing at P1-T2 imports it by name.\n * @public\n */\nexport interface ColumnBinding {\n readonly binding: Binding;\n readonly column: Column;\n readonly version: number;\n readonly eligibility: GpuEligibility;\n readonly components: number;\n}\n\n/**\n * An ad hoc array on the device (spec 4.1 last row); `destroy()` is the caller's when no owner was given. Exported\n * by contract 3.8: P3's model resolves column inputs to a registered ArrayBinding; nothing at P1-T2 imports it by\n * name.\n * @public\n */\nexport interface ArrayBinding {\n readonly binding: Binding;\n readonly byteLength: number;\n readonly owner: GraphSnapshot | null;\n destroy(): void;\n}\n\n/**\n * stats() shape (spec 4.1). Exported by contract 3.8 for the callers of ctx.residency.stats(); nothing at P1-T2\n * imports it by name.\n * @public\n */\nexport interface ResidencyStats {\n readonly buffers: number;\n readonly bytes: number;\n readonly snapshots: number;\n readonly perSnapshot: readonly {\n readonly serial: number;\n readonly label: string | null;\n readonly bytes: number;\n readonly buffers: number;\n }[];\n}\n\n/** One buffer the residency owns. */\ninterface Resident {\n /** The typed-array object or the Column object the buffer was uploaded for. */\n readonly key: object;\n readonly buffer: GPUBuffer;\n readonly byteLength: number;\n /** The owning record's serial, or null for an owner-less ad hoc array. */\n readonly serial: number | null;\n /** For columns: the column.version the buffer holds. */\n version: number;\n destroyed: boolean;\n}\n\n/** One uploaded segment of the arena buffer. */\ninterface ArenaSegmentBinding {\n readonly offset: number;\n readonly size: number;\n}\n\n/** Everything recorded for one serial (a snapshot and its withColumns() siblings). */\ninterface ResidencyRecord {\n readonly serial: number;\n readonly label: string | null;\n readonly entries: Resident[];\n plan: \"arena\" | \"perArray\" | \"windowed\" | null;\n arena: {\n readonly buffer: GPUBuffer;\n readonly segments: Readonly<Record<CoreArrayName, ArenaSegmentBinding | null>>;\n } | null;\n readonly bindings: Map<CoreArrayName, Binding>;\n /** Memo of the P7 views by `name` or `name + \":packed\"`, so a second view() call uploads nothing (spec 4.3). */\n readonly views: Map<string, ViewBinding>;\n /**\n * One fresh marker object per PACKED view, keyed the same way as `views`. It is the `key` argument of\n * upload(): a packed view must never be keyed on one of the snapshot's own arrays, because upload()\n * memoises on the key object and does NOT compare byte lengths, and `s.reverse()` is cached\n * (graph-format `graph-snapshot.ts:600-601`) so the packed and the unpacked builder see the same\n * `rev.rowPtr` object.\n */\n readonly packKeys: Map<string, object>;\n /** One marker object per window buffer, keyed `<name>:<bufferIndex>` (the packKey pattern: never one of the snapshot's own arrays). */\n readonly windowKeys: Map<string, object>;\n /** The windowed plan's windows, or null on the arena / perArray plans. */\n windows: readonly ArcWindow[] | null;\n /** The window buffers of every arc-indexed array uploaded so far (windowed plan only). */\n readonly arcBuffers: Map<CoreArrayName, GPUBuffer[]>;\n released: boolean;\n}\n\n/**\n * Whether a core array is arc-indexed (split into window buffers by a windowed plan).\n * @param name - the core array\n * @returns true for colIdx, weights and arcToEdge\n */\nfunction isArcIndexed(name: CoreArrayName): name is \"colIdx\" | \"weights\" | \"arcToEdge\" {\n return (ARC_INDEXED as readonly CoreArrayName[]).includes(name);\n}\n\n/**\n * Whether an ArrayBuffer-like is a SharedArrayBuffer (checked by tag so the global need not exist).\n * @param buffer - the buffer to test\n * @returns true for a SharedArrayBuffer\n */\nfunction isSharedBuffer(buffer: ArrayBufferLike): boolean {\n return Object.prototype.toString.call(buffer) === \"[object SharedArrayBuffer]\";\n}\n\n/**\n * The E_INVALID_ARGUMENT error of a bad residency argument.\n * @param argument - the argument name\n * @param value - the value given\n * @param expected - what was expected\n * @returns the error to throw\n */\nfunction invalid(argument: string, value: unknown, expected: string): WebGpuGraphError {\n return new WebGpuGraphError(\"E_INVALID_ARGUMENT\", `${argument}: expected ${expected}`, {\n argument,\n value,\n expected,\n });\n}\n\n/**\n * Throws E_SNAPSHOT { reason: \"detached\" } for a snapshot whose core was transferred away.\n * @param s - the snapshot\n */\nfunction assertAttached(s: GraphSnapshot): void {\n if (s.detached) {\n throw new WebGpuGraphError(\"E_SNAPSHOT\", `snapshot ${s.serial} is detached (its core was transferred away)`, {\n reason: \"detached\",\n serial: s.serial,\n });\n }\n}\n\n/**\n * Whether a core array exists on the snapshot, from counts and flags alone (mirrors coreByteLengths of\n * ./upload-plan.ts; spec 5.6: zero-length arrays are never uploaded; spec 4.1: identity permutations never\n * materialised).\n * @param s - the snapshot\n * @param name - the core array\n * @returns true when the array has bytes to upload\n */\nfunction isPresent(s: GraphSnapshot, name: CoreArrayName): boolean {\n switch (name) {\n case \"rowPtr\":\n return true;\n case \"colIdx\":\n return s.arcCount > 0;\n case \"weights\":\n return s.flags.weighted && s.arcCount > 0;\n case \"arcToEdge\":\n return !s.flags.arcToEdgeIsIdentity && s.arcCount > 0;\n case \"edgeToArc\":\n return !s.flags.arcToEdgeIsIdentity && s.edgeCount > 0;\n default:\n return false;\n }\n}\n\n/**\n * The array object of a PRESENT core array (the caller checked isPresent, so the two getters never materialise).\n * @param s - the snapshot\n * @param name - the core array\n * @returns the array\n */\nfunction coreArray(s: GraphSnapshot, name: CoreArrayName): TypedArrayData {\n switch (name) {\n case \"rowPtr\":\n return s.rowPtr;\n case \"colIdx\":\n return s.colIdx;\n case \"weights\": {\n const { weights } = s;\n if (weights === null) {\n throw invalid(\"weights\", null, \"a weighted snapshot\");\n }\n return weights;\n }\n case \"arcToEdge\":\n return s.arcToEdge;\n case \"edgeToArc\":\n return s.edgeToArc;\n default:\n throw invalid(\"name\", name, \"a core array name\");\n }\n}\n\n/** The upload cache (spec 4.1): WeakMap on array objects, WeakMap on snapshots, a strong Map by serial; @internal (reached as ctx.residency). */\nexport class GraphResidency {\n private readonly device: GPUDevice;\n private readonly caps: PlanCaps;\n private readonly allocator: AllocationTracker;\n private readonly warnUnreleasedSnapshots: number;\n private readonly warn: (message: string) => void;\n /** Fast lookup by the uploaded object (a typed array or a Column). */\n private readonly residents = new WeakMap<object, Resident>();\n /** Fast lookup of a snapshot's record (entries of released records are recognised by `released`). */\n private readonly records = new WeakMap<GraphSnapshot, ResidencyRecord>();\n /** The strong map by serial: withColumns() siblings share one record; cleared by release. */\n private readonly bySerial = new Map<number, ResidencyRecord>();\n /** Owner-less ad hoc arrays. */\n private readonly orphans = new Set<Resident>();\n /** Serials released and not re-uploaded. */\n private readonly tombstones = new Set<number>();\n private liveCount = 0;\n private liveBytesValue = 0;\n private warned = false;\n private disposed = false;\n\n /**\n * Creates an empty residency over a device.\n * @param device - the device (queue.writeBuffer)\n * @param caps - the device capabilities the planner reads\n * @param allocator - the context's OOM-scoped allocator (every buffer is created and destroyed through it)\n * @param options - the once-only warning\n * @param options.warnUnreleasedSnapshots - the resident-snapshot count above which the warning fires once\n * @param options.warn - the warning sink; default console.warn\n */\n constructor(\n device: GPUDevice,\n caps: PlanCaps,\n allocator: AllocationTracker,\n options: { readonly warnUnreleasedSnapshots: number; readonly warn?: ((message: string) => void) | undefined },\n ) {\n this.device = device;\n this.caps = caps;\n this.allocator = allocator;\n this.warnUnreleasedSnapshots = options.warnUnreleasedSnapshots;\n this.warn =\n options.warn ??\n ((message: string): void => {\n console.warn(message);\n });\n }\n\n /**\n * Uploads (or finds) the core; `need` defaults to [\"rowPtr\", \"colIdx\", \"weights\"]; cold segments on demand\n * (spec 4.2). Never materialises an identity permutation. A windowed plan (spec 4.2, PD-8) uploads every\n * arc-indexed array as the plan's buffer ranges and binds window 0 as its default binding; rowPtr and edgeToArc\n * stay whole. A tombstoned serial is lifted and re-uploaded (PLAN DECISION 7).\n * @param s - the snapshot\n * @param need - the core arrays to bind (rowPtr is always included; absent arrays are ignored)\n * @returns the core binding (a frozen object; grows as cold segments are added)\n */\n core(s: GraphSnapshot, need?: readonly CoreArrayName[]): CoreBinding {\n this.assertLive();\n assertAttached(s);\n const wanted = need ?? DEFAULT_NEED;\n const names = CORE_ORDER.filter((name) => (name === \"rowPtr\" || wanted.includes(name)) && isPresent(s, name));\n const plan = planUpload(s, this.caps, names);\n const record = this.ensureRecord(s);\n if (record.plan === null) {\n record.plan = plan.kind;\n if (plan.kind === \"arena\" && s.arena !== null) {\n const { arena } = s;\n const resident = this.upload(\n record,\n s.rowPtr,\n new Uint8Array(arena.buffer, arena.byteOffset, plan.bytes),\n `residency:core:${record.serial}:arena`,\n );\n record.arena = { buffer: resident.buffer, segments: plan.segments };\n }\n if (plan.kind === \"windowed\") {\n record.windows = plan.windows;\n }\n }\n for (const name of names) {\n if (!record.bindings.has(name)) {\n const planned = plan.kind === \"windowed\" ? plan.arrays.find((a) => a.name === name) : undefined;\n record.bindings.set(\n name,\n planned !== undefined && planned.buffers.length > 0 && record.windows !== null && isArcIndexed(name)\n ? this.bindWindowed(record, s, name, planned.buffers, record.windows[0])\n : this.bindCore(record, s, name),\n );\n }\n }\n const rowPtr = record.bindings.get(\"rowPtr\");\n if (rowPtr === undefined) {\n throw invalid(\"rowPtr\", null, \"a bound rowPtr (internal invariant)\");\n }\n const weights = record.bindings.get(\"weights\") ?? null;\n return Object.freeze({\n serial: record.serial,\n plan: plan.kind,\n rowPtr,\n colIdx: record.bindings.get(\"colIdx\") ?? null,\n weights,\n arcToEdge: record.bindings.get(\"arcToEdge\") ?? null,\n edgeToArc: record.bindings.get(\"edgeToArc\") ?? null,\n windows: record.windows,\n arcBuffers:\n record.windows === null\n ? null\n : Object.freeze({\n colIdx: Object.freeze([...(record.arcBuffers.get(\"colIdx\") ?? [])]),\n weights: Object.freeze([...(record.arcBuffers.get(\"weights\") ?? [])]),\n arcToEdge: Object.freeze([...(record.arcBuffers.get(\"arcToEdge\") ?? [])]),\n }),\n hasWeights: weights !== null,\n });\n }\n\n /**\n * Uploads (or finds) a view: outDegree / inDegree / degreeOrder / reverseDegreeOrder upload one array each;\n * reverse and edgeList (P7) upload their arrays perArray, never into the arena, and are memoised per record so\n * a second call uploads nothing (spec 4.3). coo uploads its per-arc `src` (P11; the rest aliases the core); mate ->\n * E_UNSUPPORTED. packViews concatenates a\n * reverse or edgeList view into ONE buffer at STORAGE_ALIGN offsets; on any other view `true` is E_UNSUPPORTED\n * { option: \"packViews\" }.\n * @param s - the snapshot\n * @param name - the view\n * @param options - view options\n * @param options.packViews - pack the reverse / edgeList arrays into one buffer (a no-op on an undirected reverse)\n * @returns the view binding\n */\n view(\n s: GraphSnapshot,\n name: \"reverse\" | \"coo\" | \"edgeList\" | \"outDegree\" | \"inDegree\" | \"degreeOrder\" | \"reverseDegreeOrder\" | \"mate\",\n options?: { readonly packViews?: boolean | undefined },\n ): ViewBinding {\n this.assertLive();\n assertAttached(s);\n const packed = options?.packViews === true;\n if (name === \"reverse\" || name === \"edgeList\") {\n this.assertNotReleased(s);\n this.assertNonEmpty(s);\n const memoKey = packed ? `${name}:packed` : name;\n const record = this.ensureRecord(s);\n const memo = record.views.get(memoKey);\n if (memo !== undefined) {\n return memo;\n }\n const built =\n name === \"reverse\" ? this.buildReverse(s, record, packed) : this.buildEdgeList(s, record, packed);\n record.views.set(memoKey, built);\n return built;\n }\n if (packed) {\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"packViews applies to the reverse and edgeList views only\", {\n option: \"packViews\",\n hint: `the ${name} view uploads one array`,\n });\n }\n let array: TypedArrayData;\n let bindingName: string;\n let scalars: Readonly<Record<string, readonly number[]>> = {};\n switch (name) {\n case \"outDegree\":\n this.assertNotReleased(s);\n this.assertNonEmpty(s);\n array = s.outDegree();\n bindingName = \"outDegree\";\n break;\n case \"inDegree\":\n this.assertNotReleased(s);\n this.assertNonEmpty(s);\n array = s.inDegree();\n bindingName = \"inDegree\";\n break;\n case \"degreeOrder\": {\n this.assertNotReleased(s);\n this.assertNonEmpty(s);\n const order = s.degreeOrder();\n array = order.perm;\n bindingName = \"perm\";\n scalars = { segmentOffsets: Array.from(order.segmentOffsets) };\n break;\n }\n case \"reverseDegreeOrder\": {\n this.assertNotReleased(s);\n this.assertNonEmpty(s);\n const order = s.degreeOrder({ of: \"reverse\" });\n array = order.perm;\n bindingName = \"perm\";\n scalars = { segmentOffsets: Array.from(order.segmentOffsets) };\n break;\n }\n case \"coo\":\n // dst, arcToEdge and weights alias the core's colIdx / arcToEdge / weights (graph-format design 7.2):\n // only the per-arc source is new, and a kernel binds the rest from core()\n this.assertNotReleased(s);\n this.assertNonEmpty(s);\n if (s.arcCount === 0) {\n return Object.freeze({ view: name, bindings: Object.freeze({}), scalars: Object.freeze({}) });\n }\n array = s.coo().src;\n bindingName = \"src\";\n break;\n case \"mate\":\n throw new WebGpuGraphError(\"E_UNSUPPORTED\", \"the mate view is not uploaded: no kernel reads it\", {\n feature: \"view:mate\",\n hint: \"outDegree, inDegree, degreeOrder, reverseDegreeOrder, coo, reverse and edgeList are uploaded\",\n });\n default:\n throw invalid(\"name\", name, \"a view name\");\n }\n const record = this.ensureRecord(s);\n const resident = this.upload(record, array, array, `residency:view:${record.serial}:${name}`);\n const binding: Binding = { buffer: resident.buffer, offset: 0, size: resident.byteLength, window: null };\n return Object.freeze({\n view: name,\n bindings: Object.freeze({ [bindingName]: binding }),\n scalars: Object.freeze(scalars),\n });\n }\n\n /**\n * The reverse adjacency's bindings. On an UNDIRECTED snapshot graph-format invariant I7 makes reverse() return\n * the FORWARD arrays, so the core bindings ARE the reverse bindings and nothing is uploaded -- delegating to\n * core() rather than re-uploading the arrays is what makes that true on the arena plan as well, where the\n * per-array WeakMap key resolves to the whole-arena resident (spec 4.3 lines 1182-1186). `fwdArc` is never\n * uploaded (spec 13 row P7). `packed` is ignored when undirected: there is nothing to pack.\n * @param s - the snapshot\n * @param record - its residency record\n * @param packed - concatenate the arrays into one buffer (directed only)\n * @returns the view binding\n */\n private buildReverse(s: GraphSnapshot, record: ResidencyRecord, packed: boolean): ViewBinding {\n const rev = s.reverse();\n if (!s.directed) {\n const core = this.core(s, [\"rowPtr\", \"colIdx\", \"weights\"]);\n if (core.plan === \"windowed\") {\n // a view is never windowed (spec 4.3): window 0's colIdx must not pose as the whole reverse adjacency\n throw new WebGpuGraphError(\n \"E_TOO_LARGE\",\n `snapshot ${s.serial}: the undirected reverse view is the core, which needs arc windows (${core.windows?.length ?? 0}) that no view executes`,\n {\n needed: 4 * s.arcCount,\n limit: this.caps.limits.maxStorageBufferBindingSize,\n path: \"windowed\",\n algorithm: null,\n },\n );\n }\n const bindings: Record<string, Binding> = { rowPtr: core.rowPtr };\n if (core.colIdx !== null) {\n bindings.colIdx = core.colIdx;\n }\n if (core.weights !== null) {\n bindings.weights = core.weights;\n }\n return Object.freeze({\n view: \"reverse\",\n bindings: Object.freeze(bindings),\n scalars: Object.freeze({ arcCount: [rev.arcCount], directed: [0] }),\n });\n }\n const arrays: [string, TypedArrayData][] = [\n [\"rowPtr\", rev.rowPtr],\n [\"colIdx\", rev.colIdx],\n ];\n if (rev.weights !== null) {\n arrays.push([\"weights\", rev.weights]);\n }\n const bindings = packed\n ? this.packArrays(\n record,\n arrays,\n this.packKey(record, \"reverse:packed\"),\n `residency:view:${record.serial}:reverse:packed`,\n )\n : this.separateArrays(record, arrays, `residency:view:${record.serial}:reverse`);\n return Object.freeze({\n view: \"reverse\",\n bindings,\n scalars: Object.freeze({ arcCount: [rev.arcCount], directed: [1] }),\n });\n }\n\n /**\n * The each-edge-once binding an edge-parallel kernel uses on directed and undirected snapshots alike (spec 8.1\n * row 2); `arc` is not uploaded (no kernel of P7 reads it).\n * @param s - the snapshot\n * @param record - its residency record\n * @param packed - concatenate into one buffer\n * @returns the view binding\n */\n private buildEdgeList(s: GraphSnapshot, record: ResidencyRecord, packed: boolean): ViewBinding {\n const list = s.edgeList();\n const arrays: [string, TypedArrayData][] = [\n [\"src\", list.src],\n [\"dst\", list.dst],\n ];\n if (list.weights !== null) {\n arrays.push([\"weights\", list.weights]);\n }\n const bindings = packed\n ? this.packArrays(\n record,\n arrays,\n this.packKey(record, \"edgeList:packed\"),\n `residency:view:${record.serial}:edgeList:packed`,\n )\n : this.separateArrays(record, arrays, `residency:view:${record.serial}:edgeList`);\n return Object.freeze({\n view: \"edgeList\",\n bindings,\n scalars: Object.freeze({ edgeCount: [s.edgeCount] }),\n });\n }\n\n /**\n * One resident per array (spec 4.3: views upload in perArray mode, never into the arena). An empty array (the\n * colIdx of an edgeless directed reverse view, the src / dst of an edgeless edgeList) is skipped: spec 5.6 never\n * uploads a zero-length array, and Kernel.bind rejects a zero-size binding, so it is absent as in core().\n * @param record - the owning record\n * @param arrays - the named arrays\n * @param label - the buffer label prefix\n * @returns the bindings by name\n */\n private separateArrays(\n record: ResidencyRecord,\n arrays: readonly (readonly [string, TypedArrayData])[],\n label: string,\n ): Readonly<Record<string, Binding>> {\n const bindings: Record<string, Binding> = {};\n for (const [name, array] of arrays) {\n if (array.byteLength === 0) {\n continue;\n }\n const resident = this.upload(record, array, array, `${label}:${name}`);\n bindings[name] = { buffer: resident.buffer, offset: 0, size: resident.byteLength, window: null };\n }\n return Object.freeze(bindings);\n }\n\n /**\n * The arrays concatenated into ONE buffer at STORAGE_ALIGN-aligned offsets (spec 4.3 packViews): one\n * createBuffer and one writeBuffer instead of three of each, which is what the option buys. The resident is\n * keyed on `key`, a marker object owned by the record (packKey), NOT on one of the snapshot's arrays: upload()\n * returns an existing resident whenever the key matches and the serial matches, without comparing byte\n * lengths, so keying the packed buffer on `rev.rowPtr` would make the packed and the unpacked view of one\n * snapshot collide -- whichever was built second would get the other's buffer. The record still owns the\n * resident, so release(s) destroys it with the rest. Offsets are STORAGE_ALIGN-aligned because Kernel.bind\n * rejects any other offset synchronously (E_INVALID_ARGUMENT { argument: \"offset\" }). Empty arrays are left\n * out as in separateArrays; when nothing is left, nothing is uploaded.\n * @param record - the owning record\n * @param all - the named arrays, in buffer order\n * @param key - the marker object the resident is keyed on\n * @param label - the buffer label\n * @returns the bindings by name, all into the one buffer\n */\n private packArrays(\n record: ResidencyRecord,\n all: readonly (readonly [string, TypedArrayData])[],\n key: object,\n label: string,\n ): Readonly<Record<string, Binding>> {\n const arrays = all.filter(([, array]) => array.byteLength > 0);\n if (arrays.length === 0) {\n return Object.freeze({});\n }\n const offsets: number[] = [];\n let total = 0;\n for (const [, array] of arrays) {\n offsets.push(total);\n total += Math.ceil(array.byteLength / STORAGE_ALIGN) * STORAGE_ALIGN;\n }\n const staging = new Uint8Array(total);\n arrays.forEach(([, array], i) => {\n staging.set(new Uint8Array(array.buffer, array.byteOffset, array.byteLength), offsets[i]);\n });\n const resident = this.upload(record, key, staging, label);\n const bindings: Record<string, Binding> = {};\n arrays.forEach(([name, array], i) => {\n bindings[name] = { buffer: resident.buffer, offset: offsets[i], size: array.byteLength, window: null };\n });\n return Object.freeze(bindings);\n }\n\n /**\n * The upload key of a packed view: a marker object allocated once per record and memo name, never one of the\n * snapshot's arrays.\n * @param record - the owning record\n * @param memoKey - the `views` memo key of this packed view\n * @returns the stable marker object\n */\n private packKey(record: ResidencyRecord, memoKey: string): object {\n const existing = record.packKeys.get(memoKey);\n if (existing !== undefined) {\n return existing;\n }\n const created = {};\n record.packKeys.set(memoKey, created);\n return created;\n }\n\n /**\n * gpuView(name) + column.version; re-uploads in place when the version changed and the byte length did not\n * (spec 4.3). CONTRACT DECISION: `owner` is required so release(owner) can find the buffer (a table has no\n * back-reference to its snapshot). The key is the Column object (PLAN DECISION 8). E_GPU_INELIGIBLE and\n * E_UNKNOWN_COLUMN from the format pass through unchanged.\n * @param table - the table holding the column\n * @param name - the column name\n * @param owner - the snapshot the buffer is recorded against\n * @returns the column binding\n */\n column(table: AttributeTable, name: string, owner: GraphSnapshot): ColumnBinding {\n this.assertLive();\n assertAttached(owner);\n this.assertNotReleased(owner);\n const column = table.require(name);\n const data = table.gpuView(name);\n if (data.byteLength === 0) {\n throw invalid(\"column\", name, \"a column with at least one row (zero-length arrays are never uploaded)\");\n }\n const record = this.ensureRecord(owner);\n const label = `residency:column:${record.serial}:${column.meta.domain}.${name}`;\n const existing = this.residents.get(column);\n let resident: Resident;\n if (\n existing !== undefined &&\n !existing.destroyed &&\n existing.serial === record.serial &&\n existing.byteLength === data.byteLength\n ) {\n resident = existing;\n if (resident.version !== column.version) {\n this.device.queue.writeBuffer(resident.buffer, 0, data);\n resident.version = column.version;\n }\n } else {\n if (existing !== undefined) {\n // the stale buffer stays in its record until release (spec 4.1: no leak, no stale read)\n this.residents.delete(column);\n }\n resident = this.upload(record, column, data, label);\n resident.version = column.version;\n }\n return Object.freeze({\n binding: { buffer: resident.buffer, offset: 0, size: resident.byteLength, window: null },\n column,\n version: resident.version,\n eligibility: column.gpu,\n components: column.meta.components,\n });\n }\n\n /**\n * Any format array keyed on the object; registered against `owner` when given (spec 4.1).\n * @param key - the array (a non-empty, 4-byte-multiple array over a plain ArrayBuffer)\n * @param label - the buffer label suffix\n * @param owner - the snapshot to record the buffer against, or undefined for a caller-owned buffer\n * @returns the array binding; `destroy()` is idempotent (PLAN DECISION 12)\n */\n array(key: TypedArrayData, label: string, owner?: GraphSnapshot): ArrayBinding {\n this.assertLive();\n if (key.byteLength === 0 || key.byteLength % 4 !== 0) {\n throw invalid(\"key\", key.byteLength, \"a non-empty array whose byteLength is a multiple of 4\");\n }\n if (isSharedBuffer(key.buffer)) {\n throw invalid(\"key\", \"SharedArrayBuffer\", \"an array over a plain ArrayBuffer\");\n }\n let record: ResidencyRecord | null = null;\n if (owner !== undefined) {\n assertAttached(owner);\n this.assertNotReleased(owner);\n record = this.ensureRecord(owner);\n }\n const resident = this.upload(record, key, key, `residency:array:${label}`);\n const binding: Binding = { buffer: resident.buffer, offset: 0, size: resident.byteLength, window: null };\n return {\n binding,\n byteLength: resident.byteLength,\n owner: owner ?? null,\n destroy: (): void => {\n this.destroyResident(resident, record);\n },\n };\n }\n\n /**\n * Destroys every buffer recorded for s.serial (siblings included, Q-27) and tombstones the serial; idempotent\n * (spec 4.5); safe on a snapshot never uploaded (nothing to tombstone, PLAN DECISION 7).\n * @param s - the snapshot (or any withColumns() sibling)\n */\n release(s: GraphSnapshot): void {\n const record = this.bySerial.get(s.serial);\n if (record === undefined) {\n return;\n }\n for (const resident of [...record.entries]) {\n this.destroyResident(resident, record);\n }\n this.forget(record);\n this.tombstones.add(s.serial);\n }\n\n /** Drops every record WITHOUT destroying (device lost: the buffers are gone). @internal */\n clearOnLoss(): void {\n for (const record of [...this.bySerial.values()]) {\n for (const resident of record.entries) {\n resident.destroyed = true;\n if (this.residents.get(resident.key) === resident) {\n this.residents.delete(resident.key);\n }\n }\n record.entries.length = 0;\n this.forget(record);\n }\n for (const resident of this.orphans) {\n resident.destroyed = true;\n if (this.residents.get(resident.key) === resident) {\n this.residents.delete(resident.key);\n }\n }\n this.orphans.clear();\n this.liveCount = 0;\n this.liveBytesValue = 0;\n }\n\n /** Destroys everything (ctx.dispose()); idempotent. @internal */\n destroyAll(): void {\n for (const record of [...this.bySerial.values()]) {\n for (const resident of [...record.entries]) {\n this.destroyResident(resident, record);\n }\n this.forget(record);\n }\n for (const resident of [...this.orphans]) {\n this.destroyResident(resident, null);\n }\n this.disposed = true;\n }\n\n /**\n * The resident buffers, bytes and snapshots (spec 4.1).\n * @returns the statistics\n */\n stats(): ResidencyStats {\n const perSnapshot = [...this.bySerial.values()].map((record) => ({\n serial: record.serial,\n label: record.label,\n bytes: record.entries.reduce((sum, resident) => sum + resident.byteLength, 0),\n buffers: record.entries.length,\n }));\n return { buffers: this.liveCount, bytes: this.liveBytesValue, snapshots: this.bySerial.size, perSnapshot };\n }\n\n /**\n * Bytes of every resident buffer (graft: C R-18).\n * @returns the resident byte count\n */\n get residentBytes(): number {\n return this.liveBytesValue;\n }\n\n /**\n * True when the serial was released and not re-uploaded. @internal\n * @param serial - a snapshot serial\n * @returns whether a live user holding bindings of that serial must stop\n */\n isReleased(serial: number): boolean {\n return this.tombstones.has(serial);\n }\n\n /**\n * Binds one core array: a segment of the arena buffer when the buffer holds it, else its own buffer keyed on\n * the array object (the cold-segment-on-demand path of spec 4.2, and the whole perArray path).\n * @param record - the snapshot's record\n * @param s - the snapshot\n * @param name - a PRESENT core array\n * @returns the binding\n */\n private bindCore(record: ResidencyRecord, s: GraphSnapshot, name: CoreArrayName): Binding {\n if (record.arena !== null) {\n const segment = record.arena.segments[name];\n if (segment !== null) {\n return { buffer: record.arena.buffer, offset: segment.offset, size: segment.size, window: null };\n }\n }\n const array = coreArray(s, name);\n const resident = this.upload(record, array, array, `residency:core:${record.serial}:${name}`);\n return { buffer: resident.buffer, offset: 0, size: resident.byteLength, window: null };\n }\n\n /**\n * Uploads one arc-indexed array as the windowed plan's buffer ranges (spec 4.2: an array above maxBufferSize is\n * split across buffers at window boundaries), each keyed on a marker object of the record (windowKey), and\n * returns window 0's binding so a caller that ignores windows still binds something valid (PD-8).\n * @param record - the snapshot's record\n * @param s - the snapshot\n * @param name - a PRESENT arc-indexed core array\n * @param ranges - the plan's buffer ranges of the array\n * @param first - window 0\n * @returns the binding of window 0\n */\n private bindWindowed(\n record: ResidencyRecord,\n s: GraphSnapshot,\n name: \"colIdx\" | \"weights\" | \"arcToEdge\",\n ranges: readonly { readonly byteOffset: number; readonly byteLength: number }[],\n first: ArcWindow,\n ): Binding {\n const array = coreArray(s, name);\n const buffers = ranges.map(\n (range, index) =>\n this.upload(\n record,\n this.windowKey(record, `${name}:${index}`),\n new Uint8Array(array.buffer, array.byteOffset + range.byteOffset, range.byteLength),\n `residency:core:${record.serial}:${name}:w${index}`,\n ).buffer,\n );\n record.arcBuffers.set(name, buffers);\n return {\n buffer: buffers[first.bufferIndex],\n offset: first.offset,\n size: 4 * (first.end - first.start),\n window: first,\n };\n }\n\n /**\n * The upload key of one window buffer: a marker object allocated once per record and `<name>:<bufferIndex>`.\n * @param record - the owning record\n * @param memoKey - `<name>:<bufferIndex>`\n * @returns the stable marker object\n */\n private windowKey(record: ResidencyRecord, memoKey: string): object {\n const existing = record.windowKeys.get(memoKey);\n if (existing !== undefined) {\n return existing;\n }\n const created = {};\n record.windowKeys.set(memoKey, created);\n return created;\n }\n\n /**\n * Uploads `data` into a new buffer keyed on `key`, or returns the resident already uploaded for that key by\n * the same owner (PLAN DECISION 11: a resident belongs to one record).\n * @param record - the owning record, or null for an owner-less array\n * @param key - the object the buffer is keyed on\n * @param data - the bytes (byteLength a multiple of 4, graph-format invariant I10; a view over a plain\n * ArrayBuffer, which is what writeBuffer's GPUAllowSharedBufferSource accepts under @webgpu/types 0.1.72)\n * @param label - the buffer label\n * @returns the resident\n */\n private upload(\n record: ResidencyRecord | null,\n key: object,\n data: ArrayBufferView<ArrayBuffer>,\n label: string,\n ): Resident {\n const serial = record === null ? null : record.serial;\n const existing = this.residents.get(key);\n if (existing !== undefined && !existing.destroyed && existing.serial === serial) {\n return existing;\n }\n const buffer = this.allocator.createBuffer({ label, size: data.byteLength, usage: RESIDENT_USAGE });\n this.device.queue.writeBuffer(buffer, 0, data);\n const resident: Resident = { key, buffer, byteLength: data.byteLength, serial, version: 0, destroyed: false };\n this.residents.set(key, resident);\n if (record === null) {\n this.orphans.add(resident);\n } else {\n record.entries.push(resident);\n }\n this.liveCount++;\n this.liveBytesValue += data.byteLength;\n return resident;\n }\n\n /**\n * Destroys one resident buffer and unregisters it; idempotent.\n * @param resident - the resident\n * @param record - its owning record, or null for an orphan\n */\n private destroyResident(resident: Resident, record: ResidencyRecord | null): void {\n if (resident.destroyed) {\n return;\n }\n resident.destroyed = true;\n this.allocator.destroy(resident.buffer);\n if (this.residents.get(resident.key) === resident) {\n this.residents.delete(resident.key);\n }\n if (record === null) {\n this.orphans.delete(resident);\n } else {\n const index = record.entries.indexOf(resident);\n if (index >= 0) {\n record.entries.splice(index, 1);\n }\n }\n this.liveCount--;\n this.liveBytesValue -= resident.byteLength;\n }\n\n /**\n * Marks a record released and drops it from the serial map (the snapshot WeakMap entries recognise it by the flag).\n * @param record - the record\n */\n private forget(record: ResidencyRecord): void {\n record.released = true;\n record.bindings.clear();\n record.views.clear();\n record.packKeys.clear();\n record.windowKeys.clear();\n record.arcBuffers.clear();\n record.windows = null;\n record.arena = null;\n record.plan = null;\n this.bySerial.delete(record.serial);\n }\n\n /**\n * The record of a snapshot's serial, created when absent (which lifts a tombstone and may fire the warning).\n * @param s - the snapshot\n * @returns the record\n */\n private ensureRecord(s: GraphSnapshot): ResidencyRecord {\n let record = this.records.get(s);\n if (record !== undefined && record.released) {\n record = undefined;\n }\n if (record === undefined) {\n record = this.bySerial.get(s.serial);\n }\n if (record === undefined) {\n record = {\n serial: s.serial,\n label: s.label,\n entries: [],\n plan: null,\n arena: null,\n bindings: new Map<CoreArrayName, Binding>(),\n views: new Map<string, ViewBinding>(),\n packKeys: new Map<string, object>(),\n windowKeys: new Map<string, object>(),\n windows: null,\n arcBuffers: new Map<CoreArrayName, GPUBuffer[]>(),\n released: false,\n };\n this.bySerial.set(s.serial, record);\n this.tombstones.delete(s.serial);\n if (!this.warned && this.bySerial.size > this.warnUnreleasedSnapshots) {\n this.warned = true;\n this.warn(\n `[webgpu-graph-algorithms] ${this.bySerial.size} snapshots are resident on the device (warnUnreleasedSnapshots = ${this.warnUnreleasedSnapshots}); call ctx.release(snapshot) for superseded snapshots -- GPU memory is never freed by garbage collection (spec 4.1)`,\n );\n }\n }\n this.records.set(s, record);\n return record;\n }\n\n /**\n * Throws E_RELEASED for a tombstoned serial (a bind without a fresh core()).\n * @param s - the snapshot\n */\n private assertNotReleased(s: GraphSnapshot): void {\n if (this.tombstones.has(s.serial)) {\n throw new WebGpuGraphError(\n \"E_RELEASED\",\n `snapshot ${s.serial} was released; upload it again through core() before binding views, columns or arrays`,\n { serial: s.serial },\n );\n }\n }\n\n /**\n * Throws E_INVALID_ARGUMENT for an empty snapshot (a view of it would be a zero-length array, spec 5.6).\n * @param s - the snapshot\n */\n private assertNonEmpty(s: GraphSnapshot): void {\n if (s.nodeCount === 0) {\n throw invalid(\"snapshot\", 0, \"nodeCount > 0 (an empty snapshot has no per-node view to upload)\");\n }\n }\n\n /** Throws E_DISPOSED after destroyAll() (PLAN DECISION 13). */\n private assertLive(): void {\n if (this.disposed) {\n throw new WebGpuGraphError(\"E_DISPOSED\", \"the residency was disposed\", { label: \"residency\" });\n }\n }\n}\n","/**\n * GpuContext (spec 2.2, 2.8, 3.3, 5.7; contract 3.5): one device, its caps and the singletons built on it --\n * the composition root of D26. probe() never creates a device; create() runs the six steps of spec 2.2 in\n * order; from() adopts a device the caller owns. Step 5 (the uncapturederror sink and the device.lost\n * watcher) and step 6 (the AllocationTracker, GraphResidency, BufferPool, Readback and PipelineCache) run\n * in the private constructor. The Profiler is constructed when \"timestamp-query\" is on the device (contract\n * 3.5; P2-T1) with `quantised` = runtime !== \"node\" (Dawn-node is the only runtime whose ticks are known\n * unquantised, spec 2.6). This file never imports ./kernels.js or ./wgsl/**.\n */\n\nimport type { GraphSnapshot } from \"@graphty/graph-format\";\n\nimport { DEFAULT_WARN_UNRELEASED_SNAPSHOTS } from \"./constants.js\";\nimport {\n buildRequiredFeatures,\n buildRequiredLimits,\n requestAdapter,\n requestDevice,\n summarizeAdapter,\n} from \"./device/acquire.js\";\nimport { assertPlanLimits, capsFromDevice, captureCaps, workgroupSizeFor } from \"./device/caps.js\";\nimport { AllocationTracker } from \"./device/error-scope.js\";\nimport { deviceLostError, installUncapturedErrorSink, PendingErrorSlot, watchDeviceLost } from \"./device/lost.js\";\nimport { isWebGpuGraphError, WebGpuGraphError } from \"./errors.js\";\nimport { PipelineCache } from \"./kernel/pipeline-cache.js\";\nimport { Profiler } from \"./kernel/profiler.js\";\nimport { BufferPool } from \"./memory/buffer-pool.js\";\nimport { Readback } from \"./memory/readback.js\";\nimport { GraphResidency } from \"./memory/residency.js\";\nimport type { GpuCaps, GpuContextOptions, GpuDebugFlags, ProbeOptions, ProbeResult } from \"./types/context.js\";\n\n/** The label a context and its device carry when create() is given none. */\nconst DEFAULT_LABEL = \"webgpu-graph-algorithms\";\n/** The optionalFeatures default of spec 2.2. */\nconst DEFAULT_OPTIONAL_FEATURES: readonly GPUFeatureName[] = Object.freeze([\"subgroups\", \"timestamp-query\"]);\n/** The powerPreference default of spec 2.2 (Chrome 145 needs it; Dawn-node ignores it). */\nconst DEFAULT_POWER_PREFERENCE: GPUPowerPreference = \"high-performance\";\n\n/** What the private constructor takes: the device, its caps and the create-time choices. */\ninterface ContextInit {\n readonly device: GPUDevice;\n readonly caps: GpuCaps;\n readonly ownsDevice: boolean;\n readonly label: string;\n readonly onError: ((error: WebGpuGraphError) => void) | null;\n readonly warnUnreleasedSnapshots: number;\n}\n\n/**\n * Step 1 of create(): the caller's UNUSED adapter, else one requested from `gpu`; neither -> E_NO_WEBGPU.\n * @param options - the create options\n * @returns an adapter no device was requested from\n */\nasync function adapterOf(options: GpuContextOptions): Promise<GPUAdapter> {\n if (options.adapter !== undefined) {\n return options.adapter;\n }\n if (options.gpu !== undefined) {\n return requestAdapter(options.gpu, options.powerPreference ?? DEFAULT_POWER_PREFERENCE);\n }\n throw new WebGpuGraphError(\"E_NO_WEBGPU\", \"GpuContext.create needs one of gpu, adapter or device\", {\n reason: \"no gpu, adapter or device given\",\n hint: \"pass navigator.gpu (browser) or the gpu of createNodeGpu() (Node), or use the ./browser and ./node entries\",\n });\n}\n\n/** One device, its caps and the singletons built on it (spec 3.3; the composition root of D26). */\nexport class GpuContext {\n /** The device (owned when create() made it, adopted otherwise). */\n readonly device: GPUDevice;\n /** The capability record captured from device.limits / device.features (spec 3.3). */\n readonly caps: GpuCaps;\n /** Resolves with the lost info once the device is lost or destroyed (spec 2.8). */\n readonly lost: Promise<GPUDeviceLostInfo>;\n /**\n * The upload cache (spec 3.3).\n * @internal\n */\n readonly residency: GraphResidency;\n /** Non-null when \"timestamp-query\" was granted (P2-T1 makes it functional; P1 always null). */\n readonly profiler: Profiler | null;\n /**\n * The compile-once pipeline cache.\n * @internal\n */\n readonly pipelines: PipelineCache;\n /**\n * The scratch pool.\n * @internal\n */\n readonly pool: BufferPool;\n /**\n * The staging ring.\n * @internal\n */\n readonly readback: Readback;\n /**\n * The OOM-scoped allocator shared by residency and pool.\n * @internal\n */\n readonly allocator: AllocationTracker;\n /**\n * The workgroup size of this device (spec 5.1).\n * @internal\n */\n readonly workgroupSize: number;\n /**\n * True when create() made the device (dispose() destroys it).\n * @internal\n */\n readonly ownsDevice: boolean;\n /**\n * The label given to create().\n * @internal\n */\n readonly label: string;\n /**\n * Mutable test-build flags (GpuDebugFlags).\n * @internal\n */\n readonly debug: GpuDebugFlags;\n\n private currentState: \"ready\" | \"lost\" | \"disposed\" = \"ready\";\n private lostError: WebGpuGraphError | null = null;\n private readonly slot = new PendingErrorSlot();\n private readonly uninstallSink: () => void;\n private readonly lostListeners = new Set<(info: GPUDeviceLostInfo) => void>();\n private readonly disposers: (() => void)[] = [];\n private batchCounter = 0;\n\n /**\n * Steps 5 and 6 of create() (spec 2.2): the sink, the loss watcher and the singletons.\n * @param init - the device, its caps and the create-time choices\n */\n private constructor(init: ContextInit) {\n this.device = init.device;\n this.caps = init.caps;\n this.ownsDevice = init.ownsDevice;\n this.label = init.label;\n this.debug = { inspect: false };\n this.workgroupSize = workgroupSizeFor(init.caps);\n this.allocator = new AllocationTracker(init.device);\n this.residency = new GraphResidency(init.device, init.caps, this.allocator, {\n warnUnreleasedSnapshots: init.warnUnreleasedSnapshots,\n });\n this.pool = new BufferPool(init.device, this.allocator, init.caps.limits.maxBufferSize);\n this.readback = new Readback(init.device, this.allocator);\n this.pipelines = new PipelineCache(init.device, init.caps);\n this.profiler = init.device.features.has(\"timestamp-query\")\n ? new Profiler(init.device, true, init.caps.runtime !== \"node\")\n : null;\n this.uninstallSink = installUncapturedErrorSink(init.device, this.slot, init.onError);\n this.lost = watchDeviceLost(init.device, (info) => {\n this.handleLost(info);\n });\n }\n\n /**\n * Probe without creating a device (spec 2.2); never throws. `gpu === undefined` -> E_NO_WEBGPU;\n * requestAdapter() null or a throw -> E_NO_ADAPTER; `rejectSoftware && software` -> E_SOFTWARE_ONLY (the\n * adapter and its summary are still reported); else OK with the UNUSED adapter and its summary.\n * @param options - the GPU object, the power preference and the software policy\n * @returns the probe result\n */\n static async probe(options: ProbeOptions): Promise<ProbeResult> {\n const { gpu } = options;\n if (gpu === undefined) {\n return {\n ok: false,\n code: \"E_NO_WEBGPU\",\n reason: \"no GPU object: navigator.gpu is undefined (no WebGPU in this runtime)\",\n adapter: null,\n summary: null,\n };\n }\n let adapter: GPUAdapter;\n try {\n adapter = await requestAdapter(gpu, options.powerPreference ?? DEFAULT_POWER_PREFERENCE);\n } catch (err) {\n const reason = isWebGpuGraphError(err) ? err.message : String(err);\n return { ok: false, code: \"E_NO_ADAPTER\", reason, adapter: null, summary: null };\n }\n const summary = summarizeAdapter(adapter);\n if (options.rejectSoftware === true && summary.software) {\n return {\n ok: false,\n code: \"E_SOFTWARE_ONLY\",\n reason: `software adapter rejected: ${summary.vendor}/${summary.architecture}`,\n adapter,\n summary,\n };\n }\n return { ok: true, code: \"OK\", reason: null, adapter, summary };\n }\n\n /**\n * The six-step acquisition of spec 2.2: adopt `device`, else take `adapter`, else request one from `gpu`\n * (step 1); the software test (step 2); the limits / features and requestDevice (step 3); the caps from\n * device.limits plus assertPlanLimits (step 4); the sink, the loss watcher and the singletons (steps 5-6,\n * in the constructor).\n * @param options - see GpuContextOptions\n * @returns the context\n */\n static async create(options: GpuContextOptions): Promise<GpuContext> {\n const runtime = options.runtime ?? \"unknown\";\n const label = options.label ?? DEFAULT_LABEL;\n const onError = options.onError ?? null;\n const warnUnreleasedSnapshots = options.warnUnreleasedSnapshots ?? DEFAULT_WARN_UNRELEASED_SNAPSHOTS;\n if (options.device !== undefined) {\n const adopted = capsFromDevice(options.device, { runtime });\n assertPlanLimits(adopted);\n return new GpuContext({\n device: options.device,\n caps: adopted,\n ownsDevice: false,\n label,\n onError,\n warnUnreleasedSnapshots,\n });\n }\n const adapter = await adapterOf(options);\n const summary = summarizeAdapter(adapter);\n if (options.rejectSoftware === true && summary.software) {\n throw new WebGpuGraphError(\n \"E_SOFTWARE_ONLY\",\n `software adapter rejected by rejectSoftware: ${summary.vendor}/${summary.architecture}`,\n { adapter: summary },\n );\n }\n const requiredLimits = buildRequiredLimits(adapter, options.limits ?? \"raise\");\n const requiredFeatures = buildRequiredFeatures(\n adapter,\n options.requiredFeatures ?? [],\n options.optionalFeatures ?? DEFAULT_OPTIONAL_FEATURES,\n );\n const device = await requestDevice(adapter, { label, requiredLimits, requiredFeatures });\n const caps = captureCaps(device, adapter.info, runtime, options.gpu?.wgslLanguageFeatures ?? []);\n try {\n assertPlanLimits(caps);\n } catch (err) {\n device.destroy();\n throw err;\n }\n return new GpuContext({ device, caps, ownsDevice: true, label, onError, warnUnreleasedSnapshots });\n }\n\n /**\n * Zero-cost adoption of a device the caller owns (ownsDevice false, runtime \"unknown\" unless info says\n * otherwise). The context is labelled with the device's label, or \"GpuContext.from\" when it has none.\n * @param device - the device to adopt\n * @param info - what the caller knows about the adapter, if anything\n * @returns the context\n */\n static from(device: GPUDevice, info?: Partial<GpuCaps>): GpuContext {\n const caps = capsFromDevice(device, info);\n assertPlanLimits(caps);\n const deviceLabel: string = device.label ?? \"\";\n return new GpuContext({\n device,\n caps,\n ownsDevice: false,\n label: deviceLabel === \"\" ? \"GpuContext.from\" : deviceLabel,\n onError: null,\n warnUnreleasedSnapshots: DEFAULT_WARN_UNRELEASED_SNAPSHOTS,\n });\n }\n\n /**\n * \"ready\" | \"lost\" | \"disposed\".\n * @returns the lifecycle state\n */\n get state(): \"ready\" | \"lost\" | \"disposed\" {\n return this.currentState;\n }\n\n /**\n * Throws E_DEVICE_LOST / E_DISPOSED by state and rethrows a pending uncaptured error (spec 5.7: \"thrown\n * from the next public call\").\n * @internal\n */\n assertReady(): void {\n if (this.currentState === \"disposed\") {\n throw new WebGpuGraphError(\"E_DISPOSED\", `GpuContext \"${this.label}\" is disposed`, { label: this.label });\n }\n if (this.lostError !== null) {\n throw this.lostError;\n }\n const pending = this.slot.take();\n if (pending !== null) {\n throw pending;\n }\n }\n\n /**\n * Takes the pending uncaptured error (used by CommandBatch right after submit).\n * @internal\n * @returns the error, or null\n */\n takePendingError(): WebGpuGraphError | null {\n return this.slot.take();\n }\n\n /**\n * Monotonically increasing batch ids, starting at 1.\n * @internal\n * @returns the next id\n */\n nextBatchId(): number {\n this.batchCounter += 1;\n return this.batchCounter;\n }\n\n /**\n * Registers a device-loss listener (simulations enter \"disposed\"); returns the unregister function.\n * @internal\n * @param listener - called once with the lost info\n * @returns removes the listener\n */\n onLost(listener: (info: GPUDeviceLostInfo) => void): () => void {\n this.lostListeners.add(listener);\n return () => {\n this.lostListeners.delete(listener);\n };\n }\n\n /**\n * A disposer run by dispose() (the Node entry attaches the GPU handle's dispose); attached after\n * dispose() it runs immediately.\n * @internal\n * @param dispose - the disposer\n */\n attachDisposer(dispose: () => void): void {\n if (this.currentState === \"disposed\") {\n dispose();\n return;\n }\n this.disposers.push(dispose);\n }\n\n /**\n * Destroys every buffer recorded for the snapshot (spec 4.5), then `pool.trim()` (spec 4.4: idle scratch\n * goes with the graph); idempotent; safe on a snapshot never uploaded; a no-op after dispose().\n * @param snapshot - the snapshot whose buffers are released\n */\n release(snapshot: GraphSnapshot): void {\n if (this.currentState === \"disposed\") {\n return;\n }\n this.residency.release(snapshot);\n this.pool.trim();\n }\n\n /**\n * Rejects pending work with E_DISPOSED (every later public call), destroys residency, pool and staging\n * ring, destroys the device when owned, runs attached disposers; idempotent (spec 2.8).\n */\n dispose(): void {\n if (this.currentState === \"disposed\") {\n return;\n }\n this.currentState = \"disposed\";\n this.uninstallSink();\n this.residency.destroyAll();\n this.pool.destroyAll();\n this.readback.destroyAll();\n if (this.profiler !== null) {\n this.profiler.destroy();\n }\n if (this.ownsDevice) {\n this.device.destroy();\n }\n const disposers = this.disposers.splice(0);\n for (const dispose of disposers) {\n dispose();\n }\n }\n\n /**\n * Step 5 of spec 2.2 on loss: state \"lost\", the residency cleared without destroying (the buffers are\n * gone with the device), every registered listener run once; a loss reported after dispose() (the owned\n * device was destroyed by dispose) changes nothing.\n * @param info - the device.lost result\n */\n private handleLost(info: GPUDeviceLostInfo): void {\n if (this.currentState === \"disposed\") {\n return;\n }\n this.currentState = \"lost\";\n this.lostError = deviceLostError(info);\n this.residency.clearOnLoss();\n for (const listener of Array.from(this.lostListeners)) {\n try {\n listener(info);\n } catch {\n // a throwing listener must not stop the fan-out; the others still learn of the loss\n }\n }\n }\n}\n"],"names":["messageOf","isSharedBuffer","invalid","entry","CORE_ORDER","ARC_INDEXED","record","bindings"],"mappings":"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"}