@aardworx/wombat.rendering 0.9.33 → 0.19.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/dist/core/renderObject.d.ts +16 -0
- package/dist/core/renderObject.d.ts.map +1 -1
- 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/heapAdapter.d.ts.map +1 -1
- package/dist/runtime/heapAdapter.js +17 -0
- package/dist/runtime/heapAdapter.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 +55 -0
- package/dist/runtime/heapScene/freelist.d.ts.map +1 -0
- package/dist/runtime/heapScene/freelist.js +188 -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 +84 -42
- package/dist/runtime/heapScene/pools.d.ts.map +1 -1
- package/dist/runtime/heapScene/pools.js +309 -134
- package/dist/runtime/heapScene/pools.js.map +1 -1
- package/dist/runtime/heapScene.d.ts +24 -0
- package/dist/runtime/heapScene.d.ts.map +1 -1
- package/dist/runtime/heapScene.js +1158 -92
- package/dist/runtime/heapScene.js.map +1 -1
- package/dist/runtime/hybridScene.d.ts +15 -0
- package/dist/runtime/hybridScene.d.ts.map +1 -1
- package/dist/runtime/hybridScene.js +16 -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/dist/runtime/textureAtlas/atlasPool.d.ts +12 -0
- package/dist/runtime/textureAtlas/atlasPool.d.ts.map +1 -1
- package/dist/runtime/textureAtlas/atlasPool.js +20 -0
- package/dist/runtime/textureAtlas/atlasPool.js.map +1 -1
- package/package.json +1 -1
- package/src/core/renderObject.ts +16 -0
- 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/heapAdapter.ts +17 -0
- package/src/runtime/heapEligibility.ts +22 -1
- package/src/runtime/heapScene/chunkedArena.ts +238 -0
- package/src/runtime/heapScene/freelist.ts +196 -0
- package/src/runtime/heapScene/growBuffer.ts +39 -2
- package/src/runtime/heapScene/pools.ts +350 -143
- package/src/runtime/heapScene.ts +1350 -88
- package/src/runtime/hybridScene.ts +31 -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/textureAtlas/atlasPool.ts +19 -0
- package/src/runtime/derivedModes/gpuDispatcher.ts +0 -226
- package/src/runtime/derivedModes/gpuKernel.ts +0 -98
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunkedArena.js","sourceRoot":"","sources":["../../../src/runtime/heapScene/chunkedArena.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A best-fit free-block manager. All offsets and sizes are in the
|
|
3
|
+
* caller's units (bytes for the attribute arena, u32 elements for
|
|
4
|
+
* the index allocator); the freelist doesn't interpret them.
|
|
5
|
+
*/
|
|
6
|
+
export declare class Freelist {
|
|
7
|
+
/** size → set of starting offsets currently free at that size. */
|
|
8
|
+
private readonly bySize;
|
|
9
|
+
/** Sorted ascending list of every size present in `bySize`. */
|
|
10
|
+
private readonly sizes;
|
|
11
|
+
/** off → size, for the right-coalesce probe in `release`. */
|
|
12
|
+
private readonly byStart;
|
|
13
|
+
/** off+size (= end offset) → off, for the left-coalesce probe. */
|
|
14
|
+
private readonly byEnd;
|
|
15
|
+
/** Number of distinct free blocks currently tracked. */
|
|
16
|
+
get blockCount(): number;
|
|
17
|
+
/**
|
|
18
|
+
* Return any offset of a free block whose size is ≥ `size`, splitting
|
|
19
|
+
* off any leftover bytes back into the freelist. Returns `undefined`
|
|
20
|
+
* when no block fits.
|
|
21
|
+
*/
|
|
22
|
+
alloc(size: number): number | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Reintroduce a `(off, size)` block, coalescing with any immediate
|
|
25
|
+
* neighbour on the left (some other block ending at `off`) or right
|
|
26
|
+
* (some other block starting at `off + size`).
|
|
27
|
+
*/
|
|
28
|
+
release(off: number, size: number): void;
|
|
29
|
+
/**
|
|
30
|
+
* Take and remove the free block whose end offset is exactly
|
|
31
|
+
* `endOff`, if any exists. Used by `AttributeArena` /
|
|
32
|
+
* `IndexAllocator` to shrink the bump cursor back when releases
|
|
33
|
+
* expose a free tail (§5 — cursor-shrink hygiene for long-lived
|
|
34
|
+
* high-churn scenes).
|
|
35
|
+
*/
|
|
36
|
+
takeBlockEndingAt(endOff: number): {
|
|
37
|
+
off: number;
|
|
38
|
+
size: number;
|
|
39
|
+
} | undefined;
|
|
40
|
+
/** Drop every block. */
|
|
41
|
+
clear(): void;
|
|
42
|
+
/** Snapshot for tests / debugging — sorted by offset. */
|
|
43
|
+
toArray(): Array<{
|
|
44
|
+
off: number;
|
|
45
|
+
size: number;
|
|
46
|
+
}>;
|
|
47
|
+
/** Internal consistency check (paranoia mode). Walks the freelist
|
|
48
|
+
* and asserts no two blocks overlap. O(N log N). Cheap enough to
|
|
49
|
+
* run after every alloc/release while debugging an allocator
|
|
50
|
+
* invariant violation. Throws with the offending pair on failure. */
|
|
51
|
+
assertInvariants(where: string): void;
|
|
52
|
+
private addBlock;
|
|
53
|
+
private removeBlock;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=freelist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"freelist.d.ts","sourceRoot":"","sources":["../../../src/runtime/heapScene/freelist.ts"],"names":[],"mappings":"AA+BA;;;;GAIG;AACH,qBAAa,QAAQ;IACnB,kEAAkE;IAClE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,+DAA+D;IAC/D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,kEAAkE;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IAEnD,wDAAwD;IACxD,IAAI,UAAU,IAAI,MAAM,CAA8B;IAEtD;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAavC;;;;OAIG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAqBxC;;;;;;OAMG;IACH,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAQ5E,wBAAwB;IACxB,KAAK,IAAI,IAAI;IAOb,yDAAyD;IACzD,OAAO,IAAI,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAO/C;;;0EAGsE;IACtE,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IA+BrC,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,WAAW;CAYpB"}
|
|
@@ -0,0 +1,188 @@
|
|
|
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
|
+
/** Internal consistency check (paranoia mode). Walks the freelist
|
|
122
|
+
* and asserts no two blocks overlap. O(N log N). Cheap enough to
|
|
123
|
+
* run after every alloc/release while debugging an allocator
|
|
124
|
+
* invariant violation. Throws with the offending pair on failure. */
|
|
125
|
+
assertInvariants(where) {
|
|
126
|
+
const blocks = this.toArray();
|
|
127
|
+
for (let i = 1; i < blocks.length; i++) {
|
|
128
|
+
const a = blocks[i - 1];
|
|
129
|
+
const b = blocks[i];
|
|
130
|
+
if (a.off + a.size > b.off) {
|
|
131
|
+
throw new Error(`Freelist@${where}: overlapping free blocks ` +
|
|
132
|
+
`(${a.off},${a.size}) and (${b.off},${b.size}) — ` +
|
|
133
|
+
`${a.off}+${a.size}=${a.off + a.size} > ${b.off}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
for (const [off, size] of this.byStart) {
|
|
137
|
+
const endLookup = this.byEnd.get(off + size);
|
|
138
|
+
if (endLookup !== off) {
|
|
139
|
+
throw new Error(`Freelist@${where}: byStart/byEnd desync — byStart[${off}]=${size} ` +
|
|
140
|
+
`but byEnd[${off + size}]=${endLookup} (expected ${off})`);
|
|
141
|
+
}
|
|
142
|
+
const sizeSet = this.bySize.get(size);
|
|
143
|
+
if (sizeSet === undefined || !sizeSet.has(off)) {
|
|
144
|
+
throw new Error(`Freelist@${where}: byStart/bySize desync — byStart[${off}]=${size} ` +
|
|
145
|
+
`but bySize[${size}] does not contain ${off}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
addBlock(off, size) {
|
|
150
|
+
let set = this.bySize.get(size);
|
|
151
|
+
if (set === undefined) {
|
|
152
|
+
set = new Set();
|
|
153
|
+
this.bySize.set(size, set);
|
|
154
|
+
const idx = lowerBound(this.sizes, size);
|
|
155
|
+
this.sizes.splice(idx, 0, size);
|
|
156
|
+
}
|
|
157
|
+
set.add(off);
|
|
158
|
+
this.byStart.set(off, size);
|
|
159
|
+
this.byEnd.set(off + size, off);
|
|
160
|
+
}
|
|
161
|
+
removeBlock(off, size) {
|
|
162
|
+
const set = this.bySize.get(size);
|
|
163
|
+
if (set === undefined)
|
|
164
|
+
return;
|
|
165
|
+
set.delete(off);
|
|
166
|
+
if (set.size === 0) {
|
|
167
|
+
this.bySize.delete(size);
|
|
168
|
+
const idx = lowerBound(this.sizes, size);
|
|
169
|
+
if (this.sizes[idx] === size)
|
|
170
|
+
this.sizes.splice(idx, 1);
|
|
171
|
+
}
|
|
172
|
+
this.byStart.delete(off);
|
|
173
|
+
this.byEnd.delete(off + size);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/** Index of the first element of `arr` that is `>= target`. */
|
|
177
|
+
function lowerBound(arr, target) {
|
|
178
|
+
let lo = 0, hi = arr.length;
|
|
179
|
+
while (lo < hi) {
|
|
180
|
+
const mid = (lo + hi) >>> 1;
|
|
181
|
+
if (arr[mid] < target)
|
|
182
|
+
lo = mid + 1;
|
|
183
|
+
else
|
|
184
|
+
hi = mid;
|
|
185
|
+
}
|
|
186
|
+
return lo;
|
|
187
|
+
}
|
|
188
|
+
//# 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-
|
|
@@ -87,6 +105,8 @@ export declare class DrawHeap {
|
|
|
87
105
|
private readonly slotBytes;
|
|
88
106
|
private free;
|
|
89
107
|
private nextSlot;
|
|
108
|
+
/** DEBUG: tracks slot live/free state. true = live (in use). */
|
|
109
|
+
private readonly live;
|
|
90
110
|
constructor(buf: GrowBuffer, slotBytes: number);
|
|
91
111
|
get buffer(): GPUBuffer;
|
|
92
112
|
/** Bytes per slot — caller multiplies by slot index for byte offsets. */
|
|
@@ -107,7 +127,12 @@ export declare class DrawHeap {
|
|
|
107
127
|
export declare class AttributeArena {
|
|
108
128
|
private readonly buf;
|
|
109
129
|
private cursor;
|
|
110
|
-
private
|
|
130
|
+
private readonly freelist;
|
|
131
|
+
/** DEBUG: tracks every live allocation by start byte → size. Set
|
|
132
|
+
* on alloc, cleared on release. Used by `assertNoOverlap()` to
|
|
133
|
+
* detect allocator returning overlapping ranges. Enabled in
|
|
134
|
+
* development; cheap (one Map insert/delete per alloc). */
|
|
135
|
+
private readonly liveAllocs;
|
|
111
136
|
/** CPU shadow of the entire GPU buffer; writes go here first then
|
|
112
137
|
* flush() emits one writeBuffer per dirty contiguous range. */
|
|
113
138
|
private shadow;
|
|
@@ -117,34 +142,42 @@ export declare class AttributeArena {
|
|
|
117
142
|
get buffer(): GPUBuffer;
|
|
118
143
|
get capacity(): number;
|
|
119
144
|
get usedBytes(): number;
|
|
145
|
+
/** Read 4 u32s from the CPU shadow starting at byte `off`. Used by
|
|
146
|
+
* the validator to compare against the GPU's read-back values:
|
|
147
|
+
* if CPU shadow is correct but GPU shows garbage → the corruption
|
|
148
|
+
* came from a GPU-side write (a compute kernel writing to a wrong
|
|
149
|
+
* byte). If both differ from what pool.acquire wrote → CPU-side
|
|
150
|
+
* write path is the culprit. */
|
|
151
|
+
peekShadowU32(off: number, count: number): Uint32Array;
|
|
120
152
|
write(dst: number, data: Uint8Array): void;
|
|
121
153
|
flush(device: GPUDevice): void;
|
|
122
154
|
/**
|
|
123
155
|
* Allocate space for one attribute. Returns the byte ref (offset
|
|
124
156
|
* to the header — data lives at ref + 16).
|
|
125
157
|
*/
|
|
158
|
+
/** Non-throwing alloc — returns `undefined` when the request
|
|
159
|
+
* would exceed the underlying GrowBuffer's `maxCapacity` cap.
|
|
160
|
+
* Used by `ChunkedAttributeArena` to probe before spilling to
|
|
161
|
+
* the next chunk. */
|
|
162
|
+
tryAlloc(dataBytes: number): number | undefined;
|
|
126
163
|
alloc(dataBytes: number): number;
|
|
127
164
|
release(ref: number, dataBytes: number): void;
|
|
165
|
+
/** Throws if the just-returned alloc overlaps any live allocation. */
|
|
166
|
+
private recordAlloc;
|
|
128
167
|
onResize(cb: () => void): IDisposable;
|
|
129
168
|
destroy(): void;
|
|
130
169
|
}
|
|
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
170
|
/**
|
|
140
171
|
* Element-bump allocator over an index GrowBuffer (units = u32). Each
|
|
141
172
|
* draw's index range is allocated as one block; on release the block
|
|
142
|
-
* is returned to a
|
|
173
|
+
* is returned to a Freelist and can be reused best-fit.
|
|
143
174
|
*/
|
|
144
175
|
export declare class IndexAllocator {
|
|
145
176
|
private readonly buf;
|
|
146
177
|
private cursor;
|
|
147
|
-
private
|
|
178
|
+
private readonly freelist;
|
|
179
|
+
/** DEBUG: live index allocations tracked by start element. */
|
|
180
|
+
private readonly liveAllocs;
|
|
148
181
|
private shadow;
|
|
149
182
|
private dirtyMin;
|
|
150
183
|
private dirtyMax;
|
|
@@ -153,6 +186,11 @@ export declare class IndexAllocator {
|
|
|
153
186
|
get usedElements(): number;
|
|
154
187
|
write(dstByteOffset: number, data: Uint8Array): void;
|
|
155
188
|
flush(device: GPUDevice): void;
|
|
189
|
+
/** Non-throwing alloc — returns `undefined` when the request
|
|
190
|
+
* would exceed the underlying GrowBuffer's `maxCapacity` cap.
|
|
191
|
+
* Used by `ChunkedIndexAllocator` to probe before spilling. */
|
|
192
|
+
tryAlloc(elements: number): number | undefined;
|
|
193
|
+
private recordAlloc;
|
|
156
194
|
alloc(elements: number): number;
|
|
157
195
|
release(off: number, elements: number): void;
|
|
158
196
|
onResize(cb: () => void): IDisposable;
|
|
@@ -161,13 +199,17 @@ export declare class IndexAllocator {
|
|
|
161
199
|
/**
|
|
162
200
|
* Global arena state: attribute / uniform data lives in `attrs`
|
|
163
201
|
* (multi-typed-view storage); indices live in `indices` (separate
|
|
164
|
-
* INDEX-usage buffer).
|
|
202
|
+
* INDEX-usage buffer). Both are chunked: each chunk owns a separate
|
|
203
|
+
* GPUBuffer + Freelist. Refs that downstream code stores are byte
|
|
204
|
+
* offsets within a chunk; the chunk identity is carried alongside
|
|
205
|
+
* (via bucket.chunkIdx in heapScene) and made implicit at draw
|
|
206
|
+
* time by which chunk's bind group is active.
|
|
165
207
|
*/
|
|
166
208
|
export interface ArenaState {
|
|
167
|
-
readonly attrs:
|
|
168
|
-
readonly indices:
|
|
209
|
+
readonly attrs: ChunkedAttributeArena;
|
|
210
|
+
readonly indices: ChunkedIndexAllocator;
|
|
169
211
|
}
|
|
170
|
-
export declare function buildArenaState(device: GPUDevice, attrBytesHint: number, idxBytesHint: number, label: string, idxExtraUsage?: GPUBufferUsageFlags): ArenaState;
|
|
212
|
+
export declare function buildArenaState(device: GPUDevice, attrBytesHint: number, idxBytesHint: number, label: string, idxExtraUsage?: GPUBufferUsageFlags, maxChunkBytes?: number | undefined): ArenaState;
|
|
171
213
|
export declare function arenaBytes(arena: ArenaState): number;
|
|
172
214
|
/** Upload a single attribute — header (typeId, length) + data — into the arena at byte offset `ref`. */
|
|
173
215
|
export declare function writeAttribute(device: GPUDevice, buf: GPUBuffer, ref: number, typeId: number, length: number, data: Float32Array): void;
|