isard 2.0.0 → 2.1.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/CHANGELOG.md +32 -0
  2. package/README.md +1 -1
  3. package/dist/basemap/vectortiles/vectors.d.ts +3 -1
  4. package/dist/basemap/vectortiles/vectors.js +2 -0
  5. package/dist/basemap/vectortiles/vectors.js.map +1 -1
  6. package/dist/basemap/vectortiles.d.ts +1 -3
  7. package/dist/basemap/vectortiles.js +1 -3
  8. package/dist/basemap/vectortiles.js.map +1 -1
  9. package/dist/bind/layers.js +2 -2
  10. package/dist/bind/layers.js.map +1 -1
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/isard_webgl2_bg.wasm +0 -0
  14. package/dist/isard_webgpu_bg.wasm +0 -0
  15. package/dist/layers/extrusions.d.ts +6 -1
  16. package/dist/layers/extrusions.js +15 -4
  17. package/dist/layers/extrusions.js.map +1 -1
  18. package/dist/layers/ground.d.ts +1 -1
  19. package/dist/layers/ground.js +1 -1
  20. package/dist/layers/ground.js.map +1 -1
  21. package/dist/layers/layers.js +1 -1
  22. package/dist/layers/layers.js.map +1 -1
  23. package/dist/layers/models.d.ts +7 -1
  24. package/dist/layers/models.js +19 -1
  25. package/dist/layers/models.js.map +1 -1
  26. package/dist/layers/pointclouds.d.ts +2 -2
  27. package/dist/layers/pointclouds.js +3 -3
  28. package/dist/layers/pointclouds.js.map +1 -1
  29. package/dist/layers/raster.js +5 -0
  30. package/dist/layers/raster.js.map +1 -1
  31. package/dist/layers/tiles3d.d.ts +4 -6
  32. package/dist/layers/tiles3d.js +9 -14
  33. package/dist/layers/tiles3d.js.map +1 -1
  34. package/dist/layers/vectors.d.ts +6 -0
  35. package/dist/layers/vectors.js +18 -1
  36. package/dist/layers/vectors.js.map +1 -1
  37. package/dist/map/engine-settings.d.ts +4 -1
  38. package/dist/map/engine-settings.js +13 -2
  39. package/dist/map/engine-settings.js.map +1 -1
  40. package/dist/map/layer-stack.d.ts +5 -6
  41. package/dist/map/layer-stack.js +5 -6
  42. package/dist/map/layer-stack.js.map +1 -1
  43. package/dist/map.d.ts +22 -9
  44. package/dist/map.js +52 -16
  45. package/dist/map.js.map +1 -1
  46. package/dist/react/VectorGeometry.d.ts +4 -1
  47. package/dist/react/VectorGeometry.js +5 -1
  48. package/dist/react/VectorGeometry.js.map +1 -1
  49. package/dist/settings.d.ts +2 -0
  50. package/dist/settings.js +1 -1
  51. package/dist/settings.js.map +1 -1
  52. package/dist/types.d.ts +23 -4
  53. package/dist/types.js.map +1 -1
  54. package/dist/wasm/isard_webgl2.d.ts +21 -7
  55. package/dist/wasm/isard_webgl2.js +42 -21
  56. package/dist/wasm/isard_webgpu.d.ts +21 -7
  57. package/dist/wasm/isard_webgpu.js +42 -21
  58. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  /**
2
- * The drawing order of a map's layers, kept beside the engine's: the layers waiting for the engine with 3D Tiles are
3
- * in the order but not in the engine yet, and the order recreates the layers in a new engine after a context loss.
2
+ * The drawing order of a map's layers, kept beside the engine's: it recreates the layers in a new engine after a
3
+ * context loss; a layer whose creation failed stays in the order, not in the engine.
4
4
  */
5
5
  import type { Layer } from '../layers/layers.ts';
6
6
  import type { Engine } from '../wasm/isard_webgpu.js';
