@luma.gl/webgl 9.1.0-alpha.2 → 9.1.0-beta.1

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 (216) hide show
  1. package/dist/adapter/converters/device-parameters.d.ts +3 -3
  2. package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
  3. package/dist/adapter/converters/device-parameters.js +19 -11
  4. package/dist/adapter/converters/device-parameters.js.map +1 -0
  5. package/dist/adapter/converters/sampler-parameters.js +7 -4
  6. package/dist/adapter/converters/sampler-parameters.js.map +1 -0
  7. package/dist/adapter/converters/shader-formats.js +1 -0
  8. package/dist/adapter/converters/shader-formats.js.map +1 -0
  9. package/dist/adapter/converters/vertex-formats.js +1 -0
  10. package/dist/adapter/converters/vertex-formats.js.map +1 -0
  11. package/dist/adapter/converters/webgl-texture-table.d.ts +40 -0
  12. package/dist/adapter/converters/webgl-texture-table.d.ts.map +1 -0
  13. package/dist/adapter/converters/webgl-texture-table.js +304 -0
  14. package/dist/adapter/converters/webgl-texture-table.js.map +1 -0
  15. package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
  16. package/dist/adapter/device-helpers/webgl-device-features.js +2 -3
  17. package/dist/adapter/device-helpers/webgl-device-features.js.map +1 -0
  18. package/dist/adapter/device-helpers/webgl-device-info.js +1 -0
  19. package/dist/adapter/device-helpers/webgl-device-info.js.map +1 -0
  20. package/dist/adapter/device-helpers/webgl-device-limits.js +1 -0
  21. package/dist/adapter/device-helpers/webgl-device-limits.js.map +1 -0
  22. package/dist/adapter/helpers/decode-webgl-types.js +1 -0
  23. package/dist/adapter/helpers/decode-webgl-types.js.map +1 -0
  24. package/dist/adapter/helpers/format-utils.d.ts.map +1 -0
  25. package/dist/{classic → adapter/helpers}/format-utils.js +7 -0
  26. package/dist/adapter/helpers/format-utils.js.map +1 -0
  27. package/dist/adapter/helpers/get-shader-layout.d.ts +1 -1
  28. package/dist/adapter/helpers/get-shader-layout.d.ts.map +1 -1
  29. package/dist/adapter/helpers/get-shader-layout.js +5 -4
  30. package/dist/adapter/helpers/get-shader-layout.js.map +1 -0
  31. package/dist/adapter/helpers/parse-shader-compiler-log.js +1 -0
  32. package/dist/adapter/helpers/parse-shader-compiler-log.js.map +1 -0
  33. package/dist/adapter/helpers/set-uniform.js +1 -0
  34. package/dist/adapter/helpers/set-uniform.js.map +1 -0
  35. package/dist/adapter/helpers/typed-array-utils.d.ts.map +1 -0
  36. package/dist/{classic → adapter/helpers}/typed-array-utils.js +1 -0
  37. package/dist/adapter/helpers/typed-array-utils.js.map +1 -0
  38. package/dist/adapter/helpers/webgl-texture-utils.d.ts +100 -29
  39. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  40. package/dist/adapter/helpers/webgl-texture-utils.js +231 -240
  41. package/dist/adapter/helpers/webgl-texture-utils.js.map +1 -0
  42. package/dist/adapter/helpers/webgl-topology-utils.js +1 -0
  43. package/dist/adapter/helpers/webgl-topology-utils.js.map +1 -0
  44. package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
  45. package/dist/adapter/resources/webgl-buffer.js +4 -1
  46. package/dist/adapter/resources/webgl-buffer.js.map +1 -0
  47. package/dist/adapter/resources/webgl-command-buffer.d.ts +59 -2
  48. package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
  49. package/dist/adapter/resources/webgl-command-buffer.js +89 -32
  50. package/dist/adapter/resources/webgl-command-buffer.js.map +1 -0
  51. package/dist/adapter/resources/webgl-command-encoder.d.ts.map +1 -1
  52. package/dist/adapter/resources/webgl-command-encoder.js +4 -0
  53. package/dist/adapter/resources/webgl-command-encoder.js.map +1 -0
  54. package/dist/adapter/resources/webgl-external-texture.js +15 -0
  55. package/dist/adapter/resources/webgl-external-texture.js.map +1 -0
  56. package/dist/adapter/resources/webgl-framebuffer.d.ts +33 -35
  57. package/dist/adapter/resources/webgl-framebuffer.d.ts.map +1 -1
  58. package/dist/adapter/resources/webgl-framebuffer.js +71 -76
  59. package/dist/adapter/resources/webgl-framebuffer.js.map +1 -0
  60. package/dist/adapter/resources/webgl-query-set.js +1 -0
  61. package/dist/adapter/resources/webgl-query-set.js.map +1 -0
  62. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  63. package/dist/adapter/resources/webgl-render-pass.js +49 -21
  64. package/dist/adapter/resources/webgl-render-pass.js.map +1 -0
  65. package/dist/adapter/resources/webgl-render-pipeline.d.ts +3 -4
  66. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  67. package/dist/adapter/resources/webgl-render-pipeline.js +45 -23
  68. package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -0
  69. package/dist/adapter/resources/webgl-sampler.js +1 -0
  70. package/dist/adapter/resources/webgl-sampler.js.map +1 -0
  71. package/dist/adapter/resources/webgl-shader.d.ts +1 -0
  72. package/dist/adapter/resources/webgl-shader.d.ts.map +1 -1
  73. package/dist/adapter/resources/webgl-shader.js +13 -6
  74. package/dist/adapter/resources/webgl-shader.js.map +1 -0
  75. package/dist/adapter/resources/webgl-texture-view.js +1 -0
  76. package/dist/adapter/resources/webgl-texture-view.js.map +1 -0
  77. package/dist/adapter/resources/webgl-texture.d.ts +33 -21
  78. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  79. package/dist/adapter/resources/webgl-texture.js +172 -242
  80. package/dist/adapter/resources/webgl-texture.js.map +1 -0
  81. package/dist/adapter/resources/webgl-transform-feedback.js +1 -0
  82. package/dist/adapter/resources/webgl-transform-feedback.js.map +1 -0
  83. package/dist/adapter/resources/webgl-vertex-array.js +1 -0
  84. package/dist/adapter/resources/webgl-vertex-array.js.map +1 -0
  85. package/dist/adapter/webgl-adapter.d.ts +21 -0
  86. package/dist/adapter/webgl-adapter.d.ts.map +1 -0
  87. package/dist/adapter/webgl-adapter.js +86 -0
  88. package/dist/adapter/webgl-adapter.js.map +1 -0
  89. package/dist/adapter/webgl-canvas-context.d.ts +4 -6
  90. package/dist/adapter/webgl-canvas-context.d.ts.map +1 -1
  91. package/dist/adapter/webgl-canvas-context.js +13 -17
  92. package/dist/adapter/webgl-canvas-context.js.map +1 -0
  93. package/dist/adapter/webgl-device.d.ts +35 -46
  94. package/dist/adapter/webgl-device.d.ts.map +1 -1
  95. package/dist/adapter/webgl-device.js +100 -156
  96. package/dist/adapter/webgl-device.js.map +1 -0
  97. package/dist/context/debug/spector-types.d.ts +1108 -0
  98. package/dist/context/debug/spector-types.d.ts.map +1 -0
  99. package/dist/context/debug/spector-types.js +698 -0
  100. package/dist/context/debug/spector-types.js.map +1 -0
  101. package/dist/context/debug/spector.d.ts +12 -8
  102. package/dist/context/debug/spector.d.ts.map +1 -1
  103. package/dist/context/debug/spector.js +24 -17
  104. package/dist/context/debug/spector.js.map +1 -0
  105. package/dist/context/debug/webgl-developer-tools.d.ts +2 -3
  106. package/dist/context/debug/webgl-developer-tools.d.ts.map +1 -1
  107. package/dist/context/debug/webgl-developer-tools.js +7 -19
  108. package/dist/context/debug/webgl-developer-tools.js.map +1 -0
  109. package/dist/context/helpers/create-browser-context.d.ts +6 -22
  110. package/dist/context/helpers/create-browser-context.d.ts.map +1 -1
  111. package/dist/context/helpers/create-browser-context.js +41 -32
  112. package/dist/context/helpers/create-browser-context.js.map +1 -0
  113. package/dist/context/helpers/webgl-context-data.js +1 -0
  114. package/dist/context/helpers/webgl-context-data.js.map +1 -0
  115. package/dist/context/helpers/webgl-extensions.js +1 -0
  116. package/dist/context/helpers/webgl-extensions.js.map +1 -0
  117. package/dist/context/parameters/unified-parameter-api.js +1 -0
  118. package/dist/context/parameters/unified-parameter-api.js.map +1 -0
  119. package/dist/context/parameters/webgl-parameter-tables.d.ts +1 -1
  120. package/dist/context/parameters/webgl-parameter-tables.d.ts.map +1 -1
  121. package/dist/context/parameters/webgl-parameter-tables.js +3 -2
  122. package/dist/context/parameters/webgl-parameter-tables.js.map +1 -0
  123. package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts +9 -0
  124. package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts.map +1 -0
  125. package/dist/context/polyfills/polyfill-webgl1-extensions.js +182 -0
  126. package/dist/context/polyfills/polyfill-webgl1-extensions.js.map +1 -0
  127. package/dist/context/state-tracker/deep-array-equal.js +1 -0
  128. package/dist/context/state-tracker/deep-array-equal.js.map +1 -0
  129. package/dist/context/state-tracker/webgl-state-tracker.d.ts +43 -0
  130. package/dist/context/state-tracker/webgl-state-tracker.d.ts.map +1 -0
  131. package/dist/context/state-tracker/{track-context-state.js → webgl-state-tracker.js} +45 -74
  132. package/dist/context/state-tracker/webgl-state-tracker.js.map +1 -0
  133. package/dist/context/state-tracker/with-parameters.d.ts.map +1 -1
  134. package/dist/context/state-tracker/with-parameters.js +6 -4
  135. package/dist/context/state-tracker/with-parameters.js.map +1 -0
  136. package/dist/deprecated/accessor.d.ts.map +1 -0
  137. package/dist/{classic → deprecated}/accessor.js +37 -1
  138. package/dist/deprecated/accessor.js.map +1 -0
  139. package/dist/dist.dev.js +2397 -2430
  140. package/dist/dist.min.js +2 -2
  141. package/dist/index.cjs +2273 -2298
  142. package/dist/index.cjs.map +4 -4
  143. package/dist/index.d.ts +5 -4
  144. package/dist/index.d.ts.map +1 -1
  145. package/dist/index.js +6 -6
  146. package/dist/index.js.map +1 -0
  147. package/dist/types.js +1 -0
  148. package/dist/types.js.map +1 -0
  149. package/dist/utils/fill-array.d.ts +4 -4
  150. package/dist/utils/fill-array.d.ts.map +1 -1
  151. package/dist/utils/fill-array.js +1 -0
  152. package/dist/utils/fill-array.js.map +1 -0
  153. package/dist/utils/load-script.js +1 -0
  154. package/dist/utils/load-script.js.map +1 -0
  155. package/dist/utils/split-uniforms-and-bindings.d.ts +1 -1
  156. package/dist/utils/split-uniforms-and-bindings.d.ts.map +1 -1
  157. package/dist/utils/split-uniforms-and-bindings.js +1 -0
  158. package/dist/utils/split-uniforms-and-bindings.js.map +1 -0
  159. package/dist/utils/uid.d.ts +7 -0
  160. package/dist/utils/uid.d.ts.map +1 -0
  161. package/dist/utils/uid.js +15 -0
  162. package/dist/utils/uid.js.map +1 -0
  163. package/package.json +5 -5
  164. package/src/adapter/converters/device-parameters.ts +21 -15
  165. package/src/adapter/converters/sampler-parameters.ts +6 -4
  166. package/src/adapter/converters/webgl-texture-table.ts +404 -0
  167. package/src/adapter/device-helpers/webgl-device-features.ts +5 -3
  168. package/src/{classic → adapter/helpers}/format-utils.ts +6 -0
  169. package/src/adapter/helpers/get-shader-layout.ts +7 -4
  170. package/src/adapter/helpers/webgl-texture-utils.ts +410 -64
  171. package/src/adapter/resources/webgl-buffer.ts +3 -1
  172. package/src/adapter/resources/webgl-command-buffer.ts +125 -41
  173. package/src/adapter/resources/webgl-command-encoder.ts +6 -0
  174. package/src/adapter/resources/webgl-external-texture.ts +14 -0
  175. package/src/adapter/resources/webgl-framebuffer.ts +80 -86
  176. package/src/adapter/resources/webgl-render-pass.ts +72 -45
  177. package/src/adapter/resources/webgl-render-pipeline.ts +58 -27
  178. package/src/adapter/resources/webgl-shader.ts +15 -7
  179. package/src/adapter/resources/webgl-texture.ts +202 -274
  180. package/src/adapter/webgl-adapter.ts +105 -0
  181. package/src/adapter/webgl-canvas-context.ts +16 -19
  182. package/src/adapter/webgl-device.ts +144 -210
  183. package/src/context/debug/spector-types.ts +1154 -0
  184. package/src/context/debug/spector.ts +38 -29
  185. package/src/context/debug/webgl-developer-tools.ts +8 -31
  186. package/src/context/helpers/create-browser-context.ts +53 -63
  187. package/src/context/parameters/webgl-parameter-tables.ts +2 -2
  188. package/src/context/polyfills/polyfill-webgl1-extensions.ts +202 -0
  189. package/src/context/state-tracker/{track-context-state.ts → webgl-state-tracker.ts} +55 -94
  190. package/src/context/state-tracker/with-parameters.ts +5 -4
  191. package/src/{classic → deprecated}/accessor.ts +44 -3
  192. package/src/index.ts +7 -12
  193. package/src/utils/fill-array.ts +4 -4
  194. package/src/utils/split-uniforms-and-bindings.ts +3 -3
  195. package/src/utils/uid.ts +16 -0
  196. package/dist/adapter/converters/texture-formats.d.ts +0 -83
  197. package/dist/adapter/converters/texture-formats.d.ts.map +0 -1
  198. package/dist/adapter/converters/texture-formats.js +0 -518
  199. package/dist/classic/accessor.d.ts.map +0 -1
  200. package/dist/classic/clear.d.ts +0 -22
  201. package/dist/classic/clear.d.ts.map +0 -1
  202. package/dist/classic/clear.js +0 -86
  203. package/dist/classic/copy-and-blit.d.ts +0 -63
  204. package/dist/classic/copy-and-blit.d.ts.map +0 -1
  205. package/dist/classic/copy-and-blit.js +0 -193
  206. package/dist/classic/format-utils.d.ts.map +0 -1
  207. package/dist/classic/typed-array-utils.d.ts.map +0 -1
  208. package/dist/context/state-tracker/track-context-state.d.ts +0 -22
  209. package/dist/context/state-tracker/track-context-state.d.ts.map +0 -1
  210. package/src/adapter/converters/texture-formats.ts +0 -665
  211. package/src/classic/clear.ts +0 -115
  212. package/src/classic/copy-and-blit.ts +0 -318
  213. /package/dist/{classic → adapter/helpers}/format-utils.d.ts +0 -0
  214. /package/dist/{classic → adapter/helpers}/typed-array-utils.d.ts +0 -0
  215. /package/dist/{classic → deprecated}/accessor.d.ts +0 -0
  216. /package/src/{classic → adapter/helpers}/typed-array-utils.ts +0 -0
