@woosh/meep-engine 3.32.0 → 3.33.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.
Files changed (58) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/package.json +1 -1
  3. package/src/core/collection/table/RowFirstTable.d.ts +8 -0
  4. package/src/core/collection/table/RowFirstTable.d.ts.map +1 -1
  5. package/src/core/collection/table/RowFirstTable.js +40 -11
  6. package/src/engine/graphics/ecs/sprite/Sprite.d.ts +3 -0
  7. package/src/engine/graphics/ecs/sprite/Sprite.d.ts.map +1 -1
  8. package/src/engine/graphics/ecs/sprite/Sprite.js +3 -0
  9. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts +3 -0
  10. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.d.ts.map +1 -1
  11. package/src/engine/graphics/ecs/sprite/SpriteSystemPE.js +3 -0
  12. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  13. package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts +20 -3
  14. package/src/shade/device/mock/SoftwareGPURenderPassEncoder.d.ts.map +1 -1
  15. package/src/shade/device/mock/SoftwareGPURenderPassEncoder.js +21 -3
  16. package/src/shade/renderer/GraphicsContext.d.ts +11 -0
  17. package/src/shade/renderer/GraphicsContext.d.ts.map +1 -1
  18. package/src/shade/renderer/GraphicsContext.js +52 -38
  19. package/src/shade/renderer/buffer/GPUBufferReadbackAllocator.d.ts +6 -5
  20. package/src/shade/renderer/buffer/GPUBufferReadbackAllocator.d.ts.map +1 -1
  21. package/src/shade/renderer/buffer/GPUBufferReadbackAllocator.js +241 -240
  22. package/src/shade/renderer/buffer/GPUBufferStagingAllocator.d.ts +51 -0
  23. package/src/shade/renderer/buffer/GPUBufferStagingAllocator.d.ts.map +1 -1
  24. package/src/shade/renderer/buffer/GPUBufferStagingAllocator.js +214 -28
  25. package/src/shade/renderer/dynamic/DynamicMeshAVBOITChannel.d.ts +2 -1
  26. package/src/shade/renderer/dynamic/DynamicMeshAVBOITChannel.d.ts.map +1 -1
  27. package/src/shade/renderer/dynamic/DynamicMeshAVBOITChannel.js +19 -17
  28. package/src/shade/renderer/dynamic/GPUDynamicMeshDrawList.d.ts +70 -0
  29. package/src/shade/renderer/dynamic/GPUDynamicMeshDrawList.d.ts.map +1 -0
  30. package/src/shade/renderer/dynamic/GPUDynamicMeshDrawList.js +257 -0
  31. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.d.ts.map +1 -1
  32. package/src/shade/renderer/dynamic/GPUDynamicMeshRenderer.js +19 -34
  33. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts +6 -20
  34. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.d.ts.map +1 -1
  35. package/src/shade/renderer/dynamic/GPUDynamicMeshResidency.js +42 -36
  36. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.d.ts +2 -1
  37. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.d.ts.map +1 -1
  38. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_avboit_vertex.js +4 -3
  39. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_vertex.d.ts +4 -3
  40. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_vertex.d.ts.map +1 -1
  41. package/src/shade/renderer/dynamic/chunk_dynamic_mesh_vertex.js +7 -4
  42. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.d.ts +14 -15
  43. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.d.ts.map +1 -1
  44. package/src/shade/renderer/dynamic/graph_dynamic_mesh_avboit.js +49 -83
  45. package/src/shade/renderer/dynamic/shader_dynamic_mesh.d.ts +19 -3
  46. package/src/shade/renderer/dynamic/shader_dynamic_mesh.d.ts.map +1 -1
  47. package/src/shade/renderer/dynamic/shader_dynamic_mesh.js +26 -6
  48. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.d.ts +2 -1
  49. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.d.ts.map +1 -1
  50. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_draw.js +12 -6
  51. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.d.ts +3 -2
  52. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.d.ts.map +1 -1
  53. package/src/shade/renderer/dynamic/shader_dynamic_mesh_avboit_splat.js +21 -13
  54. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  55. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  56. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +20 -0
  57. package/src/shade/renderer/shader/type/serde/write_gpu_typed_buffer.d.ts.map +1 -1
  58. package/src/shade/renderer/shader/type/serde/write_gpu_typed_buffer.js +8 -1
