@aardworx/wombat.rendering 0.19.23 → 0.19.25

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.
Files changed (101) hide show
  1. package/dist/core/elementType.d.ts +2 -0
  2. package/dist/core/elementType.d.ts.map +1 -1
  3. package/dist/core/elementType.js +10 -0
  4. package/dist/core/elementType.js.map +1 -1
  5. package/dist/core/provider.d.ts.map +1 -1
  6. package/dist/core/provider.js +65 -32
  7. package/dist/core/provider.js.map +1 -1
  8. package/dist/core/renderObject.d.ts +9 -0
  9. package/dist/core/renderObject.d.ts.map +1 -1
  10. package/dist/resources/preparedRenderObject.d.ts.map +1 -1
  11. package/dist/resources/preparedRenderObject.js +19 -2
  12. package/dist/resources/preparedRenderObject.js.map +1 -1
  13. package/dist/runtime/derivedModes/modeKeyCpu.d.ts +2 -12
  14. package/dist/runtime/derivedModes/modeKeyCpu.d.ts.map +1 -1
  15. package/dist/runtime/derivedModes/modeKeyCpu.js +30 -13
  16. package/dist/runtime/derivedModes/modeKeyCpu.js.map +1 -1
  17. package/dist/runtime/derivedModes/partitionDispatcher.d.ts +11 -0
  18. package/dist/runtime/derivedModes/partitionDispatcher.d.ts.map +1 -1
  19. package/dist/runtime/derivedModes/partitionDispatcher.js +31 -0
  20. package/dist/runtime/derivedModes/partitionDispatcher.js.map +1 -1
  21. package/dist/runtime/derivedUniforms/dispatch.d.ts +5 -1
  22. package/dist/runtime/derivedUniforms/dispatch.d.ts.map +1 -1
  23. package/dist/runtime/derivedUniforms/dispatch.js +28 -13
  24. package/dist/runtime/derivedUniforms/dispatch.js.map +1 -1
  25. package/dist/runtime/derivedUniforms/records.d.ts +15 -0
  26. package/dist/runtime/derivedUniforms/records.d.ts.map +1 -1
  27. package/dist/runtime/derivedUniforms/records.js +81 -14
  28. package/dist/runtime/derivedUniforms/records.js.map +1 -1
  29. package/dist/runtime/derivedUniforms/sceneIntegration.d.ts +6 -0
  30. package/dist/runtime/derivedUniforms/sceneIntegration.d.ts.map +1 -1
  31. package/dist/runtime/derivedUniforms/sceneIntegration.js +9 -0
  32. package/dist/runtime/derivedUniforms/sceneIntegration.js.map +1 -1
  33. package/dist/runtime/flattenTree.d.ts.map +1 -1
  34. package/dist/runtime/flattenTree.js +46 -2
  35. package/dist/runtime/flattenTree.js.map +1 -1
  36. package/dist/runtime/heapAdapter.d.ts +3 -1
  37. package/dist/runtime/heapAdapter.d.ts.map +1 -1
  38. package/dist/runtime/heapAdapter.js +42 -4
  39. package/dist/runtime/heapAdapter.js.map +1 -1
  40. package/dist/runtime/heapDecoder.d.ts.map +1 -1
  41. package/dist/runtime/heapDecoder.js +8 -3
  42. package/dist/runtime/heapDecoder.js.map +1 -1
  43. package/dist/runtime/heapEffect.d.ts +14 -1
  44. package/dist/runtime/heapEffect.d.ts.map +1 -1
  45. package/dist/runtime/heapEffect.js +13 -1
  46. package/dist/runtime/heapEffect.js.map +1 -1
  47. package/dist/runtime/heapEffectIR.d.ts.map +1 -1
  48. package/dist/runtime/heapEffectIR.js +18 -9
  49. package/dist/runtime/heapEffectIR.js.map +1 -1
  50. package/dist/runtime/heapEligibility.d.ts.map +1 -1
  51. package/dist/runtime/heapEligibility.js +64 -12
  52. package/dist/runtime/heapEligibility.js.map +1 -1
  53. package/dist/runtime/heapIrBuilders.d.ts +8 -0
  54. package/dist/runtime/heapIrBuilders.d.ts.map +1 -1
  55. package/dist/runtime/heapIrBuilders.js +47 -2
  56. package/dist/runtime/heapIrBuilders.js.map +1 -1
  57. package/dist/runtime/heapScene/chunkedArena.d.ts +20 -28
  58. package/dist/runtime/heapScene/chunkedArena.d.ts.map +1 -1
  59. package/dist/runtime/heapScene/chunkedArena.js +28 -91
  60. package/dist/runtime/heapScene/chunkedArena.js.map +1 -1
  61. package/dist/runtime/heapScene/freelist.d.ts +1 -1
  62. package/dist/runtime/heapScene/freelist.js +3 -3
  63. package/dist/runtime/heapScene/freelist.js.map +1 -1
  64. package/dist/runtime/heapScene/pools.d.ts +103 -59
  65. package/dist/runtime/heapScene/pools.d.ts.map +1 -1
  66. package/dist/runtime/heapScene/pools.js +335 -194
  67. package/dist/runtime/heapScene/pools.js.map +1 -1
  68. package/dist/runtime/heapScene.d.ts +116 -1
  69. package/dist/runtime/heapScene.d.ts.map +1 -1
  70. package/dist/runtime/heapScene.js +581 -125
  71. package/dist/runtime/heapScene.js.map +1 -1
  72. package/dist/runtime/hybridScene.d.ts.map +1 -1
  73. package/dist/runtime/hybridScene.js +19 -3
  74. package/dist/runtime/hybridScene.js.map +1 -1
  75. package/dist/runtime/index.d.ts +1 -1
  76. package/dist/runtime/index.d.ts.map +1 -1
  77. package/dist/runtime/index.js +1 -1
  78. package/dist/runtime/index.js.map +1 -1
  79. package/package.json +1 -1
  80. package/src/core/elementType.ts +10 -0
  81. package/src/core/provider.ts +56 -28
  82. package/src/core/renderObject.ts +9 -0
  83. package/src/resources/preparedRenderObject.ts +22 -3
  84. package/src/runtime/derivedModes/modeKeyCpu.ts +26 -11
  85. package/src/runtime/derivedModes/partitionDispatcher.ts +30 -0
  86. package/src/runtime/derivedUniforms/dispatch.ts +26 -10
  87. package/src/runtime/derivedUniforms/records.ts +70 -15
  88. package/src/runtime/derivedUniforms/sceneIntegration.ts +10 -0
  89. package/src/runtime/flattenTree.ts +47 -2
  90. package/src/runtime/heapAdapter.ts +40 -5
  91. package/src/runtime/heapDecoder.ts +8 -3
  92. package/src/runtime/heapEffect.ts +15 -1
  93. package/src/runtime/heapEffectIR.ts +18 -9
  94. package/src/runtime/heapEligibility.ts +39 -12
  95. package/src/runtime/heapIrBuilders.ts +50 -2
  96. package/src/runtime/heapScene/chunkedArena.ts +29 -94
  97. package/src/runtime/heapScene/freelist.ts +3 -3
  98. package/src/runtime/heapScene/pools.ts +340 -218
  99. package/src/runtime/heapScene.ts +717 -141
  100. package/src/runtime/hybridScene.ts +20 -3
  101. package/src/runtime/index.ts +5 -0
