@graphty/webgpu-graph-algorithms 0.0.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/README.md +378 -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,120 @@
1
+ /**
2
+ * Timestamp profiling of spec 5.5: when "timestamp-query" was granted the context owns a Profiler
3
+ * whose query set (PROFILER_QUERY_SLOTS slots, two per pass) is written by the timestampWrites of
4
+ * every CommandBatch pass; `resolveInto(batch)` records the resolve plus a copy into the batch's
5
+ * staging slot and `timings(bytes, request)` decodes `{ label, ns }` per pass from the batch's
6
+ * readback bytes. Chromium quantises timestamps to 100 us (`quantised: true`); Dawn-node reports
7
+ * 1,024 ns ticks (spec 2.6). The profiler never throws: a full query set drops timings and a device
8
+ * without the feature disables it. Slot pairs are handed out in order and the cursor restarts at 0
9
+ * after every resolve: queue order guarantees the resolve of batch A reads its slots before batch B
10
+ * overwrites them, and one resolve buffer suffices for the same reason.
11
+ */
12
+ import { PROFILER_QUERY_SLOTS } from "../constants.js";
13
+ import { BufferUsage } from "../device/webgpu-constants.js";
14
+ /** Timestamp profiling when "timestamp-query" was granted (spec 5.5). */
15
+ export class Profiler {
16
+ /**
17
+ * Creates the query set and the resolve buffer when usable; `slots` defaults to PROFILER_QUERY_SLOTS = 256
18
+ * (spec 5.5); 2 query slots per pass. `enabled` is also false when the device lacks "timestamp-query" or
19
+ * `slots < 2`, so no caller can make the profiler raise a validation error.
20
+ * @param device - the device the query set is created on
21
+ * @param enabled - whether the caller wants profiling (the context passes `features.has("timestamp-query")`)
22
+ * @param quantised - true in browsers
23
+ * @param slots - query slots, two per pass (default PROFILER_QUERY_SLOTS)
24
+ */
25
+ constructor(device, enabled, quantised, slots) {
26
+ this.labels = new WeakMap();
27
+ this.pending = [];
28
+ this.cursor = 0;
29
+ this.destroyed = false;
30
+ const count = slots ?? PROFILER_QUERY_SLOTS;
31
+ this.quantised = quantised;
32
+ this.slots = count;
33
+ const usable = enabled && count >= 2 && device.features.has("timestamp-query");
34
+ this.enabled = usable;
35
+ if (usable) {
36
+ this.querySet = device.createQuerySet({ label: "profiler/timestamps", type: "timestamp", count });
37
+ this.resolveBuffer = device.createBuffer({
38
+ label: "profiler/resolve",
39
+ size: count * 8,
40
+ usage: BufferUsage.QUERY_RESOLVE | BufferUsage.COPY_SRC,
41
+ });
42
+ }
43
+ else {
44
+ this.querySet = null;
45
+ this.resolveBuffer = null;
46
+ }
47
+ }
48
+ /**
49
+ * The timestampWrites descriptor for a new pass, or undefined when disabled / out of slots.
50
+ * @param label - the pass name reported by `timings()`
51
+ * @returns the descriptor a CommandBatch puts on beginComputePass, or undefined
52
+ */
53
+ beginPass(label) {
54
+ if (this.querySet === null || this.destroyed || this.cursor + 2 > this.slots) {
55
+ return undefined;
56
+ }
57
+ const begin = this.cursor;
58
+ this.cursor += 2;
59
+ this.pending.push({ label, begin });
60
+ return { querySet: this.querySet, beginningOfPassWriteIndex: begin, endOfPassWriteIndex: begin + 1 };
61
+ }
62
+ /**
63
+ * Records the resolve + copy into the batch's staging slot; returns the request's byte range, or null when
64
+ * nothing was written (disabled, destroyed, or no pass begun since the last resolve).
65
+ * @param batch - the batch whose passes were timed (it must still be open)
66
+ * @returns the readback request `timings()` decodes, or null
67
+ */
68
+ resolveInto(batch) {
69
+ if (this.querySet === null || this.resolveBuffer === null || this.destroyed || this.pending.length === 0) {
70
+ return null;
71
+ }
72
+ const count = this.cursor;
73
+ batch.resolveQuerySet(this.querySet, 0, count, this.resolveBuffer);
74
+ const request = batch.readback(this.resolveBuffer, 0, count * 8);
75
+ this.labels.set(request, this.pending.map((pass) => pass.label));
76
+ this.pending = [];
77
+ this.cursor = 0;
78
+ return request;
79
+ }
80
+ /**
81
+ * Decodes the timings of a batch from its readback bytes.
82
+ * @param bytes - the resolved readback of the batch
83
+ * @param request - the request `resolveInto()` returned for it
84
+ * @returns one timing per pass in pass order (empty for a request this profiler did not create)
85
+ */
86
+ timings(bytes, request) {
87
+ const labels = this.labels.get(request);
88
+ if (labels === undefined) {
89
+ return [];
90
+ }
91
+ const view = new DataView(bytes);
92
+ const out = [];
93
+ for (let i = 0; i < labels.length; i++) {
94
+ const at = request.offset + i * 16;
95
+ if (at + 16 > bytes.byteLength) {
96
+ break;
97
+ }
98
+ const begin = view.getBigUint64(at, true);
99
+ const end = view.getBigUint64(at + 8, true);
100
+ out.push({ label: labels[i], ns: Number(end - begin) });
101
+ }
102
+ return out;
103
+ }
104
+ /** Destroys the query set and the resolve buffer; idempotent. */
105
+ destroy() {
106
+ if (this.destroyed) {
107
+ return;
108
+ }
109
+ this.destroyed = true;
110
+ this.pending = [];
111
+ this.cursor = 0;
112
+ if (this.querySet !== null) {
113
+ this.querySet.destroy();
114
+ }
115
+ if (this.resolveBuffer !== null) {
116
+ this.resolveBuffer.destroy();
117
+ }
118
+ }
119
+ }
120
+ //# sourceMappingURL=profiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiler.js","sourceRoot":"","sources":["../../../src/kernel/profiler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * UniformBlock (spec 5.3, D20): one field table generates BOTH the padded WGSL `struct` text spliced into a module
3
+ * and the byte writer / reader the host uses, so the two cannot disagree. The layout is the strict WGSL layout
4
+ * every runtime accepts (Chromium 139 lacks `uniform_buffer_standard_layout`): scalars 4-aligned, vec2 8-aligned,
5
+ * vec4 16-aligned, no vec3, no bool, no arrays, and the total padded to a multiple of 16 (or to `padTo`) through an
6
+ * explicit `@size` on the last member.
7
+ */
8
+ /** Field types a block may hold; no vec3 (spec 5.3), no bool (not host-shareable), no arrays. */
9
+ export type UniformFieldType = "u32" | "i32" | "f32" | "vec2f" | "vec2u" | "vec4f" | "vec4u";
10
+ /** One field. */
11
+ export type UniformField = readonly [name: string, type: UniformFieldType];
12
+ /** The values written into or read from a block: scalars as numbers, vectors as number arrays of the vector's width. */
13
+ export type UniformValues = Readonly<Record<string, number | readonly number[]>>;
14
+ /** A generated struct: the padded WGSL text and the byte writer / reader share one field table, so they cannot disagree (D20). */
15
+ export declare class UniformBlock {
16
+ /** The WGSL struct name. */
17
+ readonly name: string;
18
+ /** "uniform" (the default) or "storage"; both lay out identically, the tag documents the block's address space. */
19
+ readonly layout: "uniform" | "storage";
20
+ /** The fields in declaration (= byte) order. */
21
+ readonly fields: readonly UniformField[];
22
+ /** The padded byte length (a multiple of 16). */
23
+ readonly byteLength: number;
24
+ /** The `struct <name> { ... }` text with explicit `@size` / `@align` where padding is needed. */
25
+ readonly wgsl: string;
26
+ /** The laid-out fields by name. */
27
+ private readonly table;
28
+ /** The laid-out fields in order. */
29
+ private readonly laidOut;
30
+ /**
31
+ * Declares a block; fields are laid out in order with 16-byte alignment for vec4 / the struct, 8 for vec2, 4 for
32
+ * scalars; the total is padded to 16 (uniform, storage) or to `padTo` when given.
33
+ * PLAN DECISION: rejects an empty field list and a struct or field name that is not a WGSL identifier or is a
34
+ * reserved word (spec 3.6: every throwing call leaves state unchanged; a reserved name would be invalid WGSL).
35
+ * PLAN DECISION: optional PARAMETERS (`options?` here, `byteOffset?` of write / read / readField) are spelled
36
+ * `?: T` rather than the contract's `?: T | undefined` because the root ESLint rule
37
+ * no-duplicate-type-constituents rejects the explicit undefined on an optional parameter; every call site is
38
+ * identical, and optional PROPERTIES keep `?: T | undefined`.
39
+ * @param name - the WGSL struct name
40
+ * @param fields - the fields in byte order
41
+ * @param options - the layout tag and the optional padding
42
+ * @param options.layout - "uniform" (default) or "storage"; the tag documents the address space, the layout is the same
43
+ * @param options.padTo - the byte length to pad to (a multiple of 16 not below the natural size)
44
+ * @returns the block
45
+ */
46
+ static define(name: string, fields: readonly UniformField[], options?: {
47
+ readonly layout?: "uniform" | "storage" | undefined;
48
+ readonly padTo?: number | undefined;
49
+ }): UniformBlock;
50
+ /**
51
+ * Built by `define()` only.
52
+ * @param name - the struct name
53
+ * @param layout - the address-space tag
54
+ * @param fields - the declared fields
55
+ * @param byteLength - the padded byte length
56
+ * @param wgsl - the struct text
57
+ * @param laidOut - the laid-out fields in order
58
+ * @param table - the laid-out fields by name
59
+ */
60
+ private constructor();
61
+ /**
62
+ * Byte offset of a field; E_INVALID_ARGUMENT for an unknown field.
63
+ * @param field - the field name
64
+ * @returns the byte offset inside the block
65
+ */
66
+ offsetOf(field: string): number;
67
+ /**
68
+ * Writes `values` at `byteOffset` (default 0); a missing field is written as 0; an unknown key is
69
+ * E_INVALID_ARGUMENT; a vector of the wrong width is E_INVALID_ARGUMENT. Always little-endian. Every byte of the
70
+ * block's region is written (padding as zero), so a written block is byte-exact.
71
+ * PLAN DECISION: every value is validated first (u32 / vec*u components integers in [0, 2^32 - 1], i32 in
72
+ * [-2^31, 2^31 - 1]) and only then is the region zeroed and written, so a rejected call leaves the view unchanged.
73
+ * @param view - the target view (the region must lie inside it)
74
+ * @param values - the field values
75
+ * @param byteOffset - the region's start inside the view
76
+ */
77
+ write(view: DataView, values: UniformValues, byteOffset?: number): void;
78
+ /**
79
+ * The validated components of one field's value: null for an absent field, else `width` numbers.
80
+ * @param field - the laid-out field
81
+ * @param value - the value given for it (undefined when absent)
82
+ * @returns the components or null
83
+ */
84
+ private components;
85
+ /**
86
+ * Reads every field at `byteOffset` (storage mode's reader; also used by tests on uniform blocks).
87
+ * @param view - the source view
88
+ * @param byteOffset - the region's start inside the view
89
+ * @returns the field values (vectors as arrays)
90
+ */
91
+ read(view: DataView, byteOffset?: number): UniformValues;
92
+ /**
93
+ * Reads one field.
94
+ * @param view - the source view
95
+ * @param field - the field name
96
+ * @param byteOffset - the region's start inside the view
97
+ * @returns the value (a number, or an array for a vector)
98
+ */
99
+ readField(view: DataView, field: string, byteOffset?: number): number | readonly number[];
100
+ /**
101
+ * The laid-out field of a name.
102
+ * @param field - the field name
103
+ * @returns the layout
104
+ */
105
+ private fieldLayout;
106
+ /**
107
+ * Validates the region `[byteOffset, byteOffset + byteLength)` against the view.
108
+ * @param view - the view
109
+ * @param byteOffset - the requested start (default 0)
110
+ * @returns the start
111
+ */
112
+ private regionStart;
113
+ /**
114
+ * Decodes one field from a view.
115
+ * @param view - the source view
116
+ * @param field - the laid-out field
117
+ * @param base - the region start
118
+ * @returns the value
119
+ */
120
+ private decode;
121
+ }
122
+ //# sourceMappingURL=struct-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"struct-block.d.ts","sourceRoot":"","sources":["../../../src/kernel/struct-block.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,iGAAiG;AACjG,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAC7F,iBAAiB;AACjB,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC;AAC3E,wHAAwH;AACxH,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;AA+HjF,kIAAkI;AAClI,qBAAa,YAAY;IACrB,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mHAAmH;IACnH,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IACvC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;IACzC,iDAAiD;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,iGAAiG;IACjG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,oCAAoC;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IAEjD;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,MAAM,CACT,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GACvG,YAAY;IA+Df;;;;;;;;;OASG;IACH,OAAO;IAkBP;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAI/B;;;;;;;;;OASG;IACH,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IA6BvE;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IA6BlB;;;;;OAKG;IACH,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,aAAa;IASxD;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE;IAKzF;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAYnB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAgBnB;;;;;;OAMG;IACH,OAAO,CAAC,MAAM;CAWjB"}
@@ -0,0 +1,353 @@
1
+ /**
2
+ * UniformBlock (spec 5.3, D20): one field table generates BOTH the padded WGSL `struct` text spliced into a module
3
+ * and the byte writer / reader the host uses, so the two cannot disagree. The layout is the strict WGSL layout
4
+ * every runtime accepts (Chromium 139 lacks `uniform_buffer_standard_layout`): scalars 4-aligned, vec2 8-aligned,
5
+ * vec4 16-aligned, no vec3, no bool, no arrays, and the total padded to a multiple of 16 (or to `padTo`) through an
6
+ * explicit `@size` on the last member.
7
+ */
8
+ import { WebGpuGraphError } from "../errors.js";
9
+ import { WGSL_RESERVED_WORDS } from "./prelude.js";
10
+ const TYPE_INFO = Object.freeze({
11
+ u32: { size: 4, align: 4, width: 1, scalar: "u32" },
12
+ i32: { size: 4, align: 4, width: 1, scalar: "i32" },
13
+ f32: { size: 4, align: 4, width: 1, scalar: "f32" },
14
+ vec2f: { size: 8, align: 8, width: 2, scalar: "f32" },
15
+ vec2u: { size: 8, align: 8, width: 2, scalar: "u32" },
16
+ vec4f: { size: 16, align: 16, width: 4, scalar: "f32" },
17
+ vec4u: { size: 16, align: 16, width: 4, scalar: "u32" },
18
+ });
19
+ const STRUCT_ALIGN = 16;
20
+ const IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
21
+ const U32_LIMIT = 0xffffffff;
22
+ const I32_MIN = -2147483648;
23
+ const I32_MAX = 2147483647;
24
+ /**
25
+ * Rounds `value` up to the next multiple of `align` (arithmetic, never a bit trick: byte offsets are never operated
26
+ * on bitwise, spec 3.6).
27
+ * @param value - the value to round
28
+ * @param align - the alignment, a positive integer
29
+ * @returns the rounded value
30
+ */
31
+ function roundUp(value, align) {
32
+ return Math.ceil(value / align) * align;
33
+ }
34
+ /**
35
+ * Validates a WGSL identifier for a struct or field name.
36
+ * @param argument - the E_INVALID_ARGUMENT `argument` to report
37
+ * @param name - the identifier
38
+ */
39
+ function assertIdentifier(argument, name) {
40
+ if (!IDENTIFIER.test(name) || WGSL_RESERVED_WORDS.includes(name)) {
41
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock: "${name}" is not a usable WGSL identifier`, {
42
+ argument,
43
+ value: name,
44
+ expected: "a WGSL identifier that is not a reserved word",
45
+ });
46
+ }
47
+ }
48
+ /**
49
+ * Validates one scalar component of a value against its scalar kind.
50
+ * @param field - the field name (for the error)
51
+ * @param kind - the scalar kind
52
+ * @param value - the component
53
+ */
54
+ function assertScalar(field, kind, value) {
55
+ if (typeof value !== "number") {
56
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock: field "${field}" expects a number`, {
57
+ argument: field,
58
+ value,
59
+ expected: kind,
60
+ });
61
+ }
62
+ if (kind === "u32" && !(Number.isInteger(value) && value >= 0 && value <= U32_LIMIT)) {
63
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock: field "${field}" is not a u32`, {
64
+ argument: field,
65
+ value,
66
+ expected: "an integer in [0, 4294967295]",
67
+ });
68
+ }
69
+ if (kind === "i32" && !(Number.isInteger(value) && value >= I32_MIN && value <= I32_MAX)) {
70
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock: field "${field}" is not an i32`, {
71
+ argument: field,
72
+ value,
73
+ expected: "an integer in [-2147483648, 2147483647]",
74
+ });
75
+ }
76
+ }
77
+ /**
78
+ * Writes one scalar component little-endian.
79
+ * @param view - the target view
80
+ * @param kind - the scalar kind
81
+ * @param offset - the byte offset
82
+ * @param value - the component
83
+ */
84
+ function setScalar(view, kind, offset, value) {
85
+ if (kind === "u32") {
86
+ view.setUint32(offset, value, true);
87
+ }
88
+ else if (kind === "i32") {
89
+ view.setInt32(offset, value, true);
90
+ }
91
+ else {
92
+ view.setFloat32(offset, value, true);
93
+ }
94
+ }
95
+ /**
96
+ * Reads one scalar component little-endian.
97
+ * @param view - the source view
98
+ * @param kind - the scalar kind
99
+ * @param offset - the byte offset
100
+ * @returns the component
101
+ */
102
+ function getScalar(view, kind, offset) {
103
+ if (kind === "u32") {
104
+ return view.getUint32(offset, true);
105
+ }
106
+ if (kind === "i32") {
107
+ return view.getInt32(offset, true);
108
+ }
109
+ return view.getFloat32(offset, true);
110
+ }
111
+ /** A generated struct: the padded WGSL text and the byte writer / reader share one field table, so they cannot disagree (D20). */
112
+ export class UniformBlock {
113
+ /**
114
+ * Declares a block; fields are laid out in order with 16-byte alignment for vec4 / the struct, 8 for vec2, 4 for
115
+ * scalars; the total is padded to 16 (uniform, storage) or to `padTo` when given.
116
+ * PLAN DECISION: rejects an empty field list and a struct or field name that is not a WGSL identifier or is a
117
+ * reserved word (spec 3.6: every throwing call leaves state unchanged; a reserved name would be invalid WGSL).
118
+ * PLAN DECISION: optional PARAMETERS (`options?` here, `byteOffset?` of write / read / readField) are spelled
119
+ * `?: T` rather than the contract's `?: T | undefined` because the root ESLint rule
120
+ * no-duplicate-type-constituents rejects the explicit undefined on an optional parameter; every call site is
121
+ * identical, and optional PROPERTIES keep `?: T | undefined`.
122
+ * @param name - the WGSL struct name
123
+ * @param fields - the fields in byte order
124
+ * @param options - the layout tag and the optional padding
125
+ * @param options.layout - "uniform" (default) or "storage"; the tag documents the address space, the layout is the same
126
+ * @param options.padTo - the byte length to pad to (a multiple of 16 not below the natural size)
127
+ * @returns the block
128
+ */
129
+ static define(name, fields, options) {
130
+ assertIdentifier("name", name);
131
+ if (fields.length === 0) {
132
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock ${name}: a block needs at least one field`, {
133
+ argument: "fields",
134
+ value: fields.length,
135
+ expected: ">= 1 field",
136
+ });
137
+ }
138
+ const laidOut = [];
139
+ const table = new Map();
140
+ let cursor = 0;
141
+ for (const [fieldName, type] of fields) {
142
+ assertIdentifier("fields", fieldName);
143
+ if (table.has(fieldName)) {
144
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock ${name}: duplicate field "${fieldName}"`, {
145
+ argument: "fields",
146
+ value: fieldName,
147
+ expected: "unique field names",
148
+ });
149
+ }
150
+ const info = TYPE_INFO[type];
151
+ if (info === undefined) {
152
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock ${name}: unknown field type "${type}"`, {
153
+ argument: "fields",
154
+ value: type,
155
+ expected: Object.keys(TYPE_INFO).join(" | "),
156
+ });
157
+ }
158
+ const offset = roundUp(cursor, info.align);
159
+ const field = { name: fieldName, type, offset, info };
160
+ laidOut.push(field);
161
+ table.set(fieldName, field);
162
+ cursor = offset + info.size;
163
+ }
164
+ const natural = roundUp(cursor, STRUCT_ALIGN);
165
+ const padTo = options?.padTo;
166
+ if (padTo !== undefined && (!Number.isInteger(padTo) || padTo % STRUCT_ALIGN !== 0 || padTo < natural)) {
167
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock ${name}: padTo ${padTo} is not a multiple of 16 >= ${natural}`, {
168
+ argument: "padTo",
169
+ value: padTo,
170
+ expected: `a multiple of ${STRUCT_ALIGN} not below ${natural}`,
171
+ });
172
+ }
173
+ const byteLength = padTo ?? natural;
174
+ const lines = laidOut.map((field, index) => {
175
+ const last = index === laidOut.length - 1;
176
+ const end = field.offset + field.info.size;
177
+ const size = last && end < byteLength ? `@size(${byteLength - field.offset}) ` : "";
178
+ return ` ${size}${field.name}: ${field.type},`;
179
+ });
180
+ const wgsl = `struct ${name} {\n${lines.join("\n")}\n}`;
181
+ return new UniformBlock(name, options?.layout ?? "uniform", fields, byteLength, wgsl, laidOut, table);
182
+ }
183
+ /**
184
+ * Built by `define()` only.
185
+ * @param name - the struct name
186
+ * @param layout - the address-space tag
187
+ * @param fields - the declared fields
188
+ * @param byteLength - the padded byte length
189
+ * @param wgsl - the struct text
190
+ * @param laidOut - the laid-out fields in order
191
+ * @param table - the laid-out fields by name
192
+ */
193
+ constructor(name, layout, fields, byteLength, wgsl, laidOut, table) {
194
+ this.name = name;
195
+ this.layout = layout;
196
+ this.fields = Object.freeze(fields.map(([fieldName, type]) => Object.freeze([fieldName, type])));
197
+ this.byteLength = byteLength;
198
+ this.wgsl = wgsl;
199
+ this.laidOut = laidOut;
200
+ this.table = table;
201
+ }
202
+ /**
203
+ * Byte offset of a field; E_INVALID_ARGUMENT for an unknown field.
204
+ * @param field - the field name
205
+ * @returns the byte offset inside the block
206
+ */
207
+ offsetOf(field) {
208
+ return this.fieldLayout(field).offset;
209
+ }
210
+ /**
211
+ * Writes `values` at `byteOffset` (default 0); a missing field is written as 0; an unknown key is
212
+ * E_INVALID_ARGUMENT; a vector of the wrong width is E_INVALID_ARGUMENT. Always little-endian. Every byte of the
213
+ * block's region is written (padding as zero), so a written block is byte-exact.
214
+ * PLAN DECISION: every value is validated first (u32 / vec*u components integers in [0, 2^32 - 1], i32 in
215
+ * [-2^31, 2^31 - 1]) and only then is the region zeroed and written, so a rejected call leaves the view unchanged.
216
+ * @param view - the target view (the region must lie inside it)
217
+ * @param values - the field values
218
+ * @param byteOffset - the region's start inside the view
219
+ */
220
+ write(view, values, byteOffset) {
221
+ const base = this.regionStart(view, byteOffset);
222
+ for (const key of Object.keys(values)) {
223
+ if (!this.table.has(key)) {
224
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock ${this.name}: unknown field "${key}"`, {
225
+ argument: "values",
226
+ value: key,
227
+ expected: this.laidOut.map((f) => f.name).join(", "),
228
+ });
229
+ }
230
+ }
231
+ // validate every value first, so a rejected call leaves the view unchanged (spec 3.6)
232
+ const components = this.laidOut.map((field) => this.components(field, values[field.name]));
233
+ for (let at = 0; at < this.byteLength; at += 4) {
234
+ view.setUint32(base + at, 0, true);
235
+ }
236
+ this.laidOut.forEach((field, index) => {
237
+ const lanes = components[index];
238
+ if (lanes === null) {
239
+ return;
240
+ }
241
+ lanes.forEach((component, lane) => {
242
+ setScalar(view, field.info.scalar, base + field.offset + 4 * lane, component);
243
+ });
244
+ });
245
+ }
246
+ /**
247
+ * The validated components of one field's value: null for an absent field, else `width` numbers.
248
+ * @param field - the laid-out field
249
+ * @param value - the value given for it (undefined when absent)
250
+ * @returns the components or null
251
+ */
252
+ components(field, value) {
253
+ if (value === undefined) {
254
+ return null;
255
+ }
256
+ const { scalar, width } = field.info;
257
+ if (width === 1) {
258
+ assertScalar(field.name, scalar, value);
259
+ return [value];
260
+ }
261
+ if (!Array.isArray(value) || value.length !== width) {
262
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock ${this.name}: field "${field.name}" expects ${width} components`, {
263
+ argument: field.name,
264
+ value,
265
+ expected: `an array of ${width} numbers`,
266
+ });
267
+ }
268
+ const lanes = [];
269
+ for (let lane = 0; lane < width; lane++) {
270
+ const component = value[lane];
271
+ assertScalar(field.name, scalar, component);
272
+ lanes.push(component);
273
+ }
274
+ return lanes;
275
+ }
276
+ /**
277
+ * Reads every field at `byteOffset` (storage mode's reader; also used by tests on uniform blocks).
278
+ * @param view - the source view
279
+ * @param byteOffset - the region's start inside the view
280
+ * @returns the field values (vectors as arrays)
281
+ */
282
+ read(view, byteOffset) {
283
+ const base = this.regionStart(view, byteOffset);
284
+ const out = {};
285
+ for (const field of this.laidOut) {
286
+ out[field.name] = this.decode(view, field, base);
287
+ }
288
+ return out;
289
+ }
290
+ /**
291
+ * Reads one field.
292
+ * @param view - the source view
293
+ * @param field - the field name
294
+ * @param byteOffset - the region's start inside the view
295
+ * @returns the value (a number, or an array for a vector)
296
+ */
297
+ readField(view, field, byteOffset) {
298
+ const layout = this.fieldLayout(field);
299
+ return this.decode(view, layout, this.regionStart(view, byteOffset));
300
+ }
301
+ /**
302
+ * The laid-out field of a name.
303
+ * @param field - the field name
304
+ * @returns the layout
305
+ */
306
+ fieldLayout(field) {
307
+ const layout = this.table.get(field);
308
+ if (layout === undefined) {
309
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock ${this.name}: unknown field "${field}"`, {
310
+ argument: "field",
311
+ value: field,
312
+ expected: this.laidOut.map((f) => f.name).join(", "),
313
+ });
314
+ }
315
+ return layout;
316
+ }
317
+ /**
318
+ * Validates the region `[byteOffset, byteOffset + byteLength)` against the view.
319
+ * @param view - the view
320
+ * @param byteOffset - the requested start (default 0)
321
+ * @returns the start
322
+ */
323
+ regionStart(view, byteOffset) {
324
+ const base = byteOffset ?? 0;
325
+ if (!Number.isInteger(base) || base < 0 || base + this.byteLength > view.byteLength) {
326
+ throw new WebGpuGraphError("E_INVALID_ARGUMENT", `UniformBlock ${this.name}: region [${base}, ${base + this.byteLength}) is outside the view`, {
327
+ argument: "byteOffset",
328
+ value: base,
329
+ expected: `0 <= byteOffset <= ${view.byteLength - this.byteLength}`,
330
+ });
331
+ }
332
+ return base;
333
+ }
334
+ /**
335
+ * Decodes one field from a view.
336
+ * @param view - the source view
337
+ * @param field - the laid-out field
338
+ * @param base - the region start
339
+ * @returns the value
340
+ */
341
+ decode(view, field, base) {
342
+ const { scalar, width } = field.info;
343
+ if (width === 1) {
344
+ return getScalar(view, scalar, base + field.offset);
345
+ }
346
+ const lanes = [];
347
+ for (let lane = 0; lane < width; lane++) {
348
+ lanes.push(getScalar(view, scalar, base + field.offset + 4 * lane));
349
+ }
350
+ return lanes;
351
+ }
352
+ }
353
+ //# sourceMappingURL=struct-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"struct-block.js","sourceRoot":"","sources":["../../../src/kernel/struct-block.ts"],"names":[],"mappings":"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"}