@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.
- package/README.md +378 -23
- package/dist/browser.d.ts +1 -0
- package/dist/browser.js +32 -0
- package/dist/browser.js.map +1 -0
- package/dist/chunks/context-E6iKaeuJ.js +3136 -0
- package/dist/chunks/context-E6iKaeuJ.js.map +1 -0
- package/dist/node.d.ts +1 -0
- package/dist/node.js +131 -0
- package/dist/node.js.map +1 -0
- package/dist/src/accelerator.d.ts +26 -0
- package/dist/src/accelerator.d.ts.map +1 -0
- package/dist/src/accelerator.js +101 -0
- package/dist/src/accelerator.js.map +1 -0
- package/dist/src/algorithms/degree.d.ts +35 -0
- package/dist/src/algorithms/degree.d.ts.map +1 -0
- package/dist/src/algorithms/degree.js +119 -0
- package/dist/src/algorithms/degree.js.map +1 -0
- package/dist/src/browser/index.d.ts +23 -0
- package/dist/src/browser/index.d.ts.map +1 -0
- package/dist/src/browser/index.js +48 -0
- package/dist/src/browser/index.js.map +1 -0
- package/dist/src/constants.d.ts +92 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +92 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/context.d.ts +84 -0
- package/dist/src/context.d.ts.map +1 -0
- package/dist/src/context.js +304 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/device/acquire.d.ts +57 -0
- package/dist/src/device/acquire.d.ts.map +1 -0
- package/dist/src/device/acquire.js +232 -0
- package/dist/src/device/acquire.js.map +1 -0
- package/dist/src/device/caps.d.ts +43 -0
- package/dist/src/device/caps.d.ts.map +1 -0
- package/dist/src/device/caps.js +104 -0
- package/dist/src/device/caps.js.map +1 -0
- package/dist/src/device/error-scope.d.ts +75 -0
- package/dist/src/device/error-scope.d.ts.map +1 -0
- package/dist/src/device/error-scope.js +152 -0
- package/dist/src/device/error-scope.js.map +1 -0
- package/dist/src/device/lost.d.ts +51 -0
- package/dist/src/device/lost.d.ts.map +1 -0
- package/dist/src/device/lost.js +130 -0
- package/dist/src/device/lost.js.map +1 -0
- package/dist/src/device/webgpu-constants.d.ts +31 -0
- package/dist/src/device/webgpu-constants.d.ts.map +1 -0
- package/dist/src/device/webgpu-constants.js +31 -0
- package/dist/src/device/webgpu-constants.js.map +1 -0
- package/dist/src/errors.d.ts +56 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +57 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/index.d.ts +29 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +27 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/kernel/batch.d.ts +116 -0
- package/dist/src/kernel/batch.d.ts.map +1 -0
- package/dist/src/kernel/batch.js +335 -0
- package/dist/src/kernel/batch.js.map +1 -0
- package/dist/src/kernel/dispatch.d.ts +59 -0
- package/dist/src/kernel/dispatch.d.ts.map +1 -0
- package/dist/src/kernel/dispatch.js +139 -0
- package/dist/src/kernel/dispatch.js.map +1 -0
- package/dist/src/kernel/kernel.d.ts +84 -0
- package/dist/src/kernel/kernel.d.ts.map +1 -0
- package/dist/src/kernel/kernel.js +239 -0
- package/dist/src/kernel/kernel.js.map +1 -0
- package/dist/src/kernel/pipeline-cache.d.ts +90 -0
- package/dist/src/kernel/pipeline-cache.d.ts.map +1 -0
- package/dist/src/kernel/pipeline-cache.js +251 -0
- package/dist/src/kernel/pipeline-cache.js.map +1 -0
- package/dist/src/kernel/prelude.d.ts +35 -0
- package/dist/src/kernel/prelude.d.ts.map +1 -0
- package/dist/src/kernel/prelude.js +211 -0
- package/dist/src/kernel/prelude.js.map +1 -0
- package/dist/src/kernel/profiler.d.ts +64 -0
- package/dist/src/kernel/profiler.d.ts.map +1 -0
- package/dist/src/kernel/profiler.js +120 -0
- package/dist/src/kernel/profiler.js.map +1 -0
- package/dist/src/kernel/struct-block.d.ts +122 -0
- package/dist/src/kernel/struct-block.d.ts.map +1 -0
- package/dist/src/kernel/struct-block.js +353 -0
- package/dist/src/kernel/struct-block.js.map +1 -0
- package/dist/src/kernel/uniform-ring.d.ts +70 -0
- package/dist/src/kernel/uniform-ring.d.ts.map +1 -0
- package/dist/src/kernel/uniform-ring.js +146 -0
- package/dist/src/kernel/uniform-ring.js.map +1 -0
- package/dist/src/kernel/wgsl.d.ts +88 -0
- package/dist/src/kernel/wgsl.d.ts.map +1 -0
- package/dist/src/kernel/wgsl.js +390 -0
- package/dist/src/kernel/wgsl.js.map +1 -0
- package/dist/src/kernels.d.ts +81 -0
- package/dist/src/kernels.d.ts.map +1 -0
- package/dist/src/kernels.js +417 -0
- package/dist/src/kernels.js.map +1 -0
- package/dist/src/layouts/force-simulation.d.ts +498 -0
- package/dist/src/layouts/force-simulation.d.ts.map +1 -0
- package/dist/src/layouts/force-simulation.js +1650 -0
- package/dist/src/layouts/force-simulation.js.map +1 -0
- package/dist/src/layouts/forceatlas2.d.ts +210 -0
- package/dist/src/layouts/forceatlas2.d.ts.map +1 -0
- package/dist/src/layouts/forceatlas2.js +759 -0
- package/dist/src/layouts/forceatlas2.js.map +1 -0
- package/dist/src/layouts/inputs.d.ts +40 -0
- package/dist/src/layouts/inputs.d.ts.map +1 -0
- package/dist/src/layouts/inputs.js +185 -0
- package/dist/src/layouts/inputs.js.map +1 -0
- package/dist/src/layouts/repulsion-exact.d.ts +85 -0
- package/dist/src/layouts/repulsion-exact.d.ts.map +1 -0
- package/dist/src/layouts/repulsion-exact.js +134 -0
- package/dist/src/layouts/repulsion-exact.js.map +1 -0
- package/dist/src/layouts/seed.d.ts +56 -0
- package/dist/src/layouts/seed.d.ts.map +1 -0
- package/dist/src/layouts/seed.js +173 -0
- package/dist/src/layouts/seed.js.map +1 -0
- package/dist/src/memory/buffer-pool.d.ts +73 -0
- package/dist/src/memory/buffer-pool.d.ts.map +1 -0
- package/dist/src/memory/buffer-pool.js +170 -0
- package/dist/src/memory/buffer-pool.js.map +1 -0
- package/dist/src/memory/lease.d.ts +53 -0
- package/dist/src/memory/lease.d.ts.map +1 -0
- package/dist/src/memory/lease.js +85 -0
- package/dist/src/memory/lease.js.map +1 -0
- package/dist/src/memory/readback.d.ts +143 -0
- package/dist/src/memory/readback.d.ts.map +1 -0
- package/dist/src/memory/readback.js +375 -0
- package/dist/src/memory/readback.js.map +1 -0
- package/dist/src/memory/residency.d.ts +83 -0
- package/dist/src/memory/residency.d.ts.map +1 -0
- package/dist/src/memory/residency.js +573 -0
- package/dist/src/memory/residency.js.map +1 -0
- package/dist/src/memory/upload-plan.d.ts +101 -0
- package/dist/src/memory/upload-plan.d.ts.map +1 -0
- package/dist/src/memory/upload-plan.js +265 -0
- package/dist/src/memory/upload-plan.js.map +1 -0
- package/dist/src/node/index.d.ts +64 -0
- package/dist/src/node/index.d.ts.map +1 -0
- package/dist/src/node/index.js +183 -0
- package/dist/src/node/index.js.map +1 -0
- package/dist/src/primitives/reduce.d.ts +57 -0
- package/dist/src/primitives/reduce.d.ts.map +1 -0
- package/dist/src/primitives/reduce.js +161 -0
- package/dist/src/primitives/reduce.js.map +1 -0
- package/dist/src/primitives/segmented-reduce.d.ts +38 -0
- package/dist/src/primitives/segmented-reduce.d.ts.map +1 -0
- package/dist/src/primitives/segmented-reduce.js +211 -0
- package/dist/src/primitives/segmented-reduce.js.map +1 -0
- package/dist/src/types/accelerator.d.ts +209 -0
- package/dist/src/types/accelerator.d.ts.map +1 -0
- package/dist/src/types/accelerator.js +8 -0
- package/dist/src/types/accelerator.js.map +1 -0
- package/dist/src/types/context.d.ts +114 -0
- package/dist/src/types/context.d.ts.map +1 -0
- package/dist/src/types/context.js +7 -0
- package/dist/src/types/context.js.map +1 -0
- package/dist/src/types/layout.d.ts +95 -0
- package/dist/src/types/layout.d.ts.map +1 -0
- package/dist/src/types/layout.js +6 -0
- package/dist/src/types/layout.js.map +1 -0
- package/dist/src/types/memory.d.ts +22 -0
- package/dist/src/types/memory.d.ts.map +1 -0
- package/dist/src/types/memory.js +7 -0
- package/dist/src/types/memory.js.map +1 -0
- package/dist/src/types/options.d.ts +78 -0
- package/dist/src/types/options.d.ts.map +1 -0
- package/dist/src/types/options.js +7 -0
- package/dist/src/types/options.js.map +1 -0
- package/dist/src/types/run.d.ts +13 -0
- package/dist/src/types/run.d.ts.map +1 -0
- package/dist/src/types/run.js +6 -0
- package/dist/src/types/run.js.map +1 -0
- package/dist/src/wgsl/degree.wgsl.d.ts +10 -0
- package/dist/src/wgsl/degree.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/degree.wgsl.js +25 -0
- package/dist/src/wgsl/degree.wgsl.js.map +1 -0
- package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +12 -0
- package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/fa2-attraction.wgsl.js +37 -0
- package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -0
- package/dist/src/wgsl/fa2-integrate.wgsl.d.ts +13 -0
- package/dist/src/wgsl/fa2-integrate.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/fa2-integrate.wgsl.js +69 -0
- package/dist/src/wgsl/fa2-integrate.wgsl.js.map +1 -0
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts +12 -0
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js +79 -0
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js.map +1 -0
- package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts +15 -0
- package/dist/src/wgsl/fa2-speed-finalize.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/fa2-speed-finalize.wgsl.js +54 -0
- package/dist/src/wgsl/fa2-speed-finalize.wgsl.js.map +1 -0
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +14 -0
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +57 -0
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -0
- package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts +11 -0
- package/dist/src/wgsl/fa2-to-scene.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/fa2-to-scene.wgsl.js +19 -0
- package/dist/src/wgsl/fa2-to-scene.wgsl.js.map +1 -0
- package/dist/src/wgsl/fill.wgsl.d.ts +7 -0
- package/dist/src/wgsl/fill.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/fill.wgsl.js +14 -0
- package/dist/src/wgsl/fill.wgsl.js.map +1 -0
- package/dist/src/wgsl/reduce.wgsl.d.ts +10 -0
- package/dist/src/wgsl/reduce.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/reduce.wgsl.js +63 -0
- package/dist/src/wgsl/reduce.wgsl.js.map +1 -0
- package/dist/src/wgsl/segmented-reduce.wgsl.d.ts +13 -0
- package/dist/src/wgsl/segmented-reduce.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/segmented-reduce.wgsl.js +35 -0
- package/dist/src/wgsl/segmented-reduce.wgsl.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/webgpu-graph-algorithms.d.ts +1 -0
- package/dist/webgpu-graph-algorithms.js +4454 -0
- package/dist/webgpu-graph-algorithms.js.map +1 -0
- package/package.json +108 -17
- package/src/accelerator.ts +117 -0
- package/src/algorithms/degree.ts +142 -0
- package/src/browser/index.ts +57 -0
- package/src/constants.ts +116 -0
- package/src/context.ts +399 -0
- package/src/device/acquire.ts +256 -0
- package/src/device/caps.ts +122 -0
- package/src/device/error-scope.ts +171 -0
- package/src/device/lost.ts +142 -0
- package/src/device/webgpu-constants.ts +44 -0
- package/src/errors.ts +94 -0
- package/src/index.ts +102 -0
- package/src/kernel/batch.ts +427 -0
- package/src/kernel/dispatch.ts +162 -0
- package/src/kernel/kernel.ts +311 -0
- package/src/kernel/pipeline-cache.ts +288 -0
- package/src/kernel/prelude.ts +229 -0
- package/src/kernel/profiler.ts +148 -0
- package/src/kernel/struct-block.ts +439 -0
- package/src/kernel/uniform-ring.ts +184 -0
- package/src/kernel/wgsl.ts +490 -0
- package/src/kernels.ts +511 -0
- package/src/layouts/force-simulation.ts +2111 -0
- package/src/layouts/forceatlas2.ts +942 -0
- package/src/layouts/inputs.ts +252 -0
- package/src/layouts/repulsion-exact.ts +183 -0
- package/src/layouts/seed.ts +198 -0
- package/src/memory/buffer-pool.ts +204 -0
- package/src/memory/lease.ts +93 -0
- package/src/memory/readback.ts +429 -0
- package/src/memory/residency.ts +753 -0
- package/src/memory/upload-plan.ts +350 -0
- package/src/node/index.ts +230 -0
- package/src/primitives/reduce.ts +233 -0
- package/src/primitives/segmented-reduce.ts +270 -0
- package/src/types/accelerator.ts +236 -0
- package/src/types/context.ts +135 -0
- package/src/types/layout.ts +103 -0
- package/src/types/memory.ts +23 -0
- package/src/types/options.ts +84 -0
- package/src/types/run.ts +13 -0
- package/src/wgsl/degree.wgsl.ts +24 -0
- package/src/wgsl/fa2-attraction.wgsl.ts +37 -0
- package/src/wgsl/fa2-integrate.wgsl.ts +69 -0
- package/src/wgsl/fa2-repulsion-exact.wgsl.ts +78 -0
- package/src/wgsl/fa2-speed-finalize.wgsl.ts +53 -0
- package/src/wgsl/fa2-stats-finalize.wgsl.ts +57 -0
- package/src/wgsl/fa2-to-scene.wgsl.ts +19 -0
- package/src/wgsl/fill.wgsl.ts +13 -0
- package/src/wgsl/reduce.wgsl.ts +62 -0
- 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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"}
|