@@ -1,240 +1,241 @@
1
- import { assert } from "../../../core/assert.js";
2
- import { binarySearchHighIndex } from "../../../core/collection/array/binarySearchHighIndex.js";
3
- import { round_up } from "../../../core/math/round_up.js";
4
- import { MEGABYTE } from "../../../core/science/units/memory/MEGABYTE.js";
5
-
6
- /**
7
- * Sizes are rounded up to this when a buffer is created, so that batches whose byte count breathes
8
- * by a few rows keep landing in the same buffer instead of each size making a new one.
9
- *
10
- * @type {number}
11
- */
12
- const SIZE_GRANULARITY = 256;
13
-
14
- /**
15
- * How many bytes of *free* readback buffers are kept. Buffers handed out are the holder's to bound;
16
- * this bounds what an idle pool pins after a spike — one 50k-row batch is ~3 MB, and without a cap
17
- * it would stay for the life of the process, which is what the ring this replaced did.
18
- *
19
- * @type {number}
20
- */
21
- const DEFAULT_BUDGET_BYTES = 16 * MEGABYTE;
22
-
23
- /**
24
- * @type {number}
25
- */
26
- let id_count = 0;
27
-
28
- /**
29
- * @param {{size: number}} a
30
- * @param {{size: number}} b
31
- * @returns {number}
32
- */
33
- function by_size(a, b) {
34
- return a.size - b.size;
35
- }
36
-
37
- /**
38
- * Persistent `MAP_READ | COPY_DST` buffers for reading GPU data back — {@link GPUBufferStagingAllocator}
39
- * run the other way.
40
- *
41
- * The same shape on purpose: a size-sorted free list, `get(min_size)` serving the smallest buffer
42
- * that fits and creating one when none does, `release(buffer)` putting it back. Where the staging
43
- * pool re-maps a buffer on release because the next writer needs it mapped, this one *unmaps*,
44
- * because the next copy into it needs it unmapped; the mapping is the holder's, taken after the
45
- * copy has landed and read at the holder's own apply point.
46
- *
47
- * Why not `buffer_allocator_main`: `TransientResourcePool`'s reuse safety rests on transients being
48
- * GPU-only, and a readback buffer is held by the CPU across frames.
49
- *
50
- * Why not a ring: a ring hands out `null` when its slots are busy and leaves the caller to defer a
51
- * whole frame's work, and growing a slot destroys a perfectly good smaller buffer. A free list makes
52
- * another buffer and keeps both sizes.
53
- *
54
- * @see GPUDatabaseReadback the holder
55
- */
56
- export class GPUBufferReadbackAllocator {
57
- /**
58
- * @type {GPUDevice}
59
- */
60
- #device;
61
-
62
- /**
63
- * Free buffers, ascending by size.
64
- * @type {GPUBuffer[]}
65
- */
66
- #ready = [];
67
-
68
- /**
69
- * @type {number}
70
- */
71
- #ready_byte_size = 0;
72
-
73
- /**
74
- * Bytes in buffers handed out and not yet given back.
75
- * @type {number}
76
- */
77
- #held_byte_size = 0;
78
-
79
- /**
80
- * @type {number}
81
- */
82
- #budget_bytes;
83
-
84
- /**
85
- * @param {GPUDevice} device
86
- * @param {Object} [options]
87
- * @param {number} [options.budget_bytes] free bytes kept before the largest free buffers are destroyed
88
- */
89
- constructor(device, { budget_bytes = DEFAULT_BUDGET_BYTES } = {}) {
90
- assert.defined(device, 'device');
91
- assert.isNonNegativeInteger(budget_bytes, 'budget_bytes');
92
-
93
- this.#device = device;
94
- this.#budget_bytes = budget_bytes;
95
- }
96
-
97
- /**
98
- * Bytes in every buffer this pool has made and not destroyed, held or free.
99
- * @returns {number}
100
- */
101
- get gpu_memory_usage() {
102
- return this.#ready_byte_size + this.#held_byte_size;
103
- }
104
-
105
- /**
106
- * Bytes sitting in the free list.
107
- * @returns {number}
108
- */
109
- get ready_byte_size() {
110
- return this.#ready_byte_size;
111
- }
112
-
113
- /**
114
- * Bytes in buffers currently handed out.
115
- * @returns {number}
116
- */
117
- get held_byte_size() {
118
- return this.#held_byte_size;
119
- }
120
-
121
- /**
122
- * Free buffers.
123
- * @returns {number}
124
- */
125
- get ready_count() {
126
- return this.#ready.length;
127
- }
128
-
129
- /**
130
- * The smallest free buffer of at least `min_size_bytes`, or a new one. **Unmapped**, ready to be
131
- * the destination of a copy. Contents are whatever the last use left.
132
- *
133
- * @param {number} min_size_bytes
134
- * @returns {GPUBuffer}
135
- */
136
- get(min_size_bytes) {
137
- assert.isNonNegativeInteger(min_size_bytes, 'min_size_bytes');
138
- assert.greaterThan(min_size_bytes, 0, 'min_size_bytes');
139
-
140
- const ready = this.#ready;
141
- const index = binarySearchHighIndex(ready, { size: min_size_bytes }, by_size);
142
-
143
- let result;
144
-
145
- if (index < ready.length) {
146
- result = ready[index];
147
-
148
- ready.splice(index, 1);
149
-
150
- this.#ready_byte_size -= result.size;
151
- } else {
152
- result = this.#device.createBuffer({
153
- label: `readback ${id_count++}`,
154
- size: round_up(min_size_bytes, SIZE_GRANULARITY),
155
- // the only usage pair WebGPU permits alongside MAP_READ
156
- usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
157
- mappedAtCreation: false,
158
- });
159
- }
160
-
161
- assert.greaterThanOrEqual(result.size, min_size_bytes, 'result.size < min_size_bytes');
162
- assert.equal(result.mapState, "unmapped", 'result.mapState !== "unmapped"');
163
-
164
- this.#held_byte_size += result.size;
165
-
166
- return result;
167
- }
168
-
169
- /**
170
- * Give a buffer back. A mapped buffer is unmapped here; a buffer whose mapping is still pending
171
- * cannot be given back — let the mapping settle, or {@link discard} it.
172
- *
173
- * @param {GPUBuffer} buffer
174
- */
175
- release(buffer) {
176
- assert.defined(buffer, 'buffer');
177
- assert.equal(buffer.usage, GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, 'buffer.usage !== GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST');
178
-
179
- const state = buffer.mapState;
180
-
181
- if (state === "mapped") {
182
- buffer.unmap();
183
- } else if (state !== "unmapped") {
184
- throw new Error(`Invalid map state: ${state}`);
185
- }
186
-
187
- this.#held_byte_size -= buffer.size;
188
-
189
- const ready = this.#ready;
190
- const index = binarySearchHighIndex(ready, buffer, by_size);
191
-
192
- ready.splice(index, 0, buffer);
193
-
194
- this.#ready_byte_size += buffer.size;
195
-
196
- this.#trim();
197
- }
198
-
199
- /**
200
- * Destroy a buffer that was handed out, instead of giving it back — for a holder being torn down
201
- * while a mapping is still pending, which WebGPU lets `destroy()` abort but not `unmap()`.
202
- *
203
- * @param {GPUBuffer} buffer
204
- */
205
- discard(buffer) {
206
- assert.defined(buffer, 'buffer');
207
-
208
- this.#held_byte_size -= buffer.size;
209
-
210
- buffer.destroy();
211
- }
212
-
213
- /**
214
- * Keep the free list under budget, dropping the largest buffers first: they cost the most, and a
215
- * spike is the least likely size to be asked for again.
216
- */
217
- #trim() {
218
- const ready = this.#ready;
219
-
220
- while (this.#ready_byte_size > this.#budget_bytes && ready.length > 0) {
221
- const largest = ready.pop();
222
-
223
- this.#ready_byte_size -= largest.size;
224
-
225
- largest.destroy();
226
- }
227
- }
228
-
229
- destroy() {
230
- const ready = this.#ready;
231
-
232
- for (let i = 0; i < ready.length; i++) {
233
- ready[i].destroy();
234
- }
235
-
236
- ready.length = 0;
237
-
238
- this.#ready_byte_size = 0;
239
- }
240
- }
1
+ import { assert } from "../../../core/assert.js";
2
+ import { binarySearchHighIndex } from "../../../core/collection/array/binarySearchHighIndex.js";
3
+ import { round_up } from "../../../core/math/round_up.js";
4
+ import { MEGABYTE } from "../../../core/science/units/memory/MEGABYTE.js";
5
+
6
+ /**
7
+ * Sizes are rounded up to this when a buffer is created, so that batches whose byte count breathes
8
+ * by a few rows keep landing in the same buffer instead of each size making a new one.
9
+ *
10
+ * @type {number}
11
+ */
12
+ const SIZE_GRANULARITY = 256;
13
+
14
+ /**
15
+ * How many bytes of *free* readback buffers are kept. Buffers handed out are the holder's to bound;
16
+ * this bounds what an idle pool pins after a spike — one 50k-row batch is ~3 MB, and without a cap
17
+ * it would stay for the life of the process, which is what the ring this replaced did.
18
+ *
19
+ * @type {number}
20
+ */
21
+ const DEFAULT_BUDGET_BYTES = 16 * MEGABYTE;
22
+
23
+ /**
24
+ * @type {number}
25
+ */
26
+ let id_count = 0;
27
+
28
+ /**
29
+ * @param {{size: number}} a
30
+ * @param {{size: number}} b
31
+ * @returns {number}
32
+ */
33
+ function by_size(a, b) {
34
+ return a.size - b.size;
35
+ }
36
+
37
+ /**
38
+ * Persistent `MAP_READ | COPY_DST` buffers for reading GPU data back — {@link GPUBufferStagingAllocator}
39
+ * run the other way.
40
+ *
41
+ * The same shape: a size-sorted free list, `get(min_size)` serving the smallest buffer that fits
42
+ * and creating one when none does, `release(buffer)` putting it back. Where the staging pool re-maps
43
+ * a buffer on release because the next writer needs it mapped, this one *unmaps*, because the next
44
+ * copy into it needs it unmapped; the mapping is the holder's, taken after the copy has landed and
45
+ * read at the holder's own apply point. Unlike the staging pool, this one has no bound on how much
46
+ * larger than the request a buffer it serves may be, no size classes and no reclaim.
47
+ *
48
+ * Why not `buffer_allocator_main`: `TransientResourcePool`'s reuse safety rests on transients being
49
+ * GPU-only, and a readback buffer is held by the CPU across frames.
50
+ *
51
+ * Why not a ring: a ring hands out `null` when its slots are busy and leaves the caller to defer a
52
+ * whole frame's work, and growing a slot destroys a perfectly good smaller buffer. A free list makes
53
+ * another buffer and keeps both sizes.
54
+ *
55
+ * @see GPUDatabaseReadback the holder
56
+ */
57
+ export class GPUBufferReadbackAllocator {
58
+ /**
59
+ * @type {GPUDevice}
60
+ */
61
+ #device;
62
+
63
+ /**
64
+ * Free buffers, ascending by size.
65
+ * @type {GPUBuffer[]}
66
+ */
67
+ #ready = [];
68
+
69
+ /**
70
+ * @type {number}
71
+ */
72
+ #ready_byte_size = 0;
73
+
74
+ /**
75
+ * Bytes in buffers handed out and not yet given back.
76
+ * @type {number}
77
+ */
78
+ #held_byte_size = 0;
79
+
80
+ /**
81
+ * @type {number}
82
+ */
83
+ #budget_bytes;
84
+
85
+ /**
86
+ * @param {GPUDevice} device
87
+ * @param {Object} [options]
88
+ * @param {number} [options.budget_bytes] free bytes kept before the largest free buffers are destroyed
89
+ */
90
+ constructor(device, { budget_bytes = DEFAULT_BUDGET_BYTES } = {}) {
91
+ assert.defined(device, 'device');
92
+ assert.isNonNegativeInteger(budget_bytes, 'budget_bytes');
93
+
94
+ this.#device = device;
95
+ this.#budget_bytes = budget_bytes;
96
+ }
97
+
98
+ /**
99
+ * Bytes in every buffer this pool has made and not destroyed, held or free.
100
+ * @returns {number}
101
+ */
102
+ get gpu_memory_usage() {
103
+ return this.#ready_byte_size + this.#held_byte_size;
104
+ }
105
+
106
+ /**
107
+ * Bytes sitting in the free list.
108
+ * @returns {number}
109
+ */
110
+ get ready_byte_size() {
111
+ return this.#ready_byte_size;
112
+ }
113
+
114
+ /**
115
+ * Bytes in buffers currently handed out.
116
+ * @returns {number}
117
+ */
118
+ get held_byte_size() {
119
+ return this.#held_byte_size;
120
+ }
121
+
122
+ /**
123
+ * Free buffers.
124
+ * @returns {number}
125
+ */
126
+ get ready_count() {
127
+ return this.#ready.length;
128
+ }
129
+
130
+ /**
131
+ * The smallest free buffer of at least `min_size_bytes`, or a new one. **Unmapped**, ready to be
132
+ * the destination of a copy. Contents are whatever the last use left.
133
+ *
134
+ * @param {number} min_size_bytes
135
+ * @returns {GPUBuffer}
136
+ */
137
+ get(min_size_bytes) {
138
+ assert.isNonNegativeInteger(min_size_bytes, 'min_size_bytes');
139
+ assert.greaterThan(min_size_bytes, 0, 'min_size_bytes');
140
+
141
+ const ready = this.#ready;
142
+ const index = binarySearchHighIndex(ready, { size: min_size_bytes }, by_size);
143
+
144
+ let result;
145
+
146
+ if (index < ready.length) {
147
+ result = ready[index];
148
+
149
+ ready.splice(index, 1);
150
+
151
+ this.#ready_byte_size -= result.size;
152
+ } else {
153
+ result = this.#device.createBuffer({
154
+ label: `readback ${id_count++}`,
155
+ size: round_up(min_size_bytes, SIZE_GRANULARITY),
156
+ // the only usage pair WebGPU permits alongside MAP_READ
157
+ usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
158
+ mappedAtCreation: false,
159
+ });
160
+ }
161
+
162
+ assert.greaterThanOrEqual(result.size, min_size_bytes, 'result.size < min_size_bytes');
163
+ assert.equal(result.mapState, "unmapped", 'result.mapState !== "unmapped"');
164
+
165
+ this.#held_byte_size += result.size;
166
+
167
+ return result;
168
+ }
169
+
170
+ /**
171
+ * Give a buffer back. A mapped buffer is unmapped here; a buffer whose mapping is still pending
172
+ * cannot be given back — let the mapping settle, or {@link discard} it.
173
+ *
174
+ * @param {GPUBuffer} buffer
175
+ */
176
+ release(buffer) {
177
+ assert.defined(buffer, 'buffer');
178
+ assert.equal(buffer.usage, GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, 'buffer.usage !== GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST');
179
+
180
+ const state = buffer.mapState;
181
+
182
+ if (state === "mapped") {
183
+ buffer.unmap();
184
+ } else if (state !== "unmapped") {
185
+ throw new Error(`Invalid map state: ${state}`);
186
+ }
187
+
188
+ this.#held_byte_size -= buffer.size;
189
+
190
+ const ready = this.#ready;
191
+ const index = binarySearchHighIndex(ready, buffer, by_size);
192
+
193
+ ready.splice(index, 0, buffer);
194
+
195
+ this.#ready_byte_size += buffer.size;
196
+
197
+ this.#trim();
198
+ }
199
+
200
+ /**
201
+ * Destroy a buffer that was handed out, instead of giving it back — for a holder being torn down
202
+ * while a mapping is still pending, which WebGPU lets `destroy()` abort but not `unmap()`.
203
+ *
204
+ * @param {GPUBuffer} buffer
205
+ */
206
+ discard(buffer) {
207
+ assert.defined(buffer, 'buffer');
208
+
209
+ this.#held_byte_size -= buffer.size;
210
+
211
+ buffer.destroy();
212
+ }
213
+
214
+ /**
215
+ * Keep the free list under budget, dropping the largest buffers first: they cost the most, and a
216
+ * spike is the least likely size to be asked for again.
217
+ */
218
+ #trim() {
219
+ const ready = this.#ready;
220
+
221
+ while (this.#ready_byte_size > this.#budget_bytes && ready.length > 0) {
222
+ const largest = ready.pop();
223
+
224
+ this.#ready_byte_size -= largest.size;
225
+
226
+ largest.destroy();
227
+ }
228
+ }
229
+
230
+ destroy() {
231
+ const ready = this.#ready;
232
+
233
+ for (let i = 0; i < ready.length; i++) {
234
+ ready[i].destroy();
235
+ }
236
+
237
+ ready.length = 0;
238
+
239
+ this.#ready_byte_size = 0;
240
+ }
241
+ }
@@ -6,6 +6,13 @@
6
6
  * that is the cheaper road; for thousands of small writes a frame the round trips are the cost, which
