@graphty/webgpu-graph-algorithms 0.5.1 → 0.6.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 +459 -58
- package/dist/browser.js +1 -1
- package/dist/chunks/{context-BR7fx3vR.js → context-BXqgCifx.js} +190 -40
- package/dist/chunks/context-BXqgCifx.js.map +1 -0
- package/dist/node.js +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 +38 -8
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +38 -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 +6 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +8 -3
- 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 +6 -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 +17 -7
- package/dist/src/kernels.d.ts.map +1 -1
- package/dist/src/kernels.js +323 -16
- 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 +39 -4
- package/dist/src/layouts/force-simulation.d.ts.map +1 -1
- package/dist/src/layouts/force-simulation.js +71 -19
- package/dist/src/layouts/force-simulation.js.map +1 -1
- package/dist/src/layouts/forceatlas2.d.ts +107 -36
- package/dist/src/layouts/forceatlas2.d.ts.map +1 -1
- package/dist/src/layouts/forceatlas2.js +296 -100
- package/dist/src/layouts/forceatlas2.js.map +1 -1
- package/dist/src/layouts/fruchterman-reingold.d.ts +73 -27
- package/dist/src/layouts/fruchterman-reingold.d.ts.map +1 -1
- package/dist/src/layouts/fruchterman-reingold.js +230 -70
- package/dist/src/layouts/fruchterman-reingold.js.map +1 -1
- package/dist/src/layouts/model-common.d.ts +41 -3
- package/dist/src/layouts/model-common.d.ts.map +1 -1
- package/dist/src/layouts/model-common.js +74 -3
- package/dist/src/layouts/model-common.js.map +1 -1
- 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 +75 -30
- package/dist/src/layouts/spring-electrical.d.ts.map +1 -1
- package/dist/src/layouts/spring-electrical.js +231 -74
- package/dist/src/layouts/spring-electrical.js.map +1 -1
- 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/context.d.ts +53 -0
- package/dist/src/types/context.d.ts.map +1 -1
- package/dist/src/types/layout.d.ts +20 -0
- package/dist/src/types/layout.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 -11
- package/dist/src/wgsl/fa2-attraction.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-attraction.wgsl.js +98 -20
- package/dist/src/wgsl/fa2-attraction.wgsl.js.map +1 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts +6 -2
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.d.ts.map +1 -1
- package/dist/src/wgsl/fa2-stats-finalize.wgsl.js +22 -1
- 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 +3815 -1003
- package/dist/webgpu-graph-algorithms.js.map +1 -1
- package/package.json +9 -8
- 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 +38 -8
- package/src/errors.ts +3 -1
- package/src/index.ts +14 -4
- package/src/kernel/dispatch.ts +18 -7
- package/src/kernel/kernel.ts +59 -5
- package/src/kernel/prelude.ts +9 -0
- package/src/kernel/profiler.ts +28 -4
- package/src/kernels.ts +356 -18
- package/src/layouts/calibrate.ts +187 -0
- package/src/layouts/force-simulation.ts +91 -23
- package/src/layouts/forceatlas2.ts +331 -106
- package/src/layouts/fruchterman-reingold.ts +255 -74
- package/src/layouts/model-common.ts +98 -3
- package/src/layouts/repulsion-grid.ts +451 -0
- package/src/layouts/spring-electrical.ts +257 -78
- 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/context.ts +56 -0
- package/src/types/layout.ts +22 -0
- package/src/wgsl/counting-scatter.wgsl.ts +16 -0
- package/src/wgsl/fa2-attraction.wgsl.ts +98 -20
- package/src/wgsl/fa2-stats-finalize.wgsl.ts +22 -1
- 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-BR7fx3vR.js.map +0 -1
package/dist/browser.js
CHANGED
|
@@ -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;
|
|
@@ -81,6 +82,12 @@ const SE_DEFAULTS = Object.freeze({
|
|
|
81
82
|
iterationsPerStep: 1,
|
|
82
83
|
maxInFlight: 2
|
|
83
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;
|
|
84
91
|
const PASSTHROUGH_FORMAT_CODES = Object.freeze(["E_GPU_INELIGIBLE", "E_UNKNOWN_NODE", "E_UNKNOWN_COLUMN", "E_COLUMN_LENGTH"]);
|
|
85
92
|
const EMPTY_DETAILS = Object.freeze({});
|
|
86
93
|
class WebGpuGraphError extends Error {
|
|
@@ -543,6 +550,7 @@ function deviceLostError(info) {
|
|
|
543
550
|
message: info.message
|
|
544
551
|
});
|
|
545
552
|
}
|
|
553
|
+
const INDIRECT_ARGS_STRIDE = 16;
|
|
546
554
|
const bufferIds = /* @__PURE__ */ new WeakMap();
|
|
547
555
|
let nextBufferId = 1;
|
|
548
556
|
function bufferId(buffer) {
|
|
@@ -733,6 +741,42 @@ class Kernel {
|
|
|
733
741
|
* @param dynamicOffsets - one byte offset per entry of bound.dynamicGroups
|
|
734
742
|
*/
|
|
735
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) {
|
|
736
780
|
const { id } = this.spec;
|
|
737
781
|
if (bound.kernel !== this) {
|
|
738
782
|
throw new WebGpuGraphError(
|
|
@@ -756,9 +800,15 @@ class Kernel {
|
|
|
756
800
|
}
|
|
757
801
|
);
|
|
758
802
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
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) {
|
|
762
812
|
pass.setPipeline(this.pipeline);
|
|
763
813
|
let next = 0;
|
|
764
814
|
bound.bindGroups.forEach((bindGroup, group) => {
|
|
@@ -775,7 +825,6 @@ class Kernel {
|
|
|
775
825
|
pass.setBindGroup(group, bindGroup);
|
|
776
826
|
}
|
|
777
827
|
});
|
|
778
|
-
pass.dispatchWorkgroups(plan.x, plan.y, 1);
|
|
779
828
|
}
|
|
780
829
|
/** Drops cached bind groups (a layout's buffers changed). */
|
|
781
830
|
invalidate() {
|
|
@@ -842,6 +891,11 @@ const FA2_FLAG_FIRST: u32 = ${FA2_FLAG_FIRST}u;
|
|
|
842
891
|
const FA2_FLAG_ADAPTIVE: u32 = ${FA2_FLAG_ADAPTIVE}u;
|
|
843
892
|
const FR_COOLING_STEP: f32 = ${wgslF32Literal(FR_COOLING_STEP)};
|
|
844
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;
|
|
845
899
|
const F32_MAX: f32 = 0x1.fffffep+127;
|
|
846
900
|
override WG: u32 = ${WORKGROUP_SIZE}u;
|
|
847
901
|
override USE_PERM: bool = false;
|
|
@@ -1510,8 +1564,10 @@ class Profiler {
|
|
|
1510
1564
|
*/
|
|
1511
1565
|
constructor(device, enabled, quantised, slots) {
|
|
1512
1566
|
this.labels = /* @__PURE__ */ new WeakMap();
|
|
1567
|
+
this.partialRequests = /* @__PURE__ */ new WeakSet();
|
|
1513
1568
|
this.pending = [];
|
|
1514
1569
|
this.cursor = 0;
|
|
1570
|
+
this.refused = 0;
|
|
1515
1571
|
this.destroyed = false;
|
|
1516
1572
|
const count = slots ?? PROFILER_QUERY_SLOTS;
|
|
1517
1573
|
this.quantised = quantised;
|
|
@@ -1531,12 +1587,17 @@ class Profiler {
|
|
|
1531
1587
|
}
|
|
1532
1588
|
}
|
|
1533
1589
|
/**
|
|
1534
|
-
* 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.
|
|
1535
1592
|
* @param label - the pass name reported by `timings()`
|
|
1536
1593
|
* @returns the descriptor a CommandBatch puts on beginComputePass, or undefined
|
|
1537
1594
|
*/
|
|
1538
1595
|
beginPass(label) {
|
|
1539
|
-
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++;
|
|
1540
1601
|
return void 0;
|
|
1541
1602
|
}
|
|
1542
1603
|
const begin = this.cursor;
|
|
@@ -1561,10 +1622,23 @@ class Profiler {
|
|
|
1561
1622
|
request,
|
|
1562
1623
|
this.pending.map((pass) => pass.label)
|
|
1563
1624
|
);
|
|
1625
|
+
if (this.refused > 0) {
|
|
1626
|
+
this.partialRequests.add(request);
|
|
1627
|
+
}
|
|
1564
1628
|
this.pending = [];
|
|
1565
1629
|
this.cursor = 0;
|
|
1630
|
+
this.refused = 0;
|
|
1566
1631
|
return request;
|
|
1567
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
|
+
}
|
|
1568
1642
|
/**
|
|
1569
1643
|
* Decodes the timings of a batch from its readback bytes.
|
|
1570
1644
|
* @param bytes - the resolved readback of the batch
|
|
@@ -1597,6 +1671,7 @@ class Profiler {
|
|
|
1597
1671
|
this.destroyed = true;
|
|
1598
1672
|
this.pending = [];
|
|
1599
1673
|
this.cursor = 0;
|
|
1674
|
+
this.refused = 0;
|
|
1600
1675
|
if (this.querySet !== null) {
|
|
1601
1676
|
this.querySet.destroy();
|
|
1602
1677
|
}
|
|
@@ -2165,7 +2240,7 @@ class Readback {
|
|
|
2165
2240
|
}
|
|
2166
2241
|
}
|
|
2167
2242
|
const CORE_ORDER$1 = Object.freeze(["rowPtr", "colIdx", "weights", "arcToEdge", "edgeToArc"]);
|
|
2168
|
-
const ARC_INDEXED = /* @__PURE__ */ new Set(["colIdx", "weights", "arcToEdge"]);
|
|
2243
|
+
const ARC_INDEXED$1 = /* @__PURE__ */ new Set(["colIdx", "weights", "arcToEdge"]);
|
|
2169
2244
|
function coreByteLengths(s) {
|
|
2170
2245
|
const arcs = s.arcCount;
|
|
2171
2246
|
const identity = s.flags.arcToEdgeIsIdentity;
|
|
@@ -2339,13 +2414,17 @@ function planUpload(s, caps, need) {
|
|
|
2339
2414
|
const windows = planArcWindows(s.rowPtr, s.arcCount, arcsPerWindow);
|
|
2340
2415
|
const { buffers, placed } = placeWindows(windows, 4 * s.arcCount, bufferLimit);
|
|
2341
2416
|
const arrays = names.map(
|
|
2342
|
-
(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] }] }
|
|
2343
2418
|
);
|
|
2344
2419
|
return { kind: "windowed", arrays, windows: placed, arcsPerWindow };
|
|
2345
2420
|
}
|
|
2346
2421
|
const DEFAULT_NEED = Object.freeze(["rowPtr", "colIdx", "weights"]);
|
|
2347
2422
|
const CORE_ORDER = Object.freeze(["rowPtr", "colIdx", "weights", "arcToEdge", "edgeToArc"]);
|
|
2423
|
+
const ARC_INDEXED = Object.freeze(["colIdx", "weights", "arcToEdge"]);
|
|
2348
2424
|
const RESIDENT_USAGE = BufferUsage.STORAGE | BufferUsage.COPY_DST | BufferUsage.COPY_SRC;
|
|
2425
|
+
function isArcIndexed(name) {
|
|
2426
|
+
return ARC_INDEXED.includes(name);
|
|
2427
|
+
}
|
|
2349
2428
|
function isSharedBuffer(buffer) {
|
|
2350
2429
|
return Object.prototype.toString.call(buffer) === "[object SharedArrayBuffer]";
|
|
2351
2430
|
}
|
|
@@ -2431,8 +2510,9 @@ class GraphResidency {
|
|
|
2431
2510
|
}
|
|
2432
2511
|
/**
|
|
2433
2512
|
* Uploads (or finds) the core; `need` defaults to ["rowPtr", "colIdx", "weights"]; cold segments on demand
|
|
2434
|
-
* (spec 4.2). Never materialises an identity permutation. A windowed plan
|
|
2435
|
-
*
|
|
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).
|
|
2436
2516
|
* @param s - the snapshot
|
|
2437
2517
|
* @param need - the core arrays to bind (rowPtr is always included; absent arrays are ignored)
|
|
2438
2518
|
* @returns the core binding (a frozen object; grows as cold segments are added)
|
|
@@ -2443,18 +2523,6 @@ class GraphResidency {
|
|
|
2443
2523
|
const wanted = need ?? DEFAULT_NEED;
|
|
2444
2524
|
const names = CORE_ORDER.filter((name) => (name === "rowPtr" || wanted.includes(name)) && isPresent(s, name));
|
|
2445
2525
|
const plan = planUpload(s, this.caps, names);
|
|
2446
|
-
if (plan.kind === "windowed") {
|
|
2447
|
-
throw new WebGpuGraphError(
|
|
2448
|
-
"E_TOO_LARGE",
|
|
2449
|
-
`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`,
|
|
2450
|
-
{
|
|
2451
|
-
needed: 4 * s.arcCount,
|
|
2452
|
-
limit: this.caps.limits.maxStorageBufferBindingSize,
|
|
2453
|
-
path: "windowed",
|
|
2454
|
-
algorithm: null
|
|
2455
|
-
}
|
|
2456
|
-
);
|
|
2457
|
-
}
|
|
2458
2526
|
const record = this.ensureRecord(s);
|
|
2459
2527
|
if (record.plan === null) {
|
|
2460
2528
|
record.plan = plan.kind;
|
|
@@ -2468,10 +2536,17 @@ class GraphResidency {
|
|
|
2468
2536
|
);
|
|
2469
2537
|
record.arena = { buffer: resident.buffer, segments: plan.segments };
|
|
2470
2538
|
}
|
|
2539
|
+
if (plan.kind === "windowed") {
|
|
2540
|
+
record.windows = plan.windows;
|
|
2541
|
+
}
|
|
2471
2542
|
}
|
|
2472
2543
|
for (const name of names) {
|
|
2473
2544
|
if (!record.bindings.has(name)) {
|
|
2474
|
-
|
|
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
|
+
);
|
|
2475
2550
|
}
|
|
2476
2551
|
}
|
|
2477
2552
|
const rowPtr = record.bindings.get("rowPtr");
|
|
@@ -2487,7 +2562,12 @@ class GraphResidency {
|
|
|
2487
2562
|
weights,
|
|
2488
2563
|
arcToEdge: record.bindings.get("arcToEdge") ?? null,
|
|
2489
2564
|
edgeToArc: record.bindings.get("edgeToArc") ?? null,
|
|
2490
|
-
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
|
+
}),
|
|
2491
2571
|
hasWeights: weights !== null
|
|
2492
2572
|
});
|
|
2493
2573
|
}
|
|
@@ -2593,6 +2673,18 @@ class GraphResidency {
|
|
|
2593
2673
|
const rev = s.reverse();
|
|
2594
2674
|
if (!s.directed) {
|
|
2595
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
|
+
}
|
|
2596
2688
|
const bindings2 = { rowPtr: core.rowPtr };
|
|
2597
2689
|
if (core.colIdx !== null) {
|
|
2598
2690
|
bindings2.colIdx = core.colIdx;
|
|
@@ -2892,6 +2984,50 @@ class GraphResidency {
|
|
|
2892
2984
|
const resident = this.upload(record, array, array, `residency:core:${record.serial}:${name}`);
|
|
2893
2985
|
return { buffer: resident.buffer, offset: 0, size: resident.byteLength, window: null };
|
|
2894
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
|
+
}
|
|
2895
3031
|
/**
|
|
2896
3032
|
* Uploads `data` into a new buffer keyed on `key`, or returns the resident already uploaded for that key by
|
|
2897
3033
|
* the same owner (PLAN DECISION 11: a resident belongs to one record).
|
|
@@ -2955,6 +3091,9 @@ class GraphResidency {
|
|
|
2955
3091
|
record.bindings.clear();
|
|
2956
3092
|
record.views.clear();
|
|
2957
3093
|
record.packKeys.clear();
|
|
3094
|
+
record.windowKeys.clear();
|
|
3095
|
+
record.arcBuffers.clear();
|
|
3096
|
+
record.windows = null;
|
|
2958
3097
|
record.arena = null;
|
|
2959
3098
|
record.plan = null;
|
|
2960
3099
|
this.bySerial.delete(record.serial);
|
|
@@ -2982,6 +3121,9 @@ class GraphResidency {
|
|
|
2982
3121
|
bindings: /* @__PURE__ */ new Map(),
|
|
2983
3122
|
views: /* @__PURE__ */ new Map(),
|
|
2984
3123
|
packKeys: /* @__PURE__ */ new Map(),
|
|
3124
|
+
windowKeys: /* @__PURE__ */ new Map(),
|
|
3125
|
+
windows: null,
|
|
3126
|
+
arcBuffers: /* @__PURE__ */ new Map(),
|
|
2985
3127
|
released: false
|
|
2986
3128
|
};
|
|
2987
3129
|
this.bySerial.set(s.serial, record);
|
|
@@ -3307,31 +3449,39 @@ export {
|
|
|
3307
3449
|
EXACT_MAX_NODES as E,
|
|
3308
3450
|
FA2_DEFAULTS as F,
|
|
3309
3451
|
GpuContext as G,
|
|
3452
|
+
INDIRECT_ARGS_STRIDE as I,
|
|
3310
3453
|
LAYOUT_TUNING_DEFAULTS as L,
|
|
3311
3454
|
MAX_WORKGROUPS_PER_DIM as M,
|
|
3312
3455
|
PARTIAL_BYTES as P,
|
|
3456
|
+
RADIX_BINS as R,
|
|
3313
3457
|
STATE_HEADER_BYTES as S,
|
|
3314
3458
|
TRACE_RECORD_BYTES as T,
|
|
3315
3459
|
UNIFORM_SLOT_BYTES as U,
|
|
3316
3460
|
WebGpuGraphError as W,
|
|
3317
3461
|
WGSL_RESERVED_WORDS as a,
|
|
3318
3462
|
U32_MAX as b,
|
|
3319
|
-
|
|
3463
|
+
GRID_COARSEST_SIDE as c,
|
|
3320
3464
|
deviceLostError as d,
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
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,
|
|
3325
3469
|
isWebGpuGraphError as i,
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
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
|
|
3336
3486
|
};
|
|
3337
|
-
//# sourceMappingURL=context-
|
|
3487
|
+
//# sourceMappingURL=context-BXqgCifx.js.map
|