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