@graphty/webgpu-graph-algorithms 0.5.0 → 0.6.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 +104 -52
- package/dist/browser.js +1 -1
- package/dist/chunks/{context-CRbw2Wyo.js → context-BXqgCifx.js} +225 -33
- package/dist/chunks/context-BXqgCifx.js.map +1 -0
- package/dist/node.js +1 -1
- package/dist/src/accelerator.d.ts +12 -10
- package/dist/src/accelerator.d.ts.map +1 -1
- package/dist/src/accelerator.js +32 -10
- package/dist/src/accelerator.js.map +1 -1
- package/dist/src/algorithms/components.d.ts.map +1 -1
- package/dist/src/algorithms/components.js +12 -13
- package/dist/src/algorithms/components.js.map +1 -1
- package/dist/src/algorithms/degree.d.ts +6 -8
- package/dist/src/algorithms/degree.d.ts.map +1 -1
- package/dist/src/algorithms/degree.js +58 -35
- package/dist/src/algorithms/degree.js.map +1 -1
- package/dist/src/algorithms/pagerank.d.ts.map +1 -1
- package/dist/src/algorithms/pagerank.js +16 -14
- package/dist/src/algorithms/pagerank.js.map +1 -1
- package/dist/src/algorithms/power-iteration.d.ts +2 -2
- package/dist/src/algorithms/power-iteration.d.ts.map +1 -1
- package/dist/src/algorithms/power-iteration.js +17 -14
- package/dist/src/algorithms/power-iteration.js.map +1 -1
- package/dist/src/constants.d.ts +85 -8
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +85 -8
- package/dist/src/constants.js.map +1 -1
- package/dist/src/errors.d.ts +3 -2
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +2 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +10 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +14 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/kernel/dispatch.d.ts +8 -3
- package/dist/src/kernel/dispatch.d.ts.map +1 -1
- package/dist/src/kernel/dispatch.js +18 -7
- package/dist/src/kernel/dispatch.js.map +1 -1
- package/dist/src/kernel/kernel.d.ts +30 -1
- package/dist/src/kernel/kernel.d.ts.map +1 -1
- package/dist/src/kernel/kernel.js +49 -5
- package/dist/src/kernel/kernel.js.map +1 -1
- package/dist/src/kernel/prelude.d.ts.map +1 -1
- package/dist/src/kernel/prelude.js +9 -1
- package/dist/src/kernel/prelude.js.map +1 -1
- package/dist/src/kernel/profiler.d.ts +15 -3
- package/dist/src/kernel/profiler.d.ts.map +1 -1
- package/dist/src/kernel/profiler.js +27 -4
- package/dist/src/kernel/profiler.js.map +1 -1
- package/dist/src/kernels.d.ts +18 -8
- package/dist/src/kernels.d.ts.map +1 -1
- package/dist/src/kernels.js +345 -22
- package/dist/src/kernels.js.map +1 -1
- package/dist/src/layouts/calibrate.d.ts +51 -0
- package/dist/src/layouts/calibrate.d.ts.map +1 -0
- package/dist/src/layouts/calibrate.js +172 -0
- package/dist/src/layouts/calibrate.js.map +1 -0
- package/dist/src/layouts/force-simulation.d.ts +42 -5
- package/dist/src/layouts/force-simulation.d.ts.map +1 -1
- package/dist/src/layouts/force-simulation.js +84 -22
- package/dist/src/layouts/force-simulation.js.map +1 -1
- package/dist/src/layouts/forceatlas2.d.ts +107 -38
- package/dist/src/layouts/forceatlas2.d.ts.map +1 -1
- package/dist/src/layouts/forceatlas2.js +297 -290
- package/dist/src/layouts/forceatlas2.js.map +1 -1
- package/dist/src/layouts/fruchterman-reingold.d.ts +241 -0
- package/dist/src/layouts/fruchterman-reingold.d.ts.map +1 -0
- package/dist/src/layouts/fruchterman-reingold.js +739 -0
- package/dist/src/layouts/fruchterman-reingold.js.map +1 -0
- package/dist/src/layouts/model-common.d.ts +140 -0
- package/dist/src/layouts/model-common.d.ts.map +1 -0
- package/dist/src/layouts/model-common.js +269 -0
- package/dist/src/layouts/model-common.js.map +1 -0
- package/dist/src/layouts/repulsion-grid.d.ts +152 -0
- package/dist/src/layouts/repulsion-grid.d.ts.map +1 -0
- package/dist/src/layouts/repulsion-grid.js +318 -0
- package/dist/src/layouts/repulsion-grid.js.map +1 -0
- package/dist/src/layouts/spring-electrical.d.ts +224 -0
- package/dist/src/layouts/spring-electrical.d.ts.map +1 -0
- package/dist/src/layouts/spring-electrical.js +665 -0
- package/dist/src/layouts/spring-electrical.js.map +1 -0
- package/dist/src/memory/residency.d.ts +6 -2
- package/dist/src/memory/residency.d.ts.map +1 -1
- package/dist/src/memory/residency.js +84 -14
- package/dist/src/memory/residency.js.map +1 -1
- package/dist/src/primitives/core-shape.d.ts +38 -2
- package/dist/src/primitives/core-shape.d.ts.map +1 -1
- package/dist/src/primitives/core-shape.js +71 -3
- package/dist/src/primitives/core-shape.js.map +1 -1
- package/dist/src/primitives/grid-pyramid.d.ts +71 -0
- package/dist/src/primitives/grid-pyramid.d.ts.map +1 -0
- package/dist/src/primitives/grid-pyramid.js +143 -0
- package/dist/src/primitives/grid-pyramid.js.map +1 -0
- package/dist/src/primitives/grid.d.ts +118 -0
- package/dist/src/primitives/grid.d.ts.map +1 -0
- package/dist/src/primitives/grid.js +225 -0
- package/dist/src/primitives/grid.js.map +1 -0
- package/dist/src/primitives/histogram.d.ts +67 -0
- package/dist/src/primitives/histogram.d.ts.map +1 -0
- package/dist/src/primitives/histogram.js +190 -0
- package/dist/src/primitives/histogram.js.map +1 -0
- package/dist/src/primitives/radix-sort.d.ts +75 -0
- package/dist/src/primitives/radix-sort.d.ts.map +1 -0
- package/dist/src/primitives/radix-sort.js +168 -0
- package/dist/src/primitives/radix-sort.js.map +1 -0
- package/dist/src/primitives/scan.d.ts +44 -0
- package/dist/src/primitives/scan.d.ts.map +1 -0
- package/dist/src/primitives/scan.js +151 -0
- package/dist/src/primitives/scan.js.map +1 -0
- package/dist/src/primitives/segmented-reduce.d.ts +25 -17
- package/dist/src/primitives/segmented-reduce.d.ts.map +1 -1
- package/dist/src/primitives/segmented-reduce.js +166 -47
- package/dist/src/primitives/segmented-reduce.js.map +1 -1
- package/dist/src/primitives/spmv.d.ts +18 -14
- package/dist/src/primitives/spmv.d.ts.map +1 -1
- package/dist/src/primitives/spmv.js +94 -58
- package/dist/src/primitives/spmv.js.map +1 -1
- package/dist/src/primitives/verify.d.ts +49 -0
- package/dist/src/primitives/verify.d.ts.map +1 -0
- package/dist/src/primitives/verify.js +229 -0
- package/dist/src/primitives/verify.js.map +1 -0
- package/dist/src/types/accelerator.d.ts +7 -3
- package/dist/src/types/accelerator.d.ts.map +1 -1
- package/dist/src/types/context.d.ts +53 -0
- package/dist/src/types/context.d.ts.map +1 -1
- package/dist/src/types/layout.d.ts +52 -0
- package/dist/src/types/layout.d.ts.map +1 -1
- package/dist/src/types/options.d.ts +43 -1
- package/dist/src/types/options.d.ts.map +1 -1
- package/dist/src/wgsl/counting-scatter.wgsl.d.ts +8 -0
- package/dist/src/wgsl/counting-scatter.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/counting-scatter.wgsl.js +17 -0
- package/dist/src/wgsl/counting-scatter.wgsl.js.map +1 -0
- package/dist/src/wgsl/fa2-attraction.wgsl.d.ts +23 -8
- package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-attraction.wgsl.js +100 -17
- package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -1
- package/dist/src/wgsl/fa2-integrate.wgsl.d.ts +7 -2
- package/dist/src/wgsl/fa2-integrate.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-integrate.wgsl.js +28 -2
- package/dist/src/wgsl/fa2-integrate.wgsl.js.map +1 -1
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts +4 -2
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js +14 -5
- package/dist/src/wgsl/fa2-repulsion-exact.wgsl.js.map +1 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +12 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +54 -0
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.js.map +1 -1
- package/dist/src/wgsl/grid-cell-key.wgsl.d.ts +8 -0
- package/dist/src/wgsl/grid-cell-key.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-cell-key.wgsl.js +30 -0
- package/dist/src/wgsl/grid-cell-key.wgsl.js.map +1 -0
- package/dist/src/wgsl/grid-centroid-hub.wgsl.d.ts +8 -0
- package/dist/src/wgsl/grid-centroid-hub.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-centroid-hub.wgsl.js +29 -0
- package/dist/src/wgsl/grid-centroid-hub.wgsl.js.map +1 -0
- package/dist/src/wgsl/grid-centroid.wgsl.d.ts +8 -0
- package/dist/src/wgsl/grid-centroid.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-centroid.wgsl.js +29 -0
- package/dist/src/wgsl/grid-centroid.wgsl.js.map +1 -0
- package/dist/src/wgsl/grid-downsample.wgsl.d.ts +7 -0
- package/dist/src/wgsl/grid-downsample.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-downsample.wgsl.js +28 -0
- package/dist/src/wgsl/grid-downsample.wgsl.js.map +1 -0
- package/dist/src/wgsl/grid-far-field.wgsl.d.ts +13 -0
- package/dist/src/wgsl/grid-far-field.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-far-field.wgsl.js +98 -0
- package/dist/src/wgsl/grid-far-field.wgsl.js.map +1 -0
- package/dist/src/wgsl/grid-near-field.wgsl.d.ts +19 -0
- package/dist/src/wgsl/grid-near-field.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/grid-near-field.wgsl.js +129 -0
- package/dist/src/wgsl/grid-near-field.wgsl.js.map +1 -0
- package/dist/src/wgsl/histogram.wgsl.d.ts +7 -0
- package/dist/src/wgsl/histogram.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/histogram.wgsl.js +15 -0
- package/dist/src/wgsl/histogram.wgsl.js.map +1 -0
- package/dist/src/wgsl/indirect-finalize.wgsl.d.ts +8 -0
- package/dist/src/wgsl/indirect-finalize.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/indirect-finalize.wgsl.js +26 -0
- package/dist/src/wgsl/indirect-finalize.wgsl.js.map +1 -0
- package/dist/src/wgsl/radix-hist.wgsl.d.ts +9 -0
- package/dist/src/wgsl/radix-hist.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/radix-hist.wgsl.js +31 -0
- package/dist/src/wgsl/radix-hist.wgsl.js.map +1 -0
- package/dist/src/wgsl/radix-scatter.wgsl.d.ts +9 -0
- package/dist/src/wgsl/radix-scatter.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/radix-scatter.wgsl.js +40 -0
- package/dist/src/wgsl/radix-scatter.wgsl.js.map +1 -0
- package/dist/src/wgsl/scan-add.wgsl.d.ts +6 -0
- package/dist/src/wgsl/scan-add.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/scan-add.wgsl.js +14 -0
- package/dist/src/wgsl/scan-add.wgsl.js.map +1 -0
- package/dist/src/wgsl/scan-block.wgsl.d.ts +8 -0
- package/dist/src/wgsl/scan-block.wgsl.d.ts.map +1 -0
- package/dist/src/wgsl/scan-block.wgsl.js +30 -0
- package/dist/src/wgsl/scan-block.wgsl.js.map +1 -0
- package/dist/src/wgsl/segmented-reduce.wgsl.d.ts +22 -8
- package/dist/src/wgsl/segmented-reduce.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/segmented-reduce.wgsl.js +84 -15
- package/dist/src/wgsl/segmented-reduce.wgsl.js.map +1 -1
- package/dist/src/wgsl/spmv-pull.wgsl.d.ts +22 -11
- package/dist/src/wgsl/spmv-pull.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/spmv-pull.wgsl.js +110 -36
- package/dist/src/wgsl/spmv-pull.wgsl.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/webgpu-graph-algorithms.js +5016 -1130
- package/dist/webgpu-graph-algorithms.js.map +1 -1
- package/package.json +10 -7
- package/src/accelerator.ts +46 -12
- package/src/algorithms/components.ts +12 -16
- package/src/algorithms/degree.ts +58 -43
- package/src/algorithms/pagerank.ts +20 -18
- package/src/algorithms/power-iteration.ts +19 -18
- package/src/constants.ts +108 -8
- package/src/errors.ts +3 -1
- package/src/index.ts +25 -5
- package/src/kernel/dispatch.ts +18 -7
- package/src/kernel/kernel.ts +59 -5
- package/src/kernel/prelude.ts +15 -0
- package/src/kernel/profiler.ts +28 -4
- package/src/kernels.ts +378 -24
- package/src/layouts/calibrate.ts +187 -0
- package/src/layouts/force-simulation.ts +111 -26
- package/src/layouts/forceatlas2.ts +346 -324
- package/src/layouts/fruchterman-reingold.ts +918 -0
- package/src/layouts/model-common.ts +323 -0
- package/src/layouts/repulsion-grid.ts +451 -0
- package/src/layouts/spring-electrical.ts +845 -0
- package/src/memory/residency.ts +126 -20
- package/src/primitives/core-shape.ts +91 -4
- package/src/primitives/grid-pyramid.ts +221 -0
- package/src/primitives/grid.ts +349 -0
- package/src/primitives/histogram.ts +273 -0
- package/src/primitives/radix-sort.ts +246 -0
- package/src/primitives/scan.ts +197 -0
- package/src/primitives/segmented-reduce.ts +214 -56
- package/src/primitives/spmv.ts +125 -65
- package/src/primitives/verify.ts +249 -0
- package/src/types/accelerator.ts +15 -3
- package/src/types/context.ts +56 -0
- package/src/types/layout.ts +58 -0
- package/src/types/options.ts +45 -1
- package/src/wgsl/counting-scatter.wgsl.ts +16 -0
- package/src/wgsl/fa2-attraction.wgsl.ts +100 -17
- package/src/wgsl/fa2-integrate.wgsl.ts +28 -2
- package/src/wgsl/fa2-repulsion-exact.wgsl.ts +14 -5
- package/src/wgsl/fa2-stats-finalize.wgsl.ts +54 -0
- package/src/wgsl/grid-cell-key.wgsl.ts +29 -0
- package/src/wgsl/grid-centroid-hub.wgsl.ts +28 -0
- package/src/wgsl/grid-centroid.wgsl.ts +28 -0
- package/src/wgsl/grid-downsample.wgsl.ts +27 -0
- package/src/wgsl/grid-far-field.wgsl.ts +97 -0
- package/src/wgsl/grid-near-field.wgsl.ts +128 -0
- package/src/wgsl/histogram.wgsl.ts +14 -0
- package/src/wgsl/indirect-finalize.wgsl.ts +25 -0
- package/src/wgsl/radix-hist.wgsl.ts +30 -0
- package/src/wgsl/radix-scatter.wgsl.ts +39 -0
- package/src/wgsl/scan-add.wgsl.ts +13 -0
- package/src/wgsl/scan-block.wgsl.ts +29 -0
- package/src/wgsl/segmented-reduce.wgsl.ts +84 -15
- package/src/wgsl/spmv-pull.wgsl.ts +110 -36
- package/dist/chunks/context-CRbw2Wyo.js.map +0 -1
|
@@ -3,6 +3,7 @@ const WORKGROUP_SIZE = 256;
|
|
|
3
3
|
const MAX_WORKGROUPS_PER_DIM = 65535;
|
|
4
4
|
const MAX_1D_ITEMS = MAX_WORKGROUPS_PER_DIM * WORKGROUP_SIZE;
|
|
5
5
|
const U32_MAX = 4294967295;
|
|
6
|
+
const RADIX_BINS = 256;
|
|
6
7
|
const ARC_WINDOW_ALIGN = 64;
|
|
7
8
|
const STORAGE_ALIGN = 256;
|
|
8
9
|
const UNIFORM_SLOT_BYTES = 256;
|
|
@@ -49,6 +50,44 @@ const FA2_DISTANCE_FLOOR = 0.01;
|
|
|
49
50
|
const FA2_DISTANCE_FLOOR_SQ = 1e-4;
|
|
50
51
|
const FA2_COINCIDENT_SQ = 1e-8;
|
|
51
52
|
const FA2_FLAG_FIRST = 1;
|
|
53
|
+
const FA2_FLAG_ADAPTIVE = 2;
|
|
54
|
+
const FR_START_TEMPERATURE = 0.1;
|
|
55
|
+
const FR_REHEAT_FRACTION = 0.7;
|
|
56
|
+
const FR_COOLING_STEP = 0.9;
|
|
57
|
+
const FR_COOLING_PATIENCE = 5;
|
|
58
|
+
const FR_ADAPTIVE_MAX_ITERATIONS = 1e4;
|
|
59
|
+
const FR_DEFAULTS = Object.freeze({
|
|
60
|
+
k: null,
|
|
61
|
+
iterations: 50,
|
|
62
|
+
fixed: null,
|
|
63
|
+
dim: 2,
|
|
64
|
+
scale: 1,
|
|
65
|
+
settleThreshold: 1e-3,
|
|
66
|
+
settleWindow: 10,
|
|
67
|
+
iterationsPerStep: 1,
|
|
68
|
+
maxInFlight: 2,
|
|
69
|
+
cooling: "linear"
|
|
70
|
+
});
|
|
71
|
+
const SE_SCALE_REFERENCE_NODES = 300;
|
|
72
|
+
const SE_DEFAULTS = Object.freeze({
|
|
73
|
+
springLength: 10,
|
|
74
|
+
springCoefficient: 0.8,
|
|
75
|
+
gravity: -12,
|
|
76
|
+
dragCoefficient: 0.9,
|
|
77
|
+
timeStep: 0.5,
|
|
78
|
+
dim: 2,
|
|
79
|
+
scale: 1,
|
|
80
|
+
settleThreshold: 1e-3,
|
|
81
|
+
settleWindow: 10,
|
|
82
|
+
iterationsPerStep: 1,
|
|
83
|
+
maxInFlight: 2
|
|
84
|
+
});
|
|
85
|
+
const GRID_MIN_SIDE = 8;
|
|
86
|
+
const GRID_COARSEST_SIDE = 4;
|
|
87
|
+
const GRID_HUB_CELL = 1024;
|
|
88
|
+
const GRID_EXTENT_FLOOR = 1e-6;
|
|
89
|
+
const GRID_BBOX_MARGIN = 1.01;
|
|
90
|
+
const GRID_SORT_BITS = 24;
|
|
52
91
|
const PASSTHROUGH_FORMAT_CODES = Object.freeze(["E_GPU_INELIGIBLE", "E_UNKNOWN_NODE", "E_UNKNOWN_COLUMN", "E_COLUMN_LENGTH"]);
|
|
53
92
|
const EMPTY_DETAILS = Object.freeze({});
|
|
54
93
|
class WebGpuGraphError extends Error {
|
|
@@ -511,6 +550,7 @@ function deviceLostError(info) {
|
|
|
511
550
|
message: info.message
|
|
512
551
|
});
|
|
513
552
|
}
|
|
553
|
+
const INDIRECT_ARGS_STRIDE = 16;
|
|
514
554
|
const bufferIds = /* @__PURE__ */ new WeakMap();
|
|
515
555
|
let nextBufferId = 1;
|
|
516
556
|
function bufferId(buffer) {
|
|
@@ -701,6 +741,42 @@ class Kernel {
|
|
|
701
741
|
* @param dynamicOffsets - one byte offset per entry of bound.dynamicGroups
|
|
702
742
|
*/
|
|
703
743
|
dispatch(pass, bound, plan, dynamicOffsets) {
|
|
744
|
+
this.check(bound, dynamicOffsets);
|
|
745
|
+
if (plan.x === 0) {
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
this.setUp(pass, bound, dynamicOffsets);
|
|
749
|
+
pass.dispatchWorkgroups(plan.x, plan.y, 1);
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* setPipeline + the bind groups exactly as dispatch(), then dispatchWorkgroupsIndirect(args.buffer, args.offset +
|
|
753
|
+
* INDIRECT_ARGS_STRIDE * slot) (spec 5.4): the (x, y, 1) of the slot were written by the indirect-finalize kernel
|
|
754
|
+
* earlier in the same pass. A slot beyond the binding is E_INVALID_ARGUMENT.
|
|
755
|
+
* @param pass - the open compute pass
|
|
756
|
+
* @param bound - a BoundKernel of THIS kernel
|
|
757
|
+
* @param args - the args buffer range (usage INDIRECT | STORAGE)
|
|
758
|
+
* @param slot - the 16-byte slot index inside the range
|
|
759
|
+
* @param dynamicOffsets - one byte offset per entry of bound.dynamicGroups
|
|
760
|
+
*/
|
|
761
|
+
dispatchIndirect(pass, bound, args, slot, dynamicOffsets) {
|
|
762
|
+
this.check(bound, dynamicOffsets);
|
|
763
|
+
if (!Number.isInteger(slot) || slot < 0 || (slot + 1) * INDIRECT_ARGS_STRIDE > args.size) {
|
|
764
|
+
throw new WebGpuGraphError("E_INVALID_ARGUMENT", `${this.spec.id}: args slot ${slot} is outside the binding`, {
|
|
765
|
+
argument: "slot",
|
|
766
|
+
value: slot,
|
|
767
|
+
expected: `0 <= slot < ${Math.floor(args.size / INDIRECT_ARGS_STRIDE)}`
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
this.setUp(pass, bound, dynamicOffsets);
|
|
771
|
+
pass.dispatchWorkgroupsIndirect(args.buffer, args.offset + INDIRECT_ARGS_STRIDE * slot);
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* The argument checks dispatch() and dispatchIndirect() share: a BoundKernel of another kernel or an offset list
|
|
775
|
+
* of the wrong length is E_INVALID_ARGUMENT.
|
|
776
|
+
* @param bound - the bound kernel
|
|
777
|
+
* @param dynamicOffsets - the offsets, if any
|
|
778
|
+
*/
|
|
779
|
+
check(bound, dynamicOffsets) {
|
|
704
780
|
const { id } = this.spec;
|
|
705
781
|
if (bound.kernel !== this) {
|
|
706
782
|
throw new WebGpuGraphError(
|
|
@@ -724,9 +800,15 @@ class Kernel {
|
|
|
724
800
|
}
|
|
725
801
|
);
|
|
726
802
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* setPipeline + setBindGroup for every group (the dynamic offsets replicated over the uniform bindings of each
|
|
806
|
+
* dynamic group), the prefix dispatch() and dispatchIndirect() share.
|
|
807
|
+
* @param pass - the open compute pass
|
|
808
|
+
* @param bound - a BoundKernel of this kernel
|
|
809
|
+
* @param dynamicOffsets - one byte offset per entry of bound.dynamicGroups (absent = 0)
|
|
810
|
+
*/
|
|
811
|
+
setUp(pass, bound, dynamicOffsets) {
|
|
730
812
|
pass.setPipeline(this.pipeline);
|
|
731
813
|
let next = 0;
|
|
732
814
|
bound.bindGroups.forEach((bindGroup, group) => {
|
|
@@ -743,7 +825,6 @@ class Kernel {
|
|
|
743
825
|
pass.setBindGroup(group, bindGroup);
|
|
744
826
|
}
|
|
745
827
|
});
|
|
746
|
-
pass.dispatchWorkgroups(plan.x, plan.y, 1);
|
|
747
828
|
}
|
|
748
829
|
/** Drops cached bind groups (a layout's buffers changed). */
|
|
749
830
|
invalidate() {
|
|
@@ -807,6 +888,14 @@ const FA2_DIST_FLOOR: f32 = ${wgslF32Literal(FA2_DISTANCE_FLOOR)};
|
|
|
807
888
|
const FA2_DIST_FLOOR_SQ: f32 = ${wgslF32Literal(FA2_DISTANCE_FLOOR_SQ)};
|
|
808
889
|
const FA2_COINCIDENT_SQ: f32 = ${wgslF32Literal(FA2_COINCIDENT_SQ)};
|
|
809
890
|
const FA2_FLAG_FIRST: u32 = ${FA2_FLAG_FIRST}u;
|
|
891
|
+
const FA2_FLAG_ADAPTIVE: u32 = ${FA2_FLAG_ADAPTIVE}u;
|
|
892
|
+
const FR_COOLING_STEP: f32 = ${wgslF32Literal(FR_COOLING_STEP)};
|
|
893
|
+
const FR_COOLING_PATIENCE: u32 = ${FR_COOLING_PATIENCE}u;
|
|
894
|
+
const GRID_HUB_CELL: u32 = ${GRID_HUB_CELL}u;
|
|
895
|
+
const GRID_EXTENT_FLOOR: f32 = ${wgslF32Literal(GRID_EXTENT_FLOOR)};
|
|
896
|
+
const GRID_BBOX_MARGIN: f32 = ${wgslF32Literal(GRID_BBOX_MARGIN)};
|
|
897
|
+
const RADIX_BINS: u32 = ${RADIX_BINS}u;
|
|
898
|
+
const RADIX_DIGIT_MASK: u32 = ${RADIX_BINS - 1}u;
|
|
810
899
|
const F32_MAX: f32 = 0x1.fffffep+127;
|
|
811
900
|
override WG: u32 = ${WORKGROUP_SIZE}u;
|
|
812
901
|
override USE_PERM: bool = false;
|
|
@@ -1475,8 +1564,10 @@ class Profiler {
|
|
|
1475
1564
|
*/
|
|
1476
1565
|
constructor(device, enabled, quantised, slots) {
|
|
1477
1566
|
this.labels = /* @__PURE__ */ new WeakMap();
|
|
1567
|
+
this.partialRequests = /* @__PURE__ */ new WeakSet();
|
|
1478
1568
|
this.pending = [];
|
|
1479
1569
|
this.cursor = 0;
|
|
1570
|
+
this.refused = 0;
|
|
1480
1571
|
this.destroyed = false;
|
|
1481
1572
|
const count = slots ?? PROFILER_QUERY_SLOTS;
|
|
1482
1573
|
this.quantised = quantised;
|
|
@@ -1496,12 +1587,17 @@ class Profiler {
|
|
|
1496
1587
|
}
|
|
1497
1588
|
}
|
|
1498
1589
|
/**
|
|
1499
|
-
* The timestampWrites descriptor for a new pass, or undefined when disabled / out of slots.
|
|
1590
|
+
* The timestampWrites descriptor for a new pass, or undefined when disabled / out of slots. A pass refused for
|
|
1591
|
+
* want of slots is counted, and the next `resolveInto()` marks its request partial.
|
|
1500
1592
|
* @param label - the pass name reported by `timings()`
|
|
1501
1593
|
* @returns the descriptor a CommandBatch puts on beginComputePass, or undefined
|
|
1502
1594
|
*/
|
|
1503
1595
|
beginPass(label) {
|
|
1504
|
-
if (this.querySet === null || this.destroyed
|
|
1596
|
+
if (this.querySet === null || this.destroyed) {
|
|
1597
|
+
return void 0;
|
|
1598
|
+
}
|
|
1599
|
+
if (this.cursor + 2 > this.slots) {
|
|
1600
|
+
this.refused++;
|
|
1505
1601
|
return void 0;
|
|
1506
1602
|
}
|
|
1507
1603
|
const begin = this.cursor;
|
|
@@ -1526,10 +1622,23 @@ class Profiler {
|
|
|
1526
1622
|
request,
|
|
1527
1623
|
this.pending.map((pass) => pass.label)
|
|
1528
1624
|
);
|
|
1625
|
+
if (this.refused > 0) {
|
|
1626
|
+
this.partialRequests.add(request);
|
|
1627
|
+
}
|
|
1529
1628
|
this.pending = [];
|
|
1530
1629
|
this.cursor = 0;
|
|
1630
|
+
this.refused = 0;
|
|
1531
1631
|
return request;
|
|
1532
1632
|
}
|
|
1633
|
+
/**
|
|
1634
|
+
* Whether a pass of the batch was refused a slot pair, so `timings()` covers only its first slots / 2 passes
|
|
1635
|
+
* and their sum is not the batch's duration.
|
|
1636
|
+
* @param request - the request `resolveInto()` returned
|
|
1637
|
+
* @returns true when at least one pass of that batch went untimed
|
|
1638
|
+
*/
|
|
1639
|
+
partial(request) {
|
|
1640
|
+
return this.partialRequests.has(request);
|
|
1641
|
+
}
|
|
1533
1642
|
/**
|
|
1534
1643
|
* Decodes the timings of a batch from its readback bytes.
|
|
1535
1644
|
* @param bytes - the resolved readback of the batch
|
|
@@ -1562,6 +1671,7 @@ class Profiler {
|
|
|
1562
1671
|
this.destroyed = true;
|
|
1563
1672
|
this.pending = [];
|
|
1564
1673
|
this.cursor = 0;
|
|
1674
|
+
this.refused = 0;
|
|
1565
1675
|
if (this.querySet !== null) {
|
|
1566
1676
|
this.querySet.destroy();
|
|
1567
1677
|
}
|
|
@@ -2130,7 +2240,7 @@ class Readback {
|
|
|
2130
2240
|
}
|
|
2131
2241
|
}
|
|
2132
2242
|
const CORE_ORDER$1 = Object.freeze(["rowPtr", "colIdx", "weights", "arcToEdge", "edgeToArc"]);
|
|
2133
|
-
const ARC_INDEXED = /* @__PURE__ */ new Set(["colIdx", "weights", "arcToEdge"]);
|
|
2243
|
+
const ARC_INDEXED$1 = /* @__PURE__ */ new Set(["colIdx", "weights", "arcToEdge"]);
|
|
2134
2244
|
function coreByteLengths(s) {
|
|
2135
2245
|
const arcs = s.arcCount;
|
|
2136
2246
|
const identity = s.flags.arcToEdgeIsIdentity;
|
|
@@ -2304,13 +2414,17 @@ function planUpload(s, caps, need) {
|
|
|
2304
2414
|
const windows = planArcWindows(s.rowPtr, s.arcCount, arcsPerWindow);
|
|
2305
2415
|
const { buffers, placed } = placeWindows(windows, 4 * s.arcCount, bufferLimit);
|
|
2306
2416
|
const arrays = names.map(
|
|
2307
|
-
(name) => ARC_INDEXED.has(name) ? { name, byteLength: lengths[name], buffers } : { name, byteLength: lengths[name], buffers: [{ byteOffset: 0, byteLength: lengths[name] }] }
|
|
2417
|
+
(name) => ARC_INDEXED$1.has(name) ? { name, byteLength: lengths[name], buffers } : { name, byteLength: lengths[name], buffers: [{ byteOffset: 0, byteLength: lengths[name] }] }
|
|
2308
2418
|
);
|
|
2309
2419
|
return { kind: "windowed", arrays, windows: placed, arcsPerWindow };
|
|
2310
2420
|
}
|
|
2311
2421
|
const DEFAULT_NEED = Object.freeze(["rowPtr", "colIdx", "weights"]);
|
|
2312
2422
|
const CORE_ORDER = Object.freeze(["rowPtr", "colIdx", "weights", "arcToEdge", "edgeToArc"]);
|
|
2423
|
+
const ARC_INDEXED = Object.freeze(["colIdx", "weights", "arcToEdge"]);
|
|
2313
2424
|
const RESIDENT_USAGE = BufferUsage.STORAGE | BufferUsage.COPY_DST | BufferUsage.COPY_SRC;
|
|
2425
|
+
function isArcIndexed(name) {
|
|
2426
|
+
return ARC_INDEXED.includes(name);
|
|
2427
|
+
}
|
|
2314
2428
|
function isSharedBuffer(buffer) {
|
|
2315
2429
|
return Object.prototype.toString.call(buffer) === "[object SharedArrayBuffer]";
|
|
2316
2430
|
}
|
|
@@ -2396,8 +2510,9 @@ class GraphResidency {
|
|
|
2396
2510
|
}
|
|
2397
2511
|
/**
|
|
2398
2512
|
* Uploads (or finds) the core; `need` defaults to ["rowPtr", "colIdx", "weights"]; cold segments on demand
|
|
2399
|
-
* (spec 4.2). Never materialises an identity permutation. A windowed plan
|
|
2400
|
-
*
|
|
2513
|
+
* (spec 4.2). Never materialises an identity permutation. A windowed plan (spec 4.2, PD-8) uploads every
|
|
2514
|
+
* arc-indexed array as the plan's buffer ranges and binds window 0 as its default binding; rowPtr and edgeToArc
|
|
2515
|
+
* stay whole. A tombstoned serial is lifted and re-uploaded (PLAN DECISION 7).
|
|
2401
2516
|
* @param s - the snapshot
|
|
2402
2517
|
* @param need - the core arrays to bind (rowPtr is always included; absent arrays are ignored)
|
|
2403
2518
|
* @returns the core binding (a frozen object; grows as cold segments are added)
|
|
@@ -2408,18 +2523,6 @@ class GraphResidency {
|
|
|
2408
2523
|
const wanted = need ?? DEFAULT_NEED;
|
|
2409
2524
|
const names = CORE_ORDER.filter((name) => (name === "rowPtr" || wanted.includes(name)) && isPresent(s, name));
|
|
2410
2525
|
const plan = planUpload(s, this.caps, names);
|
|
2411
|
-
if (plan.kind === "windowed") {
|
|
2412
|
-
throw new WebGpuGraphError(
|
|
2413
|
-
"E_TOO_LARGE",
|
|
2414
|
-
`snapshot ${s.serial}: an arc array of ${4 * s.arcCount} bytes needs arc windows (${plan.windows.length}), which P1-P3 plan but do not execute`,
|
|
2415
|
-
{
|
|
2416
|
-
needed: 4 * s.arcCount,
|
|
2417
|
-
limit: this.caps.limits.maxStorageBufferBindingSize,
|
|
2418
|
-
path: "windowed",
|
|
2419
|
-
algorithm: null
|
|
2420
|
-
}
|
|
2421
|
-
);
|
|
2422
|
-
}
|
|
2423
2526
|
const record = this.ensureRecord(s);
|
|
2424
2527
|
if (record.plan === null) {
|
|
2425
2528
|
record.plan = plan.kind;
|
|
@@ -2433,10 +2536,17 @@ class GraphResidency {
|
|
|
2433
2536
|
);
|
|
2434
2537
|
record.arena = { buffer: resident.buffer, segments: plan.segments };
|
|
2435
2538
|
}
|
|
2539
|
+
if (plan.kind === "windowed") {
|
|
2540
|
+
record.windows = plan.windows;
|
|
2541
|
+
}
|
|
2436
2542
|
}
|
|
2437
2543
|
for (const name of names) {
|
|
2438
2544
|
if (!record.bindings.has(name)) {
|
|
2439
|
-
|
|
2545
|
+
const planned = plan.kind === "windowed" ? plan.arrays.find((a) => a.name === name) : void 0;
|
|
2546
|
+
record.bindings.set(
|
|
2547
|
+
name,
|
|
2548
|
+
planned !== void 0 && planned.buffers.length > 0 && record.windows !== null && isArcIndexed(name) ? this.bindWindowed(record, s, name, planned.buffers, record.windows[0]) : this.bindCore(record, s, name)
|
|
2549
|
+
);
|
|
2440
2550
|
}
|
|
2441
2551
|
}
|
|
2442
2552
|
const rowPtr = record.bindings.get("rowPtr");
|
|
@@ -2452,7 +2562,12 @@ class GraphResidency {
|
|
|
2452
2562
|
weights,
|
|
2453
2563
|
arcToEdge: record.bindings.get("arcToEdge") ?? null,
|
|
2454
2564
|
edgeToArc: record.bindings.get("edgeToArc") ?? null,
|
|
2455
|
-
windows:
|
|
2565
|
+
windows: record.windows,
|
|
2566
|
+
arcBuffers: record.windows === null ? null : Object.freeze({
|
|
2567
|
+
colIdx: Object.freeze([...record.arcBuffers.get("colIdx") ?? []]),
|
|
2568
|
+
weights: Object.freeze([...record.arcBuffers.get("weights") ?? []]),
|
|
2569
|
+
arcToEdge: Object.freeze([...record.arcBuffers.get("arcToEdge") ?? []])
|
|
2570
|
+
}),
|
|
2456
2571
|
hasWeights: weights !== null
|
|
2457
2572
|
});
|
|
2458
2573
|
}
|
|
@@ -2558,6 +2673,18 @@ class GraphResidency {
|
|
|
2558
2673
|
const rev = s.reverse();
|
|
2559
2674
|
if (!s.directed) {
|
|
2560
2675
|
const core = this.core(s, ["rowPtr", "colIdx", "weights"]);
|
|
2676
|
+
if (core.plan === "windowed") {
|
|
2677
|
+
throw new WebGpuGraphError(
|
|
2678
|
+
"E_TOO_LARGE",
|
|
2679
|
+
`snapshot ${s.serial}: the undirected reverse view is the core, which needs arc windows (${core.windows?.length ?? 0}) that no view executes`,
|
|
2680
|
+
{
|
|
2681
|
+
needed: 4 * s.arcCount,
|
|
2682
|
+
limit: this.caps.limits.maxStorageBufferBindingSize,
|
|
2683
|
+
path: "windowed",
|
|
2684
|
+
algorithm: null
|
|
2685
|
+
}
|
|
2686
|
+
);
|
|
2687
|
+
}
|
|
2561
2688
|
const bindings2 = { rowPtr: core.rowPtr };
|
|
2562
2689
|
if (core.colIdx !== null) {
|
|
2563
2690
|
bindings2.colIdx = core.colIdx;
|
|
@@ -2857,6 +2984,50 @@ class GraphResidency {
|
|
|
2857
2984
|
const resident = this.upload(record, array, array, `residency:core:${record.serial}:${name}`);
|
|
2858
2985
|
return { buffer: resident.buffer, offset: 0, size: resident.byteLength, window: null };
|
|
2859
2986
|
}
|
|
2987
|
+
/**
|
|
2988
|
+
* Uploads one arc-indexed array as the windowed plan's buffer ranges (spec 4.2: an array above maxBufferSize is
|
|
2989
|
+
* split across buffers at window boundaries), each keyed on a marker object of the record (windowKey), and
|
|
2990
|
+
* returns window 0's binding so a caller that ignores windows still binds something valid (PD-8).
|
|
2991
|
+
* @param record - the snapshot's record
|
|
2992
|
+
* @param s - the snapshot
|
|
2993
|
+
* @param name - a PRESENT arc-indexed core array
|
|
2994
|
+
* @param ranges - the plan's buffer ranges of the array
|
|
2995
|
+
* @param first - window 0
|
|
2996
|
+
* @returns the binding of window 0
|
|
2997
|
+
*/
|
|
2998
|
+
bindWindowed(record, s, name, ranges, first) {
|
|
2999
|
+
const array = coreArray(s, name);
|
|
3000
|
+
const buffers = ranges.map(
|
|
3001
|
+
(range, index) => this.upload(
|
|
3002
|
+
record,
|
|
3003
|
+
this.windowKey(record, `${name}:${index}`),
|
|
3004
|
+
new Uint8Array(array.buffer, array.byteOffset + range.byteOffset, range.byteLength),
|
|
3005
|
+
`residency:core:${record.serial}:${name}:w${index}`
|
|
3006
|
+
).buffer
|
|
3007
|
+
);
|
|
3008
|
+
record.arcBuffers.set(name, buffers);
|
|
3009
|
+
return {
|
|
3010
|
+
buffer: buffers[first.bufferIndex],
|
|
3011
|
+
offset: first.offset,
|
|
3012
|
+
size: 4 * (first.end - first.start),
|
|
3013
|
+
window: first
|
|
3014
|
+
};
|
|
3015
|
+
}
|
|
3016
|
+
/**
|
|
3017
|
+
* The upload key of one window buffer: a marker object allocated once per record and `<name>:<bufferIndex>`.
|
|
3018
|
+
* @param record - the owning record
|
|
3019
|
+
* @param memoKey - `<name>:<bufferIndex>`
|
|
3020
|
+
* @returns the stable marker object
|
|
3021
|
+
*/
|
|
3022
|
+
windowKey(record, memoKey) {
|
|
3023
|
+
const existing = record.windowKeys.get(memoKey);
|
|
3024
|
+
if (existing !== void 0) {
|
|
3025
|
+
return existing;
|
|
3026
|
+
}
|
|
3027
|
+
const created = {};
|
|
3028
|
+
record.windowKeys.set(memoKey, created);
|
|
3029
|
+
return created;
|
|
3030
|
+
}
|
|
2860
3031
|
/**
|
|
2861
3032
|
* Uploads `data` into a new buffer keyed on `key`, or returns the resident already uploaded for that key by
|
|
2862
3033
|
* the same owner (PLAN DECISION 11: a resident belongs to one record).
|
|
@@ -2920,6 +3091,9 @@ class GraphResidency {
|
|
|
2920
3091
|
record.bindings.clear();
|
|
2921
3092
|
record.views.clear();
|
|
2922
3093
|
record.packKeys.clear();
|
|
3094
|
+
record.windowKeys.clear();
|
|
3095
|
+
record.arcBuffers.clear();
|
|
3096
|
+
record.windows = null;
|
|
2923
3097
|
record.arena = null;
|
|
2924
3098
|
record.plan = null;
|
|
2925
3099
|
this.bySerial.delete(record.serial);
|
|
@@ -2947,6 +3121,9 @@ class GraphResidency {
|
|
|
2947
3121
|
bindings: /* @__PURE__ */ new Map(),
|
|
2948
3122
|
views: /* @__PURE__ */ new Map(),
|
|
2949
3123
|
packKeys: /* @__PURE__ */ new Map(),
|
|
3124
|
+
windowKeys: /* @__PURE__ */ new Map(),
|
|
3125
|
+
windows: null,
|
|
3126
|
+
arcBuffers: /* @__PURE__ */ new Map(),
|
|
2950
3127
|
released: false
|
|
2951
3128
|
};
|
|
2952
3129
|
this.bySerial.set(s.serial, record);
|
|
@@ -3272,24 +3449,39 @@ export {
|
|
|
3272
3449
|
EXACT_MAX_NODES as E,
|
|
3273
3450
|
FA2_DEFAULTS as F,
|
|
3274
3451
|
GpuContext as G,
|
|
3452
|
+
INDIRECT_ARGS_STRIDE as I,
|
|
3275
3453
|
LAYOUT_TUNING_DEFAULTS as L,
|
|
3276
3454
|
MAX_WORKGROUPS_PER_DIM as M,
|
|
3277
3455
|
PARTIAL_BYTES as P,
|
|
3456
|
+
RADIX_BINS as R,
|
|
3278
3457
|
STATE_HEADER_BYTES as S,
|
|
3279
3458
|
TRACE_RECORD_BYTES as T,
|
|
3280
3459
|
UNIFORM_SLOT_BYTES as U,
|
|
3281
3460
|
WebGpuGraphError as W,
|
|
3282
3461
|
WGSL_RESERVED_WORDS as a,
|
|
3283
3462
|
U32_MAX as b,
|
|
3284
|
-
|
|
3463
|
+
GRID_COARSEST_SIDE as c,
|
|
3285
3464
|
deviceLostError as d,
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3465
|
+
GRID_MIN_SIDE as e,
|
|
3466
|
+
GRID_SORT_BITS as f,
|
|
3467
|
+
MAX_ITERATIONS_PER_STEP as g,
|
|
3468
|
+
MAX_1D_ITEMS as h,
|
|
3290
3469
|
isWebGpuGraphError as i,
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3470
|
+
hasErrorCode as j,
|
|
3471
|
+
FA2_FLAG_FIRST as k,
|
|
3472
|
+
GRID_HUB_CELL as l,
|
|
3473
|
+
GRID_BBOX_MARGIN as m,
|
|
3474
|
+
GRID_EXTENT_FLOOR as n,
|
|
3475
|
+
FR_ADAPTIVE_MAX_ITERATIONS as o,
|
|
3476
|
+
FR_START_TEMPERATURE as p,
|
|
3477
|
+
FA2_FLAG_ADAPTIVE as q,
|
|
3478
|
+
FR_REHEAT_FRACTION as r,
|
|
3479
|
+
FR_DEFAULTS as s,
|
|
3480
|
+
SE_DEFAULTS as t,
|
|
3481
|
+
SE_SCALE_REFERENCE_NODES as u,
|
|
3482
|
+
PASSTHROUGH_FORMAT_CODES as v,
|
|
3483
|
+
STORAGE_ALIGN as w,
|
|
3484
|
+
WORKGROUP_SIZE as x,
|
|
3485
|
+
isSoftwareAdapter as y
|
|
3294
3486
|
};
|
|
3295
|
-
//# sourceMappingURL=context-
|
|
3487
|
+
//# sourceMappingURL=context-BXqgCifx.js.map
|