@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,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The staging ring of spec 4.4: a ring of MAP_READ | COPY_DST buffers (default DEFAULT_STAGING_SLOTS slots of 4 MiB,
|
|
3
|
+
* PLAN DECISION 15) through which every readback of the package flows. `read()` copies with its own encoder and
|
|
4
|
+
* submit, awaits mapAsync, copies out of the mapped range BEFORE unmap (the range is detached at unmap, design 10.7)
|
|
5
|
+
* and never polls onSubmittedWorkDone; requests above the slot size are chunked. Ownership is one-directional: the
|
|
6
|
+
* ring owns its buffers; a CommandBatch (P2) BORROWS one slot through borrowSlot, maps it through mapSlot and always
|
|
7
|
+
* returns it through returnSlot, which unmaps it. Slots at or above OOM_SCOPE_THRESHOLD_BYTES are created through the
|
|
8
|
+
* AllocationTracker (the out-of-memory scope of spec 5.7), the default-size ones directly on the device, so the
|
|
9
|
+
* allocator counts residency and pool buffers only. A mapAsync rejection is E_DEVICE_LOST (or E_DISPOSED after
|
|
10
|
+
* destroyAll).
|
|
11
|
+
*
|
|
12
|
+
* The one invariant every path keeps: a staging buffer whose mapAsync is PENDING is never unmapped and never
|
|
13
|
+
* destroyed. dawn-node 0.4.0 settles the pending promise synchronously on unmap() / destroy() and settles it a
|
|
14
|
+
* second time when Dawn's map callback arrives (a SIGSEGV in AsyncRunner::Reject); on the Vulkan backends the
|
|
15
|
+
* callback has already run inside device.destroy(), on Dawn's Metal backend it arrives after the device-lost
|
|
16
|
+
* fan-out, which is where the macOS host lane lost its vitest worker (CLAUDE.md "Verified Platform Facts"). The
|
|
17
|
+
* ring therefore tracks every map on its slots (mapPending) and defers an unmap, a return or a destroy that
|
|
18
|
+
* arrives during one to the moment the map settles.
|
|
19
|
+
*/
|
|
20
|
+
import { type AllocationTracker } from "../device/error-scope.js";
|
|
21
|
+
/**
|
|
22
|
+
* One MAP_READ | COPY_DST staging buffer of the ring. Exported for the borrowers of borrowSlot / returnSlot
|
|
23
|
+
* (contract 3.8): P2-T1's CommandBatch imports it as a type; nothing at P1 imports it by name.
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
export interface StagingSlot {
|
|
27
|
+
readonly index: number;
|
|
28
|
+
readonly buffer: GPUBuffer;
|
|
29
|
+
readonly capacity: number;
|
|
30
|
+
}
|
|
31
|
+
/** The staging ring (spec 4.4): default 3 slots; grows when every slot is busy; always unmaps and destroys its own buffers. */
|
|
32
|
+
export declare class Readback {
|
|
33
|
+
private readonly device;
|
|
34
|
+
private readonly allocator;
|
|
35
|
+
private readonly slotBytes;
|
|
36
|
+
private readonly ring;
|
|
37
|
+
private disposed;
|
|
38
|
+
/**
|
|
39
|
+
* Creates the ring with `slots` slots of `slotBytes` each.
|
|
40
|
+
* @param device - the device the copies run on
|
|
41
|
+
* @param allocator - the context's OOM-scoped allocator (used for slots at or above OOM_SCOPE_THRESHOLD_BYTES)
|
|
42
|
+
* @param options - ring options
|
|
43
|
+
* @param options.slots - slots created up front; default DEFAULT_STAGING_SLOTS
|
|
44
|
+
* @param options.slotBytes - capacity of each slot and the chunk size of read(); default 4 MiB; a positive multiple of 4
|
|
45
|
+
*/
|
|
46
|
+
constructor(device: GPUDevice, allocator: AllocationTracker, options?: {
|
|
47
|
+
readonly slots?: number | undefined;
|
|
48
|
+
readonly slotBytes?: number | undefined;
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Copies `byteLength` bytes from `src` at `srcOffset` (own encoder, own submit), maps, copies out BEFORE unmap;
|
|
52
|
+
* resolves the bytes (a fresh ArrayBuffer, or `dest.buffer` after `dest.set` when given). Requests above the slot
|
|
53
|
+
* size are chunked.
|
|
54
|
+
* @param src - a COPY_SRC buffer
|
|
55
|
+
* @param byteLength - bytes to read (a positive multiple of 4, within src)
|
|
56
|
+
* @param dest - an optional destination view of at least byteLength bytes over a plain ArrayBuffer
|
|
57
|
+
* @param srcOffset - the byte offset in src (default 0; a multiple of 4)
|
|
58
|
+
* @returns the bytes read
|
|
59
|
+
*/
|
|
60
|
+
read(src: GPUBuffer, byteLength: number, dest?: ArrayBufferView, srcOffset?: number): Promise<ArrayBuffer>;
|
|
61
|
+
/**
|
|
62
|
+
* Reads one u32 counter through the same ring.
|
|
63
|
+
* @param src - a COPY_SRC buffer
|
|
64
|
+
* @param byteOffset - the counter's byte offset (a multiple of 4)
|
|
65
|
+
* @returns the counter value
|
|
66
|
+
*/
|
|
67
|
+
readU32(src: GPUBuffer, byteOffset: number): Promise<number>;
|
|
68
|
+
/**
|
|
69
|
+
* Borrows an unmapped slot of at least byteLength (grows the ring when none is free); the borrower ALWAYS
|
|
70
|
+
* returns it (spec 4.4).
|
|
71
|
+
* @param byteLength - the bytes the borrower will copy into the slot
|
|
72
|
+
* @returns the slot
|
|
73
|
+
*/
|
|
74
|
+
borrowSlot(byteLength: number): StagingSlot;
|
|
75
|
+
/**
|
|
76
|
+
* mapAsync(READ) on a borrowed slot, tracked by the ring: the slot counts as borrowed, and is neither unmapped
|
|
77
|
+
* nor destroyed, until the map settles (see the file comment). Returns the runtime's own promise, untranslated:
|
|
78
|
+
* the borrower classifies a rejection (a CommandBatch races it against device loss, spec 5.7).
|
|
79
|
+
* @param slot - a slot borrowed from this ring and not yet returned
|
|
80
|
+
* @param byteLength - the bytes to map from offset 0
|
|
81
|
+
* @returns the mapAsync promise
|
|
82
|
+
*/
|
|
83
|
+
mapSlot(slot: StagingSlot, byteLength: number): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Returns a borrowed slot (unmapping it if mapped). A slot whose map through the ring is still pending stays
|
|
86
|
+
* borrowed until the map settles, when the ring unmaps and returns it; a borrower that maps a slot itself must
|
|
87
|
+
* unmap it before returning it (spec 4.4; `mapState` decides when the runtime exposes it, otherwise the ring's
|
|
88
|
+
* own record does). A no-op after destroyAll() (the ring is gone; a borrower's finally must never mask the
|
|
89
|
+
* E_DISPOSED / E_DEVICE_LOST of the read it was serving).
|
|
90
|
+
* @param slot - a slot borrowed from this ring and not yet returned
|
|
91
|
+
*/
|
|
92
|
+
returnSlot(slot: StagingSlot): void;
|
|
93
|
+
/**
|
|
94
|
+
* The entry of a slot borrowed from this ring and not yet returned.
|
|
95
|
+
* @param slot - the slot
|
|
96
|
+
* @returns its entry
|
|
97
|
+
*/
|
|
98
|
+
private borrowedEntry;
|
|
99
|
+
/**
|
|
100
|
+
* Unmaps a returned slot when it is mapped and frees it.
|
|
101
|
+
* @param entry - the slot's entry (no map pending)
|
|
102
|
+
*/
|
|
103
|
+
private finishReturn;
|
|
104
|
+
/**
|
|
105
|
+
* Tracks one mapAsync on a slot: mapPending until it settles, then the deferred work -- the destruction
|
|
106
|
+
* destroyAll() left to the settle, or the return returnSlot() left to it. The handler is attached before the
|
|
107
|
+
* promise is handed out, so it runs before any borrower's continuation.
|
|
108
|
+
* @param entry - the slot's entry
|
|
109
|
+
* @param pending - the runtime's mapAsync promise
|
|
110
|
+
* @returns the same promise
|
|
111
|
+
*/
|
|
112
|
+
private track;
|
|
113
|
+
/**
|
|
114
|
+
* Number of slots (grows).
|
|
115
|
+
* @returns the slot count
|
|
116
|
+
*/
|
|
117
|
+
get slots(): number;
|
|
118
|
+
/**
|
|
119
|
+
* Slots currently borrowed.
|
|
120
|
+
* @returns the borrowed count
|
|
121
|
+
*/
|
|
122
|
+
get borrowed(): number;
|
|
123
|
+
/**
|
|
124
|
+
* Destroys one slot's buffer through the allocator when it was created there.
|
|
125
|
+
* @param entry - the slot
|
|
126
|
+
*/
|
|
127
|
+
private destroySlot;
|
|
128
|
+
/**
|
|
129
|
+
* Creates one slot at the end of the ring.
|
|
130
|
+
* @param capacity - the slot's byte capacity
|
|
131
|
+
* @returns the new entry
|
|
132
|
+
*/
|
|
133
|
+
private addSlot;
|
|
134
|
+
/**
|
|
135
|
+
* mapAsync(READ) on a slot for read(); a rejection becomes E_DISPOSED (after destroyAll) or E_DEVICE_LOST.
|
|
136
|
+
* @param entry - the ring entry of the borrowed slot
|
|
137
|
+
* @param byteLength - the bytes to map
|
|
138
|
+
*/
|
|
139
|
+
private map;
|
|
140
|
+
/** Throws E_DISPOSED after destroyAll(). */
|
|
141
|
+
private assertLive;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=readback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readback.d.ts","sourceRoot":"","sources":["../../../src/memory/readback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAalE;;;;GAIG;AACH,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC7B;AAwCD,+HAA+H;AAC/H,qBAAa,QAAQ;IACjB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmB;IACxC,OAAO,CAAC,QAAQ,CAAS;IAEzB;;;;;;;OAOG;gBAEC,MAAM,EAAE,SAAS,EACjB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE;IAkB9F;;;;;;;;;OASG;IACG,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAiDhH;;;;;OAKG;IACG,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKlE;;;;;OAKG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW;IAkB3C;;;;;;;OAOG;IACH,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7D;;;;;;;OAOG;IACH,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI;IAYnC;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAQrB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAWpB;;;;;;;OAOG;IACH,OAAO,CAAC,KAAK;IA4Bb;;;OAGG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;;OAGG;IACH,IAAI,QAAQ,IAAI,MAAM,CAQrB;IAoBD;;;OAGG;IACH,OAAO,CAAC,WAAW;IAQnB;;;;OAIG;IACH,OAAO,CAAC,OAAO;IAqBf;;;;OAIG;YACW,GAAG;IAwBjB,4CAA4C;IAC5C,OAAO,CAAC,UAAU;CAKrB"}
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The staging ring of spec 4.4: a ring of MAP_READ | COPY_DST buffers (default DEFAULT_STAGING_SLOTS slots of 4 MiB,
|
|
3
|
+
* PLAN DECISION 15) through which every readback of the package flows. `read()` copies with its own encoder and
|
|
4
|
+
* submit, awaits mapAsync, copies out of the mapped range BEFORE unmap (the range is detached at unmap, design 10.7)
|
|
5
|
+
* and never polls onSubmittedWorkDone; requests above the slot size are chunked. Ownership is one-directional: the
|
|
6
|
+
* ring owns its buffers; a CommandBatch (P2) BORROWS one slot through borrowSlot, maps it through mapSlot and always
|
|
7
|
+
* returns it through returnSlot, which unmaps it. Slots at or above OOM_SCOPE_THRESHOLD_BYTES are created through the
|
|
8
|
+
* AllocationTracker (the out-of-memory scope of spec 5.7), the default-size ones directly on the device, so the
|
|
9
|
+
* allocator counts residency and pool buffers only. A mapAsync rejection is E_DEVICE_LOST (or E_DISPOSED after
|
|
10
|
+
* destroyAll).
|
|
11
|
+
*
|
|
12
|
+
* The one invariant every path keeps: a staging buffer whose mapAsync is PENDING is never unmapped and never
|
|
13
|
+
* destroyed. dawn-node 0.4.0 settles the pending promise synchronously on unmap() / destroy() and settles it a
|
|
14
|
+
* second time when Dawn's map callback arrives (a SIGSEGV in AsyncRunner::Reject); on the Vulkan backends the
|
|
15
|
+
* callback has already run inside device.destroy(), on Dawn's Metal backend it arrives after the device-lost
|
|
16
|
+
* fan-out, which is where the macOS host lane lost its vitest worker (CLAUDE.md "Verified Platform Facts"). The
|
|
17
|
+
* ring therefore tracks every map on its slots (mapPending) and defers an unmap, a return or a destroy that
|
|
18
|
+
* arrives during one to the moment the map settles.
|
|
19
|
+
*/
|
|
20
|
+
import { DEFAULT_STAGING_SLOTS, OOM_SCOPE_THRESHOLD_BYTES } from "../constants.js";
|
|
21
|
+
import { BufferUsage, MapMode } from "../device/webgpu-constants.js";
|
|
22
|
+
import { WebGpuGraphError } from "../errors.js";
|
|
23
|
+
/** Default capacity of one staging slot (PLAN DECISION 15). */
|
|
24
|
+
const DEFAULT_SLOT_BYTES = 4 * 1024 * 1024;
|
|
25
|
+
/** Every staging buffer is MAP_READ | COPY_DST. */
|
|
26
|
+
const STAGING_USAGE = BufferUsage.MAP_READ | BufferUsage.COPY_DST;
|
|
27
|
+
/** Grown slots are sized in 256-byte steps. */
|
|
28
|
+
const SLOT_GRANULE = 256;
|
|
29
|
+
/**
|
|
30
|
+
* Whether an ArrayBuffer-like is a SharedArrayBuffer (checked by tag so the global need not exist).
|
|
31
|
+
* @param buffer - the buffer to test
|
|
32
|
+
* @returns true for a SharedArrayBuffer
|
|
33
|
+
*/
|
|
34
|
+
function isSharedBuffer(buffer) {
|
|
35
|
+
return Object.prototype.toString.call(buffer) === "[object SharedArrayBuffer]";
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The E_INVALID_ARGUMENT error of a bad readback argument.
|
|
39
|
+
* @param argument - the argument name
|
|
40
|
+
* @param value - the value given
|
|
41
|
+
* @param expected - what was expected
|
|
42
|
+
* @returns the error to throw
|
|
43
|
+
*/
|
|
44
|
+
function invalid(argument, value, expected) {
|
|
45
|
+
return new WebGpuGraphError("E_INVALID_ARGUMENT", `${argument}: expected ${expected}`, {
|
|
46
|
+
argument,
|
|
47
|
+
value,
|
|
48
|
+
expected,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** The staging ring (spec 4.4): default 3 slots; grows when every slot is busy; always unmaps and destroys its own buffers. */
|
|
52
|
+
export class Readback {
|
|
53
|
+
/**
|
|
54
|
+
* Creates the ring with `slots` slots of `slotBytes` each.
|
|
55
|
+
* @param device - the device the copies run on
|
|
56
|
+
* @param allocator - the context's OOM-scoped allocator (used for slots at or above OOM_SCOPE_THRESHOLD_BYTES)
|
|
57
|
+
* @param options - ring options
|
|
58
|
+
* @param options.slots - slots created up front; default DEFAULT_STAGING_SLOTS
|
|
59
|
+
* @param options.slotBytes - capacity of each slot and the chunk size of read(); default 4 MiB; a positive multiple of 4
|
|
60
|
+
*/
|
|
61
|
+
constructor(device, allocator, options) {
|
|
62
|
+
this.ring = [];
|
|
63
|
+
this.disposed = false;
|
|
64
|
+
const slotBytes = options?.slotBytes ?? DEFAULT_SLOT_BYTES;
|
|
65
|
+
if (!Number.isInteger(slotBytes) || slotBytes <= 0 || slotBytes % 4 !== 0) {
|
|
66
|
+
throw invalid("slotBytes", slotBytes, "a positive multiple of 4");
|
|
67
|
+
}
|
|
68
|
+
const slots = options?.slots ?? DEFAULT_STAGING_SLOTS;
|
|
69
|
+
if (!Number.isInteger(slots) || slots < 0) {
|
|
70
|
+
throw invalid("slots", slots, "a non-negative integer");
|
|
71
|
+
}
|
|
72
|
+
this.device = device;
|
|
73
|
+
this.allocator = allocator;
|
|
74
|
+
this.slotBytes = slotBytes;
|
|
75
|
+
for (let i = 0; i < slots; i++) {
|
|
76
|
+
this.addSlot(slotBytes);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Copies `byteLength` bytes from `src` at `srcOffset` (own encoder, own submit), maps, copies out BEFORE unmap;
|
|
81
|
+
* resolves the bytes (a fresh ArrayBuffer, or `dest.buffer` after `dest.set` when given). Requests above the slot
|
|
82
|
+
* size are chunked.
|
|
83
|
+
* @param src - a COPY_SRC buffer
|
|
84
|
+
* @param byteLength - bytes to read (a positive multiple of 4, within src)
|
|
85
|
+
* @param dest - an optional destination view of at least byteLength bytes over a plain ArrayBuffer
|
|
86
|
+
* @param srcOffset - the byte offset in src (default 0; a multiple of 4)
|
|
87
|
+
* @returns the bytes read
|
|
88
|
+
*/
|
|
89
|
+
async read(src, byteLength, dest, srcOffset) {
|
|
90
|
+
this.assertLive();
|
|
91
|
+
const offset = srcOffset ?? 0;
|
|
92
|
+
if (!Number.isInteger(byteLength) || byteLength <= 0 || byteLength % 4 !== 0) {
|
|
93
|
+
throw invalid("byteLength", byteLength, "a positive multiple of 4");
|
|
94
|
+
}
|
|
95
|
+
if (!Number.isInteger(offset) || offset < 0 || offset % 4 !== 0) {
|
|
96
|
+
throw invalid("srcOffset", offset, "a non-negative multiple of 4");
|
|
97
|
+
}
|
|
98
|
+
if (offset + byteLength > src.size) {
|
|
99
|
+
throw invalid("byteLength", byteLength, `srcOffset + byteLength <= src.size (${src.size})`);
|
|
100
|
+
}
|
|
101
|
+
if ((src.usage & BufferUsage.COPY_SRC) === 0) {
|
|
102
|
+
throw invalid("src", src.label, "a buffer with COPY_SRC usage");
|
|
103
|
+
}
|
|
104
|
+
let out;
|
|
105
|
+
let outBytes;
|
|
106
|
+
if (dest === undefined) {
|
|
107
|
+
out = new ArrayBuffer(byteLength);
|
|
108
|
+
outBytes = new Uint8Array(out);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
if (isSharedBuffer(dest.buffer)) {
|
|
112
|
+
throw invalid("dest", "SharedArrayBuffer", "a view over a plain ArrayBuffer");
|
|
113
|
+
}
|
|
114
|
+
if (dest.byteLength < byteLength) {
|
|
115
|
+
throw invalid("dest", dest.byteLength, `at least ${byteLength} bytes`);
|
|
116
|
+
}
|
|
117
|
+
out = dest.buffer;
|
|
118
|
+
outBytes = new Uint8Array(out, dest.byteOffset, byteLength);
|
|
119
|
+
}
|
|
120
|
+
let done = 0;
|
|
121
|
+
while (done < byteLength) {
|
|
122
|
+
const chunk = Math.min(this.slotBytes, byteLength - done);
|
|
123
|
+
const slot = this.borrowSlot(chunk);
|
|
124
|
+
const entry = this.ring[slot.index];
|
|
125
|
+
try {
|
|
126
|
+
const encoder = this.device.createCommandEncoder({ label: "readback" });
|
|
127
|
+
encoder.copyBufferToBuffer(src, offset + done, slot.buffer, 0, chunk);
|
|
128
|
+
this.device.queue.submit([encoder.finish()]);
|
|
129
|
+
await this.map(entry, chunk);
|
|
130
|
+
outBytes.set(new Uint8Array(slot.buffer.getMappedRange(0, chunk)), done);
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
this.returnSlot(slot);
|
|
134
|
+
}
|
|
135
|
+
done += chunk;
|
|
136
|
+
}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Reads one u32 counter through the same ring.
|
|
141
|
+
* @param src - a COPY_SRC buffer
|
|
142
|
+
* @param byteOffset - the counter's byte offset (a multiple of 4)
|
|
143
|
+
* @returns the counter value
|
|
144
|
+
*/
|
|
145
|
+
async readU32(src, byteOffset) {
|
|
146
|
+
const bytes = await this.read(src, 4, undefined, byteOffset);
|
|
147
|
+
return new Uint32Array(bytes)[0];
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Borrows an unmapped slot of at least byteLength (grows the ring when none is free); the borrower ALWAYS
|
|
151
|
+
* returns it (spec 4.4).
|
|
152
|
+
* @param byteLength - the bytes the borrower will copy into the slot
|
|
153
|
+
* @returns the slot
|
|
154
|
+
*/
|
|
155
|
+
borrowSlot(byteLength) {
|
|
156
|
+
this.assertLive();
|
|
157
|
+
if (!Number.isInteger(byteLength) || byteLength <= 0) {
|
|
158
|
+
throw invalid("byteLength", byteLength, "a positive integer");
|
|
159
|
+
}
|
|
160
|
+
// a free slot is unmapped by construction: returnSlot unmaps, and only a borrower maps
|
|
161
|
+
for (const entry of this.ring) {
|
|
162
|
+
if (!entry.borrowed && entry.slot.capacity >= byteLength) {
|
|
163
|
+
entry.borrowed = true;
|
|
164
|
+
return entry.slot;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const capacity = Math.max(this.slotBytes, Math.ceil(byteLength / SLOT_GRANULE) * SLOT_GRANULE);
|
|
168
|
+
const entry = this.addSlot(capacity);
|
|
169
|
+
entry.borrowed = true;
|
|
170
|
+
return entry.slot;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* mapAsync(READ) on a borrowed slot, tracked by the ring: the slot counts as borrowed, and is neither unmapped
|
|
174
|
+
* nor destroyed, until the map settles (see the file comment). Returns the runtime's own promise, untranslated:
|
|
175
|
+
* the borrower classifies a rejection (a CommandBatch races it against device loss, spec 5.7).
|
|
176
|
+
* @param slot - a slot borrowed from this ring and not yet returned
|
|
177
|
+
* @param byteLength - the bytes to map from offset 0
|
|
178
|
+
* @returns the mapAsync promise
|
|
179
|
+
*/
|
|
180
|
+
mapSlot(slot, byteLength) {
|
|
181
|
+
this.assertLive();
|
|
182
|
+
const entry = this.borrowedEntry(slot);
|
|
183
|
+
if (entry.mapPending || entry.mapped) {
|
|
184
|
+
throw invalid("slot", slot.index, "a borrowed slot that is not mapped and has no map pending");
|
|
185
|
+
}
|
|
186
|
+
return this.track(entry, slot.buffer.mapAsync(MapMode.READ, 0, byteLength));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Returns a borrowed slot (unmapping it if mapped). A slot whose map through the ring is still pending stays
|
|
190
|
+
* borrowed until the map settles, when the ring unmaps and returns it; a borrower that maps a slot itself must
|
|
191
|
+
* unmap it before returning it (spec 4.4; `mapState` decides when the runtime exposes it, otherwise the ring's
|
|
192
|
+
* own record does). A no-op after destroyAll() (the ring is gone; a borrower's finally must never mask the
|
|
193
|
+
* E_DISPOSED / E_DEVICE_LOST of the read it was serving).
|
|
194
|
+
* @param slot - a slot borrowed from this ring and not yet returned
|
|
195
|
+
*/
|
|
196
|
+
returnSlot(slot) {
|
|
197
|
+
if (this.disposed) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const entry = this.borrowedEntry(slot);
|
|
201
|
+
if (entry.mapPending) {
|
|
202
|
+
entry.returnRequested = true;
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
this.finishReturn(entry);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* The entry of a slot borrowed from this ring and not yet returned.
|
|
209
|
+
* @param slot - the slot
|
|
210
|
+
* @returns its entry
|
|
211
|
+
*/
|
|
212
|
+
borrowedEntry(slot) {
|
|
213
|
+
const entry = this.ring[slot.index];
|
|
214
|
+
if (entry === undefined || entry.slot !== slot || !entry.borrowed) {
|
|
215
|
+
throw invalid("slot", slot.index, "a slot borrowed from this ring and not yet returned");
|
|
216
|
+
}
|
|
217
|
+
return entry;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Unmaps a returned slot when it is mapped and frees it.
|
|
221
|
+
* @param entry - the slot's entry (no map pending)
|
|
222
|
+
*/
|
|
223
|
+
finishReturn(entry) {
|
|
224
|
+
const state = entry.slot.buffer.mapState;
|
|
225
|
+
const mapped = state === undefined ? entry.mapped : state !== "unmapped";
|
|
226
|
+
if (mapped) {
|
|
227
|
+
entry.slot.buffer.unmap();
|
|
228
|
+
}
|
|
229
|
+
entry.mapped = false;
|
|
230
|
+
entry.borrowed = false;
|
|
231
|
+
entry.returnRequested = false;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Tracks one mapAsync on a slot: mapPending until it settles, then the deferred work -- the destruction
|
|
235
|
+
* destroyAll() left to the settle, or the return returnSlot() left to it. The handler is attached before the
|
|
236
|
+
* promise is handed out, so it runs before any borrower's continuation.
|
|
237
|
+
* @param entry - the slot's entry
|
|
238
|
+
* @param pending - the runtime's mapAsync promise
|
|
239
|
+
* @returns the same promise
|
|
240
|
+
*/
|
|
241
|
+
track(entry, pending) {
|
|
242
|
+
entry.mapPending = true;
|
|
243
|
+
const settle = (mapped) => {
|
|
244
|
+
entry.mapPending = false;
|
|
245
|
+
entry.mapped = mapped;
|
|
246
|
+
if (this.disposed) {
|
|
247
|
+
if (mapped) {
|
|
248
|
+
entry.slot.buffer.unmap();
|
|
249
|
+
}
|
|
250
|
+
this.destroySlot(entry);
|
|
251
|
+
entry.mapped = false;
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (entry.returnRequested) {
|
|
255
|
+
this.finishReturn(entry);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
void pending.then(() => {
|
|
259
|
+
settle(true);
|
|
260
|
+
}, () => {
|
|
261
|
+
settle(false);
|
|
262
|
+
});
|
|
263
|
+
return pending;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Number of slots (grows).
|
|
267
|
+
* @returns the slot count
|
|
268
|
+
*/
|
|
269
|
+
get slots() {
|
|
270
|
+
return this.ring.length;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Slots currently borrowed.
|
|
274
|
+
* @returns the borrowed count
|
|
275
|
+
*/
|
|
276
|
+
get borrowed() {
|
|
277
|
+
let count = 0;
|
|
278
|
+
for (const entry of this.ring) {
|
|
279
|
+
if (entry.borrowed) {
|
|
280
|
+
count++;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return count;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Destroys every staging buffer (ctx.dispose()); idempotent. A slot whose mapAsync is still pending is NOT
|
|
287
|
+
* destroyed here (the file comment: dawn-node 0.4.0 settles the promise twice); its destruction is deferred to
|
|
288
|
+
* the moment the map settles (track()), where a pending read() still rejects with E_DISPOSED as the contract
|
|
289
|
+
* promises.
|
|
290
|
+
* @internal
|
|
291
|
+
*/
|
|
292
|
+
destroyAll() {
|
|
293
|
+
for (const entry of this.ring) {
|
|
294
|
+
if (entry.mapPending) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
this.destroySlot(entry);
|
|
298
|
+
}
|
|
299
|
+
this.ring.length = 0;
|
|
300
|
+
this.disposed = true;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Destroys one slot's buffer through the allocator when it was created there.
|
|
304
|
+
* @param entry - the slot
|
|
305
|
+
*/
|
|
306
|
+
destroySlot(entry) {
|
|
307
|
+
if (entry.tracked) {
|
|
308
|
+
this.allocator.destroy(entry.slot.buffer);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
entry.slot.buffer.destroy();
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Creates one slot at the end of the ring.
|
|
316
|
+
* @param capacity - the slot's byte capacity
|
|
317
|
+
* @returns the new entry
|
|
318
|
+
*/
|
|
319
|
+
addSlot(capacity) {
|
|
320
|
+
const index = this.ring.length;
|
|
321
|
+
const descriptor = {
|
|
322
|
+
label: `readback:slot:${index}`,
|
|
323
|
+
size: capacity,
|
|
324
|
+
usage: STAGING_USAGE,
|
|
325
|
+
};
|
|
326
|
+
const tracked = capacity >= OOM_SCOPE_THRESHOLD_BYTES;
|
|
327
|
+
const buffer = tracked ? this.allocator.createBuffer(descriptor) : this.device.createBuffer(descriptor);
|
|
328
|
+
const entry = {
|
|
329
|
+
slot: Object.freeze({ index, buffer, capacity }),
|
|
330
|
+
borrowed: false,
|
|
331
|
+
mapped: false,
|
|
332
|
+
mapPending: false,
|
|
333
|
+
returnRequested: false,
|
|
334
|
+
tracked,
|
|
335
|
+
};
|
|
336
|
+
this.ring.push(entry);
|
|
337
|
+
return entry;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* mapAsync(READ) on a slot for read(); a rejection becomes E_DISPOSED (after destroyAll) or E_DEVICE_LOST.
|
|
341
|
+
* @param entry - the ring entry of the borrowed slot
|
|
342
|
+
* @param byteLength - the bytes to map
|
|
343
|
+
*/
|
|
344
|
+
async map(entry, byteLength) {
|
|
345
|
+
let mapped = false;
|
|
346
|
+
let failure = null;
|
|
347
|
+
try {
|
|
348
|
+
await this.track(entry, entry.slot.buffer.mapAsync(MapMode.READ, 0, byteLength));
|
|
349
|
+
mapped = true;
|
|
350
|
+
}
|
|
351
|
+
catch (err) {
|
|
352
|
+
failure = err;
|
|
353
|
+
}
|
|
354
|
+
if (this.disposed) {
|
|
355
|
+
// destroyAll() ran while the map was pending: track() finished the deferred destruction just before this
|
|
356
|
+
throw new WebGpuGraphError("E_DISPOSED", "the readback ring was disposed while a read was pending", {
|
|
357
|
+
label: "readback",
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
if (!mapped) {
|
|
361
|
+
const message = failure instanceof Error ? failure.message : String(failure);
|
|
362
|
+
throw new WebGpuGraphError("E_DEVICE_LOST", `mapAsync rejected: ${message}`, {
|
|
363
|
+
reason: "mapAsync",
|
|
364
|
+
message,
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
/** Throws E_DISPOSED after destroyAll(). */
|
|
369
|
+
assertLive() {
|
|
370
|
+
if (this.disposed) {
|
|
371
|
+
throw new WebGpuGraphError("E_DISPOSED", "the readback ring was disposed", { label: "readback" });
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
//# sourceMappingURL=readback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readback.js","sourceRoot":"","sources":["../../../src/memory/readback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The upload cache of spec 4.1 / 4.3 / 4.5: every core array, view array, column and ad hoc array a kernel binds
|
|
3
|
+
* lives on the device exactly once per snapshot core, keyed on the typed-array object (or the Column object for
|
|
4
|
+
* columns, PLAN DECISION 8), recorded per serial so `release(snapshot)` destroys every buffer of a snapshot and its
|
|
5
|
+
* withColumns() siblings, and tombstoned so a live user learns of the release through `isReleased` (spec 4.5).
|
|
6
|
+
* Uploads follow the pure planner of ./upload-plan.ts: the arena path writes ONE buffer with ONE writeBuffer of the
|
|
7
|
+
* hot prefix (or the full arena when a cold segment is needed and fits) and binds segments at
|
|
8
|
+
* `segment.byteOffset - arena.byteOffset`; the perArray path writes one buffer per array; a windowed plan is
|
|
9
|
+
* E_TOO_LARGE until P4 executes windows (PLAN DECISION 2). Identity permutations are never materialised: presence is
|
|
10
|
+
* decided from counts and flags, and the arcToEdge / edgeToArc getters are read only when a segment exists. Nothing
|
|
11
|
+
* is freed by garbage collection; the once-only warning above warnUnreleasedSnapshots names the missing release.
|
|
12
|
+
*/
|
|
13
|
+
import { type Column, type GpuEligibility, type GraphSnapshot } from "@graphty/graph-format";
|
|
14
|
+
import { type ArcWindow, type Binding } from "../types/memory.js";
|
|
15
|
+
/**
|
|
16
|
+
* The core arrays of a snapshot on the device (spec 4.1); a null member is absent (zero-length, unweighted or an
|
|
17
|
+
* identity permutation) and is bound as a dummy by the kernel layer (3.9). `Binding` itself is declared in
|
|
18
|
+
* src/types/memory.ts (3.3). Exported by contract 3.8: P1-T4's graphBindings / graphOverrides and every later
|
|
19
|
+
* kernel driver take it; nothing at P1-T2 imports it by name.
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export interface CoreBinding {
|
|
23
|
+
readonly serial: number;
|
|
24
|
+
readonly plan: "arena" | "perArray" | "windowed";
|
|
25
|
+
readonly rowPtr: Binding;
|
|
26
|
+
readonly colIdx: Binding | null;
|
|
27
|
+
readonly weights: Binding | null;
|
|
28
|
+
readonly arcToEdge: Binding | null;
|
|
29
|
+
readonly edgeToArc: Binding | null;
|
|
30
|
+
readonly windows: readonly ArcWindow[] | null;
|
|
31
|
+
readonly hasWeights: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A view's arrays on the device plus the CPU-side scalars (degreeOrder's segmentOffsets) (spec 4.3). Exported by
|
|
35
|
+
* contract 3.8: the degreeOrder permutation of P4's kernels is a ViewBinding; nothing at P1-T2 imports it by name.
|
|
36
|
+
* @public
|
|
37
|
+
*/
|
|
38
|
+
export interface ViewBinding {
|
|
39
|
+
readonly view: "reverse" | "coo" | "edgeList" | "outDegree" | "inDegree" | "degreeOrder" | "reverseDegreeOrder" | "mate";
|
|
40
|
+
readonly bindings: Readonly<Record<string, Binding>>;
|
|
41
|
+
readonly scalars: Readonly<Record<string, readonly number[]>>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A column's gpuView() on the device (spec 4.3). Exported by contract 3.8: P3's layout inputs register columns
|
|
45
|
+
* through it; nothing at P1-T2 imports it by name.
|
|
46
|
+
* @public
|
|
47
|
+
*/
|
|
48
|
+
export interface ColumnBinding {
|
|
49
|
+
readonly binding: Binding;
|
|
50
|
+
readonly column: Column;
|
|
51
|
+
readonly version: number;
|
|
52
|
+
readonly eligibility: GpuEligibility;
|
|
53
|
+
readonly components: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* An ad hoc array on the device (spec 4.1 last row); `destroy()` is the caller's when no owner was given. Exported
|
|
57
|
+
* by contract 3.8: P3's model resolves column inputs to a registered ArrayBinding; nothing at P1-T2 imports it by
|
|
58
|
+
* name.
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
export interface ArrayBinding {
|
|
62
|
+
readonly binding: Binding;
|
|
63
|
+
readonly byteLength: number;
|
|
64
|
+
readonly owner: GraphSnapshot | null;
|
|
65
|
+
destroy(): void;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* stats() shape (spec 4.1). Exported by contract 3.8 for the callers of ctx.residency.stats(); nothing at P1-T2
|
|
69
|
+
* imports it by name.
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
72
|
+
export interface ResidencyStats {
|
|
73
|
+
readonly buffers: number;
|
|
74
|
+
readonly bytes: number;
|
|
75
|
+
readonly snapshots: number;
|
|
76
|
+
readonly perSnapshot: readonly {
|
|
77
|
+
readonly serial: number;
|
|
78
|
+
readonly label: string | null;
|
|
79
|
+
readonly bytes: number;
|
|
80
|
+
readonly buffers: number;
|
|
81
|
+
}[];
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=residency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"residency.d.ts","sourceRoot":"","sources":["../../../src/memory/residency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAEH,KAAK,MAAM,EAEX,KAAK,cAAc,EACnB,KAAK,aAAa,EAErB,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAYlE;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,GAAG,IAAI,CAAC;IAC9C,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAChC;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IACxB,QAAQ,CAAC,IAAI,EACT,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,aAAa,GAAG,oBAAoB,GAAG,MAAM,CAAC;IAC9G,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;CACjE;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,SAAS;QAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;KAC5B,EAAE,CAAC;CACP"}
|