@reearth/ezu 0.4.2 → 0.5.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.
@@ -181,6 +181,71 @@ class Renderer {
181
181
  clearSources() {
182
182
  wasm.renderer_clearSources(this.__wbg_ptr);
183
183
  }
184
+ /**
185
+ * What this renderer is holding, in bytes, so a host can shed load
186
+ * *before* an allocation fails rather than after.
187
+ *
188
+ * Returns a JS object:
189
+ * - `heapBytes` — wasm linear memory committed to the **module**,
190
+ * shared by every `Renderer` in this instance. This is the number
191
+ * that meets an isolate's memory cap. It is a high-water mark:
192
+ * freeing Rust values returns them to the allocator, never to the
193
+ * host, so it only ever grows.
194
+ * - `glyphBytes` / `glyphRanges` — SDF bitmaps resident in the
195
+ * glyph bank, and how many 256-codepoint blocks they span. Glyphs
196
+ * accumulate for the life of the renderer and survive
197
+ * `clearSources`, so on a long-lived instance this is usually
198
+ * what grew. `glyphBudget` is the per-fontstack ceiling
199
+ * `setGlyphBudget` put on them, or `Infinity` if none — note
200
+ * `glyphBytes` totals *every* fontstack, so it can exceed the
201
+ * budget legitimately.
202
+ * - `fontBytes` — outline font files held in the font bank.
203
+ * - `imageBytes` — decoded pixels of bound images and sprite
204
+ * atlases.
205
+ * - `cacheBytes` / `cacheBudget` — the render cache's pixel
206
+ * payload against its own eviction budget; it bounds itself, so
207
+ * `cacheBytes` near `cacheBudget` is steady state, not a leak.
208
+ *
209
+ * These are payload sizes, not an accounting of the heap: they omit
210
+ * allocator overhead, decoded features, per-font glyph-path caches,
211
+ * and the buffers a render is using right now. Expect the parts to
212
+ * sum to less than `heapBytes`.
213
+ * @returns {object}
214
+ */
215
+ memoryUsage() {
216
+ const ret = wasm.renderer_memoryUsage(this.__wbg_ptr);
217
+ if (ret[2]) {
218
+ throw takeFromExternrefTable0(ret[1]);
219
+ }
220
+ return takeFromExternrefTable0(ret[0]);
221
+ }
222
+ /**
223
+ * Codepoints the currently bound features can require, as
224
+ * `{ [glyphsSourceName]: number[] }` sorted ascending.
225
+ *
226
+ * This is the precise form of
227
+ * [`neededGlyphRanges`](Self::needed_glyph_ranges): a host that
228
+ * can build its own glyph PBF — one message holding just these
229
+ * codepoints — transfers only the glyphs the tile draws instead
230
+ * of the whole 256-codepoint block around each of them. On CJK
231
+ * labels that is the difference between a few thousand glyphs and
232
+ * a few tens of megabytes. `bindSource` files each glyph by its
233
+ * own id, so such a subset may span any number of blocks and
234
+ * needs no particular `range` string.
235
+ *
236
+ * Hosts that can only fetch whole `{range}.pbf` files off a
237
+ * MapLibre glyphs endpoint want `neededGlyphRanges` instead. Both
238
+ * calls see the same set of codepoints and carry the same
239
+ * over-approximation caveat.
240
+ * @returns {object}
241
+ */
242
+ neededCodepoints() {
243
+ const ret = wasm.renderer_neededCodepoints(this.__wbg_ptr);
244
+ if (ret[2]) {
245
+ throw takeFromExternrefTable0(ret[1]);
246
+ }
247
+ return takeFromExternrefTable0(ret[0]);
248
+ }
184
249
  /**
185
250
  * Glyph ranges the currently bound features can require, as
186
251
  * `{ [glyphsSourceName]: number[] }` where each number is a range
@@ -192,6 +257,11 @@ class Renderer {
192
257
  * scraping every string in the MVT, call this after binding the
193
258
  * vector sources and bind exactly the listed ranges.
194
259
  *
260
+ * A range holds 256 codepoints and a tile typically draws a
261
+ * handful of them, so this is a coarse unit to fetch in. Hosts
262
+ * that can assemble their own subset PBF should call
263
+ * [`neededCodepoints`](Self::needed_codepoints) instead.
264
+ *
195
265
  * It is an over-approximation, deliberately: a range is listed if
196
266
  * *any* feature in a text layer carries the codepoint in a property
197
267
  * the layer's `text` expression reads, without evaluating filters,
@@ -274,6 +344,34 @@ class Renderer {
274
344
  }
275
345
  return takeFromExternrefTable0(ret[0]);
276
346
  }
347
+ /**
348
+ * Cap the glyph bytes each bound fontstack keeps resident, in
349
+ * bytes. Unset, a fontstack keeps every range ever bound to it for
350
+ * the life of the renderer — `clearSources` does not touch glyphs,
351
+ * and on a long-lived instance rendering across a basemap that is
352
+ * usually what grew.
353
+ *
354
+ * Trimming happens **after** each `renderTile`, not while binding,
355
+ * so a render never loses glyphs that were bound for it. The tile
356
+ * that just drew is therefore the most recently used, and a budget
357
+ * large enough for one tile's glyphs always keeps that tile's; what
358
+ * goes is what earlier tiles needed and this one did not. Set it
359
+ * below one tile's worth and the ceiling still holds — the stack
360
+ * empties after every render and nothing carries over, which
361
+ * renders correctly but buys no reuse.
362
+ *
363
+ * It is a per-fontstack ceiling: a style with a regular, a medium
364
+ * and an italic stack can hold three times what is set here.
365
+ *
366
+ * This host cannot refetch, so anything trimmed must be bound again
367
+ * before the next tile that needs it. `neededCodepoints()` already
368
+ * names exactly what to bind, and a host that re-binds every tile
369
+ * (rather than tracking what it sent) needs no other change.
370
+ * @param {number} bytes
371
+ */
372
+ setGlyphBudget(bytes) {
373
+ wasm.renderer_setGlyphBudget(this.__wbg_ptr, bytes);
374
+ }
277
375
  /**
278
376
  * Replace the active style. Returns the new node count. Invalidates
279
377
  * the intermediate cache and drops any pending source bindings.
@@ -301,6 +399,27 @@ class Renderer {
301
399
  if (Symbol.dispose) Renderer.prototype[Symbol.dispose] = Renderer.prototype.free;
302
400
  exports.Renderer = Renderer;
303
401
 
402
+ /**
403
+ * Wasm linear memory currently committed to this module, in bytes.
404
+ *
405
+ * This is the figure an isolate's memory cap applies to, and the one
406
+ * to watch to shed load before an allocation fails — a refused
407
+ * `memory.grow` throws [`OutOfMemory`](oom) and ends the instance.
408
+ * It never falls: freed Rust values return to the allocator for reuse,
409
+ * but wasm cannot hand pages back to the host. So a drop in demand
410
+ * leaves the number where its peak left it, and only a fresh instance
411
+ * resets it.
412
+ *
413
+ * Module-wide, not per-`Renderer`. For what a given renderer is
414
+ * holding, and which bank to evict, call `memoryUsage()`.
415
+ * @returns {number}
416
+ */
417
+ function heapBytes() {
418
+ const ret = wasm.heapBytes();
419
+ return ret >>> 0;
420
+ }
421
+ exports.heapBytes = heapBytes;
422
+
304
423
  /**
305
424
  * Whether the wasm binary was compiled with `+simd128`. Lets the demo
306
425
  * page label the renderer build accurately.
@@ -327,29 +446,29 @@ exports.threadsEnabled = threadsEnabled;
327
446
  function __wbg_get_imports() {
328
447
  const import0 = {
329
448
  __proto__: null,
330
- __wbg___wbindgen_boolean_get_2304fb8c853028c8: function(arg0) {
449
+ __wbg___wbindgen_boolean_get_fa956cfa2d1bd751: function(arg0) {
331
450
  const v = arg0;
332
451
  const ret = typeof(v) === 'boolean' ? v : undefined;
333
452
  return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
334
453
  },
335
- __wbg___wbindgen_is_null_2042690d351e14f0: function(arg0) {
454
+ __wbg___wbindgen_is_null_ea9085d691f535d3: function(arg0) {
336
455
  const ret = arg0 === null;
337
456
  return ret;
338
457
  },
339
- __wbg___wbindgen_is_undefined_35bb9f4c7fd651d5: function(arg0) {
458
+ __wbg___wbindgen_is_undefined_c05833b95a3cf397: function(arg0) {
340
459
  const ret = arg0 === undefined;
341
460
  return ret;
342
461
  },
343
- __wbg___wbindgen_number_get_f73a1244370fcc2c: function(arg0, arg1) {
462
+ __wbg___wbindgen_number_get_394265ed1e1b84ee: function(arg0, arg1) {
344
463
  const obj = arg1;
345
464
  const ret = typeof(obj) === 'number' ? obj : undefined;
346
465
  getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
347
466
  getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
348
467
  },
349
- __wbg___wbindgen_rethrow_2b7cc655458909c2: function(arg0) {
468
+ __wbg___wbindgen_rethrow_4915403b40f010b4: function(arg0) {
350
469
  throw arg0;
351
470
  },
352
- __wbg___wbindgen_string_get_d109740c0d18f4d7: function(arg0, arg1) {
471
+ __wbg___wbindgen_string_get_b0ca35b86a603356: function(arg0, arg1) {
353
472
  const obj = arg1;
354
473
  const ret = typeof(obj) === 'string' ? obj : undefined;
355
474
  var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc_command_export, wasm.__wbindgen_realloc_command_export);
@@ -357,10 +476,10 @@ function __wbg_get_imports() {
357
476
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
358
477
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
359
478
  },
360
- __wbg___wbindgen_throw_9c31b086c2b26051: function(arg0, arg1) {
479
+ __wbg___wbindgen_throw_344f42d3211c4765: function(arg0, arg1) {
361
480
  throw new Error(getStringFromWasm0(arg0, arg1));
362
481
  },
363
- __wbg_call_dfde26266607c996: function() { return handleError(function (arg0, arg1, arg2) {
482
+ __wbg_call_a6e5c5dce5018821: function() { return handleError(function (arg0, arg1, arg2) {
364
483
  const ret = arg0.call(arg1, arg2);
365
484
  return ret;
366
485
  }, arguments); },
@@ -375,15 +494,15 @@ function __wbg_get_imports() {
375
494
  wasm.__wbindgen_free_command_export(deferred0_0, deferred0_1, 1);
376
495
  }
377
496
  },
378
- __wbg_get_98fdf51d029a75eb: function(arg0, arg1) {
497
+ __wbg_get_507a50627bffa49b: function(arg0, arg1) {
379
498
  const ret = arg0[arg1 >>> 0];
380
499
  return ret;
381
500
  },
382
- __wbg_get_dcf82ab8aad1a593: function() { return handleError(function (arg0, arg1) {
501
+ __wbg_get_78f252d074a84d0b: function() { return handleError(function (arg0, arg1) {
383
502
  const ret = Reflect.get(arg0, arg1);
384
503
  return ret;
385
504
  }, arguments); },
386
- __wbg_instanceof_Object_03924e0dbda74bd8: function(arg0) {
505
+ __wbg_instanceof_Object_33f20e6f12439f3e: function(arg0) {
387
506
  let result;
388
507
  try {
389
508
  result = arg0 instanceof Object;
@@ -393,43 +512,43 @@ function __wbg_get_imports() {
393
512
  const ret = result;
394
513
  return ret;
395
514
  },
396
- __wbg_isArray_94898ed3aad6947b: function(arg0) {
515
+ __wbg_isArray_0677c962b281d01a: function(arg0) {
397
516
  const ret = Array.isArray(arg0);
398
517
  return ret;
399
518
  },
400
- __wbg_length_2591a0f4f659a55c: function(arg0) {
519
+ __wbg_length_370319915dc99107: function(arg0) {
401
520
  const ret = arg0.length;
402
521
  return ret;
403
522
  },
404
- __wbg_new_02d162bc6cf02f60: function() {
405
- const ret = new Object();
523
+ __wbg_new_227d7c05414eb861: function() {
524
+ const ret = new Error();
406
525
  return ret;
407
526
  },
408
- __wbg_new_1f236d63ba0c4784: function(arg0, arg1) {
409
- const ret = new Error(getStringFromWasm0(arg0, arg1));
527
+ __wbg_new_32b398fb48b6d94a: function() {
528
+ const ret = new Array();
410
529
  return ret;
411
530
  },
412
- __wbg_new_227d7c05414eb861: function() {
413
- const ret = new Error();
531
+ __wbg_new_b667d279fd5aa943: function(arg0, arg1) {
532
+ const ret = new Error(getStringFromWasm0(arg0, arg1));
414
533
  return ret;
415
534
  },
416
- __wbg_new_310879b66b6e95e1: function() {
417
- const ret = new Array();
535
+ __wbg_new_da52cf8fe3429cb2: function() {
536
+ const ret = new Object();
418
537
  return ret;
419
538
  },
420
- __wbg_now_81363d44c96dd239: function() {
539
+ __wbg_now_86c0d4ba3fa605b8: function() {
421
540
  const ret = Date.now();
422
541
  return ret;
423
542
  },
424
- __wbg_push_b77c476b01548d0a: function(arg0, arg1) {
543
+ __wbg_push_d2ae3af0c1217ae6: function(arg0, arg1) {
425
544
  const ret = arg0.push(arg1);
426
545
  return ret;
427
546
  },
428
- __wbg_set_a0e911be3da02782: function() { return handleError(function (arg0, arg1, arg2) {
547
+ __wbg_set_8535240470bf2500: function() { return handleError(function (arg0, arg1, arg2) {
429
548
  const ret = Reflect.set(arg0, arg1, arg2);
430
549
  return ret;
431
550
  }, arguments); },
432
- __wbg_set_name_e500733c75ec36b0: function(arg0, arg1, arg2) {
551
+ __wbg_set_name_3bbc583faefa4193: function(arg0, arg1, arg2) {
433
552
  arg0.name = getStringFromWasm0(arg1, arg2);
434
553
  },
435
554
  __wbg_stack_3b0d974bbf31e44f: function(arg0, arg1) {
Binary file
@@ -3,6 +3,7 @@
3
3
  export const memory: WebAssembly.Memory;
4
4
  export const __wbg_logsink_free: (a: number, b: number) => void;
5
5
  export const __wbg_renderer_free: (a: number, b: number) => void;
6
+ export const heapBytes: () => number;
6
7
  export const logsink_clear: (a: number) => void;
7
8
  export const logsink_drain: (a: number) => any;
8
9
  export const logsink_drainLines: (a: number) => [number, number];
@@ -15,10 +16,13 @@ export const renderer_attribution: (a: number) => [number, number];
15
16
  export const renderer_bindSource: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
16
17
  export const renderer_boundSources: (a: number) => [number, number];
17
18
  export const renderer_clearSources: (a: number) => void;
19
+ export const renderer_memoryUsage: (a: number) => [number, number, number];
20
+ export const renderer_neededCodepoints: (a: number) => [number, number, number];
18
21
  export const renderer_neededGlyphRanges: (a: number) => [number, number, number];
19
22
  export const renderer_new: (a: number, b: number) => [number, number, number];
20
23
  export const renderer_renderTile: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
21
24
  export const renderer_requestedNeighborOffsets: (a: number, b: number, c: number) => [number, number, number];
25
+ export const renderer_setGlyphBudget: (a: number, b: number) => void;
22
26
  export const renderer_setStyle: (a: number, b: number, c: number) => [number, number, number];
23
27
  export const renderer_tileSize: (a: number) => number;
24
28
  export const simdEnabled: () => number;
package/simd/web/ezu.d.ts CHANGED
@@ -92,6 +92,57 @@ export class Renderer {
92
92
  * Drop every pending source binding. Call between tile renders.
93
93
  */
94
94
  clearSources(): void;
95
+ /**
96
+ * What this renderer is holding, in bytes, so a host can shed load
97
+ * *before* an allocation fails rather than after.
98
+ *
99
+ * Returns a JS object:
100
+ * - `heapBytes` — wasm linear memory committed to the **module**,
101
+ * shared by every `Renderer` in this instance. This is the number
102
+ * that meets an isolate's memory cap. It is a high-water mark:
103
+ * freeing Rust values returns them to the allocator, never to the
104
+ * host, so it only ever grows.
105
+ * - `glyphBytes` / `glyphRanges` — SDF bitmaps resident in the
106
+ * glyph bank, and how many 256-codepoint blocks they span. Glyphs
107
+ * accumulate for the life of the renderer and survive
108
+ * `clearSources`, so on a long-lived instance this is usually
109
+ * what grew. `glyphBudget` is the per-fontstack ceiling
110
+ * `setGlyphBudget` put on them, or `Infinity` if none — note
111
+ * `glyphBytes` totals *every* fontstack, so it can exceed the
112
+ * budget legitimately.
113
+ * - `fontBytes` — outline font files held in the font bank.
114
+ * - `imageBytes` — decoded pixels of bound images and sprite
115
+ * atlases.
116
+ * - `cacheBytes` / `cacheBudget` — the render cache's pixel
117
+ * payload against its own eviction budget; it bounds itself, so
118
+ * `cacheBytes` near `cacheBudget` is steady state, not a leak.
119
+ *
120
+ * These are payload sizes, not an accounting of the heap: they omit
121
+ * allocator overhead, decoded features, per-font glyph-path caches,
122
+ * and the buffers a render is using right now. Expect the parts to
123
+ * sum to less than `heapBytes`.
124
+ */
125
+ memoryUsage(): object;
126
+ /**
127
+ * Codepoints the currently bound features can require, as
128
+ * `{ [glyphsSourceName]: number[] }` sorted ascending.
129
+ *
130
+ * This is the precise form of
131
+ * [`neededGlyphRanges`](Self::needed_glyph_ranges): a host that
132
+ * can build its own glyph PBF — one message holding just these
133
+ * codepoints — transfers only the glyphs the tile draws instead
134
+ * of the whole 256-codepoint block around each of them. On CJK
135
+ * labels that is the difference between a few thousand glyphs and
136
+ * a few tens of megabytes. `bindSource` files each glyph by its
137
+ * own id, so such a subset may span any number of blocks and
138
+ * needs no particular `range` string.
139
+ *
140
+ * Hosts that can only fetch whole `{range}.pbf` files off a
141
+ * MapLibre glyphs endpoint want `neededGlyphRanges` instead. Both
142
+ * calls see the same set of codepoints and carry the same
143
+ * over-approximation caveat.
144
+ */
145
+ neededCodepoints(): object;
95
146
  /**
96
147
  * Glyph ranges the currently bound features can require, as
97
148
  * `{ [glyphsSourceName]: number[] }` where each number is a range
@@ -103,6 +154,11 @@ export class Renderer {
103
154
  * scraping every string in the MVT, call this after binding the
104
155
  * vector sources and bind exactly the listed ranges.
105
156
  *
157
+ * A range holds 256 codepoints and a tile typically draws a
158
+ * handful of them, so this is a coarse unit to fetch in. Hosts
159
+ * that can assemble their own subset PBF should call
160
+ * [`neededCodepoints`](Self::needed_codepoints) instead.
161
+ *
106
162
  * It is an over-approximation, deliberately: a range is listed if
107
163
  * *any* feature in a text layer carries the codepoint in a property
108
164
  * the layer's `text` expression reads, without evaluating filters,
@@ -144,6 +200,31 @@ export class Renderer {
144
200
  * Throws `UnknownSource` if `name` is not declared in the style.
145
201
  */
146
202
  requestedNeighborOffsets(name: string): Array<any>;
203
+ /**
204
+ * Cap the glyph bytes each bound fontstack keeps resident, in
205
+ * bytes. Unset, a fontstack keeps every range ever bound to it for
206
+ * the life of the renderer — `clearSources` does not touch glyphs,
207
+ * and on a long-lived instance rendering across a basemap that is
208
+ * usually what grew.
209
+ *
210
+ * Trimming happens **after** each `renderTile`, not while binding,
211
+ * so a render never loses glyphs that were bound for it. The tile
212
+ * that just drew is therefore the most recently used, and a budget
213
+ * large enough for one tile's glyphs always keeps that tile's; what
214
+ * goes is what earlier tiles needed and this one did not. Set it
215
+ * below one tile's worth and the ceiling still holds — the stack
216
+ * empties after every render and nothing carries over, which
217
+ * renders correctly but buys no reuse.
218
+ *
219
+ * It is a per-fontstack ceiling: a style with a regular, a medium
220
+ * and an italic stack can hold three times what is set here.
221
+ *
222
+ * This host cannot refetch, so anything trimmed must be bound again
223
+ * before the next tile that needs it. `neededCodepoints()` already
224
+ * names exactly what to bind, and a host that re-binds every tile
225
+ * (rather than tracking what it sent) needs no other change.
226
+ */
227
+ setGlyphBudget(bytes: number): void;
147
228
  /**
148
229
  * Replace the active style. Returns the new node count. Invalidates
149
230
  * the intermediate cache and drops any pending source bindings.
@@ -161,6 +242,22 @@ export class Renderer {
161
242
  readonly tileSize: number;
162
243
  }
163
244
 
245
+ /**
246
+ * Wasm linear memory currently committed to this module, in bytes.
247
+ *
248
+ * This is the figure an isolate's memory cap applies to, and the one
249
+ * to watch to shed load before an allocation fails — a refused
250
+ * `memory.grow` throws [`OutOfMemory`](oom) and ends the instance.
251
+ * It never falls: freed Rust values return to the allocator for reuse,
252
+ * but wasm cannot hand pages back to the host. So a drop in demand
253
+ * leaves the number where its peak left it, and only a fresh instance
254
+ * resets it.
255
+ *
256
+ * Module-wide, not per-`Renderer`. For what a given renderer is
257
+ * holding, and which bank to evict, call `memoryUsage()`.
258
+ */
259
+ export function heapBytes(): number;
260
+
164
261
  /**
165
262
  * Whether the wasm binary was compiled with `+simd128`. Lets the demo
166
263
  * page label the renderer build accurately.
@@ -181,6 +278,7 @@ export interface InitOutput {
181
278
  readonly memory: WebAssembly.Memory;
182
279
  readonly __wbg_logsink_free: (a: number, b: number) => void;
183
280
  readonly __wbg_renderer_free: (a: number, b: number) => void;
281
+ readonly heapBytes: () => number;
184
282
  readonly logsink_clear: (a: number) => void;
185
283
  readonly logsink_drain: (a: number) => any;
186
284
  readonly logsink_drainLines: (a: number) => [number, number];
@@ -193,10 +291,13 @@ export interface InitOutput {
193
291
  readonly renderer_bindSource: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
194
292
  readonly renderer_boundSources: (a: number) => [number, number];
195
293
  readonly renderer_clearSources: (a: number) => void;
294
+ readonly renderer_memoryUsage: (a: number) => [number, number, number];
295
+ readonly renderer_neededCodepoints: (a: number) => [number, number, number];
196
296
  readonly renderer_neededGlyphRanges: (a: number) => [number, number, number];
197
297
  readonly renderer_new: (a: number, b: number) => [number, number, number];
198
298
  readonly renderer_renderTile: (a: number, b: number, c: number, d: number, e: number) => [number, number, number, number];
199
299
  readonly renderer_requestedNeighborOffsets: (a: number, b: number, c: number) => [number, number, number];
300
+ readonly renderer_setGlyphBudget: (a: number, b: number) => void;
200
301
  readonly renderer_setStyle: (a: number, b: number, c: number) => [number, number, number];
201
302
  readonly renderer_tileSize: (a: number) => number;
202
303
  readonly simdEnabled: () => number;