@@ -0,0 +1,105 @@
1
+ // luma.gl
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) vis.gl contributors
4
+
5
+ import {Adapter, Device, DeviceProps, log} from '@luma.gl/core';
6
+ import {WebGLDevice} from './webgl-device';
7
+ import {enforceWebGL2} from '../context/polyfills/polyfill-webgl1-extensions';
8
+ import {loadSpectorJS, DEFAULT_SPECTOR_PROPS} from '../context/debug/spector';
9
+ import {loadWebGLDeveloperTools} from '../context/debug/webgl-developer-tools';
10
+
11
+ const LOG_LEVEL = 1;
12
+
13
+ export class WebGLAdapter extends Adapter {
14
+ /** type of device's created by this adapter */
15
+ readonly type: Device['type'] = 'webgl';
16
+
17
+ constructor() {
18
+ super();
19
+
20
+ // Add spector default props to device default props, so that runtime settings are observed
21
+ Device.defaultProps = {...Device.defaultProps, ...DEFAULT_SPECTOR_PROPS};
22
+
23
+ // @ts-ignore DEPRECATED For backwards compatibility luma.registerDevices
24
+ WebGLDevice.adapter = this;
25
+ }
26
+
27
+ /** Check if WebGL 2 is available */
28
+ isSupported(): boolean {
29
+ return typeof WebGL2RenderingContext !== 'undefined';
30
+ }
31
+
32
+ /** Force any created WebGL contexts to be WebGL2 contexts, polyfilled with WebGL1 extensions */
33
+ enforceWebGL2(enable: boolean): void {
34
+ enforceWebGL2(enable);
35
+ }
36
+
37
+ /**
38
+ * Get a device instance from a GL context
39
+ * Creates and instruments the device if not already created
40
+ * @param gl
41
+ * @returns
42
+ */
43
+ async attach(gl: Device | WebGL2RenderingContext): Promise<WebGLDevice> {
44
+ if (gl instanceof WebGLDevice) {
45
+ return gl;
46
+ }
47
+ // @ts-expect-error
48
+ if (gl?.device instanceof Device) {
49
+ // @ts-expect-error
50
+ return gl.device as WebGLDevice;
51
+ }
52
+ if (!isWebGL(gl)) {
53
+ throw new Error('Invalid WebGL2RenderingContext');
54
+ }
55
+ return new WebGLDevice({_handle: gl as WebGL2RenderingContext});
56
+ }
57
+
58
+ async create(props: DeviceProps = {}): Promise<WebGLDevice> {
59
+ log.groupCollapsed(LOG_LEVEL, 'WebGLDevice created')();
60
+
61
+ const promises: Promise<unknown>[] = [];
62
+
63
+ // Load webgl and spector debug scripts from CDN if requested
64
+ if (props.debugWebGL || props.debug) {
65
+ promises.push(loadWebGLDeveloperTools());
66
+ }
67
+
68
+ if (props.debugSpectorJS) {
69
+ promises.push(loadSpectorJS(props));
70
+ }
71
+
72
+ // Wait for all the loads to settle before creating the context.
73
+ // The Device.create() functions are async, so in contrast to the constructor, we can `await` here.
74
+ const results = await Promise.allSettled(promises);
75
+ for (const result of results) {
76
+ if (result.status === 'rejected') {
77
+ log.error(`Failed to initialize debug libraries ${result.reason}`)();
78
+ }
79
+ }
80
+
81
+ const device = new WebGLDevice(props);
82
+
83
+ // Log some debug info about the newly created context
84
+ const message = `\
85
+ Created ${device.type}${device.debug ? ' debug' : ''} context: \
86
+ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContext.id}`;
87
+ log.probe(LOG_LEVEL, message)();
88
+ log.table(LOG_LEVEL, device.info)();
89
+
90
+ log.groupEnd(LOG_LEVEL)();
91
+
92
+ return device;
93
+ }
94
+ }
95
+
96
+ /** Check if supplied parameter is a WebGL2RenderingContext */
97
+ function isWebGL(gl: any): boolean {
98
+ if (typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext) {
99
+ return true;
100
+ }
101
+ // Look for debug contexts, headless gl etc
102
+ return Boolean(gl && Number.isFinite(gl._version));
103
+ }
104
+
105
+ export const webgl2Adapter = new WebGLAdapter();
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import type {CanvasContextProps, TextureFormat} from '@luma.gl/core';
5
+ import type {CanvasContextProps} 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,38 +12,31 @@ import {WEBGLFramebuffer} from './resources/webgl-framebuffer';
12
12
  */
