@graphty/webgpu-graph-algorithms 0.0.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/README.md +344 -23
  2. package/dist/browser.d.ts +1 -0
  3. package/dist/browser.js +32 -0
  4. package/dist/browser.js.map +1 -0
  5. package/dist/chunks/context-E6iKaeuJ.js +3136 -0
  6. package/dist/chunks/context-E6iKaeuJ.js.map +1 -0
  7. package/dist/node.d.ts +1 -0
  8. package/dist/node.js +131 -0
  9. package/dist/node.js.map +1 -0
  10. package/dist/src/accelerator.d.ts +26 -0
  11. package/dist/src/accelerator.d.ts.map +1 -0
  12. package/dist/src/accelerator.js +101 -0
  13. package/dist/src/accelerator.js.map +1 -0
  14. package/dist/src/algorithms/degree.d.ts +35 -0
  15. package/dist/src/algorithms/degree.d.ts.map +1 -0
  16. package/dist/src/algorithms/degree.js +119 -0
  17. package/dist/src/algorithms/degree.js.map +1 -0
  18. package/dist/src/browser/index.d.ts +23 -0
  19. package/dist/src/browser/index.d.ts.map +1 -0
  20. package/dist/src/browser/index.js +48 -0
  21. package/dist/src/browser/index.js.map +1 -0
  22. package/dist/src/constants.d.ts +92 -0
  23. package/dist/src/constants.d.ts.map +1 -0
  24. package/dist/src/constants.js +92 -0
  25. package/dist/src/constants.js.map +1 -0
  26. package/dist/src/context.d.ts +84 -0
  27. package/dist/src/context.d.ts.map +1 -0
  28. package/dist/src/context.js +304 -0
  29. package/dist/src/context.js.map +1 -0
  30. package/dist/src/device/acquire.d.ts +57 -0
  31. package/dist/src/device/acquire.d.ts.map +1 -0
  32. package/dist/src/device/acquire.js +232 -0
  33. package/dist/src/device/acquire.js.map +1 -0
  34. package/dist/src/device/caps.d.ts +43 -0
  35. package/dist/src/device/caps.d.ts.map +1 -0
  36. package/dist/src/device/caps.js +104 -0
  37. package/dist/src/device/caps.js.map +1 -0
  38. package/dist/src/device/error-scope.d.ts +75 -0
  39. package/dist/src/device/error-scope.d.ts.map +1 -0
  40. package/dist/src/device/error-scope.js +152 -0
  41. package/dist/src/device/error-scope.js.map +1 -0
  42. package/dist/src/device/lost.d.ts +51 -0
  43. package/dist/src/device/lost.d.ts.map +1 -0
  44. package/dist/src/device/lost.js +130 -0
  45. package/dist/src/device/lost.js.map +1 -0
  46. package/dist/src/device/webgpu-constants.d.ts +31 -0
  47. package/dist/src/device/webgpu-constants.d.ts.map +1 -0
  48. package/dist/src/device/webgpu-constants.js +31 -0
  49. package/dist/src/device/webgpu-constants.js.map +1 -0
  50. package/dist/src/errors.d.ts +56 -0
  51. package/dist/src/errors.d.ts.map +1 -0
  52. package/dist/src/errors.js +57 -0
  53. package/dist/src/errors.js.map +1 -0
  54. package/dist/src/index.d.ts +29 -0
  55. package/dist/src/index.d.ts.map +1 -0
  56. package/dist/src/index.js +27 -0
  57. package/dist/src/index.js.map +1 -0
  58. package/dist/src/kernel/batch.d.ts +116 -0
  59. package/dist/src/kernel/batch.d.ts.map +1 -0
  60. package/dist/src/kernel/batch.js +335 -0
  61. package/dist/src/kernel/batch.js.map +1 -0
  62. package/dist/src/kernel/dispatch.d.ts +59 -0
  63. package/dist/src/kernel/dispatch.d.ts.map +1 -0
  64. package/dist/src/kernel/dispatch.js +139 -0
  65. package/dist/src/kernel/dispatch.js.map +1 -0
  66. package/dist/src/kernel/kernel.d.ts +84 -0
  67. package/dist/src/kernel/kernel.d.ts.map +1 -0
  68. package/dist/src/kernel/kernel.js +239 -0
  69. package/dist/src/kernel/kernel.js.map +1 -0
  70. package/dist/src/kernel/pipeline-cache.d.ts +90 -0
  71. package/dist/src/kernel/pipeline-cache.d.ts.map +1 -0
  72. package/dist/src/kernel/pipeline-cache.js +251 -0
  73. package/dist/src/kernel/pipeline-cache.js.map +1 -0
  74. package/dist/src/kernel/prelude.d.ts +35 -0
  75. package/dist/src/kernel/prelude.d.ts.map +1 -0
  76. package/dist/src/kernel/prelude.js +211 -0
  77. package/dist/src/kernel/prelude.js.map +1 -0
  78. package/dist/src/kernel/profiler.d.ts +64 -0
  79. package/dist/src/kernel/profiler.d.ts.map +1 -0
  80. package/dist/src/kernel/profiler.js +120 -0
  81. package/dist/src/kernel/profiler.js.map +1 -0
  82. package/dist/src/kernel/struct-block.d.ts +122 -0
  83. package/dist/src/kernel/struct-block.d.ts.map +1 -0
  84. package/dist/src/kernel/struct-block.js +353 -0
  85. package/dist/src/kernel/struct-block.js.map +1 -0
  86. package/dist/src/kernel/uniform-ring.d.ts +70 -0
  87. package/dist/src/kernel/uniform-ring.d.ts.map +1 -0
  88. package/dist/src/kernel/uniform-ring.js +146 -0
  89. package/dist/src/kernel/uniform-ring.js.map +1 -0
  90. package/dist/src/kernel/wgsl.d.ts +88 -0
  91. package/dist/src/kernel/wgsl.d.ts.map +1 -0
  92. package/dist/src/kernel/wgsl.js +390 -0
  93. package/dist/src/kernel/wgsl.js.map +1 -0
  94. package/dist/src/kernels.d.ts +81 -0
  95. package/dist/src/kernels.d.ts.map +1 -0
  96. package/dist/src/kernels.js +417 -0
  97. package/dist/src/kernels.js.map +1 -0
  98. package/dist/src/layouts/force-simulation.d.ts +498 -0
  99. package/dist/src/layouts/force-simulation.d.ts.map +1 -0
  100. package/dist/src/layouts/force-simulation.js +1650 -0
  101. package/dist/src/layouts/force-simulation.js.map +1 -0
  102. package/dist/src/layouts/forceatlas2.d.ts +210 -0
  103. package/dist/src/layouts/forceatlas2.d.ts.map +1 -0
  104. package/dist/src/layouts/forceatlas2.js +759 -0
  105. package/dist/src/layouts/forceatlas2.js.map +1 -0
  106. package/dist/src/layouts/inputs.d.ts +40 -0
  107. package/dist/src/layouts/inputs.d.ts.map +1 -0
  108. package/dist/src/layouts/inputs.js +185 -0
  109. package/dist/src/layouts/inputs.js.map +1 -0
  110. package/dist/src/layouts/repulsion-exact.d.ts +85 -0
  111. package/dist/src/layouts/repulsion-exact.d.ts.map +1 -0
  112. package/dist/src/layouts/repulsion-exact.js +134 -0
  113. package/dist/src/layouts/repulsion-exact.js.map +1 -0
  114. package/dist/src/layouts/seed.d.ts +56 -0
  115. package/dist/src/layouts/seed.d.ts.map +1 -0
  116. package/dist/src/layouts/seed.js +173 -0
  117. package/dist/src/layouts/seed.js.map +1 -0
  118. package/dist/src/memory/buffer-pool.d.ts +73 -0
  119. package/dist/src/memory/buffer-pool.d.ts.map +1 -0
  120. package/dist/src/memory/buffer-pool.js +170 -0
  121. package/dist/src/memory/buffer-pool.js.map +1 -0
  122. package/dist/src/memory/lease.d.ts +53 -0
  123. package/dist/src/memory/lease.d.ts.map +1 -0
  124. package/dist/src/memory/lease.js +85 -0
  125. package/dist/src/memory/lease.js.map +1 -0
  126. package/dist/src/memory/readback.d.ts +143 -0
  127. package/dist/src/memory/readback.d.ts.map +1 -0
  128. package/dist/src/memory/readback.js +375 -0
  129. package/dist/src/memory/readback.js.map +1 -0
  130. package/dist/src/memory/residency.d.ts +83 -0
  131. package/dist/src/memory/residency.d.ts.map +1 -0
  132. package/dist/src/memory/residency.js +573 -0
  133. package/dist/src/memory/residency.js.map +1 -0
  134. package/dist/src/memory/upload-plan.d.ts +101 -0
  135. package/dist/src/memory/upload-plan.d.ts.map +1 -0
  136. package/dist/src/memory/upload-plan.js +265 -0
  137. package/dist/src/memory/upload-plan.js.map +1 -0
  138. package/dist/src/node/index.d.ts +64 -0
  139. package/dist/src/node/index.d.ts.map +1 -0
  140. package/dist/src/node/index.js +183 -0
  141. package/dist/src/node/index.js.map +1 -0
  142. package/dist/src/primitives/reduce.d.ts +57 -0
  143. package/dist/src/primitives/reduce.d.ts.map +1 -0
  144. package/dist/src/primitives/reduce.js +161 -0
  145. package/dist/src/primitives/reduce.js.map +1 -0
  146. package/dist/src/primitives/segmented-reduce.d.ts +38 -0
  147. package/dist/src/primitives/segmented-reduce.d.ts.map +1 -0
  148. package/dist/src/primitives/segmented-reduce.js +211 -0
  149. package/dist/src/primitives/segmented-reduce.js.map +1 -0
  150. package/dist/src/types/accelerator.d.ts +209 -0
  151. package/dist/src/types/accelerator.d.ts.map +1 -0
  152. package/dist/src/types/accelerator.js +8 -0
  153. package/dist/src/types/accelerator.js.map +1 -0
  154. package/dist/src/types/context.d.ts +114 -0
  155. package/dist/src/types/context.d.ts.map +1 -0
  156. package/dist/src/types/context.js +7 -0
  157. package/dist/src/types/context.js.map +1 -0
  158. package/dist/src/types/layout.d.ts +95 -0
  159. package/dist/src/types/layout.d.ts.map +1 -0
  160. package/dist/src/types/layout.js +6 -0
  161. package/dist/src/types/layout.js.map +1 -0
  162. package/dist/src/types/memory.d.ts +22 -0
  163. package/dist/src/types/memory.d.ts.map +1 -0
  164. package/dist/src/types/memory.js +7 -0
  165. package/dist/src/types/memory.js.map +1 -0
  166. package/dist/src/types/options.d.ts +78 -0
  167. package/dist/src/types/options.d.ts.map +1 -0
  168. package/dist/src/types/options.js +7 -0
  169. package/dist/src/types/options.js.map +1 -0
  170. package/dist/src/types/run.d.ts +13 -0
  171. package/dist/src/types/run.d.ts.map +1 -0
  172. package/dist/src/types/run.js +6 -0
  173. package/dist/src/types/run.js.map +1 -0
  174. package/dist/src/wgsl/degree.wgsl.d.ts +10 -0
  175. package/dist/src/wgsl/degree.wgsl.d.ts.map +1 -0
  176. package/dist/src/wgsl/degree.wgsl.js +25 -0
  177. package/dist/src/wgsl/degree.wgsl.js.map +1 -0
  178. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +12 -0
  179. package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -0
  180. package/dist/src/wgsl/fa2-attraction.wgsl.js +37 -0
  181. package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -0
  182. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts +13 -0
  183. package/dist/src/wgsl/fa2-integrate.wgsl.d.ts.map +1 -0
  184. package/dist/src/wgsl/fa2-integrate.wgsl.js +69 -0
  185. package/dist/src/wgsl/fa2-integrate.wgsl.js.map +1 -0
  186. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts +12 -0
  187. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts.map +1 -0
  188. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js +79 -0
  189. package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js.map +1 -0
  190. package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts +15 -0
  191. package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts.map +1 -0
  192. package/dist/src/wgsl/fa2-speed-finalize.wgsl.js +54 -0
  193. package/dist/src/wgsl/fa2-speed-finalize.wgsl.js.map +1 -0
  194. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +14 -0
  195. package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -0
  196. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +57 -0
  197. package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -0
  198. package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts +11 -0
  199. package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts.map +1 -0
  200. package/dist/src/wgsl/fa2-to-scene.wgsl.js +19 -0
  201. package/dist/src/wgsl/fa2-to-scene.wgsl.js.map +1 -0
  202. package/dist/src/wgsl/fill.wgsl.d.ts +7 -0
  203. package/dist/src/wgsl/fill.wgsl.d.ts.map +1 -0
  204. package/dist/src/wgsl/fill.wgsl.js +14 -0
  205. package/dist/src/wgsl/fill.wgsl.js.map +1 -0
  206. package/dist/src/wgsl/reduce.wgsl.d.ts +10 -0
  207. package/dist/src/wgsl/reduce.wgsl.d.ts.map +1 -0
  208. package/dist/src/wgsl/reduce.wgsl.js +63 -0
  209. package/dist/src/wgsl/reduce.wgsl.js.map +1 -0
  210. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts +13 -0
  211. package/dist/src/wgsl/segmented-reduce.wgsl.d.ts.map +1 -0
  212. package/dist/src/wgsl/segmented-reduce.wgsl.js +35 -0
  213. package/dist/src/wgsl/segmented-reduce.wgsl.js.map +1 -0
  214. package/dist/tsconfig.build.tsbuildinfo +1 -0
  215. package/dist/webgpu-graph-algorithms.d.ts +1 -0
  216. package/dist/webgpu-graph-algorithms.js +4454 -0
  217. package/dist/webgpu-graph-algorithms.js.map +1 -0
  218. package/package.json +108 -17
  219. package/src/accelerator.ts +117 -0
  220. package/src/algorithms/degree.ts +142 -0
  221. package/src/browser/index.ts +57 -0
  222. package/src/constants.ts +116 -0
  223. package/src/context.ts +399 -0
  224. package/src/device/acquire.ts +256 -0
  225. package/src/device/caps.ts +122 -0
  226. package/src/device/error-scope.ts +171 -0
  227. package/src/device/lost.ts +142 -0
  228. package/src/device/webgpu-constants.ts +44 -0
  229. package/src/errors.ts +94 -0
  230. package/src/index.ts +102 -0
  231. package/src/kernel/batch.ts +427 -0
  232. package/src/kernel/dispatch.ts +162 -0
  233. package/src/kernel/kernel.ts +311 -0
  234. package/src/kernel/pipeline-cache.ts +288 -0
  235. package/src/kernel/prelude.ts +229 -0
  236. package/src/kernel/profiler.ts +148 -0
  237. package/src/kernel/struct-block.ts +439 -0
  238. package/src/kernel/uniform-ring.ts +184 -0
  239. package/src/kernel/wgsl.ts +490 -0
  240. package/src/kernels.ts +511 -0
  241. package/src/layouts/force-simulation.ts +2111 -0
  242. package/src/layouts/forceatlas2.ts +942 -0
  243. package/src/layouts/inputs.ts +252 -0
  244. package/src/layouts/repulsion-exact.ts +183 -0
  245. package/src/layouts/seed.ts +198 -0
  246. package/src/memory/buffer-pool.ts +204 -0
  247. package/src/memory/lease.ts +93 -0
  248. package/src/memory/readback.ts +429 -0
  249. package/src/memory/residency.ts +753 -0
  250. package/src/memory/upload-plan.ts +350 -0
  251. package/src/node/index.ts +230 -0
  252. package/src/primitives/reduce.ts +233 -0
  253. package/src/primitives/segmented-reduce.ts +270 -0
  254. package/src/types/accelerator.ts +236 -0
  255. package/src/types/context.ts +135 -0
  256. package/src/types/layout.ts +103 -0
  257. package/src/types/memory.ts +23 -0
  258. package/src/types/options.ts +84 -0
  259. package/src/types/run.ts +13 -0
  260. package/src/wgsl/degree.wgsl.ts +24 -0
  261. package/src/wgsl/fa2-attraction.wgsl.ts +37 -0
  262. package/src/wgsl/fa2-integrate.wgsl.ts +69 -0
  263. package/src/wgsl/fa2-repulsion-exact.wgsl.ts +78 -0
  264. package/src/wgsl/fa2-speed-finalize.wgsl.ts +53 -0
  265. package/src/wgsl/fa2-stats-finalize.wgsl.ts +57 -0
  266. package/src/wgsl/fa2-to-scene.wgsl.ts +19 -0
  267. package/src/wgsl/fill.wgsl.ts +13 -0
  268. package/src/wgsl/reduce.wgsl.ts +62 -0
  269. package/src/wgsl/segmented-reduce.wgsl.ts +35 -0
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Dispatch planning (spec 5.2; contract 3.9): the 16,776,960 rule. `ceil(items / wg)` workgroups as a 1D dispatch
3
+ * while the count fits one dimension (65,535 groups x 256 = 16,776,960 items, NOT 2^24), else a 2D grid whose
4
+ * kernels linearise their id with the prelude's `linear_id()` and guard `id >= items`. Pure functions with no
5
+ * device: every branch is unit-tested against faked capability tables.
6
+ */
7
+ import { MAX_WORKGROUPS_PER_DIM } from "../constants.js";
8
+ import { WebGpuGraphError } from "../errors.js";
9
+ /**
10
+ * The per-dimension workgroup limit a plan honours. PLAN DECISION: the minimum of the spec constant and the table's
11
+ * `maxComputeWorkgroupsPerDimension`; the two are asserted equal on a real device at create() (spec 2.2), so every
12
+ * capability table of the tests yields the same plans and a faked table below the constant is still honoured.
13
+ * @param caps - the capability table
14
+ * @returns the limit
15
+ */
16
+ function perDimension(caps) {
17
+ return Math.min(MAX_WORKGROUPS_PER_DIM, caps.limits.maxComputeWorkgroupsPerDimension);
18
+ }
19
+ /**
20
+ * Validates a non-negative integer argument.
21
+ * @param argument - the argument name
22
+ * @param value - the value
23
+ */
24
+ function assertCount(argument, value) {
25
+ if (!Number.isInteger(value) || value < 0) {
26
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${argument} must be a non-negative integer, got ${value}`, {
27
+ argument,
28
+ value,
29
+ expected: "a non-negative integer",
30
+ });
31
+ }
32
+ }
33
+ /**
34
+ * Validates a workgroup size: a power of two >= 1 (the reduction trees of 4.3 need it). Arithmetic, no bit tricks.
35
+ * @param wg - the workgroup size
36
+ */
37
+ function assertWorkgroupSize(wg) {
38
+ let rest = wg;
39
+ while (Number.isInteger(rest) && rest > 1 && rest % 2 === 0) {
40
+ rest /= 2;
41
+ }
42
+ if (rest !== 1) {
43
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `wg must be a power of two, got ${wg}`, {
44
+ argument: "wg",
45
+ value: wg,
46
+ expected: "a power of two >= 1",
47
+ });
48
+ }
49
+ }
50
+ /**
51
+ * The grid of `groups` workgroups: 1D up to the per-dimension limit, else `x = limit`, `y = ceil(groups / limit)`.
52
+ * @param groups - the workgroup count
53
+ * @param items - the item count the plan covers (recorded in the plan)
54
+ * @param caps - the capability table
55
+ * @returns the plan
56
+ */
57
+ function grid(groups, items, caps) {
58
+ const limit = perDimension(caps);
59
+ if (groups === 0) {
60
+ return { x: 0, y: 1, z: 1, items, stride: null };
61
+ }
62
+ if (groups <= limit) {
63
+ return { x: groups, y: 1, z: 1, items, stride: null };
64
+ }
65
+ const y = Math.ceil(groups / limit);
66
+ if (y > limit) {
67
+ throw new WebGpuGraphError("E_TOO_LARGE", `${groups} workgroups exceed the 2D dispatch limit of ${limit * limit}`, {
68
+ needed: groups,
69
+ limit: limit * limit,
70
+ path: "dispatch",
71
+ algorithm: null,
72
+ items,
73
+ });
74
+ }
75
+ return { x: limit, y, z: 1, items, stride: null };
76
+ }
77
+ /**
78
+ * ceil(items / wg) groups as 1D up to MAX_WORKGROUPS_PER_DIM, else a 2D grid; items 0 -> { x: 0, y: 1 }; y above the limit -> E_TOO_LARGE.
79
+ * @param items - the item count
80
+ * @param wg - the workgroup size (a power of two)
81
+ * @param caps - the capability table
82
+ * @returns the plan
83
+ */
84
+ export function plan1d(items, wg, caps) {
85
+ assertCount("items", items);
86
+ assertWorkgroupSize(wg);
87
+ return grid(Math.ceil(items / wg), items, caps);
88
+ }
89
+ /**
90
+ * The 2D form for a group count (x = MAX_WORKGROUPS_PER_DIM, y = ceil(groups / x)); exported for the indirect finalize kernel's host twin (P4).
91
+ * PLAN DECISION: plan1d's rule applied to a group count (spec 5.4: the finalize kernel uses "the same rule as
92
+ * plan1d") -- 1D `{ x: groups, y: 1 }` up to the per-dimension limit and the `x = limit` split only above it, through
93
+ * the same `grid()` as plan1d so the two cannot drift; P4's finalize WGSL mirrors exactly this rule. `items` of the
94
+ * returned plan is `groups` (the caller knows its own wg); groups 0 -> { x: 0, y: 1 }.
95
+ * @param groups - the workgroup count
96
+ * @param caps - the capability table
97
+ * @returns the plan
98
+ */
99
+ export function plan2d(groups, caps) {
100
+ assertCount("groups", groups);
101
+ return grid(groups, groups, caps);
102
+ }
103
+ /**
104
+ * P7 (spec 5.2): groups = min(groups, maxGroups ?? (caps.software ? 64 : 4096)) with the kernel looping by stride. P1-P3: throws E_UNSUPPORTED { feature: "planGridStride" } (lead f).
105
+ * PLAN DECISION: `maxGroups?` is spelled `?: number` rather than the contract's `?: number | undefined` because the
106
+ * root ESLint rule no-duplicate-type-constituents rejects the explicit undefined on an optional parameter (the call
107
+ * signature is identical).
108
+ * @param items - the item count
109
+ * @param wg - the workgroup size
110
+ * @param caps - the capability table
111
+ * @param maxGroups - the group cap
112
+ */
113
+ export function planGridStride(items, wg, caps, maxGroups) {
114
+ throw new WebGpuGraphError("E_UNSUPPORTED", "planGridStride lands with the grid-stride kernels of P7 (spec 5.2)", {
115
+ feature: "planGridStride",
116
+ hint: `items ${items}, wg ${wg}, maxGroups ${maxGroups ?? (caps.software ? 64 : 4096)}`,
117
+ });
118
+ }
119
+ /**
120
+ * P4 (spec 5.4): the (x, y, 1) args a device-side finalize kernel writes for a count. P1-P3: throws E_UNSUPPORTED { feature: "planIndirect" } (lead f).
121
+ * @param count - the device-side count
122
+ * @param wg - the workgroup size
123
+ * @param caps - the capability table
124
+ */
125
+ export function planIndirect(count, wg, caps) {
126
+ throw new WebGpuGraphError("E_UNSUPPORTED", "planIndirect lands with the indirect dispatch of P4 (spec 5.4)", {
127
+ feature: "planIndirect",
128
+ hint: `count ${count}, wg ${wg}, limit ${perDimension(caps)}`,
129
+ });
130
+ }
131
+ /**
132
+ * The workgroup count of a plan (x * y).
133
+ * @param plan - the plan
134
+ * @returns the count
135
+ */
136
+ export function groupsOf(plan) {
137
+ return plan.x * plan.y;
138
+ }
139
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../../src/kernel/dispatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Kernel (spec 5.1; contract 3.9): a compiled pipeline bound to the binding list of its spec. `bind()` creates the
3
+ * bind groups from a `Record<name, Binding>` keyed by the declared names and caches them by the identity of the
4
+ * buffers, offsets and sizes (a layout's bind groups are created once per load(), not per iteration); `dispatch()`
5
+ * records setPipeline / setBindGroup / dispatchWorkgroups and skips an empty plan (spec 5.6).
6
+ */
7
+ import { type Binding } from "../types/memory.js";
8
+ import { type DispatchPlan } from "./dispatch.js";
9
+ import { type ComposedModule, type WgslModuleSpec } from "./wgsl.js";
10
+ /** 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). */
11
+ export type KernelBindings = Readonly<Record<string, Binding>>;
12
+ /** A kernel with its bind groups created (spec 5.1: cached per set of buffers and offsets). */
13
+ export interface BoundKernel {
14
+ readonly kernel: Kernel;
15
+ readonly bindGroups: readonly GPUBindGroup[];
16
+ /** Group indices whose bind group takes a dynamic offset (the uniform groups), in group order. */
17
+ readonly dynamicGroups: readonly number[];
18
+ }
19
+ /** A compiled pipeline plus the binding list of its spec (spec 5.1). */
20
+ export declare class Kernel {
21
+ /** The module spec the pipeline was compiled from (its bindings drive bind()). */
22
+ readonly spec: WgslModuleSpec;
23
+ /** The compiled compute pipeline. */
24
+ readonly pipeline: GPUComputePipeline;
25
+ /** The explicit bind group layouts, one per group index (an empty layout for an unused index). */
26
+ readonly layouts: readonly GPUBindGroupLayout[];
27
+ /** The workgroup size the pipeline was compiled with (the effective WG override). */
28
+ readonly workgroupSize: number;
29
+ /** The entry point name the pipeline was compiled with. */
30
+ readonly entryPoint: string;
31
+ private readonly device;
32
+ /** The declarations of each group in binding order (index = group). */
33
+ private readonly groups;
34
+ /** The uniform-binding count of each group (the dynamic offsets a setBindGroup takes). */
35
+ private readonly dynamicCounts;
36
+ /** Cached bind groups by buffer identity + offset + size. */
37
+ private readonly cache;
38
+ /**
39
+ * Wraps a compiled pipeline.
40
+ * @param device - the device the bind groups are created on
41
+ * @param spec - the module
42
+ * @param composed - the composed text (workgroup size and entry point)
43
+ * @param pipeline - the compiled pipeline
44
+ * @param layouts - the explicit bind-group layouts, one per group 0..maxGroup
45
+ */
46
+ constructor(device: GPUDevice, spec: WgslModuleSpec, composed: ComposedModule, pipeline: GPUComputePipeline, layouts: readonly GPUBindGroupLayout[]);
47
+ /**
48
+ * Creates (or reuses, keyed by every buffer identity + offset + size) the bind groups, each labelled
49
+ * `<spec.id>/<group>`; a missing or extra name is E_INVALID_ARGUMENT; two bindings of one call whose ranges
50
+ * intersect on one buffer while either slot is `storage` (read_write) is E_INVALID_ARGUMENT
51
+ * { argument: "aliasing" } (the host-side mirror of WebGPU's writable buffer-binding-aliasing rule, 3.10.1, so
52
+ * the failure is synchronous and labelled). CONTRACT DECISION: bind() is synchronous, so a createBindGroup
53
+ * validation error (a wrong-size uniform binding, a usage mismatch) is NOT thrown here -- it reaches the
54
+ * pending-error slot as E_VALIDATION { label: "<spec.id>/<group>" } and is thrown by the batch's readback
55
+ * (Dawn-node) or the next assertReady() (browser), spec 5.7. An empty bind group is created for every empty
56
+ * layout index so setBindGroup is called for 0..maxGroup.
57
+ * PLAN DECISION (verified on Dawn 0.4.0 / lavapipe): one buffer bound with two DIFFERENT access modes when one is
58
+ * `storage` is also E_INVALID_ARGUMENT { argument: "aliasing", reason: "usage" } even with disjoint ranges, because
59
+ * WebGPU's usage-scope rule rejects "writable usage and another usage in the same synchronization scope" per
60
+ * BUFFER; two `storage` slots with disjoint ranges (the state header / trace pattern) are accepted; a zero-size
61
+ * binding (never bind a zero-length buffer, spec 3.6) and an offset that is not a multiple of STORAGE_ALIGN = 256
62
+ * (spec 2.6; Dawn: "does not satisfy the minimum ... alignment (256)") are E_INVALID_ARGUMENT.
63
+ * @param resources - one Binding per declared name
64
+ * @returns the bound kernel (the same object for the same buffers, offsets and sizes until invalidate())
65
+ */
66
+ bind(resources: KernelBindings): BoundKernel;
67
+ /**
68
+ * setPipeline + setBindGroup for every group (dynamic offsets in dynamicGroups order) + dispatchWorkgroups(plan.x, plan.y, 1); a plan with x === 0 records nothing (spec 5.6).
69
+ * PLAN DECISION: one dynamic offset per dynamic GROUP, replicated over every uniform binding of that group (every
70
+ * P1-P3 kernel has exactly one params uniform per group); absent offsets mean 0; a BoundKernel of another kernel
71
+ * or an offset list of the wrong length is E_INVALID_ARGUMENT.
72
+ * PLAN DECISION: `dynamicOffsets?` is spelled `?: readonly number[]` rather than the contract's
73
+ * `?: readonly number[] | undefined` because the root ESLint rule no-duplicate-type-constituents rejects the
74
+ * explicit undefined on an optional parameter (the call signature is identical).
75
+ * @param pass - the open compute pass
76
+ * @param bound - a BoundKernel of THIS kernel
77
+ * @param plan - the dispatch shape
78
+ * @param dynamicOffsets - one byte offset per entry of bound.dynamicGroups
79
+ */
80
+ dispatch(pass: GPUComputePassEncoder, bound: BoundKernel, plan: DispatchPlan, dynamicOffsets?: readonly number[]): void;
81
+ /** Drops cached bind groups (a layout's buffers changed). */
82
+ invalidate(): void;
83
+ }
84
+ //# sourceMappingURL=kernel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kernel.d.ts","sourceRoot":"","sources":["../../../src/kernel/kernel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAoB,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAEvF,kLAAkL;AAClL,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAC/D,+FAA+F;AAC/F,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,SAAS,YAAY,EAAE,CAAC;IAC7C,kGAAkG;IAClG,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AA+BD,wEAAwE;AACxE,qBAAa,MAAM;IACf,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,kGAAkG;IAClG,QAAQ,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAChD,qFAAqF;IACrF,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,2DAA2D;IAC3D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,uEAAuE;IACvE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;IAC7D,0FAA0F;IAC1F,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoB;IAClD,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkC;IAExD;;;;;;;OAOG;gBAEC,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,cAAc,EACpB,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,SAAS,kBAAkB,EAAE;IAmB1C;;;;;;;;;;;;;;;;;;OAkBG;IACH,IAAI,CAAC,SAAS,EAAE,cAAc,GAAG,WAAW;IAuH5C;;;;;;;;;;;;OAYG;IACH,QAAQ,CACJ,IAAI,EAAE,qBAAqB,EAC3B,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,YAAY,EAClB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,GACnC,IAAI;IA8CP,6DAA6D;IAC7D,UAAU,IAAI,IAAI;CAGrB"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Kernel (spec 5.1; contract 3.9): a compiled pipeline bound to the binding list of its spec. `bind()` creates the
3
+ * bind groups from a `Record<name, Binding>` keyed by the declared names and caches them by the identity of the
4
+ * buffers, offsets and sizes (a layout's bind groups are created once per load(), not per iteration); `dispatch()`
5
+ * records setPipeline / setBindGroup / dispatchWorkgroups and skips an empty plan (spec 5.6).
6
+ */
7
+ import { STORAGE_ALIGN } from "../constants.js";
8
+ import { WebGpuGraphError } from "../errors.js";
9
+ /** Buffer identities for the bind-group cache key: every GPUBuffer seen by any Kernel gets one number, once. */
10
+ const bufferIds = new WeakMap();
11
+ let nextBufferId = 1;
12
+ /**
13
+ * The identity number of a buffer.
14
+ * @param buffer - the buffer
15
+ * @returns its number
16
+ */
17
+ function bufferId(buffer) {
18
+ let id = bufferIds.get(buffer);
19
+ if (id === undefined) {
20
+ id = nextBufferId;
21
+ nextBufferId += 1;
22
+ bufferIds.set(buffer, id);
23
+ }
24
+ return id;
25
+ }
26
+ /**
27
+ * True when two byte ranges intersect.
28
+ * @param a - one binding
29
+ * @param b - the other binding
30
+ * @returns whether [a.offset, a.offset + a.size) and [b.offset, b.offset + b.size) overlap
31
+ */
32
+ function rangesIntersect(a, b) {
33
+ return a.offset < b.offset + b.size && b.offset < a.offset + a.size;
34
+ }
35
+ /** A compiled pipeline plus the binding list of its spec (spec 5.1). */
36
+ export class Kernel {
37
+ /**
38
+ * Wraps a compiled pipeline.
39
+ * @param device - the device the bind groups are created on
40
+ * @param spec - the module
41
+ * @param composed - the composed text (workgroup size and entry point)
42
+ * @param pipeline - the compiled pipeline
43
+ * @param layouts - the explicit bind-group layouts, one per group 0..maxGroup
44
+ */
45
+ constructor(device, spec, composed, pipeline, layouts) {
46
+ /** Cached bind groups by buffer identity + offset + size. */
47
+ this.cache = new Map();
48
+ this.device = device;
49
+ this.spec = spec;
50
+ this.pipeline = pipeline;
51
+ this.layouts = layouts;
52
+ this.workgroupSize = composed.overrides.WG;
53
+ this.entryPoint = composed.entryPoint;
54
+ const groups = layouts.map(() => []);
55
+ for (const decl of spec.bindings) {
56
+ groups[decl.group].push(decl);
57
+ }
58
+ for (const group of groups) {
59
+ group.sort((a, b) => a.binding - b.binding);
60
+ }
61
+ this.groups = groups;
62
+ this.dynamicCounts = groups.map((group) => group.filter((decl) => decl.kind === "uniform").length);
63
+ }
64
+ /**
65
+ * Creates (or reuses, keyed by every buffer identity + offset + size) the bind groups, each labelled
66
+ * `<spec.id>/<group>`; a missing or extra name is E_INVALID_ARGUMENT; two bindings of one call whose ranges
67
+ * intersect on one buffer while either slot is `storage` (read_write) is E_INVALID_ARGUMENT
68
+ * { argument: "aliasing" } (the host-side mirror of WebGPU's writable buffer-binding-aliasing rule, 3.10.1, so
69
+ * the failure is synchronous and labelled). CONTRACT DECISION: bind() is synchronous, so a createBindGroup
70
+ * validation error (a wrong-size uniform binding, a usage mismatch) is NOT thrown here -- it reaches the
71
+ * pending-error slot as E_VALIDATION { label: "<spec.id>/<group>" } and is thrown by the batch's readback
72
+ * (Dawn-node) or the next assertReady() (browser), spec 5.7. An empty bind group is created for every empty
73
+ * layout index so setBindGroup is called for 0..maxGroup.
74
+ * PLAN DECISION (verified on Dawn 0.4.0 / lavapipe): one buffer bound with two DIFFERENT access modes when one is
75
+ * `storage` is also E_INVALID_ARGUMENT { argument: "aliasing", reason: "usage" } even with disjoint ranges, because
76
+ * WebGPU's usage-scope rule rejects "writable usage and another usage in the same synchronization scope" per
77
+ * BUFFER; two `storage` slots with disjoint ranges (the state header / trace pattern) are accepted; a zero-size
78
+ * binding (never bind a zero-length buffer, spec 3.6) and an offset that is not a multiple of STORAGE_ALIGN = 256
79
+ * (spec 2.6; Dawn: "does not satisfy the minimum ... alignment (256)") are E_INVALID_ARGUMENT.
80
+ * @param resources - one Binding per declared name
81
+ * @returns the bound kernel (the same object for the same buffers, offsets and sizes until invalidate())
82
+ */
83
+ bind(resources) {
84
+ const { id } = this.spec;
85
+ const declared = new Map(this.spec.bindings.map((decl) => [decl.name, decl]));
86
+ for (const name of Object.keys(resources)) {
87
+ if (!declared.has(name)) {
88
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${id}: no binding named "${name}"`, {
89
+ argument: "bindings",
90
+ value: name,
91
+ expected: [...declared.keys()].join(", "),
92
+ });
93
+ }
94
+ }
95
+ const resolved = [];
96
+ for (const decl of this.spec.bindings) {
97
+ const binding = resources[decl.name];
98
+ if (binding === undefined) {
99
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${id}: binding "${decl.name}" is missing`, {
100
+ argument: "bindings",
101
+ value: decl.name,
102
+ expected: "a Binding for every declared name",
103
+ });
104
+ }
105
+ if (!(Number.isInteger(binding.size) && binding.size > 0)) {
106
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${id}: binding "${decl.name}" has size ${binding.size}`, {
107
+ argument: decl.name,
108
+ value: binding.size,
109
+ expected: "size > 0 (a zero-length buffer is never bound)",
110
+ });
111
+ }
112
+ if (!(Number.isInteger(binding.offset) && binding.offset >= 0 && binding.offset % STORAGE_ALIGN === 0)) {
113
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${id}: binding "${decl.name}" has offset ${binding.offset}`, {
114
+ argument: decl.name,
115
+ value: binding.offset,
116
+ expected: `a multiple of ${STORAGE_ALIGN} (spec 2.6: the offset alignment the package always honours)`,
117
+ });
118
+ }
119
+ resolved.push({ decl, binding });
120
+ }
121
+ for (let i = 0; i < resolved.length; i++) {
122
+ for (let j = i + 1; j < resolved.length; j++) {
123
+ const a = resolved[i];
124
+ const b = resolved[j];
125
+ if (a.binding.buffer !== b.binding.buffer) {
126
+ continue;
127
+ }
128
+ const writable = a.decl.kind === "storage" || b.decl.kind === "storage";
129
+ if (!writable) {
130
+ continue;
131
+ }
132
+ if (a.decl.kind !== b.decl.kind) {
133
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${id}: "${a.decl.name}" and "${b.decl.name}" bind one buffer with different access modes (writable usage next to another usage)`, {
134
+ argument: "aliasing",
135
+ value: [a.decl.name, b.decl.name],
136
+ expected: "one access mode per buffer when a slot is read_write",
137
+ reason: "usage",
138
+ });
139
+ }
140
+ if (rangesIntersect(a.binding, b.binding)) {
141
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${id}: "${a.decl.name}" and "${b.decl.name}" bind intersecting ranges of one read_write buffer`, {
142
+ argument: "aliasing",
143
+ value: [a.decl.name, b.decl.name],
144
+ expected: "disjoint ranges",
145
+ reason: "range",
146
+ });
147
+ }
148
+ }
149
+ }
150
+ const key = resolved
151
+ .map(({ binding }) => `${bufferId(binding.buffer)}:${binding.offset}:${binding.size}`)
152
+ .join("|");
153
+ const cached = this.cache.get(key);
154
+ if (cached !== undefined) {
155
+ return cached;
156
+ }
157
+ const byName = new Map(resolved.map(({ decl, binding }) => [decl.name, binding]));
158
+ const bindGroups = this.layouts.map((layout, group) => this.device.createBindGroup({
159
+ label: `${id}/${group}`,
160
+ layout,
161
+ entries: this.groups[group].map((decl) => {
162
+ const binding = byName.get(decl.name);
163
+ return {
164
+ binding: decl.binding,
165
+ resource: { buffer: binding.buffer, offset: binding.offset, size: binding.size },
166
+ };
167
+ }),
168
+ }));
169
+ const dynamicGroups = [];
170
+ this.dynamicCounts.forEach((count, group) => {
171
+ if (count > 0) {
172
+ dynamicGroups.push(group);
173
+ }
174
+ });
175
+ const bound = Object.freeze({
176
+ kernel: this,
177
+ bindGroups: Object.freeze(bindGroups),
178
+ dynamicGroups: Object.freeze(dynamicGroups),
179
+ });
180
+ this.cache.set(key, bound);
181
+ return bound;
182
+ }
183
+ /**
184
+ * setPipeline + setBindGroup for every group (dynamic offsets in dynamicGroups order) + dispatchWorkgroups(plan.x, plan.y, 1); a plan with x === 0 records nothing (spec 5.6).
185
+ * PLAN DECISION: one dynamic offset per dynamic GROUP, replicated over every uniform binding of that group (every
186
+ * P1-P3 kernel has exactly one params uniform per group); absent offsets mean 0; a BoundKernel of another kernel
187
+ * or an offset list of the wrong length is E_INVALID_ARGUMENT.
188
+ * PLAN DECISION: `dynamicOffsets?` is spelled `?: readonly number[]` rather than the contract's
189
+ * `?: readonly number[] | undefined` because the root ESLint rule no-duplicate-type-constituents rejects the
190
+ * explicit undefined on an optional parameter (the call signature is identical).
191
+ * @param pass - the open compute pass
192
+ * @param bound - a BoundKernel of THIS kernel
193
+ * @param plan - the dispatch shape
194
+ * @param dynamicOffsets - one byte offset per entry of bound.dynamicGroups
195
+ */
196
+ dispatch(pass, bound, plan, dynamicOffsets) {
197
+ const { id } = this.spec;
198
+ if (bound.kernel !== this) {
199
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${id}: the bound kernel belongs to "${bound.kernel.spec.id}"`, {
200
+ argument: "bound",
201
+ value: bound.kernel.spec.id,
202
+ expected: id,
203
+ });
204
+ }
205
+ if (dynamicOffsets !== undefined && dynamicOffsets.length !== bound.dynamicGroups.length) {
206
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${id}: ${dynamicOffsets.length} dynamic offsets for ${bound.dynamicGroups.length} dynamic groups`, {
207
+ argument: "dynamicOffsets",
208
+ value: dynamicOffsets.length,
209
+ expected: bound.dynamicGroups.length,
210
+ });
211
+ }
212
+ if (plan.x === 0) {
213
+ return;
214
+ }
215
+ pass.setPipeline(this.pipeline);
216
+ let next = 0;
217
+ bound.bindGroups.forEach((bindGroup, group) => {
218
+ const count = this.dynamicCounts[group];
219
+ if (count > 0) {
220
+ const offset = dynamicOffsets?.[next] ?? 0;
221
+ next += 1;
222
+ const offsets = [];
223
+ for (let k = 0; k < count; k++) {
224
+ offsets.push(offset);
225
+ }
226
+ pass.setBindGroup(group, bindGroup, offsets);
227
+ }
228
+ else {
229
+ pass.setBindGroup(group, bindGroup);
230
+ }
231
+ });
232
+ pass.dispatchWorkgroups(plan.x, plan.y, 1);
233
+ }
234
+ /** Drops cached bind groups (a layout's buffers changed). */
235
+ invalidate() {
236
+ this.cache.clear();
237
+ }
238
+ }
239
+ //# sourceMappingURL=kernel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kernel.js","sourceRoot":"","sources":["../../../src/kernel/kernel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * PipelineCache (spec 5.1; contract 3.9): compile-once compute pipelines keyed by
3
+ * `(id, overrides, needs present on the device, snippets)` with EXPLICIT bind-group layouts derived from
4
+ * `spec.bindings` (never `layout: "auto"`, so one layout serves every dummy-binding variant and bind groups are
5
+ * reused across variants). A WGSL error is `E_SHADER_COMPILE { stage: "compile", messages, lines }` with
6
+ * body-relative line numbers; a pipeline error that is not a compilation message (an oversized workgroup, an
7
+ * invalid layout) is `E_VALIDATION`.
8
+ */
9
+ import { type PlanCaps } from "../types/context.js";
10
+ import { Kernel } from "./kernel.js";
11
+ import { type WgslModuleSpec } from "./wgsl.js";
12
+ /**
13
+ * The cache key of a spec on a device (pure; PLAN DECISION: exported so the override-matrix helper of P2-T2 can
14
+ * compute keys without a device): `id + "|" + stableJson(overrides) + "|" + needs.filter(present).join(",") + "|" + hash(snippets)`.
15
+ * @param spec - the module
16
+ * @param caps - the device capabilities (the feature set decides which needs are present)
17
+ * @returns the key
18
+ */
19
+ export declare function pipelineKey(spec: WgslModuleSpec, caps: PlanCaps): string;
20
+ /** Compile-once pipelines keyed by (id, overrides, needs present on the device, snippets) with explicit bind-group layouts (spec 5.1). */
21
+ export declare class PipelineCache {
22
+ private readonly device;
23
+ private readonly caps;
24
+ /** In-flight and finished compiles by key (a promise, so two concurrent get() calls share one compile). */
25
+ private readonly pending;
26
+ /** Finished compiles by key. */
27
+ private readonly entries;
28
+ /** Keys in the order their compiles were started (a failed compile is removed again). */
29
+ private readonly order;
30
+ private disposed;
31
+ /**
32
+ * Builds a cache over a device.
33
+ * @param device - the device pipelines are created on
34
+ * @param caps - its capabilities (WG, subgroup sizes, features)
35
+ */
36
+ constructor(device: GPUDevice, caps: PlanCaps);
37
+ /**
38
+ * The cache key of a spec on this device: `id + "|" + stableJson(overrides) + "|" + needs.filter(present).join(",") + "|" + hash(snippets)`.
39
+ * @param spec - the module
40
+ * @returns the key
41
+ */
42
+ key(spec: WgslModuleSpec): string;
43
+ /**
44
+ * 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.
45
+ * @param spec - the module
46
+ * @returns the pipeline (the same object for the same key)
47
+ */
48
+ get(spec: WgslModuleSpec): Promise<GPUComputePipeline>;
49
+ /**
50
+ * The Kernel (pipeline + layouts + binding names) for a spec; cached with the pipeline.
51
+ * @param spec - the module
52
+ * @returns the kernel (the same object for the same key)
53
+ */
54
+ kernel(spec: WgslModuleSpec): Promise<Kernel>;
55
+ /**
56
+ * Compiles every spec not yet cached (load() calls it so the first step() does not compile).
57
+ * @param specs - the modules
58
+ */
59
+ warm(specs: readonly WgslModuleSpec[]): Promise<void>;
60
+ /**
61
+ * Number of cached pipelines.
62
+ * @returns the count of finished compiles
63
+ */
64
+ get size(): number;
65
+ /**
66
+ * PLAN DECISION: forgets every pipeline and refuses further compiles with E_DISPOSED (the context's dispose()
67
+ * may call it; a GPUComputePipeline has no destroy(), so the objects are simply released).
68
+ */
69
+ dispose(): void;
70
+ /**
71
+ * The cached entry of a spec, compiling it once per key.
72
+ * @param spec - the module
73
+ * @returns the entry
74
+ */
75
+ private entry;
76
+ /**
77
+ * One compile: compose, create the shader module inside a synchronous push / pop validation pair (so concurrent
78
+ * compiles never interleave scopes), check the compilation info, create the layouts and the pipeline.
79
+ * PLAN DECISION: `E_SHADER_COMPILE` at stage "compile" also carries `lines` (the body-relative 1-based line of every
80
+ * error message, from `composed.bodyLine`) next to the contract's `messages`; a `createComputePipelineAsync`
81
+ * rejection (a GPUPipelineError, which pushes nothing into a validation scope on Dawn 0.4.0) is
82
+ * `E_VALIDATION { label: "<id>|pipeline", message }`; bool overrides travel as the pipeline constants 1 / 0
83
+ * because dawn.node's WebIDL layer rejects a boolean constant.
84
+ * @param spec - the module
85
+ * @param key - its key (the pipeline label)
86
+ * @returns the entry
87
+ */
88
+ private compile;
89
+ }
90
+ //# sourceMappingURL=pipeline-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-cache.d.ts","sourceRoot":"","sources":["../../../src/kernel/pipeline-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAgE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AA+C9G;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAGxE;AAWD,0IAA0I;AAC1I,qBAAa,aAAa;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAW;IAChC,2GAA2G;IAC3G,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0C;IAClE,gCAAgC;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,yFAAyF;IACzF,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;;OAIG;gBACS,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ;IAK7C;;;;OAIG;IACH,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM;IAIjC;;;;OAIG;IACG,GAAG,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAI5D;;;;OAIG;IACG,MAAM,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC;IAInD;;;OAGG;IACG,IAAI,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3D;;;OAGG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAuBD;;;OAGG;IACH,OAAO,IAAI,IAAI;IAOf;;;;OAIG;IACH,OAAO,CAAC,KAAK;IAgCb;;;;;;;;;;;OAWG;YACW,OAAO;CA4DxB"}