@@ -24,13 +24,12 @@ export declare class LayerStack {
24
24
  replace(layer: Layer, old: number): void;
25
25
  /** Moves a layer under all the others */
26
26
  toBottom(layer: Layer): void;
27
- /** Creates the layers in a new engine, in order, but those still `waiting` (for the engine with 3D Tiles); a layer
28
- * that fails is reported and left out */
27
+ /** Creates the layers in a new engine, in order; a layer that fails is reported and left out */
29
28
  reattach(engine: Engine): void;
30
- /** Frees what the layers hold beside the engine (custom layers' WebGL objects, models' data) */
29
+ /** Frees what the layers hold beside the engine (custom layers' GPU objects, models' data) */
31
30
  dispose(): void;
32
31
  /** Takes a layer out of the drawing order (to put it back elsewhere, or for good) */
33
32
  private unlist;
34
- /** Index in the engine of the layer at `index`: the layers waiting for the engine with 3D Tiles are not in it yet */
33
+ /** Index in the engine of the layer at `index`: the layers without an id (their creation failed) are not in it */
35
34
  private engineIndex;
36
35
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
- * The drawing order of a map's layers, kept beside the engine's: the layers waiting for the engine with 3D Tiles are
3
- * in the order but not in the engine yet, and the order recreates the layers in a new engine after a context loss.
2
+ * The drawing order of a map's layers, kept beside the engine's: it recreates the layers in a new engine after a
3
+ * context loss; a layer whose creation failed stays in the order, not in the engine.
4
4
  */
5
5
  import { report } from "./checks.js";
6
6
  /** A map's layers in drawing order, bottom first, and those kept on top */
@@ -52,8 +52,7 @@ export class LayerStack {
52
52
  this.unlist(layer);
53
53
  this.layers.unshift(layer);
54
54
  }
55
- /** Creates the layers in a new engine, in order, but those still `waiting` (for the engine with 3D Tiles); a layer
56
- * that fails is reported and left out */
55
+ /** Creates the layers in a new engine, in order; a layer that fails is reported and left out */
57
56
  reattach(engine) {
58
57
  // No layer refers to an id of the old engine while the others are created
59
58
  this.layers.forEach((layer) => {
@@ -79,7 +78,7 @@ export class LayerStack {
79
78
  }
80
79
  });
81
80
  }
82
- /** Frees what the layers hold beside the engine (custom layers' WebGL objects, models' data) */
81
+ /** Frees what the layers hold beside the engine (custom layers' GPU objects, models' data) */
83
82
  dispose() {
84
83
  this.layers.forEach((layer) => {
85
84
  layer.dispose();
@@ -91,7 +90,7 @@ export class LayerStack {
91
90
  if (index >= 0)
92
91
  this.layers.splice(index, 1);
93
92
  }
94
- /** Index in the engine of the layer at `index`: the layers waiting for the engine with 3D Tiles are not in it yet */
93
+ /** Index in the engine of the layer at `index`: the layers without an id (their creation failed) are not in it */
95
94
  engineIndex(index) {
96
95
  return this.layers.slice(0, index).filter((layer) => layer.id >= 0).length;
97
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"layer-stack.js","sourceRoot":"","sources":["../../src/map/layer-stack.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The drawing order of a map's layers, kept beside the engine's: the layers waiting for the engine with 3D Tiles are\n * in the order but not in the engine yet, and the order recreates the layers in a new engine after a context loss.\n */\n\nimport type { Layer } from '../layers/layers.ts';\nimport type { Engine } from '../wasm/isard_webgpu.js';\nimport { report } from './checks.ts';\n\n/** A map's layers in drawing order, bottom first, and those kept on top */\nexport class LayerStack {\n /** Layers in drawing order (bottom first), to recreate them after a context loss */\n readonly layers: Layer[] = [];\n /** Layers new layers go under */\n readonly onTop = new Set<Layer>();\n private readonly engine: () => Engine;\n\n /** `engine`: the map's engine of the moment */\n constructor(engine: () => Engine) {\n this.engine = engine;\n }\n\n has(layer: Layer): boolean {\n return this.layers.includes(layer);\n }\n\n /** Puts a new layer on top, under the layers kept on top (the basemap's labels) */\n add(layer: Layer): void {\n this.layers.push(layer);\n\n const top = this.layers.find((l) => this.onTop.has(l) && l !== layer);\n\n if (top) this.move(layer, top);\n }\n\n /** Forgets a removed layer */\n forget(layer: Layer): void {\n this.unlist(layer);\n this.onTop.delete(layer);\n }\n\n /** Moves a layer under `before`, or on top of all */\n move(layer: Layer, before: Layer | undefined): void {\n this.unlist(layer);\n\n const index = before ? this.layers.indexOf(before) : -1;\n const at = index < 0 ? this.layers.length : index;\n\n this.layers.splice(at, 0, layer);\n if (layer.id >= 0) this.engine().moveLayer(layer.id, this.engineIndex(at));\n }\n\n /** A layer made again in the engine under a new id: `old` removed, the new one moved to the layer's place */\n replace(layer: Layer, old: number): void {\n const engine = this.engine();\n\n engine.removeLayer(old);\n\n const index = this.layers.indexOf(layer);\n\n if (index >= 0) engine.moveLayer(layer.id, this.engineIndex(index));\n }\n\n /** Moves a layer under all the others */\n toBottom(layer: Layer): void {\n this.engine().moveLayer(layer.id, 0);\n this.unlist(layer);\n this.layers.unshift(layer);\n }\n\n /** Creates the layers in a new engine, in order, but those still `waiting` (for the engine with 3D Tiles); a layer\n * that fails is reported and left out */\n reattach(engine: Engine): void {\n // No layer refers to an id of the old engine while the others are created\n this.layers.forEach((layer) => {\n layer.forgetEngine();\n });\n this.layers.forEach((layer) => {\n try {\n layer.attach(engine);\n } catch (error) {\n report(error);\n }\n });\n // Links between layers, once every layer has its new id (buildings colored by a network above them)\n this.layers.forEach((layer) => {\n if (layer.id < 0) return;\n try {\n layer.relink(engine);\n } catch (error) {\n report(error);\n }\n });\n }\n\n /** Frees what the layers hold beside the engine (custom layers' WebGL objects, models' data) */\n dispose(): void {\n this.layers.forEach((layer) => {\n layer.dispose();\n });\n }\n\n /** Takes a layer out of the drawing order (to put it back elsewhere, or for good) */\n private unlist(layer: Layer): void {\n const index = this.layers.indexOf(layer);\n\n if (index >= 0) this.layers.splice(index, 1);\n }\n\n /** Index in the engine of the layer at `index`: the layers waiting for the engine with 3D Tiles are not in it yet */\n private engineIndex(index: number): number {\n return this.layers.slice(0, index).filter((layer) => layer.id >= 0).length;\n }\n}\n"]}
1
+ {"version":3,"file":"layer-stack.js","sourceRoot":"","sources":["../../src/map/layer-stack.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The drawing order of a map's layers, kept beside the engine's: it recreates the layers in a new engine after a\n * context loss; a layer whose creation failed stays in the order, not in the engine.\n */\n\nimport type { Layer } from '../layers/layers.ts';\nimport type { Engine } from '../wasm/isard_webgpu.js';\nimport { report } from './checks.ts';\n\n/** A map's layers in drawing order, bottom first, and those kept on top */\nexport class LayerStack {\n /** Layers in drawing order (bottom first), to recreate them after a context loss */\n readonly layers: Layer[] = [];\n /** Layers new layers go under */\n readonly onTop = new Set<Layer>();\n private readonly engine: () => Engine;\n\n /** `engine`: the map's engine of the moment */\n constructor(engine: () => Engine) {\n this.engine = engine;\n }\n\n has(layer: Layer): boolean {\n return this.layers.includes(layer);\n }\n\n /** Puts a new layer on top, under the layers kept on top (the basemap's labels) */\n add(layer: Layer): void {\n this.layers.push(layer);\n\n const top = this.layers.find((l) => this.onTop.has(l) && l !== layer);\n\n if (top) this.move(layer, top);\n }\n\n /** Forgets a removed layer */\n forget(layer: Layer): void {\n this.unlist(layer);\n this.onTop.delete(layer);\n }\n\n /** Moves a layer under `before`, or on top of all */\n move(layer: Layer, before: Layer | undefined): void {\n this.unlist(layer);\n\n const index = before ? this.layers.indexOf(before) : -1;\n const at = index < 0 ? this.layers.length : index;\n\n this.layers.splice(at, 0, layer);\n if (layer.id >= 0) this.engine().moveLayer(layer.id, this.engineIndex(at));\n }\n\n /** A layer made again in the engine under a new id: `old` removed, the new one moved to the layer's place */\n replace(layer: Layer, old: number): void {\n const engine = this.engine();\n\n engine.removeLayer(old);\n\n const index = this.layers.indexOf(layer);\n\n if (index >= 0) engine.moveLayer(layer.id, this.engineIndex(index));\n }\n\n /** Moves a layer under all the others */\n toBottom(layer: Layer): void {\n this.engine().moveLayer(layer.id, 0);\n this.unlist(layer);\n this.layers.unshift(layer);\n }\n\n /** Creates the layers in a new engine, in order; a layer that fails is reported and left out */\n reattach(engine: Engine): void {\n // No layer refers to an id of the old engine while the others are created\n this.layers.forEach((layer) => {\n layer.forgetEngine();\n });\n this.layers.forEach((layer) => {\n try {\n layer.attach(engine);\n } catch (error) {\n report(error);\n }\n });\n // Links between layers, once every layer has its new id (buildings colored by a network above them)\n this.layers.forEach((layer) => {\n if (layer.id < 0) return;\n try {\n layer.relink(engine);\n } catch (error) {\n report(error);\n }\n });\n }\n\n /** Frees what the layers hold beside the engine (custom layers' GPU objects, models' data) */\n dispose(): void {\n this.layers.forEach((layer) => {\n layer.dispose();\n });\n }\n\n /** Takes a layer out of the drawing order (to put it back elsewhere, or for good) */\n private unlist(layer: Layer): void {\n const index = this.layers.indexOf(layer);\n\n if (index >= 0) this.layers.splice(index, 1);\n }\n\n /** Index in the engine of the layer at `index`: the layers without an id (their creation failed) are not in it */\n private engineIndex(index: number): number {\n return this.layers.slice(0, index).filter((layer) => layer.id >= 0).length;\n }\n}\n"]}
package/dist/map.d.ts CHANGED
@@ -26,7 +26,7 @@ import { Tiles3dLayer } from './layers/tiles3d.ts';
26
26
  import { type TreeOptions } from './layers/trees.ts';
27
27
  import { type HoverPicking } from './map/hover-pick.ts';
28
28
  import { type LayerSpec } from './map/layer-spec.ts';
29
- import type { AnimationOptions, AtmosphereOptions, Basemap, FeatureHit, FirstPersonView, FlyToOptions, GeoMapOptions, LoadingMode, LonLat, MapEvents, MapGpuTimings, NetworkOptions, PickOptions, Point, Projection, Quality, RasterOptions, SunOptions, SwipeOptions, TerrainModel, TerrainOptions, Tiles3dOptions, ViewshedOptions } from './types.ts';
29
+ import type { AnimationOptions, AtmosphereOptions, Basemap, FeatureHit, FirstPersonView, FlyToOptions, GeoMapOptions, LoadingMode, LonLat, MapEvents, MapGpuTimings, MapMemory, NetworkOptions, PickOptions, Point, Projection, Quality, RasterOptions, SunOptions, SwipeOptions, TerrainModel, TerrainOptions, Tiles3dOptions, ViewshedOptions } from './types.ts';
30
30
  import { type Control, type ControlPosition } from './ui/controls.ts';
31
31
  import type { Camera, PickHit, RasterLayerStats } from './wasm/isard_webgpu.js';
32
32
  export type { LayerSpec } from './map/layer-spec.ts';
@@ -35,7 +35,7 @@ export declare class GeoMap {
35
35
  readonly canvas: HTMLCanvasElement;
36
36
  /** The frames' parts timed on the GPU (`setGpuTiming`), again on a new engine */
37
37
  private gpuTiming;
38
- /** The engine class (core, or with 3D Tiles) and the engine with 3D Tiles loaded when needed */
38
+ /** The engine, made asynchronously, and the workers decoding its 3D Tiles */
39
39
  private readonly engines;
40
40
  /** The layers in drawing order and those kept on top */
41
41
  private readonly stack;
@@ -49,7 +49,7 @@ export declare class GeoMap {
49
49
  /** The canvas in the container, the markers and popups over it, the controls in its corners */
50
50
  private readonly overlays;
51
51
  private readonly settings;
52
- /** The WebGL context is lost: nothing is drawn until it is restored */
52
+ /** The GPU is lost (the WebGL context, the WebGPU device): nothing is drawn until a new engine is there */
53
53
  private lost;
54
54
  private gone;
55
55
  private readonly listeners;
@@ -85,6 +85,15 @@ export declare class GeoMap {
85
85
  private get layers();
86
86
  /** Layers new layers go under */
87
87
  private get onTop();
88
+ /** The GPU is lost: nothing drawn, the engine dropped (`dropLostEngine`) */
89
+ private gpuLost;
90
+ /**
91
+ * Follows the loss of `engine`'s WebGPU device (a phone taking its memory back, a driver reset, the GPU process
92
+ * gone): while it is the map's, the map drops it and makes a new one at once, WebGPU having no event for the GPU
93
+ * given back. The device of an engine the map freed itself (replaced, the map destroyed) is lost too: not the map's
94
+ * any more, left be
95
+ */
96
+ private watchDevice;
88
97
  /**
89
98
  * The context is lost: its engine freed at once, the map's calls going to one that does nothing until `restore`
90
99
  * builds the next. The old engine's GPU objects went with the context: deleted now, it is silent (on the context
@@ -92,8 +101,8 @@ export declare class GeoMap {
92
101
  * would fail on the lost context, whose limits read 0
93
102
  */
94
103
  private dropLostEngine;
95
- /** After a context loss: a new engine with the same camera, settings and layers (same handles, same order); the
96
- * engine made asynchronously, adopted once there */
104
+ /** After the GPU lost: a new engine with the same camera, settings and layers (same handles, same order); the engine
105
+ * made asynchronously, adopted once there */
97
106
  private restore;
98
107
  /** A new engine in place of the map's (a placeholder, or a lost one): the same camera, settings and layers (same
99
108
  * handles, same order) */
@@ -178,6 +187,9 @@ export declare class GeoMap {
178
187
  setTerrain(terrain: boolean | TerrainModel | TerrainOptions): void;
179
188
  /** Color behind the map, a CSS color (its alpha ignored) */
180
189
  setBackground(color: string): void;
190
+ /** The GPU memory its layers hold (bytes): the tiles of the 3D Tiles and point clouds, kept within the budget
191
+ * (`GeoMapOptions.memory`), the rasters' pools */
192
+ memory(): MapMemory;
181
193
  /** Tile counters of the raster layers, for diagnostics */
182
194
  stats(): RasterLayerStats[];
183
195
  /** Times the parts of each frame on the GPU, for profiling (`gpuTimings`): timer queries, read a few frames later.
@@ -296,7 +308,7 @@ export declare class GeoMap {
296
308
  addTiles3d(options: Tiles3dOptions): Tiles3dLayer;
297
309
  /**
298
310
  * A point cloud (see `PointCloudOptions`): a COPC file read by range requests (IGN's LiDAR HD…), or 3D Tiles
299
- * points; with depth, on the engine with 3D Tiles; under `before` if given
311
+ * points; with depth; under `before` if given
300
312
  */
301
313
  addPointCloud(options: PointCloudOptions): PointCloudLayer;
302
314
  /**
@@ -311,7 +323,7 @@ export declare class GeoMap {
311
323
  /** Particles carried by a field of velocities (a wind, a current), their trails animated and colored by speed on
312
324
  * the globe and the relief (see `FlowOptions`) */
313
325
  addFlow(options: FlowOptions): FlowLayer;
314
- /** A glTF model drawn at positions (see `ModelOptions`), with depth; on the engine with 3D Tiles, as they are */
326
+ /** A glTF model drawn at positions (see `ModelOptions`), with depth */
315
327
  addModels(options: ModelOptions): ModelLayer;
316
328
  /** Trees at the points of a source that has them (a city's street trees), broadleaved or conifers by their data,
317
329
  * scaled to their height (see `TreeOptions`); the conifers on a layer that goes with the one returned */
@@ -320,8 +332,9 @@ export declare class GeoMap {
320
332
  * view, a 360° one on a band round its camera; resolves once its image is read */
321
333
  addPhoto(options: PhotoOptions): Promise<ModelLayer>;
322
334
  /**
323
- * The page's own WebGL drawing at its place among the layers, in every frame (see `CustomLayerInterface`): raw
324
- * WebGL, three.js… with the matrices of the frame (`frame.matrixAt`); under `before` if given
335
+ * The page's own WebGPU drawing at its place among the layers, in every frame (see `CustomLayerInterface`): raw
336
+ * WebGPU, three.js's WebGPU renderer… with the map's device and the matrices of the frame (`frame.matrixAt`); under
337
+ * `before` if given. Not drawn on the WebGL2 fallback
325
338
  */
326
339
  addCustomLayer(layer: CustomLayerInterface, options?: {
327
340
  before?: Layer;
package/dist/map.js CHANGED
@@ -82,7 +82,7 @@ export class GeoMap {
82
82
  gpuTiming = false;
83
83
  /** The work the map waits on before it is idle (`track`) */
84
84
  #working = 0;
85
- /** The engine class (core, or with 3D Tiles) and the engine with 3D Tiles loaded when needed */
85
+ /** The engine, made asynchronously, and the workers decoding its 3D Tiles */
86
86
  engines;
87
87
  /** The layers in drawing order and those kept on top */
88
88
  stack = new LayerStack(() => this.#engine);
@@ -100,7 +100,7 @@ export class GeoMap {
100
100
  tessUrl;
101
101
  /** @internal Where the workers load the grid module from (`isard_grid_bg.wasm`) */
102
102
  gridUrl;
103
- /** The WebGL context is lost: nothing is drawn until it is restored */
103
+ /** The GPU is lost (the WebGL context, the WebGPU device): nothing is drawn until a new engine is there */
104
104
  lost = false;
105
105
  gone = false;
106
106
  listeners = new MapListeners();
@@ -186,12 +186,9 @@ export class GeoMap {
186
186
  this.#engine = destroyedEngine(EARTH_START);
187
187
  // Once it has an engine: a map whose creation failed before is not left following them
188
188
  this.unwatchHeaders = onHeaderRules((rules) => sendHeaders(this.#engine, rules));
189
- // The browser may take the GPU away (driver reset, background tab on mobile): the map waits, then rebuilds
190
- this.unwatchContext = watchContext(this.canvas, () => {
191
- this.lost = true;
192
- this.frames.cancel();
193
- this.dropLostEngine();
194
- }, () => this.restore());
189
+ // The browser may take the GPU away (driver reset, background tab on mobile): the map waits, then rebuilds. A
190
+ // WebGPU device lost is watched with each engine (`adopt`)
191
+ this.unwatchContext = watchContext(this.canvas, () => this.gpuLost(), () => this.restore());
195
192
  const start = this.earth ? EARTH_START : BODY_START;
196
193
  this.setCamera({ ...start, ...options });
197
194
  this.setBasemap(options.basemap ?? (this.earth ? 'osm-positron' : 'none'), options.hillshade ?? 0);
@@ -240,6 +237,27 @@ export class GeoMap {
240
237
  get onTop() {
241
238
  return this.stack.onTop;
242
239
  }
240
+ /** The GPU is lost: nothing drawn, the engine dropped (`dropLostEngine`) */
241
+ gpuLost() {
242
+ this.lost = true;
243
+ this.frames.cancel();
244
+ this.dropLostEngine();
245
+ }
246
+ /**
247
+ * Follows the loss of `engine`'s WebGPU device (a phone taking its memory back, a driver reset, the GPU process
248
+ * gone): while it is the map's, the map drops it and makes a new one at once, WebGPU having no event for the GPU
249
+ * given back. The device of an engine the map freed itself (replaced, the map destroyed) is lost too: not the map's
250
+ * any more, left be
251
+ */
252
+ watchDevice(engine) {
253
+ void engine.gpuDevice()?.lost.then((info) => {
254
+ if (this.gone || this.#engine !== engine)
255
+ return;
256
+ console.warn(`isard: the GPU device was lost (${info.reason}: ${info.message}), the map made again`);
257
+ this.gpuLost();
258
+ this.restore();
259
+ });
260
+ }
243
261
  /**
244
262
  * The context is lost: its engine freed at once, the map's calls going to one that does nothing until `restore`
245
263
  * builds the next. The old engine's GPU objects went with the context: deleted now, it is silent (on the context
@@ -254,8 +272,8 @@ export class GeoMap {
254
272
  // Glyph ranges and icons arriving meanwhile upload to it, not to the freed engine
255
273
  this.atlases.attach(this.#engine);
256
274
  }
257
- /** After a context loss: a new engine with the same camera, settings and layers (same handles, same order); the
258
- * engine made asynchronously, adopted once there */
275
+ /** After the GPU lost: a new engine with the same camera, settings and layers (same handles, same order); the engine
276
+ * made asynchronously, adopted once there */
259
277
  restore() {
260
278
  if (this.gone)
261
279
  return;
@@ -276,6 +294,7 @@ export class GeoMap {
276
294
  this.#engine.free();
277
295
  this.#engine = engine;
278
296
  this.lost = false;
297
+ this.watchDevice(engine);
279
298
  // Still timed (profiling)
280
299
  if (this.gpuTiming)
281
300
  engineGpuTiming(engine, true);
@@ -572,6 +591,22 @@ export class GeoMap {
572
591
  this.engine.setBackground(...this.settings.background);
573
592
  this.requestRender();
574
593
  }
594
+ /** The GPU memory its layers hold (bytes): the tiles of the 3D Tiles and point clouds, kept within the budget
595
+ * (`GeoMapOptions.memory`), the rasters' pools */
596
+ memory() {
597
+ // Two numbers a layer, its id and its bytes, the relief's (id 0) last
598
+ const pairs = this.engine.memory();
599
+ const byId = new Map(Array.from({ length: pairs.length / 2 }, (_, i) => [pairs[2 * i], pairs[2 * i + 1] ?? 0]));
600
+ const layers = this.layers.flatMap((layer) => {
601
+ const bytes = layer.id >= 0 ? byId.get(layer.id) : undefined;
602
+ return bytes === undefined ? [] : [{ layer, bytes }];
603
+ });
604
+ return {
605
+ budget: this.settings.memory,
606
+ held: [...byId.values()].reduce((sum, bytes) => sum + bytes, 0),
607
+ layers,
608
+ };
609
+ }
575
610
  /** Tile counters of the raster layers, for diagnostics */
576
611
  stats() {
577
612
  return this.engine.stats();
@@ -817,7 +852,7 @@ export class GeoMap {
817
852
  }
818
853
  /** Polygons raised into blocks with depth (buildings), styled per feature; tiles of them come with `setTile` */
819
854
  addExtrusions(options = {}) {
820
- return this.place(new ExtrusionLayer(this, options.data, extrusionStyle(options)), options.before);
855
+ return this.place(new ExtrusionLayer(this, options.data, extrusionStyle(options), options.drape), options.before);
821
856
  }
822
857
  /** Text labels from GeoJSON (points, the middle of lines, the center of polygons), placed without overlaps */
823
858
  addSymbols(options) {
@@ -894,7 +929,7 @@ export class GeoMap {
894
929
  }
895
930
  /**
896
931
  * A point cloud (see `PointCloudOptions`): a COPC file read by range requests (IGN's LiDAR HD…), or 3D Tiles
897
- * points; with depth, on the engine with 3D Tiles; under `before` if given
932
+ * points; with depth; under `before` if given
898
933
  */
899
934
  addPointCloud(options) {
900
935
  return this.place(new PointCloudLayer(this, options), options.before);
@@ -913,7 +948,7 @@ export class GeoMap {
913
948
  addFlow(options) {
914
949
  return this.place(new FlowLayer(this, options), options.before);
915
950
  }
916
- /** A glTF model drawn at positions (see `ModelOptions`), with depth; on the engine with 3D Tiles, as they are */
951
+ /** A glTF model drawn at positions (see `ModelOptions`), with depth */
917
952
  addModels(options) {
918
953
  return this.place(new ModelLayer(this, options), options.before);
919
954
  }
@@ -928,8 +963,9 @@ export class GeoMap {
928
963
  return addPhoto((o) => this.addModels(o), options);
929
964
  }
930
965
  /**
931
- * The page's own WebGL drawing at its place among the layers, in every frame (see `CustomLayerInterface`): raw
932
- * WebGL, three.js… with the matrices of the frame (`frame.matrixAt`); under `before` if given
966
+ * The page's own WebGPU drawing at its place among the layers, in every frame (see `CustomLayerInterface`): raw
967
+ * WebGPU, three.js's WebGPU renderer… with the map's device and the matrices of the frame (`frame.matrixAt`); under
968
+ * `before` if given. Not drawn on the WebGL2 fallback
933
969
  */
934
970
  addCustomLayer(layer, options = {}) {
935
971
  const custom = new CustomLayer(this, layer, this, (lon, lat, altitude) => this.engines.customMatrix(lon, lat, altitude), () => this.getCamera());
@@ -990,7 +1026,7 @@ export class GeoMap {
990
1026
  this.resizeObserver.disconnect();
991
1027
  this.interaction?.destroy();
992
1028
  this.engines.destroy();
993
- // Custom layers free their WebGL objects, models their data, while the context is there
1029
+ // Custom layers free their GPU objects, models their data, while the device is there
994
1030
  this.stack.dispose();
995
1031
  this.engine.free();
996
1032
  // Work still under way (labels being shaped, tiles arriving, timers) may call the engine after this: it finds one