@luma.gl/webgl 9.1.1 → 9.1.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luma.gl/webgl",
3
- "version": "9.1.1",
3
+ "version": "9.1.3",
4
4
  "description": "WebGL2 adapter for the luma.gl core API",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -43,9 +43,9 @@
43
43
  "@luma.gl/core": "^9.1.0"
44
44
  },
45
45
  "dependencies": {
46
- "@luma.gl/constants": "9.1.1",
46
+ "@luma.gl/constants": "9.1.3",
47
47
  "@math.gl/types": "^4.1.0",
48
48
  "@probe.gl/env": "^4.0.8"
49
49
  },
50
- "gitHead": "16a8a01740728ea0735d7d86fab21a677c3df0ce"
50
+ "gitHead": "3aecf478bad9719e6de3192c7d07b35aa8544efe"
51
51
  }
@@ -89,7 +89,7 @@ export class WebGLAdapter extends Adapter {
89
89
 
90
90
  // Log some debug info about the newly created context
91
91
  const message = `\
92
- Created ${device.type}${device.debug ? ' debug' : ''} context: \
92
+ ${device._reused ? 'Reusing' : 'Created'} device with WebGL2 ${device.debug ? 'debug ' : ''}context: \
93
93
  ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContext.id}`;
94
94
  log.probe(LOG_LEVEL, message)();
95
95
  log.table(LOG_LEVEL, device.info)();
@@ -78,20 +78,21 @@ export class WebGLDevice extends Device {
78
78
  /** type of this device */
79
79
  readonly type = 'webgl';
80
80
 
81
+ // Use the ! assertion to handle the case where _reuseDevices causes the constructor to return early
81
82
  /** The underlying WebGL context */
82
- readonly handle: WebGL2RenderingContext;
83
- features: WebGLDeviceFeatures;
84
- limits: WebGLDeviceLimits;
83
+ readonly handle!: WebGL2RenderingContext;
84
+ features!: WebGLDeviceFeatures;
85
+ limits!: WebGLDeviceLimits;
85
86
 
86
- readonly info: DeviceInfo;
87
- readonly canvasContext: WebGLCanvasContext;
87
+ readonly info!: DeviceInfo;
88
+ readonly canvasContext!: WebGLCanvasContext;
88
89
 
89
90
  readonly lost: Promise<{reason: 'destroyed'; message: string}>;
90
91
 
91
92
  private _resolveContextLost?: (value: {reason: 'destroyed'; message: string}) => void;
92
93
 
93
94
  /** WebGL2 context. */
94
- readonly gl: WebGL2RenderingContext;
95
+ readonly gl!: WebGL2RenderingContext;
95
96
  readonly debug: boolean = false;
96
97
 
97
98
  /** State used by luma.gl classes: TODO - move to canvasContext*/
@@ -102,7 +103,7 @@ export class WebGLDevice extends Device {
102
103
  _polyfilled: boolean = false;
103
104
 
104
105
  /** Instance of Spector.js (if initialized) */
105
- spectorJS: Spector;
106
+ spectorJS!: Spector | null;
106
107
 
107
108
  //
108
109
  // Public API
@@ -111,13 +112,16 @@ export class WebGLDevice extends Device {
111
112
  constructor(props: DeviceProps) {
112
113
  super({...props, id: props.id || uid('webgl-device')});
113
114
 
115
+ const canvasContextProps = Device._getCanvasContextProps(props);
116
+
114
117
  // WebGL requires a canvas to be created before creating the context
115
- if (!props.createCanvasContext) {
118
+ if (!canvasContextProps) {
116
119
  throw new Error('WebGLDevice requires props.createCanvasContext to be set');
117
120
  }
118
- const canvasContextProps = props.createCanvasContext === true ? {} : props.createCanvasContext;
119
121
 
120
- // If attaching to an already attached context, return the attached device
122
+ // Check if the WebGL context is already associated with a device
123
+ // Note that this can be avoided in webgl2adapter.create() if
124
+ // DeviceProps._reuseDevices is set.
121
125
  // @ts-expect-error device is attached to context
122
126
  let device: WebGLDevice | undefined = canvasContextProps.canvas?.gl?.device;
123
127
  if (device) {
@@ -163,9 +167,20 @@ export class WebGLDevice extends Device {
163
167
  throw new Error('WebGL context creation failed');
164
168
  }
165
169
 
166
- // @ts-expect-error device is attached to context
170
+ // Note that the browser will only create one WebGL context per canvas.
171
+ // This means that a newly created gl context may already have a device attached to it.
172
+ // @ts-expect-error luma.gl stores a device reference on the context.
167
173
  device = gl.device;
168
174
  if (device) {
175
+ if (props._reuseDevices) {
176
+ log.log(
177
+ 1,
178
+ `Not creating a new Device, instead returning a reference to Device ${device.id} already attached to WebGL context`,
179
+ device
180
+ )();
181
+ device._reused = true;
182
+ return device;
183
+ }
169
184
  throw new Error(`WebGL context already attached to device ${device.id}`);
170
185
  }
171
186
 
@@ -179,6 +194,7 @@ export class WebGLDevice extends Device {
179
194
 
180
195
  // Instrument context
181
196
  (this.gl as any).device = this; // Update GL context: Link webgl context back to device
197
+ // TODO - remove, this is only used to detect debug contexts.
182
198
  (this.gl as any)._version = 2; // Update GL context: Store WebGL version field on gl context (HACK to identify debug contexts)
183
199
 
184
200
  // initialize luma Device fields
@@ -216,10 +232,26 @@ export class WebGLDevice extends Device {
216
232
  }
217
233
 
218
234
  /**
219
- * Destroys the context
220
- * @note Has no effect for WebGL browser contexts, there is no browser API for destroying contexts
235
+ * Destroys the device
236
+ *
237
+ * @note "Detaches" from the WebGL context unless _reuseDevices is true.
238
+ *
239
+ * @note The underlying WebGL context is not immediately destroyed,
240
+ * but may be destroyed later through normal JavaScript garbage collection.
241
+ * This is a fundamental limitation since WebGL does not offer any
242
+ * browser API for destroying WebGL contexts.
221
243
  */
222
- destroy(): void {}
244
+ destroy(): void {
245
+ // Note that deck.gl (especially in React strict mode) depends on being able
246
+ // to asynchronously create a Device against the same canvas (i.e. WebGL context)
247
+ // multiple times and getting the same device back. Since deck.gl is not aware
248
+ // of this sharing, it might call destroy() multiple times on the same device.
249
+ // Therefore we must do nothing in destroy() if props._reuseDevices is true
250
+ if (!this.props._reuseDevices && !this._reused) {
251
+ // Delete the reference to the device that we store on the WebGL context
252
+ delete (this.gl as any).device;
253
+ }
254
+ }
223
255
 
224
256
  get isLost(): boolean {
225
257
  return this.gl.isContextLost();