@luma.gl/webgl 9.1.0-beta.8 → 9.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 (47) hide show
  1. package/dist/adapter/converters/webgl-texture-table.js +1 -1
  2. package/dist/adapter/converters/webgl-texture-table.js.map +1 -1
  3. package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
  4. package/dist/adapter/resources/webgl-buffer.js +1 -3
  5. package/dist/adapter/resources/webgl-buffer.js.map +1 -1
  6. package/dist/adapter/resources/webgl-framebuffer.js +2 -2
  7. package/dist/adapter/resources/webgl-framebuffer.js.map +1 -1
  8. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  9. package/dist/adapter/resources/webgl-render-pass.js +2 -4
  10. package/dist/adapter/resources/webgl-render-pass.js.map +1 -1
  11. package/dist/adapter/resources/webgl-render-pipeline.d.ts +0 -1
  12. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  13. package/dist/adapter/resources/webgl-render-pipeline.js +4 -11
  14. package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -1
  15. package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
  16. package/dist/adapter/resources/webgl-shader.js +1 -5
  17. package/dist/adapter/resources/webgl-shader.js.map +1 -1
  18. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  19. package/dist/adapter/resources/webgl-texture.js +1 -6
  20. package/dist/adapter/resources/webgl-texture.js.map +1 -1
  21. package/dist/adapter/webgl-adapter.d.ts +2 -1
  22. package/dist/adapter/webgl-adapter.d.ts.map +1 -1
  23. package/dist/adapter/webgl-adapter.js +8 -2
  24. package/dist/adapter/webgl-adapter.js.map +1 -1
  25. package/dist/adapter/webgl-canvas-context.d.ts +6 -3
  26. package/dist/adapter/webgl-canvas-context.d.ts.map +1 -1
  27. package/dist/adapter/webgl-canvas-context.js +17 -6
  28. package/dist/adapter/webgl-canvas-context.js.map +1 -1
  29. package/dist/adapter/webgl-device.d.ts +6 -10
  30. package/dist/adapter/webgl-device.d.ts.map +1 -1
  31. package/dist/adapter/webgl-device.js +25 -23
  32. package/dist/adapter/webgl-device.js.map +1 -1
  33. package/dist/dist.dev.js +44 -44
  34. package/dist/dist.min.js +2 -2
  35. package/dist/index.cjs +44 -44
  36. package/dist/index.cjs.map +2 -2
  37. package/package.json +3 -3
  38. package/src/adapter/converters/webgl-texture-table.ts +2 -2
  39. package/src/adapter/resources/webgl-buffer.ts +1 -3
  40. package/src/adapter/resources/webgl-framebuffer.ts +2 -2
  41. package/src/adapter/resources/webgl-render-pass.ts +2 -5
  42. package/src/adapter/resources/webgl-render-pipeline.ts +5 -12
  43. package/src/adapter/resources/webgl-shader.ts +1 -7
  44. package/src/adapter/resources/webgl-texture.ts +1 -6
  45. package/src/adapter/webgl-adapter.ts +10 -3
  46. package/src/adapter/webgl-canvas-context.ts +19 -8
  47. package/src/adapter/webgl-device.ts +36 -38
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luma.gl/webgl",
3
- "version": "9.1.0-beta.8",
3
+ "version": "9.1.0",
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-alpha.1"
44
44
  },
45
45
  "dependencies": {
46
- "@luma.gl/constants": "9.1.0-beta.8",
46
+ "@luma.gl/constants": "9.1.0",
47
47
  "@math.gl/types": "^4.1.0",
48
48
  "@probe.gl/env": "^4.0.8"
49
49
  },
50
- "gitHead": "10846580c7a10c4cc48de01a4e5259cc0a00c249"
50
+ "gitHead": "e5cb5a93674bc7cc571c26dee4d2aef841fdff7f"
51
51
  }
