@aardworx/wombat.rendering 0.9.33 → 0.18.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/dist/runtime/derivedModes/kernelCodegen.d.ts +90 -0
- package/dist/runtime/derivedModes/kernelCodegen.d.ts.map +1 -0
- package/dist/runtime/derivedModes/kernelCodegen.js +623 -0
- package/dist/runtime/derivedModes/kernelCodegen.js.map +1 -0
- package/dist/runtime/derivedModes/modeKeyCpu.d.ts.map +1 -1
- package/dist/runtime/derivedModes/modeKeyCpu.js +23 -67
- package/dist/runtime/derivedModes/modeKeyCpu.js.map +1 -1
- package/dist/runtime/derivedModes/partitionDispatcher.d.ts +79 -0
- package/dist/runtime/derivedModes/partitionDispatcher.d.ts.map +1 -0
- package/dist/runtime/derivedModes/partitionDispatcher.js +303 -0
- package/dist/runtime/derivedModes/partitionDispatcher.js.map +1 -0
- package/dist/runtime/derivedModes/partitionKernel.d.ts +12 -0
- package/dist/runtime/derivedModes/partitionKernel.d.ts.map +1 -0
- package/dist/runtime/derivedModes/partitionKernel.js +127 -0
- package/dist/runtime/derivedModes/partitionKernel.js.map +1 -0
- package/dist/runtime/derivedModes/partitionKernelLayout.d.ts +4 -0
- package/dist/runtime/derivedModes/partitionKernelLayout.d.ts.map +1 -0
- package/dist/runtime/derivedModes/partitionKernelLayout.js +24 -0
- package/dist/runtime/derivedModes/partitionKernelLayout.js.map +1 -0
- package/dist/runtime/derivedModes/rule.d.ts +38 -86
- package/dist/runtime/derivedModes/rule.d.ts.map +1 -1
- package/dist/runtime/derivedModes/rule.js +34 -74
- package/dist/runtime/derivedModes/rule.js.map +1 -1
- package/dist/runtime/derivedUniforms/dispatch.d.ts +10 -8
- package/dist/runtime/derivedUniforms/dispatch.d.ts.map +1 -1
- package/dist/runtime/derivedUniforms/dispatch.js +31 -18
- package/dist/runtime/derivedUniforms/dispatch.js.map +1 -1
- package/dist/runtime/derivedUniforms/marker.d.ts +90 -11
- package/dist/runtime/derivedUniforms/marker.d.ts.map +1 -1
- package/dist/runtime/derivedUniforms/marker.js +161 -15
- package/dist/runtime/derivedUniforms/marker.js.map +1 -1
- package/dist/runtime/derivedUniforms/sceneIntegration.d.ts +25 -6
- package/dist/runtime/derivedUniforms/sceneIntegration.d.ts.map +1 -1
- package/dist/runtime/derivedUniforms/sceneIntegration.js +61 -20
- package/dist/runtime/derivedUniforms/sceneIntegration.js.map +1 -1
- package/dist/runtime/heapEligibility.d.ts.map +1 -1
- package/dist/runtime/heapEligibility.js +22 -2
- package/dist/runtime/heapEligibility.js.map +1 -1
- package/dist/runtime/heapScene/chunkedArena.d.ts +76 -0
- package/dist/runtime/heapScene/chunkedArena.d.ts.map +1 -0
- package/dist/runtime/heapScene/chunkedArena.js +223 -0
- package/dist/runtime/heapScene/chunkedArena.js.map +1 -0
- package/dist/runtime/heapScene/freelist.d.ts +50 -0
- package/dist/runtime/heapScene/freelist.d.ts.map +1 -0
- package/dist/runtime/heapScene/freelist.js +160 -0
- package/dist/runtime/heapScene/freelist.js.map +1 -0
- package/dist/runtime/heapScene/growBuffer.d.ts +23 -2
- package/dist/runtime/heapScene/growBuffer.d.ts.map +1 -1
- package/dist/runtime/heapScene/growBuffer.js +35 -3
- package/dist/runtime/heapScene/growBuffer.js.map +1 -1
- package/dist/runtime/heapScene/pools.d.ts +65 -42
- package/dist/runtime/heapScene/pools.d.ts.map +1 -1
- package/dist/runtime/heapScene/pools.js +206 -134
- package/dist/runtime/heapScene/pools.js.map +1 -1
- package/dist/runtime/heapScene.d.ts +12 -0
- package/dist/runtime/heapScene.d.ts.map +1 -1
- package/dist/runtime/heapScene.js +938 -85
- package/dist/runtime/heapScene.js.map +1 -1
- package/dist/runtime/hybridScene.d.ts +7 -0
- package/dist/runtime/hybridScene.d.ts.map +1 -1
- package/dist/runtime/hybridScene.js +1 -0
- package/dist/runtime/hybridScene.js.map +1 -1
- package/dist/runtime/index.d.ts +4 -3
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +4 -3
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/renderTask.d.ts +5 -0
- package/dist/runtime/renderTask.d.ts.map +1 -1
- package/dist/runtime/renderTask.js +1 -0
- package/dist/runtime/renderTask.js.map +1 -1
- package/dist/runtime/runtime.d.ts +6 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +1 -0
- package/dist/runtime/runtime.js.map +1 -1
- package/package.json +1 -1
- package/src/runtime/derivedModes/kernelCodegen.ts +673 -0
- package/src/runtime/derivedModes/modeKeyCpu.ts +22 -60
- package/src/runtime/derivedModes/partitionDispatcher.ts +349 -0
- package/src/runtime/derivedModes/partitionKernelLayout.ts +25 -0
- package/src/runtime/derivedModes/rule.ts +66 -145
- package/src/runtime/derivedUniforms/dispatch.ts +48 -21
- package/src/runtime/derivedUniforms/marker.ts +210 -16
- package/src/runtime/derivedUniforms/sceneIntegration.ts +67 -20
- package/src/runtime/heapEligibility.ts +22 -1
- package/src/runtime/heapScene/chunkedArena.ts +238 -0
- package/src/runtime/heapScene/freelist.ts +161 -0
- package/src/runtime/heapScene/growBuffer.ts +39 -2
- package/src/runtime/heapScene/pools.ts +231 -143
- package/src/runtime/heapScene.ts +1119 -81
- package/src/runtime/hybridScene.ts +8 -0
- package/src/runtime/index.ts +12 -9
- package/src/runtime/renderTask.ts +6 -0
- package/src/runtime/runtime.ts +7 -0
- package/src/runtime/derivedModes/gpuDispatcher.ts +0 -226
- package/src/runtime/derivedModes/gpuKernel.ts +0 -98
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// Freelist — best-fit free-block manager used by AttributeArena and
|
|
2
|
+
// IndexAllocator. Replaces the earlier `{off,size}[]` sorted-by-off
|
|
3
|
+
// freelist (whose alloc was O(N) first-fit and release was O(log N)
|
|
4
|
+
// binary-search-then-coalesce).
|
|
5
|
+
//
|
|
6
|
+
// Design:
|
|
7
|
+
//
|
|
8
|
+
// bySize: size → Set<off> — exact-size buckets
|
|
9
|
+
// sizes: sorted ascending array of distinct sizes — for lower_bound
|
|
10
|
+
// byStart: off → size — for right-coalesce
|
|
11
|
+
// byEnd: off+size → off — for left-coalesce
|
|
12
|
+
//
|
|
13
|
+
// `alloc(size)` → lower_bound(sizes, size) picks the smallest bucket
|
|
14
|
+
// with size ≥ requested. O(log K) lookup over distinct
|
|
15
|
+
// sizes K (typically dozens), then constant-time pop
|
|
16
|
+
// from the size's offset set. If the bucket size
|
|
17
|
+
// exceeds the request, the remainder reinserts at
|
|
18
|
+
// (off+size, leftover).
|
|
19
|
+
// `release(o,s)` → check `byEnd[o]` (left neighbour ends here) and
|
|
20
|
+
// `byStart[o+s]` (right neighbour starts here) for
|
|
21
|
+
// O(1) adjacency lookups. Coalesce both sides then
|
|
22
|
+
// reinsert one merged block.
|
|
23
|
+
//
|
|
24
|
+
// On realistic heap-renderer workloads the number of *distinct*
|
|
25
|
+
// free-block sizes is typically much smaller than the number of
|
|
26
|
+
// blocks (allocations cluster around the schema's drawHeader
|
|
27
|
+
// fields: mat4=64B, vec4=16B, …), so the K-sized sorted array's
|
|
28
|
+
// splice cost stays cheap even at thousands of live free blocks.
|
|
29
|
+
// For truly heterogeneous workloads, swap `sizes` for a balanced
|
|
30
|
+
// tree — none of the API changes.
|
|
31
|
+
/**
|
|
32
|
+
* A best-fit free-block manager. All offsets and sizes are in the
|
|
33
|
+
* caller's units (bytes for the attribute arena, u32 elements for
|
|
34
|
+
* the index allocator); the freelist doesn't interpret them.
|
|
35
|
+
*/
|
|
36
|
+
export class Freelist {
|
|
37
|
+
/** size → set of starting offsets currently free at that size. */
|
|
38
|
+
bySize = new Map();
|
|
39
|
+
/** Sorted ascending list of every size present in `bySize`. */
|
|
40
|
+
sizes = [];
|
|
41
|
+
/** off → size, for the right-coalesce probe in `release`. */
|
|
42
|
+
byStart = new Map();
|
|
43
|
+
/** off+size (= end offset) → off, for the left-coalesce probe. */
|
|
44
|
+
byEnd = new Map();
|
|
45
|
+
/** Number of distinct free blocks currently tracked. */
|
|
46
|
+
get blockCount() { return this.byStart.size; }
|
|
47
|
+
/**
|
|
48
|
+
* Return any offset of a free block whose size is ≥ `size`, splitting
|
|
49
|
+
* off any leftover bytes back into the freelist. Returns `undefined`
|
|
50
|
+
* when no block fits.
|
|
51
|
+
*/
|
|
52
|
+
alloc(size) {
|
|
53
|
+
const idx = lowerBound(this.sizes, size);
|
|
54
|
+
if (idx >= this.sizes.length)
|
|
55
|
+
return undefined;
|
|
56
|
+
const foundSize = this.sizes[idx];
|
|
57
|
+
const set = this.bySize.get(foundSize);
|
|
58
|
+
// Set iteration order is insertion order — using the first inserted
|
|
59
|
+
// gives deterministic alloc patterns under matched test workloads.
|
|
60
|
+
const off = set.values().next().value;
|
|
61
|
+
this.removeBlock(off, foundSize);
|
|
62
|
+
if (foundSize > size)
|
|
63
|
+
this.addBlock(off + size, foundSize - size);
|
|
64
|
+
return off;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Reintroduce a `(off, size)` block, coalescing with any immediate
|
|
68
|
+
* neighbour on the left (some other block ending at `off`) or right
|
|
69
|
+
* (some other block starting at `off + size`).
|
|
70
|
+
*/
|
|
71
|
+
release(off, size) {
|
|
72
|
+
let mergeOff = off;
|
|
73
|
+
let mergeSize = size;
|
|
74
|
+
// Left neighbour: a block whose end offset is exactly `off`.
|
|
75
|
+
const leftStart = this.byEnd.get(mergeOff);
|
|
76
|
+
if (leftStart !== undefined) {
|
|
77
|
+
const leftSize = this.byStart.get(leftStart);
|
|
78
|
+
this.removeBlock(leftStart, leftSize);
|
|
79
|
+
mergeOff = leftStart;
|
|
80
|
+
mergeSize += leftSize;
|
|
81
|
+
}
|
|
82
|
+
// Right neighbour: a block whose start offset is exactly `off + size`.
|
|
83
|
+
const rightStart = mergeOff + mergeSize;
|
|
84
|
+
const rightSize = this.byStart.get(rightStart);
|
|
85
|
+
if (rightSize !== undefined) {
|
|
86
|
+
this.removeBlock(rightStart, rightSize);
|
|
87
|
+
mergeSize += rightSize;
|
|
88
|
+
}
|
|
89
|
+
this.addBlock(mergeOff, mergeSize);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Take and remove the free block whose end offset is exactly
|
|
93
|
+
* `endOff`, if any exists. Used by `AttributeArena` /
|
|
94
|
+
* `IndexAllocator` to shrink the bump cursor back when releases
|
|
95
|
+
* expose a free tail (§5 — cursor-shrink hygiene for long-lived
|
|
96
|
+
* high-churn scenes).
|
|
97
|
+
*/
|
|
98
|
+
takeBlockEndingAt(endOff) {
|
|
99
|
+
const off = this.byEnd.get(endOff);
|
|
100
|
+
if (off === undefined)
|
|
101
|
+
return undefined;
|
|
102
|
+
const size = this.byStart.get(off);
|
|
103
|
+
this.removeBlock(off, size);
|
|
104
|
+
return { off, size };
|
|
105
|
+
}
|
|
106
|
+
/** Drop every block. */
|
|
107
|
+
clear() {
|
|
108
|
+
this.bySize.clear();
|
|
109
|
+
this.sizes.length = 0;
|
|
110
|
+
this.byStart.clear();
|
|
111
|
+
this.byEnd.clear();
|
|
112
|
+
}
|
|
113
|
+
/** Snapshot for tests / debugging — sorted by offset. */
|
|
114
|
+
toArray() {
|
|
115
|
+
const out = [];
|
|
116
|
+
for (const [off, size] of this.byStart)
|
|
117
|
+
out.push({ off, size });
|
|
118
|
+
out.sort((a, b) => a.off - b.off);
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
addBlock(off, size) {
|
|
122
|
+
let set = this.bySize.get(size);
|
|
123
|
+
if (set === undefined) {
|
|
124
|
+
set = new Set();
|
|
125
|
+
this.bySize.set(size, set);
|
|
126
|
+
const idx = lowerBound(this.sizes, size);
|
|
127
|
+
this.sizes.splice(idx, 0, size);
|
|
128
|
+
}
|
|
129
|
+
set.add(off);
|
|
130
|
+
this.byStart.set(off, size);
|
|
131
|
+
this.byEnd.set(off + size, off);
|
|
132
|
+
}
|
|
133
|
+
removeBlock(off, size) {
|
|
134
|
+
const set = this.bySize.get(size);
|
|
135
|
+
if (set === undefined)
|
|
136
|
+
return;
|
|
137
|
+
set.delete(off);
|
|
138
|
+
if (set.size === 0) {
|
|
139
|
+
this.bySize.delete(size);
|
|
140
|
+
const idx = lowerBound(this.sizes, size);
|
|
141
|
+
if (this.sizes[idx] === size)
|
|
142
|
+
this.sizes.splice(idx, 1);
|
|
143
|
+
}
|
|
144
|
+
this.byStart.delete(off);
|
|
145
|
+
this.byEnd.delete(off + size);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** Index of the first element of `arr` that is `>= target`. */
|
|
149
|
+
function lowerBound(arr, target) {
|
|
150
|
+
let lo = 0, hi = arr.length;
|
|
151
|
+
while (lo < hi) {
|
|
152
|
+
const mid = (lo + hi) >>> 1;
|
|
153
|
+
if (arr[mid] < target)
|
|
154
|
+
lo = mid + 1;
|
|
155
|
+
else
|
|
156
|
+
hi = mid;
|
|
157
|
+
}
|
|
158
|
+
return lo;
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=freelist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"freelist.js","sourceRoot":"","sources":["../../../src/runtime/heapScene/freelist.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,17 @@ export declare const ALIGN16: (n: number) => number;
|
|
|
12
12
|
* it allocates, and `ensureCapacity` grows when required. This
|
|
13
13
|
* separates allocation policy from grow policy.
|
|
14
14
|
*/
|
|
15
|
+
/**
|
|
16
|
+
* Default chunk capacity cap when none is provided. We pick 256 MB as
|
|
17
|
+
* a safety ceiling that's well within typical adapter
|
|
18
|
+
* `maxStorageBufferBindingSize` (WebGPU spec minimum is 128 MB; most
|
|
19
|
+
* desktop GPUs expose 2 GiB+, mobile/integrated ≥ 256 MB). Callers
|
|
20
|
+
* that know the adapter limit should pass it explicitly so chunks
|
|
21
|
+
* can grow to whatever the hardware supports — see §3 in
|
|
22
|
+
* `docs/heap-future-work.md` and `runtime/heapScene.ts`'s scene
|
|
23
|
+
* factory where the device limit is threaded in.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_MAX_BUFFER_BYTES: number;
|
|
15
26
|
export declare class GrowBuffer {
|
|
16
27
|
private readonly device;
|
|
17
28
|
private readonly label;
|
|
@@ -20,13 +31,23 @@ export declare class GrowBuffer {
|
|
|
20
31
|
private cap;
|
|
21
32
|
private used;
|
|
22
33
|
private readonly listeners;
|
|
23
|
-
|
|
34
|
+
private readonly maxBytes;
|
|
35
|
+
constructor(device: GPUDevice, label: string, usage: GPUBufferUsageFlags, initialBytes: number, maxBytes?: number);
|
|
24
36
|
get buffer(): GPUBuffer;
|
|
25
37
|
get capacity(): number;
|
|
38
|
+
get maxCapacity(): number;
|
|
26
39
|
get usedBytes(): number;
|
|
27
40
|
setUsed(n: number): void;
|
|
28
41
|
onResize(cb: () => void): IDisposable;
|
|
29
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Ensure the buffer is at least `bytes` capacity. Grows by pow2 +
|
|
44
|
+
* copies live tail. Throws if `bytes` exceeds the configured
|
|
45
|
+
* `maxBytes` cap — caller is expected to either open a new chunk
|
|
46
|
+
* (full §3 multi-draw-call path, deferred) or reject the
|
|
47
|
+
* allocation upstream (see `isHeapEligible`'s §2 large-object
|
|
48
|
+
* eject, which keeps multi-MB single ROs out of the heap arena
|
|
49
|
+
* entirely).
|
|
50
|
+
*/
|
|
30
51
|
ensureCapacity(bytes: number): void;
|
|
31
52
|
destroy(): void;
|
|
32
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"growBuffer.d.ts","sourceRoot":"","sources":["../../../src/runtime/heapScene/growBuffer.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D,eAAO,MAAM,gBAAgB,QAAY,CAAC;AAE1C,eAAO,MAAM,IAAI,GAAI,GAAG,MAAM,KAAG,MAEhC,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,WAAmB,CAAC;AAErD;;;;;;;;;GASG;AACH,qBAAa,UAAU;
|
|
1
|
+
{"version":3,"file":"growBuffer.d.ts","sourceRoot":"","sources":["../../../src/runtime/heapScene/growBuffer.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAE7D,eAAO,MAAM,gBAAgB,QAAY,CAAC;AAE1C,eAAO,MAAM,IAAI,GAAI,GAAG,MAAM,KAAG,MAEhC,CAAC;AAEF,eAAO,MAAM,OAAO,GAAI,GAAG,MAAM,WAAmB,CAAC;AAErD;;;;;;;;;GASG;AACH;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,QAAoB,CAAC;AAE1D,qBAAa,UAAU;IAOnB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IARxB,OAAO,CAAC,GAAG,CAAY;IACvB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;gBAEf,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,mBAAmB,EAC3C,YAAY,EAAE,MAAM,EACpB,QAAQ,GAAE,MAAiC;IAe7C,IAAI,MAAM,IAAI,SAAS,CAAqB;IAC5C,IAAI,QAAQ,IAAI,MAAM,CAAqB;IAC3C,IAAI,WAAW,IAAI,MAAM,CAA0B;IACnD,IAAI,SAAS,IAAI,MAAM,CAAsB;IAC7C,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,WAAW;IAIrC;;;;;;;;OAQG;IACH,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IA0BnC,OAAO,IAAI,IAAI;CAChB"}
|
|
@@ -23,6 +23,17 @@ export const ALIGN16 = (n) => (n + 15) & ~15;
|
|
|
23
23
|
* it allocates, and `ensureCapacity` grows when required. This
|
|
24
24
|
* separates allocation policy from grow policy.
|
|
25
25
|
*/
|
|
26
|
+
/**
|
|
27
|
+
* Default chunk capacity cap when none is provided. We pick 256 MB as
|
|
28
|
+
* a safety ceiling that's well within typical adapter
|
|
29
|
+
* `maxStorageBufferBindingSize` (WebGPU spec minimum is 128 MB; most
|
|
30
|
+
* desktop GPUs expose 2 GiB+, mobile/integrated ≥ 256 MB). Callers
|
|
31
|
+
* that know the adapter limit should pass it explicitly so chunks
|
|
32
|
+
* can grow to whatever the hardware supports — see §3 in
|
|
33
|
+
* `docs/heap-future-work.md` and `runtime/heapScene.ts`'s scene
|
|
34
|
+
* factory where the device limit is threaded in.
|
|
35
|
+
*/
|
|
36
|
+
export const DEFAULT_MAX_BUFFER_BYTES = 256 * 1024 * 1024;
|
|
26
37
|
export class GrowBuffer {
|
|
27
38
|
device;
|
|
28
39
|
label;
|
|
@@ -31,11 +42,16 @@ export class GrowBuffer {
|
|
|
31
42
|
cap;
|
|
32
43
|
used = 0;
|
|
33
44
|
listeners = new Set();
|
|
34
|
-
|
|
45
|
+
maxBytes;
|
|
46
|
+
constructor(device, label, usage, initialBytes, maxBytes = DEFAULT_MAX_BUFFER_BYTES) {
|
|
35
47
|
this.device = device;
|
|
36
48
|
this.label = label;
|
|
37
49
|
this.usage = usage;
|
|
38
50
|
this.cap = Math.max(MIN_BUFFER_BYTES, POW2(initialBytes));
|
|
51
|
+
this.maxBytes = Math.max(this.cap, maxBytes);
|
|
52
|
+
if (this.cap > this.maxBytes) {
|
|
53
|
+
throw new Error(`GrowBuffer '${label}': initial capacity ${this.cap} exceeds maxBytes ${this.maxBytes}`);
|
|
54
|
+
}
|
|
39
55
|
this.buf = device.createBuffer({
|
|
40
56
|
size: this.cap,
|
|
41
57
|
usage: usage | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
|
|
@@ -44,17 +60,33 @@ export class GrowBuffer {
|
|
|
44
60
|
}
|
|
45
61
|
get buffer() { return this.buf; }
|
|
46
62
|
get capacity() { return this.cap; }
|
|
63
|
+
get maxCapacity() { return this.maxBytes; }
|
|
47
64
|
get usedBytes() { return this.used; }
|
|
48
65
|
setUsed(n) { this.used = n; }
|
|
49
66
|
onResize(cb) {
|
|
50
67
|
this.listeners.add(cb);
|
|
51
68
|
return { dispose: () => { this.listeners.delete(cb); } };
|
|
52
69
|
}
|
|
53
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Ensure the buffer is at least `bytes` capacity. Grows by pow2 +
|
|
72
|
+
* copies live tail. Throws if `bytes` exceeds the configured
|
|
73
|
+
* `maxBytes` cap — caller is expected to either open a new chunk
|
|
74
|
+
* (full §3 multi-draw-call path, deferred) or reject the
|
|
75
|
+
* allocation upstream (see `isHeapEligible`'s §2 large-object
|
|
76
|
+
* eject, which keeps multi-MB single ROs out of the heap arena
|
|
77
|
+
* entirely).
|
|
78
|
+
*/
|
|
54
79
|
ensureCapacity(bytes) {
|
|
55
80
|
if (bytes <= this.cap)
|
|
56
81
|
return;
|
|
57
|
-
|
|
82
|
+
if (bytes > this.maxBytes) {
|
|
83
|
+
throw new Error(`GrowBuffer '${this.label}': requested ${bytes} bytes exceeds maxBytes ${this.maxBytes}. ` +
|
|
84
|
+
`This is the adapter's per-binding storage limit — landing larger workloads needs the ` +
|
|
85
|
+
`multi-chunk path (§3 in docs/heap-future-work.md) or upstream eviction via §2.`);
|
|
86
|
+
}
|
|
87
|
+
let newCap = POW2(bytes);
|
|
88
|
+
if (newCap > this.maxBytes)
|
|
89
|
+
newCap = this.maxBytes;
|
|
58
90
|
const newBuf = this.device.createBuffer({
|
|
59
91
|
size: newCap,
|
|
60
92
|
usage: this.usage | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"growBuffer.js","sourceRoot":"","sources":["../../../src/runtime/heapScene/growBuffer.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,kEAAkE;AAClE,EAAE;AACF,oEAAoE;AACpE,qEAAqE;AACrE,6DAA6D;AAC7D,aAAa;AAIb,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,CAAC;AAE1C,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE;IACxC,IAAI,CAAC,GAAG,CAAC,CAAC;IAAC,OAAO,CAAC,GAAG,CAAC;QAAE,CAAC,KAAK,CAAC,CAAC;IAAC,OAAO,CAAC,CAAC;AAC7C,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;AAErD;;;;;;;;;GASG;AACH,MAAM,OAAO,UAAU;
|
|
1
|
+
{"version":3,"file":"growBuffer.js","sourceRoot":"","sources":["../../../src/runtime/heapScene/growBuffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import type { aval, IDisposable } from "@aardworx/wombat.adaptive";
|
|
|
2
2
|
import type { BufferView } from "../../core/bufferView.js";
|
|
3
3
|
import type { HostBufferSource } from "../../core/buffer.js";
|
|
4
4
|
import { GrowBuffer } from "./growBuffer.js";
|
|
5
|
+
import { ChunkedAttributeArena, ChunkedIndexAllocator } from "./chunkedArena.js";
|
|
5
6
|
/** Per-allocation header: (u32 typeId, u32 length). Data follows
|
|
6
7
|
* the header aligned up to 16 bytes (so positions/normals/etc. line
|
|
7
8
|
* up for future vec4 reads). */
|
|
@@ -13,44 +14,56 @@ export declare const ENC_V3F_TIGHT = 1;
|
|
|
13
14
|
* the shader doesn't branch on this. */
|
|
14
15
|
export declare const SEM_POSITIONS = 1;
|
|
15
16
|
export declare const SEM_NORMALS = 2;
|
|
17
|
+
/**
|
|
18
|
+
* One pool entry tracks a single (aval, chunkIdx) pair. Refs are
|
|
19
|
+
* byte offsets within the chunk's GPUBuffer; chunkIdx is implicit
|
|
20
|
+
* in which chunk's bind group is active at draw time (shaders
|
|
21
|
+
* never decode it).
|
|
22
|
+
*/
|
|
16
23
|
interface PoolEntry {
|
|
17
|
-
|
|
24
|
+
readonly chunkIdx: number;
|
|
18
25
|
readonly ref: number;
|
|
19
26
|
readonly dataBytes: number;
|
|
20
27
|
readonly typeId: number;
|
|
21
|
-
/** Packer used to refresh the data region on aval marks. */
|
|
22
28
|
readonly pack: (val: unknown, dst: Float32Array, off: number) => void;
|
|
23
29
|
refcount: number;
|
|
24
30
|
}
|
|
25
31
|
/**
|
|
26
|
-
*
|
|
27
|
-
* aval
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* (
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* Sharing emerges from aval identity — no separate "frequency"
|
|
34
|
-
* declaration needed. A `cval` shared by all draws → 1 alloc.
|
|
35
|
-
* A static positions array shared across instanced draws → 1 alloc.
|
|
36
|
-
* Same code path either way.
|
|
32
|
+
* `(aval, chunkIdx)`-keyed pool of chunked-arena allocations. An
|
|
33
|
+
* aval that's referenced from multiple chunks (e.g. two ROs sharing
|
|
34
|
+
* a uniform but landing in different chunks) gets one entry per
|
|
35
|
+
* chunk — accepted duplication cost of the multi-draw-call
|
|
36
|
+
* per-chunk render path (§3). Within a single chunk, ROs sharing
|
|
37
|
+
* an aval still share the underlying allocation.
|
|
37
38
|
*/
|
|
38
39
|
export declare class UniformPool {
|
|
39
40
|
private readonly byAval;
|
|
40
|
-
has(av: aval<unknown
|
|
41
|
-
entry
|
|
41
|
+
has(av: aval<unknown>, chunkIdx: number): boolean;
|
|
42
|
+
/** True when the pool holds at least one entry for `av` in any
|
|
43
|
+
* chunk. Used by the scene's `inputChanged` dispatch to decide
|
|
44
|
+
* whether a marking aval is one of our tracked allocations. */
|
|
45
|
+
hasAny(av: aval<unknown>): boolean;
|
|
46
|
+
entry(av: aval<unknown>, chunkIdx: number): PoolEntry | undefined;
|
|
47
|
+
/** First chunk this aval is allocated in, if any. Used by `addRO`
|
|
48
|
+
* to prefer co-locating a new RO with its already-allocated
|
|
49
|
+
* shared inputs (avoids unnecessary duplication). */
|
|
50
|
+
firstChunkContaining(av: aval<unknown>): number | undefined;
|
|
42
51
|
/**
|
|
43
|
-
* Acquire (or share) an allocation for `aval
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* uploaded immediately.
|
|
52
|
+
* Acquire (or share) an allocation for `aval` in `chunkIdx`.
|
|
53
|
+
* Returns the byte offset within that chunk's GPUBuffer. If a
|
|
54
|
+
* fresh allocation is made, the value is packed + uploaded
|
|
55
|
+
* immediately into the chunk's CPU shadow.
|
|
48
56
|
*/
|
|
49
|
-
acquire(device: GPUDevice, arena:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
acquire(device: GPUDevice, arena: ChunkedAttributeArena, av: aval<unknown>, chunkIdx: number, value: unknown, dataBytes: number, typeId: number, length: number, pack: (val: unknown, dst: Float32Array, off: number) => void): number;
|
|
58
|
+
release(arena: ChunkedAttributeArena, av: aval<unknown>, chunkIdx: number): void;
|
|
59
|
+
/** Re-pack one entry's data region into every chunk that holds
|
|
60
|
+
* this aval. When an aval is shared across N chunks (each chunk
|
|
61
|
+
* has its own duplicate alloc), every duplicate needs the
|
|
62
|
+
* refresh so all the chunks' ROs see the new value. */
|
|
63
|
+
repack(device: GPUDevice, arena: ChunkedAttributeArena, av: aval<unknown>, val: unknown): void;
|
|
64
|
+
/** Total bytes touched by `repack` for this aval — sum across
|
|
65
|
+
* chunks. Used by the dirty-bytes diagnostics. */
|
|
66
|
+
totalDataBytes(av: aval<unknown>): number;
|
|
54
67
|
}
|
|
55
68
|
/**
|
|
56
69
|
* Aval-keyed pool over the `IndexAllocator`. Two draws referencing
|
|
@@ -65,16 +78,21 @@ export declare class UniformPool {
|
|
|
65
78
|
* `Uint32Array` view collapse to one allocation.
|
|
66
79
|
*/
|
|
67
80
|
export declare class IndexPool {
|
|
81
|
+
/** Per-aval, per-chunk bookkeeping. Same aval acquired in two
|
|
82
|
+
* chunks gets two entries (accepted §3 duplication). */
|
|
68
83
|
private readonly byAval;
|
|
84
|
+
/** Per-chunk constant-aval value-dedup (§5b in-chunk). */
|
|
69
85
|
private readonly byValueKey;
|
|
70
86
|
private readonly bufferIds;
|
|
71
87
|
private nextBufferId;
|
|
72
88
|
private bufferIdOf;
|
|
73
|
-
|
|
89
|
+
firstChunkContaining(av: aval<Uint32Array>): number | undefined;
|
|
90
|
+
acquire(device: GPUDevice, indices: ChunkedIndexAllocator, av: aval<Uint32Array>, chunkIdx: number, arr: Uint32Array): {
|
|
91
|
+
chunkIdx: number;
|
|
74
92
|
firstIndex: number;
|
|
75
93
|
count: number;
|
|
76
94
|
};
|
|
77
|
-
release(indices:
|
|
95
|
+
release(indices: ChunkedIndexAllocator, av: aval<Uint32Array>, chunkIdx: number): void;
|
|
78
96
|
}
|
|
79
97
|
/**
|
|
80
98
|
* Slot-indexed allocator over a GrowBuffer. `slotBytes` is set per-
|
|
@@ -107,7 +125,7 @@ export declare class DrawHeap {
|
|
|
107
125
|
export declare class AttributeArena {
|
|
108
126
|
private readonly buf;
|
|
109
127
|
private cursor;
|
|
110
|
-
private
|
|
128
|
+
private readonly freelist;
|
|
111
129
|
/** CPU shadow of the entire GPU buffer; writes go here first then
|
|
112
130
|
* flush() emits one writeBuffer per dirty contiguous range. */
|
|
113
131
|
private shadow;
|
|
@@ -123,28 +141,25 @@ export declare class AttributeArena {
|
|
|
123
141
|
* Allocate space for one attribute. Returns the byte ref (offset
|
|
124
142
|
* to the header — data lives at ref + 16).
|
|
125
143
|
*/
|
|
144
|
+
/** Non-throwing alloc — returns `undefined` when the request
|
|
145
|
+
* would exceed the underlying GrowBuffer's `maxCapacity` cap.
|
|
146
|
+
* Used by `ChunkedAttributeArena` to probe before spilling to
|
|
147
|
+
* the next chunk. */
|
|
148
|
+
tryAlloc(dataBytes: number): number | undefined;
|
|
126
149
|
alloc(dataBytes: number): number;
|
|
127
150
|
release(ref: number, dataBytes: number): void;
|
|
128
151
|
onResize(cb: () => void): IDisposable;
|
|
129
152
|
destroy(): void;
|
|
130
153
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Insert `{off, size}` into a free-list kept sorted by `off`, then
|
|
133
|
-
* coalesce with the two immediate neighbours.
|
|
134
|
-
*/
|
|
135
|
-
export declare function insertSortedFreeBlock(freeList: {
|
|
136
|
-
off: number;
|
|
137
|
-
size: number;
|
|
138
|
-
}[], off: number, size: number): void;
|
|
139
154
|
/**
|
|
140
155
|
* Element-bump allocator over an index GrowBuffer (units = u32). Each
|
|
141
156
|
* draw's index range is allocated as one block; on release the block
|
|
142
|
-
* is returned to a
|
|
157
|
+
* is returned to a Freelist and can be reused best-fit.
|
|
143
158
|
*/
|
|
144
159
|
export declare class IndexAllocator {
|
|
145
160
|
private readonly buf;
|
|
146
161
|
private cursor;
|
|
147
|
-
private
|
|
162
|
+
private readonly freelist;
|
|
148
163
|
private shadow;
|
|
149
164
|
private dirtyMin;
|
|
150
165
|
private dirtyMax;
|
|
@@ -153,6 +168,10 @@ export declare class IndexAllocator {
|
|
|
153
168
|
get usedElements(): number;
|
|
154
169
|
write(dstByteOffset: number, data: Uint8Array): void;
|
|
155
170
|
flush(device: GPUDevice): void;
|
|
171
|
+
/** Non-throwing alloc — returns `undefined` when the request
|
|
172
|
+
* would exceed the underlying GrowBuffer's `maxCapacity` cap.
|
|
173
|
+
* Used by `ChunkedIndexAllocator` to probe before spilling. */
|
|
174
|
+
tryAlloc(elements: number): number | undefined;
|
|
156
175
|
alloc(elements: number): number;
|
|
157
176
|
release(off: number, elements: number): void;
|
|
158
177
|
onResize(cb: () => void): IDisposable;
|
|
@@ -161,13 +180,17 @@ export declare class IndexAllocator {
|
|
|
161
180
|
/**
|
|
162
181
|
* Global arena state: attribute / uniform data lives in `attrs`
|
|
163
182
|
* (multi-typed-view storage); indices live in `indices` (separate
|
|
164
|
-
* INDEX-usage buffer).
|
|
183
|
+
* INDEX-usage buffer). Both are chunked: each chunk owns a separate
|
|
184
|
+
* GPUBuffer + Freelist. Refs that downstream code stores are byte
|
|
185
|
+
* offsets within a chunk; the chunk identity is carried alongside
|
|
186
|
+
* (via bucket.chunkIdx in heapScene) and made implicit at draw
|
|
187
|
+
* time by which chunk's bind group is active.
|
|
165
188
|
*/
|
|
166
189
|
export interface ArenaState {
|
|
167
|
-
readonly attrs:
|
|
168
|
-
readonly indices:
|
|
190
|
+
readonly attrs: ChunkedAttributeArena;
|
|
191
|
+
readonly indices: ChunkedIndexAllocator;
|
|
169
192
|
}
|
|
170
|
-
export declare function buildArenaState(device: GPUDevice, attrBytesHint: number, idxBytesHint: number, label: string, idxExtraUsage?: GPUBufferUsageFlags): ArenaState;
|
|
193
|
+
export declare function buildArenaState(device: GPUDevice, attrBytesHint: number, idxBytesHint: number, label: string, idxExtraUsage?: GPUBufferUsageFlags, maxChunkBytes?: number | undefined): ArenaState;
|
|
171
194
|
export declare function arenaBytes(arena: ArenaState): number;
|
|
172
195
|
/** Upload a single attribute — header (typeId, length) + data — into the arena at byte offset `ref`. */
|
|
173
196
|
export declare function writeAttribute(device: GPUDevice, buf: GPUBuffer, ref: number, typeId: number, length: number, data: Float32Array): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pools.d.ts","sourceRoot":"","sources":["../../../src/runtime/heapScene/pools.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"pools.d.ts","sourceRoot":"","sources":["../../../src/runtime/heapScene/pools.ts"],"names":[],"mappings":"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"}
|