13
13
  export class WebGLCanvasContext extends CanvasContext {
14
14
  readonly device: WebGLDevice;
15
- readonly format: TextureFormat = 'rgba8unorm';
16
- readonly depthStencilFormat: TextureFormat = 'depth24plus';
15
+ readonly handle: unknown = null;
17
16
 
18
- presentationSize: [number, number];
19
17
  private _framebuffer: WEBGLFramebuffer | null = null;
20
18
 
19
+ get [Symbol.toStringTag](): string {
20
+ return 'WebGLCanvasContext';
21
+ }
22
+
21
23
  constructor(device: WebGLDevice, props: CanvasContextProps) {
22
24
  // Note: Base class creates / looks up the canvas (unless under Node.js)
23
25
  super(props);
24
26
  this.device = device;
25
- this.presentationSize = [-1, -1];
27
+
28
+ // Base class constructor cannot access derived methods/fields, so we need to call these functions in the subclass constructor
26
29
  this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
27
- this.update();
30
+ this.updateSize([this.drawingBufferWidth, this.drawingBufferHeight]);
28
31
  }
29
32
 
30
33
  getCurrentFramebuffer(): WEBGLFramebuffer {
31
- this.update();
32
34
  // Setting handle to null returns a reference to the default framebuffer
33
35
  this._framebuffer = this._framebuffer || new WEBGLFramebuffer(this.device, {handle: null});
34
36
  return this._framebuffer;
35
37
  }
36
38
 
37
- /** Resizes and updates render targets if necessary */
38
- update() {
39
- const size = this.getPixelSize();
40
- const sizeChanged =
41
- size[0] !== this.presentationSize[0] || size[1] !== this.presentationSize[1];
42
- if (sizeChanged) {
43
- this.presentationSize = size;
44
- this.resize();
45
- }
46
- }
39
+ updateSize(size: [number, number]): void {}
47
40
 
48
41
  /**
49
42
  * Resize the canvas' drawing buffer.
@@ -60,10 +53,14 @@ export class WebGLCanvasContext extends CanvasContext {
60
53
  resize(options?: {width?: number; height?: number; useDevicePixels?: boolean | number}): void {
61
54
  if (!this.device.gl) return;
62
55
 
63
- // Resize browser context .
56
+ if (this.props.autoResize) {
57
+ return;
58
+ }
59
+
60
+ // Resize browser context. TODO - this likely needs to be rewritten
64
61
  if (this.canvas) {
65
62
  const devicePixelRatio = this.getDevicePixelRatio(options?.useDevicePixels);
66
- this.setDevicePixelRatio(devicePixelRatio, options);
63
+ this._setDevicePixelRatio(devicePixelRatio, options);
67
64
  return;
68
65
  }
69
66
  }
@@ -3,30 +3,16 @@
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
5
  import type {TypedArray} from '@math.gl/types';
6
- import type {DeviceProps, DeviceInfo, CanvasContextProps, TextureFormat} from '@luma.gl/core';
7
- import type {Buffer, Texture, Framebuffer, VertexArray, VertexArrayProps} from '@luma.gl/core';
8
- import {Device, CanvasContext, log} from '@luma.gl/core';
9
- import type {GLExtensions} from '@luma.gl/constants';
10
- import {
11
- popContextState,
12
- pushContextState,
13
- trackContextState
14
- } from '../context/state-tracker/track-context-state';
15
- import {createBrowserContext} from '../context/helpers/create-browser-context';
16
- import {getDeviceInfo} from './device-helpers/webgl-device-info';
17
- import {WebGLDeviceFeatures} from './device-helpers/webgl-device-features';
18
- import {WebGLDeviceLimits} from './device-helpers/webgl-device-limits';
19
- import {WebGLCanvasContext} from './webgl-canvas-context';
20
- import {loadSpectorJS, initializeSpectorJS} from '../context/debug/spector';
21
- import {loadWebGLDeveloperTools, makeDebugContext} from '../context/debug/webgl-developer-tools';
22
- import {
23
- isTextureFormatSupported,
24
- isTextureFormatRenderable,
25
- isTextureFormatFilterable
26
- } from './converters/texture-formats';
27
-
28
- // WebGL classes
29
6
  import type {
7
+ DeviceProps,
8
+ DeviceInfo,
9
+ DeviceTextureFormatCapabilities,
10
+ CanvasContextProps,
11
+ Buffer,
12
+ Texture,
13
+ Framebuffer,
14
+ VertexArray,
15
+ VertexArrayProps,
30
16
  BufferProps,
31
17
  ShaderProps,
32
18
  // Sampler,
@@ -46,8 +32,22 @@ import type {
46
32
  // CommandEncoder,
47
33
  CommandEncoderProps,
48
34
  TransformFeedbackProps,
49
- QuerySetProps
35
+ QuerySetProps,
36
+ Resource
50
37
  } from '@luma.gl/core';
38
+ import {Device, CanvasContext, log} from '@luma.gl/core';
39
+ import type {GLExtensions} from '@luma.gl/constants';
40
+ import {WebGLStateTracker} from '../context/state-tracker/webgl-state-tracker';
41
+ import {createBrowserContext} from '../context/helpers/create-browser-context';
42
+ import {getDeviceInfo} from './device-helpers/webgl-device-info';
43
+ import {WebGLDeviceFeatures} from './device-helpers/webgl-device-features';
44
+ import {WebGLDeviceLimits} from './device-helpers/webgl-device-limits';
45
+ import {WebGLCanvasContext} from './webgl-canvas-context';
46
+ import type {Spector} from '../context/debug/spector-types';
47
+ import {initializeSpectorJS} from '../context/debug/spector';
48
+ import {makeDebugContext} from '../context/debug/webgl-developer-tools';
49
+ import {getTextureFormatCapabilitiesWebGL} from './converters/webgl-texture-table';
50
+ import {uid} from '../utils/uid';
51
51
 
52
52
  import {WEBGLBuffer} from './resources/webgl-buffer';
53
53
  import {WEBGLShader} from './resources/webgl-shader';
@@ -61,26 +61,18 @@ import {WEBGLVertexArray} from './resources/webgl-vertex-array';
61
61
  import {WEBGLTransformFeedback} from './resources/webgl-transform-feedback';
62
62
  import {WEBGLQuerySet} from './resources/webgl-query-set';
63
63
 
64
- import {readPixelsToArray, readPixelsToBuffer} from '../classic/copy-and-blit';
64
+ import {readPixelsToArray, readPixelsToBuffer} from './helpers/webgl-texture-utils';
65
65
  import {
66
66
  setGLParameters,
67
67
  getGLParameters,
68
68
  resetGLParameters
69
69
  } from '../context/parameters/unified-parameter-api';
70
70
  import {withGLParameters} from '../context/state-tracker/with-parameters';
71
- import {clear} from '../classic/clear';
72
71
  import {getWebGLExtension} from '../context/helpers/webgl-extensions';
73
72
 
74
- const LOG_LEVEL = 1;
75
-
76
73
  /** WebGPU style Device API for a WebGL context */
77
74
  export class WebGLDevice extends Device {
78
- //
79
75
  // Public `Device` API
80
- //
81
-
82
- /** type of this device */
83
- static readonly type: string = 'webgl';
84
76
 
85
77
  /** type of this device */
86
78
  readonly type = 'webgl';
@@ -89,166 +81,129 @@ export class WebGLDevice extends Device {
89
81
  readonly handle: WebGL2RenderingContext;
90
82
  features: WebGLDeviceFeatures;
91
83
  limits: WebGLDeviceLimits;
92
-
93
84
  readonly info: DeviceInfo;
94
85
  readonly canvasContext: WebGLCanvasContext;
95
86
 
87
+ readonly preferredColorFormat = 'rgba8unorm';
88
+ readonly preferredDepthFormat = 'depth24plus';
89
+
96
90
  readonly lost: Promise<{reason: 'destroyed'; message: string}>;
97
91
 
98
92
  private _resolveContextLost?: (value: {reason: 'destroyed'; message: string}) => void;
99
93
 
100
- //
101
- // Static methods, expected to be present by `luma.createDevice()`
102
- //
103
-
104
- /** Check if WebGL 2 is available */
105
- static isSupported(): boolean {
106
- return typeof WebGL2RenderingContext !== 'undefined';
107
- }
108
-
109
- /**
110
- * Get a device instance from a GL context
111
- * Creates and instruments the device if not already created
112
- * @param gl
113
- * @returns
114
- */
115
- static attach(gl: Device | WebGL2RenderingContext): WebGLDevice {
116
- if (gl instanceof WebGLDevice) {
117
- return gl;
118
- }
119
- // @ts-expect-error
120
- if (gl?.device instanceof Device) {
121
- // @ts-expect-error
122
- return gl.device as WebGLDevice;
123
- }
124
- if (!isWebGL(gl)) {
125
- throw new Error('Invalid WebGL2RenderingContext');
126
- }
127
- return new WebGLDevice({gl: gl as WebGL2RenderingContext});
128
- }
129
-
130
- static async create(props: DeviceProps = {}): Promise<WebGLDevice> {
131
- log.groupCollapsed(LOG_LEVEL, 'WebGLDevice created')();
132
-
133
- const promises: Promise<unknown>[] = [];
134
-
135
- // Load webgl and spector debug scripts from CDN if requested
136
- if (props.debug) {
137
- promises.push(loadWebGLDeveloperTools());
138
- }
139
-
140
- if (props.spector) {
141
- promises.push(loadSpectorJS());
142
- }
143
-
144
- // Wait for page to load: if canvas is a string we need to query the DOM for the canvas element.
145
- // We only wait when props.canvas is string to avoids setting the global page onload callback unless necessary.
146
- if (typeof props.canvas === 'string') {
147
- promises.push(CanvasContext.pageLoaded);
148
- }
149
-
150
- // Wait for all the loads to settle before creating the context.
151
- // The Device.create() functions are async, so in contrast to the constructor, we can `await` here.
152
- const results = await Promise.allSettled(promises);
153
- for (const result of results) {
154
- if (result.status === 'rejected') {
155
- log.error(`Failed to initialize debug libraries ${result.reason}`)();
156
- }
157
- }
158
-
159
- log.probe(LOG_LEVEL + 1, 'DOM is loaded')();
160
-
161
- // @ts-expect-error
162
- if (props.gl?.device) {
163
- log.warn('reattaching existing device')();
164
- return WebGLDevice.attach(props.gl);
165
- }
166
-
167
- const device = new WebGLDevice(props);
94
+ /** WebGL2 context. */
95
+ readonly gl: WebGL2RenderingContext;
96
+ readonly debug: boolean = false;
168
97
 
169
- // Log some debug info about the newly created context
170
- const message = `\
171
- Created ${device.type}${device.debug ? ' debug' : ''} context: \
172
- ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContext.id}`;
173
- log.probe(LOG_LEVEL, message)();
174
- log.table(LOG_LEVEL, device.info)();
98
+ /** State used by luma.gl classes: TODO - move to canvasContext*/
99
+ readonly _canvasSizeInfo = {clientWidth: 0, clientHeight: 0, devicePixelRatio: 1};
175
100
 
176
- log.groupEnd(LOG_LEVEL)();
101
+ /** State used by luma.gl classes - TODO - not used? */
102
+ readonly _extensions: GLExtensions = {};
103
+ _polyfilled: boolean = false;
177
104
 
178
- return device;
179
- }
105
+ /** Instance of Spector.js (if initialized) */
106
+ spectorJS: Spector;
180
107
 
181
108
  //
182
109
  // Public API
183
110
  //
184
111
 
185
112
  constructor(props: DeviceProps) {
186
- super({...props, id: props.id || 'webgl-device'});
113
+ super({...props, id: props.id || uid('webgl-device')});
114
+
115
+ // WebGL requires a canvas to be created before creating the context
116
+ if (!props.createCanvasContext) {
117
+ throw new Error('WebGLDevice requires props.createCanvasContext to be set');
118
+ }
119
+ const canvasContextProps = props.createCanvasContext === true ? {} : props.createCanvasContext;
187
120
 
188
121
  // If attaching to an already attached context, return the attached device
189
122
  // @ts-expect-error device is attached to context
190
- const device: WebGLDevice | undefined = props.gl?.device;
123
+ let device: WebGLDevice | undefined = canvasContextProps.canvas?.gl?.device;
191
124
  if (device) {
192
125
  throw new Error(`WebGL context already attached to device ${device.id}`);
193
126
  }
194
127
 
195
128
  // Create and instrument context
196
- const canvas = props.gl?.canvas || props.canvas;
197
- this.canvasContext = new WebGLCanvasContext(this, {...props, canvas});
129
+ this.canvasContext = new WebGLCanvasContext(this, canvasContextProps);
198
130
 
199
131
  this.lost = new Promise<{reason: 'destroyed'; message: string}>(resolve => {
200
132
  this._resolveContextLost = resolve;
201
133
  });
202
134
 
203
- let gl: WebGL2RenderingContext | null = props.gl || null;
204
- gl ||= createBrowserContext(this.canvasContext.canvas, {
205
- ...props,
206
- onContextLost: (event: Event) =>
207
- this._resolveContextLost?.({
208
- reason: 'destroyed',
209
- message: 'Entered sleep mode, or too many apps or browser tabs are using the GPU.'
210
- })
211
- });
135
+ const webglContextAttributes: WebGLContextAttributes = {...props.webgl};
136
+ // Copy props from CanvasContextProps
137
+ if (canvasContextProps.alphaMode === 'premultiplied') {
138
+ webglContextAttributes.premultipliedAlpha = true;
139
+ }
140
+ if (props.powerPreference !== undefined) {
141
+ webglContextAttributes.powerPreference = props.powerPreference;
142
+ }
143
+
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
+ );
212
157
 
213
158
  if (!gl) {
214
159
  throw new Error('WebGL context creation failed');
215
160
  }
216
161
 
162
+ // @ts-expect-error device is attached to context
163
+ device = gl.device;
164
+ if (device) {
165
+ throw new Error(`WebGL context already attached to device ${device.id}`);
166
+ }
167
+
217
168
  this.handle = gl;
218
169
  this.gl = gl;
219
170
 
171
+ // Add spector debug instrumentation to context
172
+ // We need to trust spector integration to decide if spector should be initialized
173
+ // We also run spector instrumentation first, otherwise spector can clobber luma instrumentation.
174
+ this.spectorJS = initializeSpectorJS({...this.props, gl: this.handle});
175
+
176
+ // Instrument context
220
177
  (this.gl as any).device = this; // Update GL context: Link webgl context back to device
221
178
  (this.gl as any)._version = 2; // Update GL context: Store WebGL version field on gl context (HACK to identify debug contexts)
222
179
 
223
- // luma Device fields
180
+ // initialize luma Device fields
224
181
  this.info = getDeviceInfo(this.gl, this._extensions);
225
182
  this.limits = new WebGLDeviceLimits(this.gl);
226
- this.features = new WebGLDeviceFeatures(this.gl, this._extensions, this.props.disabledFeatures);
227
- if (this.props.initalizeFeatures) {
183
+ this.features = new WebGLDeviceFeatures(
184
+ this.gl,
185
+ this._extensions,
186
+ this.props._disabledFeatures
187
+ );
188
+ if (this.props._initializeFeatures) {
228
189
  this.features.initializeFeatures();
229
190
  }
230
191
 
231
- this.canvasContext.resize();
232
-
233
192
  // Install context state tracking
234
- // @ts-expect-error - hidden parameters
235
- const {enable = true, copyState = false} = props;
236
- trackContextState(this.gl, {
237
- enable,
238
- copyState,
193
+ const glState = new WebGLStateTracker(this.gl, {
239
194
  log: (...args: any[]) => log.log(1, ...args)()
240
195
  });
196
+ glState.trackState(this.gl, {copyState: false});
241
197
 
242
- // DEBUG contexts: Add debug instrumentation to the context, force log level to at least 1
243
- if (props.debug) {
244
- this.gl = makeDebugContext(this.gl, {...props, throwOnError: true});
245
- this.debug = true;
246
- log.level = Math.max(log.level, 1);
198
+ // DEBUG contexts: Add luma debug instrumentation to the context, force log level to at least 1
199
+ const debugWebGL = props.debugWebGL || props.debug;
200
+ const traceWebGL = props.debugWebGL;
201
+ if (debugWebGL) {
202
+ this.gl = makeDebugContext(this.gl, {debugWebGL, traceWebGL});
247
203
  log.warn('WebGL debug mode activated. Performance reduced.')();
248
- }
249
-
250
- if (props.spector) {
251
- this.spectorJS = initializeSpectorJS({...this.props, canvas: this.handle.canvas});
204
+ if (props.debugWebGL) {
205
+ log.level = Math.max(log.level, 1);
206
+ }
252
207
  }
253
208
  }
254
209
 
@@ -262,22 +217,6 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
262
217
  return this.gl.isContextLost();
263
218
  }
264
219
 
265
- getSize(): [number, number] {
266
- return [this.gl.drawingBufferWidth, this.gl.drawingBufferHeight];
267
- }
268
-
269
- isTextureFormatSupported(format: TextureFormat): boolean {
270
- return isTextureFormatSupported(this.gl, format, this._extensions);
271
- }
272
-
273
- isTextureFormatFilterable(format: TextureFormat): boolean {
274
- return isTextureFormatFilterable(this.gl, format, this._extensions);
275
- }
276
-
277
- isTextureFormatRenderable(format: TextureFormat): boolean {
278
- return isTextureFormatRenderable(this.gl, format, this._extensions);
279
- }
280
-
281
220
  // IMPLEMENTATION OF ABSTRACT DEVICE
282
221
 
283
222
  createCanvasContext(props?: CanvasContextProps): CanvasContext {
@@ -285,12 +224,11 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
285
224
  }
286
225
 
287
226
  createBuffer(props: BufferProps | ArrayBuffer | ArrayBufferView): WEBGLBuffer {
288
- const newProps = this._getBufferProps(props);
227
+ const newProps = this._normalizeBufferProps(props);
289
228
  return new WEBGLBuffer(this, newProps);
290
229
  }
291
230
 
292
- // _createTexture(props: TextureProps): WEBGLTexture {
293
- _createTexture(props: TextureProps): Texture {
231
+ createTexture(props: TextureProps): WEBGLTexture {
294
232
  return new WEBGLTexture(this, props);
295
233
  }
296
234
 
@@ -407,38 +345,21 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
407
345
  return withGLParameters(this.gl, parameters, func);
408
346
  }
409
347
 
410
- override clearWebGL(options?: {
411
- framebuffer?: Framebuffer;
412
- color?: any;
413
- depth?: any;
414
- stencil?: any;
415
- }): void {
416
- clear(this, options);
417
- }
418
-
419
348
  override resetWebGL(): void {
420
349
  log.warn('WebGLDevice.resetWebGL is deprecated, use only for debugging')();
421
350
  resetGLParameters(this.gl);
422
351
  }
423
352
 
353
+ override _getDeviceSpecificTextureFormatCapabilities(
354
+ capabilities: DeviceTextureFormatCapabilities
355
+ ): DeviceTextureFormatCapabilities {
356
+ return getTextureFormatCapabilitiesWebGL(this.gl, capabilities, this._extensions);
357
+ }
358
+
424
359
  //
425
360
  // WebGL-only API (not part of `Device` API)
426
361
  //
427
362
 
428
- /** WebGL2 context. */
429
- readonly gl: WebGL2RenderingContext;
430
- readonly debug: boolean = false;
431
-
432
- /** State used by luma.gl classes: TODO - move to canvasContext*/
433
- readonly _canvasSizeInfo = {clientWidth: 0, clientHeight: 0, devicePixelRatio: 1};
434
-
435
- /** State used by luma.gl classes - TODO - not used? */
436
- readonly _extensions: GLExtensions = {};
437
- _polyfilled: boolean = false;
438
-
439
- /** Instance of Spector.js (if initialized) */
440
- spectorJS: unknown;
441
-
442
363
  /**
443
364
  * Triggers device (or WebGL context) loss.
444
365
  * @note primarily intended for testing how application reacts to device loss
@@ -461,22 +382,14 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
461
382
 
462
383
  /** Save current WebGL context state onto an internal stack */
463
384
  pushState(): void {
464
- pushContextState(this.gl);
385
+ const webglState = WebGLStateTracker.get(this.gl);
386
+ webglState.push();
465
387
  }
466
388
 
467
389
  /** Restores previously saved context state */
468
390
  popState(): void {
469
- popContextState(this.gl);
470
- }
471
-
472
- /**
473
- * Storing data on a special field on WebGLObjects makes that data visible in SPECTOR chrome debug extension
474
- * luma.gl ids and props can be inspected
475
- */
476
- setSpectorMetadata(handle: unknown, props: Record<string, unknown>) {
477
- // @ts-expect-error
478
- // eslint-disable-next-line camelcase
479
- handle.__SPECTOR_Metadata = props;
391
+ const webglState = WebGLStateTracker.get(this.gl);
392
+ webglState.pop();
480
393
  }
481
394
 
482
395
  /**
@@ -484,18 +397,28 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
484
397
  * Be aware that there are some duplicates especially for constants that are 0,
485
398
  * so this isn't guaranteed to return the right key in all cases.
486
399
  */
487
- getGLKey(value: unknown, gl?: WebGL2RenderingContext): string {
488
- // @ts-ignore expect-error depends on settings
489
- gl = gl || this.gl2 || this.gl;
400
+ getGLKey(value: unknown, options?: {emptyIfUnknown?: boolean}): string {
490
401
  const number = Number(value);
491
- for (const key in gl) {
402
+ for (const key in this.gl) {
492
403
  // @ts-ignore expect-error depends on settings
493
- if (gl[key] === number) {
404
+ if (this.gl[key] === number) {
494
405
  return `GL.${key}`;
495
406
  }
496
407
  }
497
408
  // No constant found. Stringify the value and return it.
498
- return String(value);
409
+ return options?.emptyIfUnknown ? '' : String(value);
410
+ }
411
+
412
+ /**
413
+ * Returns a map with any GL.<KEY> constants mapped to strings, both for keys and values
414
+ */
415
+ getGLKeys(glParameters: Record<number, unknown>): Record<string, string> {
416
+ const opts = {emptyIfUnknown: true};
417
+ return Object.entries(glParameters).reduce<Record<string, string>>((keys, [key, value]) => {
418
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
419
+ keys[`${key}:${this.getGLKey(key, opts)}`] = `${value}:${this.getGLKey(value, opts)}`;
420
+ return keys;
421
+ }, {});
499
422
  }
500
423
 
501
424
  /** Store constants */
@@ -539,15 +462,26 @@ ${device.info.vendor}, ${device.info.renderer} for canvas: ${device.canvasContex
539
462
  getWebGLExtension(this.gl, name, this._extensions);
540
463
  return this._extensions;
541
464
  }
542
- }
543
465
 
544
- /** Check if supplied parameter is a WebGL2RenderingContext */
545
- function isWebGL(gl: any): boolean {
546
- if (typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext) {
547
- return true;
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;
548
484
  }
549
- // Look for debug contexts, headless gl etc
550
- return Boolean(gl && Number.isFinite(gl._version));
551
485
  }
552
486
 
553
487
  /** Set constant float array attribute */