@@ -148,8 +148,8 @@ export const WEBGL_TEXTURE_FORMATS: Record<TextureFormat, WebGLFormatInfo> = {
148
148
  'rgb9e5ufloat': {gl: GL.RGB9_E5}, // , filter: true},
149
149
  'rg11b10ufloat': {gl: GL.R11F_G11F_B10F, rb: true},
150
150
  'rgb10a2unorm': {gl: GL.RGB10_A2, rb: true},
151
- 'rgb10a2uint': {gl: GL.RGB10_A2UI, rb: true},
152
-
151
+ 'rgb10a2uint-webgl': {gl: GL.RGB10_A2UI, rb: true},
152
+
153
153
  // 48-bit formats
154
154
  'rgb16unorm-webgl': {gl: GL.RGB16_EXT}, // rgb not renderable
155
155
  'rgb16snorm-webgl': {gl: GL.RGB16_SNORM_EXT}, // rgb not renderable
@@ -33,9 +33,7 @@ export class WEBGLBuffer extends Buffer {
33
33
 
34
34
  const handle = typeof props === 'object' ? props.handle : undefined;
35
35
  this.handle = handle || this.gl.createBuffer();
36
- device._setWebGLDebugMetadata(this.handle, this, {
37
- spector: {...this.props, data: typeof this.props.data}
38
- });
36
+ device.setSpectorMetadata(this.handle, {...this.props, data: typeof this.props.data});
39
37
 
40
38
  // - In WebGL1, need to make sure we use GL.ELEMENT_ARRAY_BUFFER when initializing element buffers
41
39
  // otherwise buffer type will lock to generic (non-element) buffer
@@ -33,8 +33,8 @@ export class WEBGLFramebuffer extends Framebuffer {
33
33
  this.props.handle || isDefaultFramebuffer ? this.props.handle : this.gl.createFramebuffer();
34
34
 
35
35
  if (!isDefaultFramebuffer) {
36
- // default framebuffer handle is null, so we can't set debug metadata...
37
- device._setWebGLDebugMetadata(this.handle, this, {spector: this.props});
36
+ // default framebuffer handle is null, so we can't set spector metadata...
37
+ device.setSpectorMetadata(this.handle, {id: this.props.id, props: this.props});
38
38
 
39
39
  // Auto create textures for attachments if needed
40
40
  this.autoCreateAttachmentTextures();
@@ -9,7 +9,6 @@ import {GL, GLParameters} from '@luma.gl/constants';
9
9
  import {withGLParameters} from '../../context/state-tracker/with-parameters';
10
10
  import {setGLParameters} from '../../context/parameters/unified-parameter-api';
11
11
  import {WEBGLQuerySet} from './webgl-query-set';
12
- import {WEBGLFramebuffer} from './webgl-framebuffer';
13
12
 
14
13
  const COLOR_CHANNELS = [0x1, 0x2, 0x4, 0x8]; // GPUColorWrite RED, GREEN, BLUE, ALPHA
15
14
 
@@ -32,7 +31,7 @@ export class WEBGLRenderPass extends RenderPass {
32
31
  viewport = [0, 0, width, height];
33
32
  } else {
34
33
  // Instead of using our own book-keeping, we can just read the values from the WebGL context
35
- const [width, height] = device.getDefaultCanvasContext().getDrawingBufferSize();
34
+ const [width, height] = device.getCanvasContext().getDrawingBufferSize();
36
35
  viewport = [0, 0, width, height];
37
36
  }
38
37
  }
@@ -42,9 +41,7 @@ export class WEBGLRenderPass extends RenderPass {
42
41
  this.setParameters({viewport, ...this.props.parameters});
43
42
 
44
43
  // Specify mapping of draw buffer locations to color attachments
45
- const webglFramebuffer = this.props.framebuffer as WEBGLFramebuffer;
46
- // Default framebuffers can only be set to GL.BACK or GL.NONE
47
- if (webglFramebuffer?.handle) {
44
+ if (this.props.framebuffer) {
48
45
  const drawBuffers = this.props.framebuffer.colorAttachments.map(
49
46
  (_, i) => GL.COLOR_ATTACHMENT0 + i
50
47
  );
@@ -57,15 +57,11 @@ export class WEBGLRenderPipeline extends RenderPipeline {
57
57
  _uniformCount: number = 0;
58
58
  _uniformSetters: Record<string, Function> = {}; // TODO are these used?
59
59
 
60
- override get [Symbol.toStringTag]() {
61
- return 'WEBGLRenderPipeline';
62
- }
63
-
64
60
  constructor(device: WebGLDevice, props: RenderPipelineProps) {
65
61
  super(device, props);
66
62
  this.device = device;
67
63
  this.handle = this.props.handle || this.device.gl.createProgram();
68
- this.device._setWebGLDebugMetadata(this.handle, this, {spector: {id: this.props.id}});
64
+ this.device.setSpectorMetadata(this.handle, {id: this.props.id});
69
65
 
70
66
  // Create shaders if needed
71
67
  this.vs = props.vs as WEBGLShader;
@@ -82,9 +78,10 @@ export class WEBGLRenderPipeline extends RenderPipeline {
82
78
  }
83
79
 
84
80
  this._linkShaders();
85
- log.time(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
81
+
82
+ log.time(1, `RenderPipeline ${this.id} - shaderLayout introspection`)();
86
83
  this.introspectedLayout = getShaderLayoutFromGLSL(this.device.gl, this.handle);
87
- log.timeEnd(3, `RenderPipeline ${this.id} - shaderLayout introspection`)();
84
+ log.timeEnd(1, `RenderPipeline ${this.id} - shaderLayout introspection`)();
88
85
 
89
86
  // Merge provided layout with introspected layout
90
87
  this.shaderLayout = mergeShaderLayout(this.introspectedLayout, props.shaderLayout);
@@ -92,13 +89,9 @@ export class WEBGLRenderPipeline extends RenderPipeline {
92
89
 
93
90
  override destroy(): void {
94
91
  if (this.handle) {
95
- // log.error(`Deleting program ${this.id}`)();
96
- this.device.gl.useProgram(null);
97
92
  this.device.gl.deleteProgram(this.handle);
93
+ // this.handle = null;
98
94
  this.destroyed = true;
99
- // @ts-expect-error
100
- this.handle.destroyed = true;
101
- this.handle = null;
102
95
  }
103
96
  }
104
97
 
@@ -27,10 +27,6 @@ export class WEBGLShader extends Shader {
27
27
  default:
28
28
  throw new Error(this.props.stage);
29
29
  }
30
-
31
- // default framebuffer handle is null, so we can't set spector metadata...
32
- device._setWebGLDebugMetadata(this.handle, this, {spector: this.props});
33
-
34
30
  this._compile(this.source);
35
31
  }
36
32
 
@@ -38,10 +34,8 @@ export class WEBGLShader extends Shader {
38
34
  if (this.handle) {
39
35
  this.removeStats();
40
36
  this.device.gl.deleteShader(this.handle);
41
- this.destroyed = true;
42
- // @ts-expect-error
43
- this.handle.destroyed = true;
44
37
  // this.handle = null;
38
+ this.destroyed = true;
45
39
  }
46
40
  }
47
41
 
@@ -110,12 +110,7 @@ export class WEBGLTexture extends Texture {
110
110
  // eslint-disable-next-line max-statements
111
111
  _initialize(propsWithData: TextureProps): void {
112
112
  this.handle = this.props.handle || this.gl.createTexture();
113
- this.device._setWebGLDebugMetadata(this.handle, this, {
114
- spector: {
115
- ...this.props,
116
- data: propsWithData.data
117
- }
118
- });
113
+ this.device.setSpectorMetadata(this.handle, {...this.props, data: propsWithData.data});
119
114
 
120
115
  let {width, height} = propsWithData;
121
116
 
@@ -36,7 +36,8 @@ export class WebGLAdapter extends Adapter {
36
36
 
37
37
  /**
38
38
  * Get a device instance from a GL context
39
- * Creates and instruments the device if not already created
39
+ * Creates a WebGLCanvasContext against the contexts canvas
40
+ * @note autoResize will be disabled, assuming that whoever created the external context will be handling resizes.
40
41
  * @param gl
41
42
  * @returns
42
43
  */
@@ -52,7 +53,13 @@ export class WebGLAdapter extends Adapter {
52
53
  if (!isWebGL(gl)) {
53
54
  throw new Error('Invalid WebGL2RenderingContext');
54
55
  }
55
- return new WebGLDevice({_handle: gl as WebGL2RenderingContext});
56
+
57
+ // We create a new device using the provided WebGL context and its canvas
58
+ // Assume that whoever created the external context will be handling resizes.
59
+ return new WebGLDevice({
60
+ _handle: gl,
61
+ createCanvasContext: {canvas: gl.canvas, autoResize: false}
62
+ });
56
63
  }
57
64
 
58
65
  async create(props: DeviceProps = {}): Promise<WebGLDevice> {
@@ -94,7 +101,7 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
94
101
  }
95
102
 
96
103
  /** Check if supplied parameter is a WebGL2RenderingContext */
97
- function isWebGL(gl: any): boolean {
104
+ function isWebGL(gl: any): gl is WebGL2RenderingContext {
98
105
  if (typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext) {
99
106
  return true;
100
107
  }
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import type {CanvasContextProps} from '@luma.gl/core';
5
+ import type {CanvasContextProps, TextureFormat} from '@luma.gl/core';
6
6
  import {CanvasContext} from '@luma.gl/core';
7
7
  import {WebGLDevice} from './webgl-device';
8
8
  import {WEBGLFramebuffer} from './resources/webgl-framebuffer';
@@ -12,8 +12,10 @@ import {WEBGLFramebuffer} from './resources/webgl-framebuffer';
12
12
  */
13
13
  export class WebGLCanvasContext extends CanvasContext {
14
14
  readonly device: WebGLDevice;
15
- readonly handle: unknown = null;
15
+ readonly format: TextureFormat = 'rgba8unorm';
16
+ readonly depthStencilFormat: TextureFormat = 'depth24plus';
16
17
 
18
+ presentationSize: [number, number];
17
19
  private _framebuffer: WEBGLFramebuffer | null = null;
18
20
 
19
21
  get [Symbol.toStringTag](): string {
@@ -24,19 +26,28 @@ export class WebGLCanvasContext extends CanvasContext {
24
26
  // Note: Base class creates / looks up the canvas (unless under Node.js)
25
27
  super(props);
26
28
  this.device = device;
27
-
28
- // Base class constructor cannot access derived methods/fields, so we need to call these functions in the subclass constructor
29
+ this.presentationSize = [-1, -1];
29
30
  this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
30
- this.updateSize([this.drawingBufferWidth, this.drawingBufferHeight]);
31
+ this.update();
31
32
  }
32
33
 
33
34
  getCurrentFramebuffer(): WEBGLFramebuffer {
35
+ this.update();
34
36
  // Setting handle to null returns a reference to the default framebuffer
35
37
  this._framebuffer = this._framebuffer || new WEBGLFramebuffer(this.device, {handle: null});
36
38
  return this._framebuffer;
37
39
  }
38
40
 
39
- updateSize(size: [number, number]): void {}
41
+ /** Resizes and updates render targets if necessary */
42
+ update() {
43
+ const size = this.getPixelSize();
44
+ const sizeChanged =
45
+ size[0] !== this.presentationSize[0] || size[1] !== this.presentationSize[1];
46
+ if (sizeChanged) {
47
+ this.presentationSize = size;
48
+ this.resize();
49
+ }
50
+ }
40
51
 
41
52
  /**
42
53
  * Resize the canvas' drawing buffer.
@@ -53,10 +64,10 @@ export class WebGLCanvasContext extends CanvasContext {
53
64
  resize(options?: {width?: number; height?: number; useDevicePixels?: boolean | number}): void {
54
65
  if (!this.device.gl) return;
55
66
 
56
- // Resize browser context. TODO - this likely needs to be rewritten
67
+ // Resize browser context .
57
68
  if (this.canvas) {
58
69
  const devicePixelRatio = this.getDevicePixelRatio(options?.useDevicePixels);
59
- this._setDevicePixelRatio(devicePixelRatio, options);
70
+ this.setDevicePixelRatio(devicePixelRatio, options);
60
71
  return;
61
72
  }
62
73
  }
@@ -32,8 +32,7 @@ import type {
32
32
  // CommandEncoder,
33
33
  CommandEncoderProps,
34
34
  TransformFeedbackProps,
35
- QuerySetProps,
36
- Resource
35
+ QuerySetProps
37
36
  } from '@luma.gl/core';
38
37
  import {Device, CanvasContext, log} from '@luma.gl/core';
39
38
  import type {GLExtensions} from '@luma.gl/constants';
@@ -72,7 +71,9 @@ import {getWebGLExtension} from '../context/helpers/webgl-extensions';
72
71
 
73
72
  /** WebGPU style Device API for a WebGL context */
74
73
  export class WebGLDevice extends Device {
74
+ //
75
75
  // Public `Device` API
76
+ //
76
77
 
77
78
  /** type of this device */
78
79
  readonly type = 'webgl';
@@ -81,12 +82,10 @@ export class WebGLDevice extends Device {
81
82
  readonly handle: WebGL2RenderingContext;
82
83
  features: WebGLDeviceFeatures;
83
84
  limits: WebGLDeviceLimits;
85
+
84
86
  readonly info: DeviceInfo;
85
87
  readonly canvasContext: WebGLCanvasContext;
86
88
 
87
- readonly preferredColorFormat = 'rgba8unorm';
88
- readonly preferredDepthFormat = 'depth24plus';
89
-
90
89
  readonly lost: Promise<{reason: 'destroyed'; message: string}>;
91
90
 
92
91
  private _resolveContextLost?: (value: {reason: 'destroyed'; message: string}) => void;
@@ -141,19 +140,24 @@ export class WebGLDevice extends Device {
141
140
  webglContextAttributes.powerPreference = props.powerPreference;
142
141
  }
143
142
 
144
- const gl = createBrowserContext(
145
- this.canvasContext.canvas,
146
- {
147
- onContextLost: (event: Event) =>
148
- this._resolveContextLost?.({
149
- reason: 'destroyed',
150
- message: 'Entered sleep mode, or too many apps or browser tabs are using the GPU.'
151
- }),
152
- // eslint-disable-next-line no-console
153
- onContextRestored: (event: Event) => console.log('WebGL context restored')
154
- },
155
- webglContextAttributes
156
- );
143
+ // Check if we should attach to an externally created context or create a new context
144
+ const externalGLContext = this.props._handle as WebGL2RenderingContext | null;
145
+
146
+ const gl =
147
+ externalGLContext ||
148
+ createBrowserContext(
149
+ this.canvasContext.canvas,
150
+ {
151
+ onContextLost: (event: Event) =>
152
+ this._resolveContextLost?.({
153
+ reason: 'destroyed',
154
+ message: 'Entered sleep mode, or too many apps or browser tabs are using the GPU.'
155
+ }),
156
+ // eslint-disable-next-line no-console
157
+ onContextRestored: (event: Event) => console.log('WebGL context restored')
158
+ },
159
+ webglContextAttributes
160
+ );
157
161
 
158
162
  if (!gl) {
159
163
  throw new Error('WebGL context creation failed');
@@ -189,6 +193,10 @@ export class WebGLDevice extends Device {
189
193
  this.features.initializeFeatures();
190
194
  }
191
195
 
196
+ if (canvasContextProps.autoResize !== false) {
197
+ this.canvasContext.resize();
198
+ }
199
+
192
200
  // Install context state tracking
193
201
  const glState = new WebGLStateTracker(this.gl, {
194
202
  log: (...args: any[]) => log.log(1, ...args)()
@@ -392,6 +400,16 @@ export class WebGLDevice extends Device {
392
400
  webglState.pop();
393
401
  }
394
402
 
403
+ /**
404
+ * Storing data on a special field on WebGLObjects makes that data visible in SPECTOR chrome debug extension
405
+ * luma.gl ids and props can be inspected
406
+ */
407
+ setSpectorMetadata(handle: unknown, props: Record<string, unknown>) {
408
+ // @ts-expect-error
409
+ // eslint-disable-next-line camelcase
410
+ handle.__SPECTOR_Metadata = props;
411
+ }
412
+
395
413
  /**
396
414
  * Returns the GL.<KEY> constant that corresponds to a numeric value of a GL constant
397
415
  * Be aware that there are some duplicates especially for constants that are 0,
@@ -462,26 +480,6 @@ export class WebGLDevice extends Device {
462
480
  getWebGLExtension(this.gl, name, this._extensions);
463
481
  return this._extensions;
464
482
  }
465
-
466
- // INTERNAL SUPPORT METHODS FOR WEBGL RESOURCES
467
-
468
- /**
469
- * Storing data on a special field on WebGLObjects makes that data visible in SPECTOR chrome debug extension
470
- * luma.gl ids and props can be inspected
471
- */
472
- _setWebGLDebugMetadata(
473
- handle: unknown,
474
- resource: Resource<any>,
475
- options: {spector: Record<string, unknown>}
476
- ): void {
477
- // @ts-expect-error
478
- handle.luma = resource;
479
-
480
- const spectorMetadata = {props: options.spector, id: options.spector.id};
481
- // @ts-expect-error
482
- // eslint-disable-next-line camelcase
483
- handle.__SPECTOR_Metadata = spectorMetadata;
484
- }
485
483
  }
486
484
 
487
485
  /** Set constant float array attribute */