@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.
package/simd/web/ezu.js CHANGED
@@ -180,6 +180,71 @@ export class Renderer {
180
180
  clearSources() {
181
181
  wasm.renderer_clearSources(this.__wbg_ptr);
182
182
  }
183
+ /**
184
+ * What this renderer is holding, in bytes, so a host can shed load
185
+ * *before* an allocation fails rather than after.
186
+ *
187
+ * Returns a JS object:
188
+ * - `heapBytes` — wasm linear memory committed to the **module**,
189
+ * shared by every `Renderer` in this instance. This is the number
190
+ * that meets an isolate's memory cap. It is a high-water mark:
191
+ * freeing Rust values returns them to the allocator, never to the
192
+ * host, so it only ever grows.
193
+ * - `glyphBytes` / `glyphRanges` — SDF bitmaps resident in the
194
+ * glyph bank, and how many 256-codepoint blocks they span. Glyphs
195
+ * accumulate for the life of the renderer and survive
196
+ * `clearSources`, so on a long-lived instance this is usually
197
+ * what grew. `glyphBudget` is the per-fontstack ceiling
198
+ * `setGlyphBudget` put on them, or `Infinity` if none — note
199
+ * `glyphBytes` totals *every* fontstack, so it can exceed the
200
+ * budget legitimately.
201
+ * - `fontBytes` — outline font files held in the font bank.
202
+ * - `imageBytes` — decoded pixels of bound images and sprite
203
+ * atlases.
204
+ * - `cacheBytes` / `cacheBudget` — the render cache's pixel
205
+ * payload against its own eviction budget; it bounds itself, so
206
+ * `cacheBytes` near `cacheBudget` is steady state, not a leak.
207
+ *
208
+ * These are payload sizes, not an accounting of the heap: they omit
209
+ * allocator overhead, decoded features, per-font glyph-path caches,
210
+ * and the buffers a render is using right now. Expect the parts to
211
+ * sum to less than `heapBytes`.
212
+ * @returns {object}
213
+ */
214
+ memoryUsage() {
215
+ const ret = wasm.renderer_memoryUsage(this.__wbg_ptr);
216
+ if (ret[2]) {
217
+ throw takeFromExternrefTable0(ret[1]);
218
+ }
219
+ return takeFromExternrefTable0(ret[0]);
220
+ }
221
+ /**
222
+ * Codepoints the currently bound features can require, as
223
+ * `{ [glyphsSourceName]: number[] }` sorted ascending.
224
+ *
225
+ * This is the precise form of
226
+ * [`neededGlyphRanges`](Self::needed_glyph_ranges): a host that
227
+ * can build its own glyph PBF — one message holding just these
228
+ * codepoints — transfers only the glyphs the tile draws instead
229
+ * of the whole 256-codepoint block around each of them. On CJK
230
+ * labels that is the difference between a few thousand glyphs and
231
+ * a few tens of megabytes. `bindSource` files each glyph by its
232
+ * own id, so such a subset may span any number of blocks and
233
+ * needs no particular `range` string.
234
+ *
235
+ * Hosts that can only fetch whole `{range}.pbf` files off a
236
+ * MapLibre glyphs endpoint want `neededGlyphRanges` instead. Both
237
+ * calls see the same set of codepoints and carry the same
238
+ * over-approximation caveat.
239
+ * @returns {object}
240
+ */
241
+ neededCodepoints() {
242
+ const ret = wasm.renderer_neededCodepoints(this.__wbg_ptr);
243
+ if (ret[2]) {
244
+ throw takeFromExternrefTable0(ret[1]);
245
+ }
246
+ return takeFromExternrefTable0(ret[0]);
247
+ }
183
248
  /**
184
249
  * Glyph ranges the currently bound features can require, as
185
250
  * `{ [glyphsSourceName]: number[] }` where each number is a range
@@ -191,6 +256,11 @@ export class Renderer {
191
256
  * scraping every string in the MVT, call this after binding the
192
257
  * vector sources and bind exactly the listed ranges.
193
258
  *
259
+ * A range holds 256 codepoints and a tile typically draws a
260
+ * handful of them, so this is a coarse unit to fetch in. Hosts
261
+ * that can assemble their own subset PBF should call
262
+ * [`neededCodepoints`](Self::needed_codepoints) instead.
263
+ *
194
264
  * It is an over-approximation, deliberately: a range is listed if
195
265
  * *any* feature in a text layer carries the codepoint in a property
196
266
  * the layer's `text` expression reads, without evaluating filters,
@@ -273,6 +343,34 @@ export class Renderer {
273
343
  }
274
344
  return takeFromExternrefTable0(ret[0]);
275
345
  }
346
+ /**
347
+ * Cap the glyph bytes each bound fontstack keeps resident, in
348
+ * bytes. Unset, a fontstack keeps every range ever bound to it for
349
+ * the life of the renderer — `clearSources` does not touch glyphs,
350
+ * and on a long-lived instance rendering across a basemap that is
351
+ * usually what grew.
352
+ *
353
+ * Trimming happens **after** each `renderTile`, not while binding,
354
+ * so a render never loses glyphs that were bound for it. The tile
355
+ * that just drew is therefore the most recently used, and a budget
356
+ * large enough for one tile's glyphs always keeps that tile's; what
357
+ * goes is what earlier tiles needed and this one did not. Set it
358
+ * below one tile's worth and the ceiling still holds — the stack
359
+ * empties after every render and nothing carries over, which
360
+ * renders correctly but buys no reuse.
361
+ *
362
+ * It is a per-fontstack ceiling: a style with a regular, a medium
363
+ * and an italic stack can hold three times what is set here.
364
+ *
365
+ * This host cannot refetch, so anything trimmed must be bound again
366
+ * before the next tile that needs it. `neededCodepoints()` already
367
+ * names exactly what to bind, and a host that re-binds every tile
368
+ * (rather than tracking what it sent) needs no other change.
369
+ * @param {number} bytes
370
+ */
371
+ setGlyphBudget(bytes) {
372
+ wasm.renderer_setGlyphBudget(this.__wbg_ptr, bytes);
373
+ }
276
374
  /**
277
375
  * Replace the active style. Returns the new node count. Invalidates
278
376
  * the intermediate cache and drops any pending source bindings.
@@ -299,6 +397,26 @@ export class Renderer {
299
397
  }
300
398
  if (Symbol.dispose) Renderer.prototype[Symbol.dispose] = Renderer.prototype.free;
301
399
 
400
+ /**
401
+ * Wasm linear memory currently committed to this module, in bytes.
402
+ *
403
+ * This is the figure an isolate's memory cap applies to, and the one
404
+ * to watch to shed load before an allocation fails — a refused
405
+ * `memory.grow` throws [`OutOfMemory`](oom) and ends the instance.
406
+ * It never falls: freed Rust values return to the allocator for reuse,
407
+ * but wasm cannot hand pages back to the host. So a drop in demand
408
+ * leaves the number where its peak left it, and only a fresh instance
409
+ * resets it.
410
+ *
411
+ * Module-wide, not per-`Renderer`. For what a given renderer is
412
+ * holding, and which bank to evict, call `memoryUsage()`.
413
+ * @returns {number}
414
+ */
415
+ export function heapBytes() {
416
+ const ret = wasm.heapBytes();
417
+ return ret >>> 0;
418
+ }
419
+
302
420
  /**
303
421
  * Whether the wasm binary was compiled with `+simd128`. Lets the demo
304
422
  * page label the renderer build accurately.
@@ -323,29 +441,29 @@ export function threadsEnabled() {
323
441
  function __wbg_get_imports() {
324
442
  const import0 = {
325
443
  __proto__: null,
326
- __wbg___wbindgen_boolean_get_2304fb8c853028c8: function(arg0) {
444
+ __wbg___wbindgen_boolean_get_fa956cfa2d1bd751: function(arg0) {
327
445
  const v = arg0;
328
446
  const ret = typeof(v) === 'boolean' ? v : undefined;
329
447
  return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
330
448
  },
331
- __wbg___wbindgen_is_null_2042690d351e14f0: function(arg0) {
449
+ __wbg___wbindgen_is_null_ea9085d691f535d3: function(arg0) {
332
450
  const ret = arg0 === null;
333
451
  return ret;
334
452
  },
335
- __wbg___wbindgen_is_undefined_35bb9f4c7fd651d5: function(arg0) {
453
+ __wbg___wbindgen_is_undefined_c05833b95a3cf397: function(arg0) {
336
454
  const ret = arg0 === undefined;
337
455
  return ret;
338
456
  },
339
- __wbg___wbindgen_number_get_f73a1244370fcc2c: function(arg0, arg1) {
457
+ __wbg___wbindgen_number_get_394265ed1e1b84ee: function(arg0, arg1) {
340
458
  const obj = arg1;
341
459
  const ret = typeof(obj) === 'number' ? obj : undefined;
342
460
  getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
343
461
  getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
344
462
  },
345
- __wbg___wbindgen_rethrow_2b7cc655458909c2: function(arg0) {
463
+ __wbg___wbindgen_rethrow_4915403b40f010b4: function(arg0) {
346
464
  throw arg0;
347
465
  },
348
- __wbg___wbindgen_string_get_d109740c0d18f4d7: function(arg0, arg1) {
466
+ __wbg___wbindgen_string_get_b0ca35b86a603356: function(arg0, arg1) {
349
467
  const obj = arg1;
350
468
  const ret = typeof(obj) === 'string' ? obj : undefined;
351
469
  var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc_command_export, wasm.__wbindgen_realloc_command_export);
@@ -353,10 +471,10 @@ function __wbg_get_imports() {
353
471
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
354
472
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
355
473
  },
356
- __wbg___wbindgen_throw_9c31b086c2b26051: function(arg0, arg1) {
474
+ __wbg___wbindgen_throw_344f42d3211c4765: function(arg0, arg1) {
357
475
  throw new Error(getStringFromWasm0(arg0, arg1));
358
476
  },
359
- __wbg_call_dfde26266607c996: function() { return handleError(function (arg0, arg1, arg2) {
477
+ __wbg_call_a6e5c5dce5018821: function() { return handleError(function (arg0, arg1, arg2) {
360
478
  const ret = arg0.call(arg1, arg2);
361
479
  return ret;
362
480
  }, arguments); },
@@ -371,15 +489,15 @@ function __wbg_get_imports() {
371
489
  wasm.__wbindgen_free_command_export(deferred0_0, deferred0_1, 1);
372
490
  }
373
491
  },
374
- __wbg_get_98fdf51d029a75eb: function(arg0, arg1) {
492
+ __wbg_get_507a50627bffa49b: function(arg0, arg1) {
375
493
  const ret = arg0[arg1 >>> 0];
376
494
  return ret;
377
495
  },
378
- __wbg_get_dcf82ab8aad1a593: function() { return handleError(function (arg0, arg1) {
496
+ __wbg_get_78f252d074a84d0b: function() { return handleError(function (arg0, arg1) {
379
497
  const ret = Reflect.get(arg0, arg1);
380
498
  return ret;
381
499
  }, arguments); },
382
- __wbg_instanceof_Object_03924e0dbda74bd8: function(arg0) {
500
+ __wbg_instanceof_Object_33f20e6f12439f3e: function(arg0) {
383
501
  let result;
384
502
  try {
385
503
  result = arg0 instanceof Object;
@@ -389,43 +507,43 @@ function __wbg_get_imports() {
389
507
  const ret = result;
390
508
  return ret;
391
509
  },
392
- __wbg_isArray_94898ed3aad6947b: function(arg0) {
510
+ __wbg_isArray_0677c962b281d01a: function(arg0) {
393
511
  const ret = Array.isArray(arg0);
394
512
  return ret;
395
513
  },
396
- __wbg_length_2591a0f4f659a55c: function(arg0) {
514
+ __wbg_length_370319915dc99107: function(arg0) {
397
515
  const ret = arg0.length;
398
516
  return ret;
399
517
  },
400
- __wbg_new_02d162bc6cf02f60: function() {
401
- const ret = new Object();
518
+ __wbg_new_227d7c05414eb861: function() {
519
+ const ret = new Error();
402
520
  return ret;
403
521
  },
404
- __wbg_new_1f236d63ba0c4784: function(arg0, arg1) {
405
- const ret = new Error(getStringFromWasm0(arg0, arg1));
522
+ __wbg_new_32b398fb48b6d94a: function() {
523
+ const ret = new Array();
406
524
  return ret;
407
525
  },
408
- __wbg_new_227d7c05414eb861: function() {
409
- const ret = new Error();
526
+ __wbg_new_b667d279fd5aa943: function(arg0, arg1) {
527
+ const ret = new Error(getStringFromWasm0(arg0, arg1));
410
528
  return ret;
411
529
  },
412
- __wbg_new_310879b66b6e95e1: function() {
413
- const ret = new Array();
530
+ __wbg_new_da52cf8fe3429cb2: function() {
531
+ const ret = new Object();
414
532
  return ret;
415
533
  },
416
- __wbg_now_81363d44c96dd239: function() {
534
+ __wbg_now_86c0d4ba3fa605b8: function() {
417
535
  const ret = Date.now();
418
536
  return ret;
419
537
  },
420
- __wbg_push_b77c476b01548d0a: function(arg0, arg1) {
538
+ __wbg_push_d2ae3af0c1217ae6: function(arg0, arg1) {
421
539
  const ret = arg0.push(arg1);
422
540
  return ret;
423
541
  },
424
- __wbg_set_a0e911be3da02782: function() { return handleError(function (arg0, arg1, arg2) {
542
+ __wbg_set_8535240470bf2500: function() { return handleError(function (arg0, arg1, arg2) {
425
543
  const ret = Reflect.set(arg0, arg1, arg2);
426
544
  return ret;
427
545
  }, arguments); },
428
- __wbg_set_name_e500733c75ec36b0: function(arg0, arg1, arg2) {
546
+ __wbg_set_name_3bbc583faefa4193: function(arg0, arg1, arg2) {
429
547
  arg0.name = getStringFromWasm0(arg1, arg2);
430
548
  },
431
549
  __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;
@@ -9,5 +9,5 @@ glue.__wbg_set_wasm(instance.exports);
9
9
  instance.exports.__wbindgen_start();
10
10
 
11
11
  export {
12
- LogSink, Renderer, simdEnabled, threadsEnabled
12
+ LogSink, Renderer, heapBytes, simdEnabled, threadsEnabled
13
13
  } from "../bundler/ezu_bg.js";
package/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;