7
7
  * is why a {@link ShadeGPUCommandContext} brings only its large writes here (see
8
8
  * `MAPPED_UPLOAD_THRESHOLD`).
9
+ *
10
+ * A buffer is made up to a quarter larger than asked, so a size that drifts keeps its buffer, and is
11
+ * handed out again only to requests at least half its size ({@link REUSE_LIMIT_SCALE}), so a burst's
12
+ * large buffers do not end up mapped whole for every smaller write after it. Of buffers of one size
13
+ * the one given back last goes out first, so a steady writer keeps one and the rest go idle. What
14
+ * sits idle is destroyed by {@link update}, as {@link TransientResourcePool#update} does for the
15
+ * frame's transients: without that, a burst's buffers stayed until the device went.
9
16
  */
10
17
  export class GPUBufferStagingAllocator {
11
18
  /**
@@ -13,6 +20,38 @@ export class GPUBufferStagingAllocator {
13
20
  * @param {GPUDevice} device
14
21
  */
15
22
  constructor(device: GPUDevice);
23
+ /**
24
+ * Idle bytes above which buffers idle for {@link param_over_budget_idle_frames} are destroyed.
25
+ * The same as the upload blocks' budget.
26
+ *
27
+ * @type {number}
28
+ */
29
+ param_soft_byte_budget: number;
30
+ /**
31
+ * Frames a buffer may sit idle while the pool is over its budget: long enough that a write made
32
+ * every few frames keeps its buffer, short enough that a burst's go within a second or so.
33
+ *
34
+ * @type {number}
35
+ */
36
+ param_over_budget_idle_frames: number;
37
+ /**
38
+ * An idle buffer is destroyed after this many frames even with the pool under its budget.
39
+ *
40
+ * @type {number}
41
+ */
42
+ param_backstop_frames: number;
43
+ /**
44
+ * Most buffers destroyed by one {@link update}.
45
+ *
46
+ * @type {number}
47
+ */
48
+ param_max_reclaim_per_frame: number;
49
+ /**
50
+ * Most idle buffers one {@link update} looks at.
51
+ *
52
+ * @type {number}
53
+ */
54
+ param_scan_budget: number;
16
55
  /**
17
56
  * Bytes in every buffer this pool has made and not destroyed: free, handed out, or on the way
18
57
  * back.
@@ -33,6 +72,18 @@ export class GPUBufferStagingAllocator {
33
72
  * this pool did not hand out
34
73
  */
35
74
  release(buffer: GPUBuffer): boolean;
75
+ /**
76
+ * Advance the pool's frame clock; once a frame, with the other pools'.
77
+ */
78
+ increment_time(): void;
79
+ /**
80
+ * Once-a-frame housekeeping: destroy the buffers nothing has asked for in a while — idle past
81
+ * {@link param_backstop_frames}, or, while more than {@link param_soft_byte_budget} bytes sit
82
+ * idle, past {@link param_over_budget_idle_frames}. A bounded sweep from where the last one
83
+ * stopped, at most {@link param_scan_budget} buffers looked at and
84
+ * {@link param_max_reclaim_per_frame} destroyed, as {@link TransientResourcePool#update}.
85
+ */
86
+ update(): void;
36
87
  destroy(): void;
37
88
  #private;
38
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"GPUBufferStagingAllocator.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/buffer/GPUBufferStagingAllocator.js"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH;IA8CI;;;OAGG;IACH,+BAIC;IAED;;;;;OAKG;IACH,+BAEC;IAGD;;;;OAIG;IACH,oBAHW,MAAM,aAsChB;IAkCD;;;;;OAKG;IACH,4BAHa,OAAO,CA0BnB;IAgCD,gBAUC;;CACJ"}
1
+ {"version":3,"file":"GPUBufferStagingAllocator.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/buffer/GPUBufferStagingAllocator.js"],"names":[],"mappings":"AAwFA;;;;;;;;;;;;;;;GAeG;AACH;IA0GI;;;OAGG;IACH,+BAIC;IA9GD;;;;;OAKG;IACH,wBAFU,MAAM,CAEuB;IAEvC;;;;;OAKG;IACH,+BAFU,MAAM,CAEmB;IAEnC;;;;OAIG;IACH,uBAFU,MAAM,CAEY;IAE5B;;;;OAIG;IACH,6BAFU,MAAM,CAEgB;IAEhC;;;;OAIG;IACH,mBAFU,MAAM,CAEO;IA6EvB;;;;;OAKG;IACH,+BAEC;IAGD;;;;OAIG;IACH,oBAHW,MAAM,aA2ChB;IAsBD;;;;;OAKG;IACH,4BAHa,OAAO,CAwBnB;IAkCD;;OAEG;IACH,uBAEC;IAED;;;;;;OAMG;IACH,eA+BC;IAED,gBAUC;;CACJ"}