@@ -14,7 +14,7 @@
14
14
 
15
15
  import type { IDisposable } from "@aardworx/wombat.adaptive";
16
16
  import { GrowBuffer, DEFAULT_MAX_BUFFER_BYTES } from "./growBuffer.js";
17
- import { AttributeArena, IndexAllocator } from "./pools.js";
17
+ import { AttributeArena } from "./pools.js";
18
18
 
19
19
  /** Address inside a chunked arena. */
20
20
  export interface ChunkedRef {
@@ -46,6 +46,15 @@ export class ChunkedAttributeArena {
46
46
  get chunks(): ReadonlyArray<AttributeArena> { return this._chunks; }
47
47
  chunk(i: number): AttributeArena { return this._chunks[i]!; }
48
48
 
49
+ /** Bump headroom (bytes) of chunk `i` — free space before its cap, used by
50
+ * group placement. Out-of-range → 0. */
51
+ bumpHeadroom(i: number): number {
52
+ return i >= 0 && i < this._chunks.length ? this._chunks[i]!.bumpHeadroom : 0;
53
+ }
54
+ /** Open a fresh empty chunk (page) and return its index. Used by group
55
+ * placement when no existing chunk can hold a draw's whole group. */
56
+ openPage(): number { return this.openChunk(); }
57
+
49
58
  /**
50
59
  * Allocate `dataBytes` of attribute storage. Tries the `hint`
51
60
  * chunk first when given (caller passes the RO's chunk to keep all
@@ -81,12 +90,12 @@ export class ChunkedAttributeArena {
81
90
  c.release(off, dataBytes);
82
91
  }
83
92
 
84
- /** Push the dirty CPU shadow of every chunk to its GPU buffer. */
93
+ /** No-op (mirror-less arena writes upload immediately). Kept for API compat. */
85
94
  flush(device: GPUDevice): void {
86
95
  for (const c of this._chunks) c.flush(device);
87
96
  }
88
97
 
89
- /** Write into a specific chunk's CPU shadow. */
98
+ /** Write into a specific chunk (immediate GPU upload). */
90
99
  write(chunkIdx: number, dst: number, data: Uint8Array): void {
91
100
  this._chunks[chunkIdx]!.write(dst, data);
92
101
  }
@@ -124,100 +133,25 @@ export class ChunkedAttributeArena {
124
133
  return s;
125
134
  }
126
135
 
127
- destroy(): void {
128
- for (const c of this._chunks) c.destroy();
129
- this._chunks.length = 0;
130
- }
131
-
132
- private openChunk(): number {
133
- const idx = this._chunks.length;
134
- const buf = new GrowBuffer(
135
- this.device, `${this.label}/c${idx}`, this.usage,
136
- this.initialChunkBytes, this.maxChunkBytes,
137
- );
138
- this._chunks.push(new AttributeArena(buf));
139
- for (const cb of this.onChunkAddedCbs) cb(idx);
140
- return idx;
141
- }
142
- }
143
-
144
- /** Multi-chunk wrapper around `IndexAllocator`. Element-bump units
145
- * are u32. Same chunk-open / hint / fallback semantics as
146
- * `ChunkedAttributeArena`. */
147
- export class ChunkedIndexAllocator {
148
- private readonly _chunks: IndexAllocator[] = [];
149
- private readonly onChunkAddedCbs = new Set<(chunkIdx: number) => void>();
150
-
151
- constructor(
152
- private readonly device: GPUDevice,
153
- private readonly label: string,
154
- private readonly usage: GPUBufferUsageFlags,
155
- private readonly initialChunkBytes: number,
156
- private readonly maxChunkBytes: number = DEFAULT_MAX_BUFFER_BYTES,
157
- ) {
158
- this.openChunk();
159
- }
160
-
161
- get chunkCount(): number { return this._chunks.length; }
162
- get chunks(): ReadonlyArray<IndexAllocator> { return this._chunks; }
163
- chunk(i: number): IndexAllocator { return this._chunks[i]!; }
164
-
165
- alloc(elements: number, hint?: number): ChunkedRef {
166
- if (hint !== undefined && hint >= 0 && hint < this._chunks.length) {
167
- const off = this._chunks[hint]!.tryAlloc(elements);
168
- if (off !== undefined) return { chunkIdx: hint, off };
169
- }
170
- for (let i = this._chunks.length - 1; i >= 0; i--) {
171
- if (i === hint) continue;
172
- const off = this._chunks[i]!.tryAlloc(elements);
173
- if (off !== undefined) return { chunkIdx: i, off };
174
- }
175
- const newIdx = this.openChunk();
176
- const off = this._chunks[newIdx]!.tryAlloc(elements);
177
- if (off === undefined) {
178
- throw new Error(
179
- `ChunkedIndexAllocator '${this.label}': allocation of ${elements} elements exceeds maxChunkBytes/4 ${this.maxChunkBytes / 4}`,
180
- );
181
- }
182
- return { chunkIdx: newIdx, off };
183
- }
184
-
185
- release(chunkIdx: number, off: number, elements: number): void {
186
- const c = this._chunks[chunkIdx];
187
- if (c === undefined) return;
188
- c.release(off, elements);
189
- }
190
-
191
- flush(device: GPUDevice): void {
192
- for (const c of this._chunks) c.flush(device);
193
- }
194
-
195
- write(chunkIdx: number, dst: number, data: Uint8Array): void {
196
- this._chunks[chunkIdx]!.write(dst, data);
197
- }
198
-
199
- onChunkAdded(cb: (chunkIdx: number) => void): IDisposable {
200
- this.onChunkAddedCbs.add(cb);
201
- return { dispose: () => { this.onChunkAddedCbs.delete(cb); } };
136
+ /** Total fragmentation waste across all chunks (diagnostic / trigger). */
137
+ totalWasteBytes(): number {
138
+ let s = 0;
139
+ for (const c of this._chunks) s += c.wasteBytes;
140
+ return s;
202
141
  }
203
142
 
204
- onAnyResize(cb: (chunkIdx: number) => void): IDisposable {
205
- const disposables: IDisposable[] = [];
143
+ /** Waste-triggered compaction across every chunk. Returns one entry per
144
+ * chunk that actually relocated data — `remap` maps OLD→NEW byte offset
145
+ * within that chunk. Empty array when nothing was worth compacting. The
146
+ * caller must have flushed pending arena writes first (the GPU copy reads
147
+ * the live buffers). */
148
+ compact(device: GPUDevice, wasteFloorBytes: number, force = false): Array<{ chunkIdx: number; remap: Map<number, number> }> {
149
+ const out: Array<{ chunkIdx: number; remap: Map<number, number> }> = [];
206
150
  for (let i = 0; i < this._chunks.length; i++) {
207
- const idx = i;
208
- disposables.push(this._chunks[i]!.onResize(() => cb(idx)));
151
+ const remap = this._chunks[i]!.compact(device, wasteFloorBytes, force);
152
+ if (remap.size > 0) out.push({ chunkIdx: i, remap });
209
153
  }
210
- disposables.push(this.onChunkAdded((idx) => {
211
- disposables.push(this._chunks[idx]!.onResize(() => cb(idx)));
212
- cb(idx);
213
- }));
214
- return { dispose: () => { for (const d of disposables) d.dispose(); } };
215
- }
216
-
217
- totalUsedElements(): number {
218
- let s = 0;
219
- for (const c of this._chunks) s += c.usedElements;
220
- return s;
154
+ return out;
221
155
  }
222
156
 
223
157
  destroy(): void {
@@ -231,8 +165,9 @@ export class ChunkedIndexAllocator {
231
165
  this.device, `${this.label}/c${idx}`, this.usage,
232
166
  this.initialChunkBytes, this.maxChunkBytes,
233
167
  );
234
- this._chunks.push(new IndexAllocator(buf));
168
+ this._chunks.push(new AttributeArena(this.device, buf));
235
169
  for (const cb of this.onChunkAddedCbs) cb(idx);
236
170
  return idx;
237
171
  }
238
172
  }
173
+
@@ -1,5 +1,5 @@
1
- // Freelist — best-fit free-block manager used by AttributeArena and
2
- // IndexAllocator. Replaces the earlier `{off,size}[]` sorted-by-off
1
+ // Freelist — best-fit free-block manager used by AttributeArena.
2
+ // Replaces the earlier `{off,size}[]` sorted-by-off
3
3
  // freelist (whose alloc was O(N) first-fit and release was O(log N)
4
4
  // binary-search-then-coalesce).
5
5
  //
@@ -94,7 +94,7 @@ export class Freelist {
94
94
  /**
95
95
  * Take and remove the free block whose end offset is exactly
96
96
  * `endOff`, if any exists. Used by `AttributeArena` /
97
- * `IndexAllocator` to shrink the bump cursor back when releases
97
+ * `AttributeArena` to shrink the bump cursor back when releases
98
98
  * expose a free tail (§5 — cursor-shrink hygiene for long-lived
99
99
  * high-churn scenes).
100
100
  */