@aardworx/wombat.rendering 0.9.13 → 0.9.15

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 (70) hide show
  1. package/dist/runtime/derivedModes/modeKeyCpu.d.ts +45 -0
  2. package/dist/runtime/derivedModes/modeKeyCpu.d.ts.map +1 -0
  3. package/dist/runtime/derivedModes/modeKeyCpu.js +179 -0
  4. package/dist/runtime/derivedModes/modeKeyCpu.js.map +1 -0
  5. package/dist/runtime/derivedModes/partition.d.ts +36 -0
  6. package/dist/runtime/derivedModes/partition.d.ts.map +1 -0
  7. package/dist/runtime/derivedModes/partition.js +170 -0
  8. package/dist/runtime/derivedModes/partition.js.map +1 -0
  9. package/dist/runtime/derivedModes/slotTable.d.ts +70 -0
  10. package/dist/runtime/derivedModes/slotTable.d.ts.map +1 -0
  11. package/dist/runtime/derivedModes/slotTable.js +130 -0
  12. package/dist/runtime/derivedModes/slotTable.js.map +1 -0
  13. package/dist/runtime/derivedUniforms/marker.d.ts +11 -3
  14. package/dist/runtime/derivedUniforms/marker.d.ts.map +1 -1
  15. package/dist/runtime/derivedUniforms/marker.js +10 -5
  16. package/dist/runtime/derivedUniforms/marker.js.map +1 -1
  17. package/dist/runtime/heapScene/growBuffer.d.ts +33 -0
  18. package/dist/runtime/heapScene/growBuffer.d.ts.map +1 -0
  19. package/dist/runtime/heapScene/growBuffer.js +76 -0
  20. package/dist/runtime/heapScene/growBuffer.js.map +1 -0
  21. package/dist/runtime/heapScene/packers.d.ts +25 -0
  22. package/dist/runtime/heapScene/packers.d.ts.map +1 -0
  23. package/dist/runtime/heapScene/packers.js +111 -0
  24. package/dist/runtime/heapScene/packers.js.map +1 -0
  25. package/dist/runtime/heapScene/pools.d.ts +181 -0
  26. package/dist/runtime/heapScene/pools.d.ts.map +1 -0
  27. package/dist/runtime/heapScene/pools.js +417 -0
  28. package/dist/runtime/heapScene/pools.js.map +1 -0
  29. package/dist/runtime/heapScene/scanKernel.d.ts +11 -0
  30. package/dist/runtime/heapScene/scanKernel.d.ts.map +1 -0
  31. package/dist/runtime/heapScene/scanKernel.js +181 -0
  32. package/dist/runtime/heapScene/scanKernel.js.map +1 -0
  33. package/dist/runtime/heapScene.d.ts.map +1 -1
  34. package/dist/runtime/heapScene.js +228 -937
  35. package/dist/runtime/heapScene.js.map +1 -1
  36. package/dist/runtime/index.d.ts +4 -0
  37. package/dist/runtime/index.d.ts.map +1 -1
  38. package/dist/runtime/index.js +5 -0
  39. package/dist/runtime/index.js.map +1 -1
  40. package/dist/runtime/pipelineCache/bitfield.d.ts +5 -0
  41. package/dist/runtime/pipelineCache/bitfield.d.ts.map +1 -0
  42. package/dist/runtime/pipelineCache/bitfield.js +201 -0
  43. package/dist/runtime/pipelineCache/bitfield.js.map +1 -0
  44. package/dist/runtime/pipelineCache/cache.d.ts +36 -0
  45. package/dist/runtime/pipelineCache/cache.d.ts.map +1 -0
  46. package/dist/runtime/pipelineCache/cache.js +108 -0
  47. package/dist/runtime/pipelineCache/cache.js.map +1 -0
  48. package/dist/runtime/pipelineCache/descriptor.d.ts +58 -0
  49. package/dist/runtime/pipelineCache/descriptor.d.ts.map +1 -0
  50. package/dist/runtime/pipelineCache/descriptor.js +100 -0
  51. package/dist/runtime/pipelineCache/descriptor.js.map +1 -0
  52. package/dist/runtime/pipelineCache/index.d.ts +5 -0
  53. package/dist/runtime/pipelineCache/index.d.ts.map +1 -0
  54. package/dist/runtime/pipelineCache/index.js +12 -0
  55. package/dist/runtime/pipelineCache/index.js.map +1 -0
  56. package/package.json +1 -1
  57. package/src/runtime/derivedModes/modeKeyCpu.ts +213 -0
  58. package/src/runtime/derivedModes/partition.ts +206 -0
  59. package/src/runtime/derivedModes/slotTable.ts +153 -0
  60. package/src/runtime/derivedUniforms/marker.ts +19 -6
  61. package/src/runtime/heapScene/growBuffer.ts +75 -0
  62. package/src/runtime/heapScene/packers.ts +127 -0
  63. package/src/runtime/heapScene/pools.ts +492 -0
  64. package/src/runtime/heapScene/scanKernel.ts +184 -0
  65. package/src/runtime/heapScene.ts +283 -1064
  66. package/src/runtime/index.ts +40 -0
  67. package/src/runtime/pipelineCache/bitfield.ts +225 -0
  68. package/src/runtime/pipelineCache/cache.ts +129 -0
  69. package/src/runtime/pipelineCache/descriptor.ts +150 -0
  70. package/src/runtime/pipelineCache/index.ts +37 -0
@@ -0,0 +1,181 @@
1
+ import type { aval, IDisposable } from "@aardworx/wombat.adaptive";
2
+ import type { BufferView } from "../../core/bufferView.js";
3
+ import type { HostBufferSource } from "../../core/buffer.js";
4
+ import { GrowBuffer } from "./growBuffer.js";
5
+ /** Per-allocation header: (u32 typeId, u32 length). Data follows
6
+ * the header aligned up to 16 bytes (so positions/normals/etc. line
7
+ * up for future vec4 reads). */
8
+ export declare const ALLOC_HEADER_BYTES = 8;
9
+ export declare const ALLOC_HEADER_PAD_TO = 16;
10
+ /** Encoding-tag enum (low 16 bits of typeId). */
11
+ export declare const ENC_V3F_TIGHT = 1;
12
+ /** Semantic-tag enum (high 16 bits of typeId). Optional metadata —
13
+ * the shader doesn't branch on this. */
14
+ export declare const SEM_POSITIONS = 1;
15
+ export declare const SEM_NORMALS = 2;
16
+ interface PoolEntry {
17
+ /** Byte offset into the arena. Data starts at ref + ALLOC_HEADER_PAD_TO. */
18
+ readonly ref: number;
19
+ readonly dataBytes: number;
20
+ readonly typeId: number;
21
+ /** Packer used to refresh the data region on aval marks. */
22
+ readonly pack: (val: unknown, dst: Float32Array, off: number) => void;
23
+ refcount: number;
24
+ }
25
+ /**
26
+ * Aval-keyed pool of arena allocations. One allocation per unique
27
+ * aval (object identity). Two draws referencing the same aval share
28
+ * the allocation; their DrawHeaders carry the same u32 ref. Holds
29
+ * uniforms (fixed-size scalars/vectors/matrices) AND attribute arrays
30
+ * (variable-size). The caller decides `dataBytes` + `length` per
31
+ * acquisition — the pool just keys on aval identity and refcounts.
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.
37
+ */
38
+ export declare class UniformPool {
39
+ private readonly byAval;
40
+ has(av: aval<unknown>): boolean;
41
+ entry(av: aval<unknown>): PoolEntry | undefined;
42
+ /**
43
+ * Acquire (or share) an allocation for `aval`. Caller passes the
44
+ * pre-read `value` (so the pool doesn't need a token) plus the
45
+ * (`dataBytes`, `typeId`, `length`, `pack`) describing how to lay
46
+ * it out. If a new allocation is made, the value is packed and
47
+ * uploaded immediately.
48
+ */
49
+ acquire(device: GPUDevice, arena: AttributeArena, av: aval<unknown>, value: unknown, dataBytes: number, typeId: number, length: number, pack: (val: unknown, dst: Float32Array, off: number) => void): number;
50
+ /** Decrement refcount; if zero, free the arena allocation. */
51
+ release(arena: AttributeArena, av: aval<unknown>): void;
52
+ /** Re-pack one entry's data region into the arena's CPU shadow. */
53
+ repack(device: GPUDevice, arena: AttributeArena, av: aval<unknown>, val: unknown): void;
54
+ }
55
+ /**
56
+ * Aval-keyed pool over the `IndexAllocator`. Two draws referencing
57
+ * the same `Uint32Array` (or aval thereof) share an index range —
58
+ * 19K instanced clones of the same mesh share one allocation, one
59
+ * upload.
60
+ *
61
+ * **Value-equality dedup for constant avals (§5b):** when an
62
+ * incoming aval has `isConstant === true`, the pool also keys by
63
+ * the underlying `ArrayBuffer` tuple `(buffer, byteOffset,
64
+ * byteLength)`. Two distinct constant avals wrapping the same
65
+ * `Uint32Array` view collapse to one allocation.
66
+ */
67
+ export declare class IndexPool {
68
+ private readonly byAval;
69
+ private readonly byValueKey;
70
+ private readonly bufferIds;
71
+ private nextBufferId;
72
+ private bufferIdOf;
73
+ acquire(device: GPUDevice, indices: IndexAllocator, av: aval<Uint32Array>, arr: Uint32Array): {
74
+ firstIndex: number;
75
+ count: number;
76
+ };
77
+ release(indices: IndexAllocator, av: aval<Uint32Array>): void;
78
+ }
79
+ /**
80
+ * Slot-indexed allocator over a GrowBuffer. `slotBytes` is set per-
81
+ * instance — each bucket sizes its DrawHeader from its effect's
82
+ * schema, so a bucket whose layout is e.g. 96 B / slot uses a
83
+ * DrawHeap with `slotBytes=96`.
84
+ */
85
+ export declare class DrawHeap {
86
+ private readonly buf;
87
+ private readonly slotBytes;
88
+ private free;
89
+ private nextSlot;
90
+ constructor(buf: GrowBuffer, slotBytes: number);
91
+ get buffer(): GPUBuffer;
92
+ /** Bytes per slot — caller multiplies by slot index for byte offsets. */
93
+ get bytesPerSlot(): number;
94
+ /** High-water mark in bytes (used to size bind-group entry on rebuild). */
95
+ get usedBytes(): number;
96
+ alloc(): number;
97
+ release(slot: number): void;
98
+ onResize(cb: () => void): IDisposable;
99
+ destroy(): void;
100
+ }
101
+ /**
102
+ * Byte-bump allocator over a GrowBuffer for variable-size attribute
103
+ * allocations. Each allocation gets a 16-byte aligned start (8-byte
104
+ * (typeId, length) header at the start, data 16 bytes in). Frees go
105
+ * onto a sorted free list with coalesce on insert.
106
+ */
107
+ export declare class AttributeArena {
108
+ private readonly buf;
109
+ private cursor;
110
+ private freeList;
111
+ /** CPU shadow of the entire GPU buffer; writes go here first then
112
+ * flush() emits one writeBuffer per dirty contiguous range. */
113
+ private shadow;
114
+ private dirtyMin;
115
+ private dirtyMax;
116
+ constructor(buf: GrowBuffer);
117
+ get buffer(): GPUBuffer;
118
+ get capacity(): number;
119
+ get usedBytes(): number;
120
+ write(dst: number, data: Uint8Array): void;
121
+ flush(device: GPUDevice): void;
122
+ /**
123
+ * Allocate space for one attribute. Returns the byte ref (offset
124
+ * to the header — data lives at ref + 16).
125
+ */
126
+ alloc(dataBytes: number): number;
127
+ release(ref: number, dataBytes: number): void;
128
+ onResize(cb: () => void): IDisposable;
129
+ destroy(): void;
130
+ }
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
+ /**
140
+ * Element-bump allocator over an index GrowBuffer (units = u32). Each
141
+ * draw's index range is allocated as one block; on release the block
142
+ * is returned to a free list and can be reused first-fit.
143
+ */
144
+ export declare class IndexAllocator {
145
+ private readonly buf;
146
+ private cursor;
147
+ private freeList;
148
+ private shadow;
149
+ private dirtyMin;
150
+ private dirtyMax;
151
+ constructor(buf: GrowBuffer);
152
+ get buffer(): GPUBuffer;
153
+ get usedElements(): number;
154
+ write(dstByteOffset: number, data: Uint8Array): void;
155
+ flush(device: GPUDevice): void;
156
+ alloc(elements: number): number;
157
+ release(off: number, elements: number): void;
158
+ onResize(cb: () => void): IDisposable;
159
+ destroy(): void;
160
+ }
161
+ /**
162
+ * Global arena state: attribute / uniform data lives in `attrs`
163
+ * (multi-typed-view storage); indices live in `indices` (separate
164
+ * INDEX-usage buffer).
165
+ */
166
+ export interface ArenaState {
167
+ readonly attrs: AttributeArena;
168
+ readonly indices: IndexAllocator;
169
+ }
170
+ export declare function buildArenaState(device: GPUDevice, attrBytesHint: number, idxBytesHint: number, label: string, idxExtraUsage?: GPUBufferUsageFlags): ArenaState;
171
+ export declare function arenaBytes(arena: ArenaState): number;
172
+ /** Upload a single attribute — header (typeId, length) + data — into the arena at byte offset `ref`. */
173
+ export declare function writeAttribute(device: GPUDevice, buf: GPUBuffer, ref: number, typeId: number, length: number, data: Float32Array): void;
174
+ export declare function asAval<T>(v: aval<T> | T): aval<T>;
175
+ /** Heuristic predicate — BufferView has `buffer: aval<IBuffer>` + elementType. */
176
+ export declare function isBufferView(v: unknown): v is BufferView;
177
+ /** Float32 view over a host-side buffer source. Used by the BufferView
178
+ * packer to hand the pool a typed array it can `set()` from. */
179
+ export declare function asFloat32(data: HostBufferSource): Float32Array;
180
+ export {};
181
+ //# sourceMappingURL=pools.d.ts.map
@@ -0,0 +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,EAAW,MAAM,iBAAiB,CAAC;AAItD;;iCAEiC;AACjC,eAAO,MAAM,kBAAkB,IAAM,CAAC;AACtC,eAAO,MAAM,mBAAmB,KAAM,CAAC;AAEvC,iDAAiD;AACjD,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B;yCACyC;AACzC,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,eAAO,MAAM,WAAW,IAAM,CAAC;AAI/B,UAAU,SAAS;IACjB,4EAA4E;IAC5E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACtE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAW;IAKtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAE9D,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,OAAO;IAC/B,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,SAAS;IAE/C;;;;;;OAMG;IACH,OAAO,CACL,MAAM,EAAE,SAAS,EACjB,KAAK,EAAE,cAAc,EACrB,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,EACjB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,GAC3D,MAAM;IAuBT,8DAA8D;IAC9D,OAAO,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI;IASvD,mEAAmE;IACnE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,OAAO,GAAG,IAAI;CAWxF;AAID;;;;;;;;;;;GAWG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAGnB;IACJ,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqC;IAChE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0C;IACpE,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,UAAU;IASlB,OAAO,CACL,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,cAAc,EACvB,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,EACrB,GAAG,EAAE,WAAW,GACf;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE;IA6BxC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI;CAY9D;AAWD;;;;;GAKG;AACH,qBAAa,QAAQ;IAGP,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAc,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFxE,OAAO,CAAC,IAAI,CAAgB;IAC5B,OAAO,CAAC,QAAQ,CAAK;gBACQ,GAAG,EAAE,UAAU,EAAmB,SAAS,EAAE,MAAM;IAChF,IAAI,MAAM,IAAI,SAAS,CAA4B;IACnD,yEAAyE;IACzE,IAAI,YAAY,IAAI,MAAM,CAA2B;IACrD,2EAA2E;IAC3E,IAAI,SAAS,IAAI,MAAM,CAA2C;IAClE,KAAK,IAAI,MAAM;IAMf,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,WAAW;IACrC,OAAO,IAAI,IAAI;CAChB;AAID;;;;;GAKG;AACH,qBAAa,cAAc;IAQb,OAAO,CAAC,QAAQ,CAAC,GAAG;IAPhC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAuC;IACvD;oEACgE;IAChE,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,QAAQ,CAAK;gBACQ,GAAG,EAAE,UAAU;IAQ5C,IAAI,MAAM,IAAI,SAAS,CAA4B;IACnD,IAAI,QAAQ,IAAI,MAAM,CAA8B;IACpD,IAAI,SAAS,IAAI,MAAM,CAAwB;IAC/C,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAM1C,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAU9B;;;OAGG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAkBhC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAI7C,QAAQ,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,WAAW;IACrC,OAAO,IAAI,IAAI;CAChB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,EACzC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,IAAI,CAwBN;AAID;;;;GAIG;AACH,qBAAa,cAAc;IAMb,OAAO,CAAC,QAAQ,CAAC,GAAG;IALhC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAuC;IACvD,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,QAAQ,CAAK;gBACQ,GAAG,EAAE,UAAU;IAQ5C,IAAI,MAAM,IAAI,SAAS,CAA4B;IACnD,IAAI,YAAY,IAAI,MAAM,CAAwB;IAClD,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAMpD,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAU9B,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;IAgB/B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAG5C,QAAQ,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,WAAW;IACrC,OAAO,IAAI,IAAI;CAChB;AAID;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAK,cAAc,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAG,cAAc,CAAC;CACnC;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EACjB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,aAAa,GAAE,mBAAuB,GACrC,UAAU,CAUZ;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEpD;AAED,wGAAwG;AACxG,wBAAgB,cAAc,CAC5B,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GACjG,IAAI,CASN;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAIjD;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,UAAU,CAMxD;AAED;iEACiE;AACjE,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CAM9D"}
@@ -0,0 +1,417 @@
1
+ // Arena + pool allocators that back the heap renderer's per-RO
2
+ // storage. Pulled out of heapScene.ts as a unit because the five
3
+ // classes here are tightly interleaved:
4
+ //
5
+ // AttributeArena — byte-bump over a STORAGE GrowBuffer
6
+ // IndexAllocator — element-bump over an INDEX GrowBuffer
7
+ // DrawHeap — slot-indexed allocator over a STORAGE GrowBuffer
8
+ // (one slot per RO drawHeader)
9
+ // UniformPool — aval-keyed refcounted alloc on top of AttributeArena
10
+ // IndexPool — aval-keyed refcounted alloc on top of IndexAllocator,
11
+ // with value-tuple dedup for constant avals (§5b).
12
+ //
13
+ // Plus the per-allocation header constants used by all of them and
14
+ // the `buildArenaState` / `arenaBytes` / `writeAttribute` / `asAval`
15
+ // / `isBufferView` / `asFloat32` helpers that the heap-scene factory
16
+ // uses to assemble the arena.
17
+ import { AVal } from "@aardworx/wombat.adaptive";
18
+ import { GrowBuffer, ALIGN16 } from "./growBuffer.js";
19
+ // ─── Per-allocation header layout ──────────────────────────────────────
20
+ /** Per-allocation header: (u32 typeId, u32 length). Data follows
21
+ * the header aligned up to 16 bytes (so positions/normals/etc. line
22
+ * up for future vec4 reads). */
23
+ export const ALLOC_HEADER_BYTES = 8;
24
+ export const ALLOC_HEADER_PAD_TO = 16;
25
+ /** Encoding-tag enum (low 16 bits of typeId). */
26
+ export const ENC_V3F_TIGHT = 1; // tightly-packed array of vec3<f32> (12 B/elt)
27
+ /** Semantic-tag enum (high 16 bits of typeId). Optional metadata —
28
+ * the shader doesn't branch on this. */
29
+ export const SEM_POSITIONS = 1;
30
+ export const SEM_NORMALS = 2;
31
+ /**
32
+ * Aval-keyed pool of arena allocations. One allocation per unique
33
+ * aval (object identity). Two draws referencing the same aval share
34
+ * the allocation; their DrawHeaders carry the same u32 ref. Holds
35
+ * uniforms (fixed-size scalars/vectors/matrices) AND attribute arrays
36
+ * (variable-size). The caller decides `dataBytes` + `length` per
37
+ * acquisition — the pool just keys on aval identity and refcounts.
38
+ *
39
+ * Sharing emerges from aval identity — no separate "frequency"
40
+ * declaration needed. A `cval` shared by all draws → 1 alloc.
41
+ * A static positions array shared across instanced draws → 1 alloc.
42
+ * Same code path either way.
43
+ */
44
+ export class UniformPool {
45
+ // Keyed by `aval<unknown>` *by reference* (a plain JS `Map`). These
46
+ // keys are overwhelmingly reactive `cval`s (per-object trafos,
47
+ // colours, …) and the hot path is `acquire`/`release` ~once per
48
+ // drawHeader field per RO.
49
+ byAval = new Map();
50
+ has(av) { return this.byAval.has(av); }
51
+ entry(av) { return this.byAval.get(av); }
52
+ /**
53
+ * Acquire (or share) an allocation for `aval`. Caller passes the
54
+ * pre-read `value` (so the pool doesn't need a token) plus the
55
+ * (`dataBytes`, `typeId`, `length`, `pack`) describing how to lay
56
+ * it out. If a new allocation is made, the value is packed and
57
+ * uploaded immediately.
58
+ */
59
+ acquire(device, arena, av, value, dataBytes, typeId, length, pack) {
60
+ const existing = this.byAval.get(av);
61
+ if (existing !== undefined) {
62
+ existing.refcount++;
63
+ return existing.ref;
64
+ }
65
+ const ref = arena.alloc(dataBytes);
66
+ const allocBytes = ALIGN16(ALLOC_HEADER_PAD_TO + dataBytes);
67
+ const buf = new ArrayBuffer(allocBytes);
68
+ const u32 = new Uint32Array(buf);
69
+ const f32 = new Float32Array(buf);
70
+ u32[0] = typeId;
71
+ u32[1] = length;
72
+ // stride_bytes (offset 8): bytes per element. Lets the VS decode
73
+ // pick V3- vs V4-tight load expressions for vec4 attributes.
74
+ u32[2] = length > 0 ? Math.floor(dataBytes / length) : 0;
75
+ pack(value, f32, ALLOC_HEADER_PAD_TO / 4);
76
+ arena.write(ref, new Uint8Array(buf));
77
+ void device;
78
+ this.byAval.set(av, { ref, dataBytes, typeId, pack, refcount: 1 });
79
+ return ref;
80
+ }
81
+ /** Decrement refcount; if zero, free the arena allocation. */
82
+ release(arena, av) {
83
+ const e = this.byAval.get(av);
84
+ if (e === undefined)
85
+ return;
86
+ e.refcount--;
87
+ if (e.refcount > 0)
88
+ return;
89
+ arena.release(e.ref, ALIGN16(ALLOC_HEADER_PAD_TO + e.dataBytes));
90
+ this.byAval.delete(av);
91
+ }
92
+ /** Re-pack one entry's data region into the arena's CPU shadow. */
93
+ repack(device, arena, av, val) {
94
+ const e = this.byAval.get(av);
95
+ if (e === undefined)
96
+ return;
97
+ const dst = new Float32Array(e.dataBytes / 4);
98
+ e.pack(val, dst, 0);
99
+ arena.write(e.ref + ALLOC_HEADER_PAD_TO, new Uint8Array(dst.buffer, dst.byteOffset, e.dataBytes));
100
+ void device;
101
+ }
102
+ }
103
+ // ─── IndexPool ─────────────────────────────────────────────────────────
104
+ /**
105
+ * Aval-keyed pool over the `IndexAllocator`. Two draws referencing
106
+ * the same `Uint32Array` (or aval thereof) share an index range —
107
+ * 19K instanced clones of the same mesh share one allocation, one
108
+ * upload.
109
+ *
110
+ * **Value-equality dedup for constant avals (§5b):** when an
111
+ * incoming aval has `isConstant === true`, the pool also keys by
112
+ * the underlying `ArrayBuffer` tuple `(buffer, byteOffset,
113
+ * byteLength)`. Two distinct constant avals wrapping the same
114
+ * `Uint32Array` view collapse to one allocation.
115
+ */
116
+ export class IndexPool {
117
+ byAval = new Map();
118
+ byValueKey = new Map();
119
+ bufferIds = new WeakMap();
120
+ nextBufferId = 1;
121
+ bufferIdOf(buf) {
122
+ let id = this.bufferIds.get(buf);
123
+ if (id === undefined) {
124
+ id = this.nextBufferId++;
125
+ this.bufferIds.set(buf, id);
126
+ }
127
+ return id;
128
+ }
129
+ acquire(device, indices, av, arr) {
130
+ const bound = this.byAval.get(av);
131
+ if (bound !== undefined) {
132
+ bound.perAvalCount++;
133
+ bound.entry.totalRefcount++;
134
+ return { firstIndex: bound.entry.firstIndex, count: bound.entry.count };
135
+ }
136
+ let valueKey;
137
+ if (av.isConstant) {
138
+ valueKey = `${this.bufferIdOf(arr.buffer)}:${arr.byteOffset}:${arr.byteLength}`;
139
+ const shared = this.byValueKey.get(valueKey);
140
+ if (shared !== undefined) {
141
+ shared.totalRefcount++;
142
+ this.byAval.set(av, { entry: shared, perAvalCount: 1 });
143
+ return { firstIndex: shared.firstIndex, count: shared.count };
144
+ }
145
+ }
146
+ const firstIndex = indices.alloc(arr.length);
147
+ indices.write(firstIndex * 4, new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength));
148
+ void device;
149
+ const entry = { firstIndex, count: arr.length, totalRefcount: 1, valueKey };
150
+ this.byAval.set(av, { entry, perAvalCount: 1 });
151
+ if (valueKey !== undefined)
152
+ this.byValueKey.set(valueKey, entry);
153
+ return { firstIndex, count: arr.length };
154
+ }
155
+ release(indices, av) {
156
+ const bound = this.byAval.get(av);
157
+ if (bound === undefined)
158
+ return;
159
+ bound.perAvalCount--;
160
+ bound.entry.totalRefcount--;
161
+ if (bound.perAvalCount === 0)
162
+ this.byAval.delete(av);
163
+ if (bound.entry.totalRefcount > 0)
164
+ return;
165
+ indices.release(bound.entry.firstIndex, bound.entry.count);
166
+ if (bound.entry.valueKey !== undefined) {
167
+ this.byValueKey.delete(bound.entry.valueKey);
168
+ }
169
+ }
170
+ }
171
+ // ─── DrawHeap (slot-indexed) ───────────────────────────────────────────
172
+ /**
173
+ * Slot-indexed allocator over a GrowBuffer. `slotBytes` is set per-
174
+ * instance — each bucket sizes its DrawHeader from its effect's
175
+ * schema, so a bucket whose layout is e.g. 96 B / slot uses a
176
+ * DrawHeap with `slotBytes=96`.
177
+ */
178
+ export class DrawHeap {
179
+ buf;
180
+ slotBytes;
181
+ free = [];
182
+ nextSlot = 0;
183
+ constructor(buf, slotBytes) {
184
+ this.buf = buf;
185
+ this.slotBytes = slotBytes;
186
+ }
187
+ get buffer() { return this.buf.buffer; }
188
+ /** Bytes per slot — caller multiplies by slot index for byte offsets. */
189
+ get bytesPerSlot() { return this.slotBytes; }
190
+ /** High-water mark in bytes (used to size bind-group entry on rebuild). */
191
+ get usedBytes() { return this.nextSlot * this.slotBytes; }
192
+ alloc() {
193
+ const slot = this.free.length > 0 ? this.free.pop() : this.nextSlot++;
194
+ this.buf.ensureCapacity((slot + 1) * this.slotBytes);
195
+ this.buf.setUsed(Math.max(this.buf.usedBytes, (slot + 1) * this.slotBytes));
196
+ return slot;
197
+ }
198
+ release(slot) { this.free.push(slot); }
199
+ onResize(cb) { return this.buf.onResize(cb); }
200
+ destroy() { this.buf.destroy(); }
201
+ }
202
+ // ─── AttributeArena (byte-bump) ────────────────────────────────────────
203
+ /**
204
+ * Byte-bump allocator over a GrowBuffer for variable-size attribute
205
+ * allocations. Each allocation gets a 16-byte aligned start (8-byte
206
+ * (typeId, length) header at the start, data 16 bytes in). Frees go
207
+ * onto a sorted free list with coalesce on insert.
208
+ */
209
+ export class AttributeArena {
210
+ buf;
211
+ cursor = 0;
212
+ freeList = [];
213
+ /** CPU shadow of the entire GPU buffer; writes go here first then
214
+ * flush() emits one writeBuffer per dirty contiguous range. */
215
+ shadow;
216
+ dirtyMin = Infinity;
217
+ dirtyMax = 0;
218
+ constructor(buf) {
219
+ this.buf = buf;
220
+ this.shadow = new Uint8Array(buf.capacity);
221
+ buf.onResize(() => {
222
+ const grown = new Uint8Array(buf.capacity);
223
+ grown.set(this.shadow);
224
+ this.shadow = grown;
225
+ });
226
+ }
227
+ get buffer() { return this.buf.buffer; }
228
+ get capacity() { return this.buf.capacity; }
229
+ get usedBytes() { return this.cursor; }
230
+ write(dst, data) {
231
+ this.shadow.set(data, dst);
232
+ if (dst < this.dirtyMin)
233
+ this.dirtyMin = dst;
234
+ const end = dst + data.byteLength;
235
+ if (end > this.dirtyMax)
236
+ this.dirtyMax = end;
237
+ }
238
+ flush(device) {
239
+ if (this.dirtyMax <= this.dirtyMin)
240
+ return;
241
+ device.queue.writeBuffer(this.buf.buffer, this.dirtyMin, this.shadow.buffer, this.shadow.byteOffset + this.dirtyMin, this.dirtyMax - this.dirtyMin);
242
+ this.dirtyMin = Infinity;
243
+ this.dirtyMax = 0;
244
+ }
245
+ /**
246
+ * Allocate space for one attribute. Returns the byte ref (offset
247
+ * to the header — data lives at ref + 16).
248
+ */
249
+ alloc(dataBytes) {
250
+ const allocBytes = ALIGN16(ALLOC_HEADER_PAD_TO + dataBytes);
251
+ // First-fit reuse from free list.
252
+ for (let i = 0; i < this.freeList.length; i++) {
253
+ const f = this.freeList[i];
254
+ if (f.size >= allocBytes) {
255
+ const ref = f.off;
256
+ if (f.size === allocBytes)
257
+ this.freeList.splice(i, 1);
258
+ else {
259
+ f.off += allocBytes;
260
+ f.size -= allocBytes;
261
+ }
262
+ return ref;
263
+ }
264
+ }
265
+ const ref = this.cursor;
266
+ this.cursor += allocBytes;
267
+ this.buf.ensureCapacity(this.cursor);
268
+ this.buf.setUsed(this.cursor);
269
+ return ref;
270
+ }
271
+ release(ref, dataBytes) {
272
+ const allocBytes = ALIGN16(ALLOC_HEADER_PAD_TO + dataBytes);
273
+ insertSortedFreeBlock(this.freeList, ref, allocBytes);
274
+ }
275
+ onResize(cb) { return this.buf.onResize(cb); }
276
+ destroy() { this.buf.destroy(); }
277
+ }
278
+ /**
279
+ * Insert `{off, size}` into a free-list kept sorted by `off`, then
280
+ * coalesce with the two immediate neighbours.
281
+ */
282
+ export function insertSortedFreeBlock(freeList, off, size) {
283
+ let lo = 0, hi = freeList.length;
284
+ while (lo < hi) {
285
+ const mid = (lo + hi) >>> 1;
286
+ if (freeList[mid].off <= off)
287
+ lo = mid + 1;
288
+ else
289
+ hi = mid;
290
+ }
291
+ const prev = lo > 0 ? freeList[lo - 1] : undefined;
292
+ if (prev !== undefined && prev.off + prev.size === off) {
293
+ prev.size += size;
294
+ const next = freeList[lo];
295
+ if (next !== undefined && prev.off + prev.size === next.off) {
296
+ prev.size += next.size;
297
+ freeList.splice(lo, 1);
298
+ }
299
+ return;
300
+ }
301
+ const next = freeList[lo];
302
+ if (next !== undefined && off + size === next.off) {
303
+ next.off = off;
304
+ next.size += size;
305
+ return;
306
+ }
307
+ freeList.splice(lo, 0, { off, size });
308
+ }
309
+ // ─── IndexAllocator (element-bump) ─────────────────────────────────────
310
+ /**
311
+ * Element-bump allocator over an index GrowBuffer (units = u32). Each
312
+ * draw's index range is allocated as one block; on release the block
313
+ * is returned to a free list and can be reused first-fit.
314
+ */
315
+ export class IndexAllocator {
316
+ buf;
317
+ cursor = 0; // in u32s, not bytes
318
+ freeList = [];
319
+ shadow;
320
+ dirtyMin = Infinity;
321
+ dirtyMax = 0;
322
+ constructor(buf) {
323
+ this.buf = buf;
324
+ this.shadow = new Uint8Array(buf.capacity);
325
+ buf.onResize(() => {
326
+ const grown = new Uint8Array(buf.capacity);
327
+ grown.set(this.shadow);
328
+ this.shadow = grown;
329
+ });
330
+ }
331
+ get buffer() { return this.buf.buffer; }
332
+ get usedElements() { return this.cursor; }
333
+ write(dstByteOffset, data) {
334
+ this.shadow.set(data, dstByteOffset);
335
+ if (dstByteOffset < this.dirtyMin)
336
+ this.dirtyMin = dstByteOffset;
337
+ const end = dstByteOffset + data.byteLength;
338
+ if (end > this.dirtyMax)
339
+ this.dirtyMax = end;
340
+ }
341
+ flush(device) {
342
+ if (this.dirtyMax <= this.dirtyMin)
343
+ return;
344
+ device.queue.writeBuffer(this.buf.buffer, this.dirtyMin, this.shadow.buffer, this.shadow.byteOffset + this.dirtyMin, this.dirtyMax - this.dirtyMin);
345
+ this.dirtyMin = Infinity;
346
+ this.dirtyMax = 0;
347
+ }
348
+ alloc(elements) {
349
+ for (let i = 0; i < this.freeList.length; i++) {
350
+ const f = this.freeList[i];
351
+ if (f.size >= elements) {
352
+ const off = f.off;
353
+ if (f.size === elements)
354
+ this.freeList.splice(i, 1);
355
+ else {
356
+ f.off += elements;
357
+ f.size -= elements;
358
+ }
359
+ return off;
360
+ }
361
+ }
362
+ const off = this.cursor;
363
+ this.cursor += elements;
364
+ this.buf.ensureCapacity(this.cursor * 4);
365
+ this.buf.setUsed(this.cursor * 4);
366
+ return off;
367
+ }
368
+ release(off, elements) {
369
+ insertSortedFreeBlock(this.freeList, off, elements);
370
+ }
371
+ onResize(cb) { return this.buf.onResize(cb); }
372
+ destroy() { this.buf.destroy(); }
373
+ }
374
+ export function buildArenaState(device, attrBytesHint, idxBytesHint, label, idxExtraUsage = 0) {
375
+ const attrs = new AttributeArena(new GrowBuffer(device, `${label}/attrs`, GPUBufferUsage.STORAGE, attrBytesHint));
376
+ const indices = new IndexAllocator(new GrowBuffer(device, `${label}/idx`, GPUBufferUsage.INDEX | idxExtraUsage, idxBytesHint));
377
+ return { attrs, indices };
378
+ }
379
+ export function arenaBytes(arena) {
380
+ return arena.attrs.usedBytes + arena.indices.usedElements * 4;
381
+ }
382
+ /** Upload a single attribute — header (typeId, length) + data — into the arena at byte offset `ref`. */
383
+ export function writeAttribute(device, buf, ref, typeId, length, data) {
384
+ const allocBytes = ALIGN16(ALLOC_HEADER_PAD_TO + data.byteLength);
385
+ const staging = new ArrayBuffer(allocBytes);
386
+ const u32 = new Uint32Array(staging);
387
+ const f32 = new Float32Array(staging);
388
+ u32[0] = typeId;
389
+ u32[1] = length;
390
+ f32.set(data, ALLOC_HEADER_PAD_TO / 4);
391
+ device.queue.writeBuffer(buf, ref, staging, 0, allocBytes);
392
+ }
393
+ export function asAval(v) {
394
+ return (typeof v === "object" && v !== null && typeof v.getValue === "function")
395
+ ? v
396
+ : AVal.constant(v);
397
+ }
398
+ /** Heuristic predicate — BufferView has `buffer: aval<IBuffer>` + elementType. */
399
+ export function isBufferView(v) {
400
+ if (typeof v !== "object" || v === null)
401
+ return false;
402
+ const o = v;
403
+ return typeof o.buffer === "object" && o.buffer !== null
404
+ && typeof o.buffer.getValue === "function"
405
+ && typeof o.elementType === "object" && o.elementType !== null;
406
+ }
407
+ /** Float32 view over a host-side buffer source. Used by the BufferView
408
+ * packer to hand the pool a typed array it can `set()` from. */
409
+ export function asFloat32(data) {
410
+ if (data instanceof Float32Array)
411
+ return data;
412
+ if (ArrayBuffer.isView(data)) {
413
+ return new Float32Array(data.buffer, data.byteOffset, data.byteLength / 4);
414
+ }
415
+ return new Float32Array(data); // ArrayBuffer
416
+ }
417
+ //# sourceMappingURL=pools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pools.js","sourceRoot":"","sources":["../../../src/runtime/heapScene/pools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare const SCAN_TILE_SIZE = 512;
2
+ export declare const SCAN_WG_SIZE = 256;
3
+ /** numBlocks ≤ TILE_SIZE — single-pass blockOffsets fits in shared memory. */
4
+ export declare const SCAN_MAX_RECORDS: number;
5
+ /** Tile size for the firstDrawInTile binary-search-fold index. */
6
+ export declare const TILE_K = 64;
7
+ /** drawTable record width: (firstEmit, drawIdx, indexStart, indexCount, instanceCount). */
8
+ export declare const RECORD_U32 = 5;
9
+ export declare const RECORD_BYTES: number;
10
+ export declare const HEAP_SCAN_WGSL = "\nstruct Params {\n numRecords: u32,\n numBlocks: u32,\n _pad0: u32,\n _pad1: u32,\n};\n\nstruct Record {\n firstEmit: u32,\n drawIdx: u32,\n indexStart: u32,\n indexCount: u32,\n instanceCount: u32,\n};\n\n@group(0) @binding(0) var<storage, read_write> drawTable: array<Record>;\n@group(0) @binding(1) var<storage, read_write> blockSums: array<u32>;\n@group(0) @binding(2) var<storage, read_write> blockOffsets: array<u32>;\n@group(0) @binding(3) var<storage, read_write> indirect: array<u32>;\n@group(0) @binding(4) var<uniform> params: Params;\n@group(0) @binding(5) var<storage, read_write> firstDrawInTile: array<u32>;\n\nconst TILE_SIZE: u32 = 512u;\nconst WG_SIZE: u32 = 256u;\nconst TILE_K: u32 = 64u;\n\nvar<workgroup> sdata: array<u32, 512>;\n\nfn blellochScan(tid: u32) {\n var offset: u32 = 1u;\n for (var d: u32 = TILE_SIZE >> 1u; d > 0u; d = d >> 1u) {\n workgroupBarrier();\n if (tid < d) {\n let ai = offset * (2u * tid + 1u) - 1u;\n let bi = offset * (2u * tid + 2u) - 1u;\n sdata[bi] = sdata[bi] + sdata[ai];\n }\n offset = offset * 2u;\n }\n if (tid == 0u) { sdata[TILE_SIZE - 1u] = 0u; }\n for (var d: u32 = 1u; d < TILE_SIZE; d = d * 2u) {\n offset = offset >> 1u;\n workgroupBarrier();\n if (tid < d) {\n let ai = offset * (2u * tid + 1u) - 1u;\n let bi = offset * (2u * tid + 2u) - 1u;\n let t = sdata[ai];\n sdata[ai] = sdata[bi];\n sdata[bi] = sdata[bi] + t;\n }\n }\n workgroupBarrier();\n}\n\n@compute @workgroup_size(WG_SIZE)\nfn scanTile(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wgid: vec3<u32>) {\n let tid = lid.x;\n let blockOff = wgid.x * TILE_SIZE;\n let n = params.numRecords;\n let i0 = blockOff + tid;\n let i1 = blockOff + tid + WG_SIZE;\n var v0: u32 = 0u;\n var v1: u32 = 0u;\n if (i0 < n) { v0 = drawTable[i0].indexCount * drawTable[i0].instanceCount; }\n if (i1 < n) { v1 = drawTable[i1].indexCount * drawTable[i1].instanceCount; }\n sdata[tid] = v0;\n sdata[tid + WG_SIZE] = v1;\n workgroupBarrier();\n blellochScan(tid);\n if (i0 < n) { drawTable[i0].firstEmit = sdata[tid]; }\n if (i1 < n) { drawTable[i1].firstEmit = sdata[tid + WG_SIZE]; }\n if (tid == WG_SIZE - 1u) {\n blockSums[wgid.x] = sdata[tid + WG_SIZE] + v1;\n }\n}\n\n@compute @workgroup_size(WG_SIZE)\nfn scanBlocks(@builtin(local_invocation_id) lid: vec3<u32>) {\n let tid = lid.x;\n let n = params.numBlocks;\n let i0 = tid;\n let i1 = tid + WG_SIZE;\n var v0: u32 = 0u;\n var v1: u32 = 0u;\n if (i0 < n) { v0 = blockSums[i0]; }\n if (i1 < n) { v1 = blockSums[i1]; }\n sdata[tid] = v0;\n sdata[tid + WG_SIZE] = v1;\n workgroupBarrier();\n blellochScan(tid);\n if (i0 < n) { blockOffsets[i0] = sdata[tid]; }\n if (i1 < n) { blockOffsets[i1] = sdata[tid + WG_SIZE]; }\n workgroupBarrier();\n if (tid == 0u) {\n if (n > 0u) {\n let lastIdx = n - 1u;\n let total = blockOffsets[lastIdx] + blockSums[lastIdx];\n indirect[0] = total;\n } else {\n indirect[0] = 0u;\n }\n indirect[1] = 1u;\n indirect[2] = 0u;\n indirect[3] = 0u;\n }\n}\n\n@compute @workgroup_size(WG_SIZE)\nfn addOffsets(@builtin(local_invocation_id) lid: vec3<u32>, @builtin(workgroup_id) wgid: vec3<u32>) {\n let tid = lid.x;\n let blockOff = wgid.x * TILE_SIZE;\n let n = params.numRecords;\n let off = blockOffsets[wgid.x];\n let i0 = blockOff + tid;\n let i1 = blockOff + tid + WG_SIZE;\n if (i0 < n) { drawTable[i0].firstEmit = drawTable[i0].firstEmit + off; }\n if (i1 < n) { drawTable[i1].firstEmit = drawTable[i1].firstEmit + off; }\n}\n\n@compute @workgroup_size(WG_SIZE)\nfn buildTileIndex(@builtin(global_invocation_id) gid: vec3<u32>) {\n let tileIdx = gid.x;\n // totalEmit is computed by scanBlocks into indirect[0]; reading it\n // from indirect avoids a separate uniform/storage round-trip.\n let totalEmit = indirect[0];\n let numTiles = (totalEmit + TILE_K - 1u) / TILE_K;\n if (tileIdx > numTiles) { return; }\n if (params.numRecords == 0u) {\n if (tileIdx == 0u) { firstDrawInTile[0] = 0u; }\n return;\n }\n if (tileIdx == numTiles) {\n // Sentinel for the open upper bound \u2014 the LAST VALID SLOT, not\n // numRecords. The render VS uses\n // hi = firstDrawInTile[_tileIdx + 1u]\n // and the binary search treats hi as INCLUSIVE. If the sentinel\n // were numRecords (one past last), the search would drag lo into\n // the OOB slot for emits in the last tile, since drawTable reads\n // past recordCount return 0 (binding size clamping) and 0 \u2264 emit\n // is always true. Visible symptom: the LAST few emits in the\n // bucket land on slot=numRecords (drawIdx=0, indexCount=0 \u2192 /-by-\n // zero) \u2192 degenerate / cross-RO triangle stitched to slot 0.\n firstDrawInTile[tileIdx] = params.numRecords - 1u;\n return;\n }\n let tileStart = tileIdx * TILE_K;\n var lo: u32 = 0u;\n var hi: u32 = params.numRecords - 1u;\n loop {\n if (lo >= hi) { break; }\n let mid = (lo + hi + 1u) >> 1u;\n if (drawTable[mid].firstEmit <= tileStart) { lo = mid; } else { hi = mid - 1u; }\n }\n firstDrawInTile[tileIdx] = lo;\n}\n";
11
+ //# sourceMappingURL=scanKernel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanKernel.d.ts","sourceRoot":"","sources":["../../../src/runtime/heapScene/scanKernel.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,cAAc,MAAM,CAAC;AAClC,eAAO,MAAM,YAAY,MAAQ,CAAC;AAClC,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,QAAkC,CAAC;AAEhE,kEAAkE;AAClE,eAAO,MAAM,MAAM,KAAK,CAAC;AAEzB,2FAA2F;AAC3F,eAAO,MAAM,UAAU,IAAM,CAAC;AAC9B,eAAO,MAAM,YAAY,QAAiB,CAAC;AAE3C,eAAO,MAAM,cAAc,mqKA4J1B,CAAC"}