@luma.gl/webgl 9.1.0-alpha.1 → 9.1.0-alpha.12

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 (109) hide show
  1. package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
  2. package/dist/adapter/converters/device-parameters.js +18 -11
  3. package/dist/adapter/converters/texture-formats.d.ts +1 -1
  4. package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
  5. package/dist/adapter/converters/texture-formats.js +9 -16
  6. package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
  7. package/dist/adapter/device-helpers/webgl-device-features.js +1 -3
  8. package/dist/adapter/helpers/format-utils.d.ts.map +1 -0
  9. package/dist/adapter/helpers/get-shader-layout.d.ts.map +1 -1
  10. package/dist/adapter/helpers/get-shader-layout.js +1 -3
  11. package/dist/adapter/helpers/typed-array-utils.d.ts.map +1 -0
  12. package/dist/adapter/helpers/webgl-texture-utils.d.ts +89 -22
  13. package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
  14. package/dist/adapter/helpers/webgl-texture-utils.js +220 -26
  15. package/dist/adapter/resources/webgl-framebuffer.js +1 -1
  16. package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
  17. package/dist/adapter/resources/webgl-render-pass.js +17 -4
  18. package/dist/adapter/resources/webgl-render-pipeline.d.ts +1 -3
  19. package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
  20. package/dist/adapter/resources/webgl-render-pipeline.js +1 -1
  21. package/dist/adapter/resources/webgl-shader.js +1 -1
  22. package/dist/adapter/resources/webgl-texture.d.ts +21 -3
  23. package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
  24. package/dist/adapter/resources/webgl-texture.js +49 -30
  25. package/dist/adapter/resources/webgl-transform-feedback.js +1 -1
  26. package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
  27. package/dist/adapter/resources/webgl-vertex-array.js +3 -0
  28. package/dist/adapter/webgl-adapter.d.ts +21 -0
  29. package/dist/adapter/webgl-adapter.d.ts.map +1 -0
  30. package/dist/adapter/webgl-adapter.js +91 -0
  31. package/dist/adapter/webgl-device.d.ts +16 -29
  32. package/dist/adapter/webgl-device.d.ts.map +1 -1
  33. package/dist/adapter/webgl-device.js +34 -114
  34. package/dist/context/debug/spector-types.d.ts +1108 -0
  35. package/dist/context/debug/spector-types.d.ts.map +1 -0
  36. package/dist/context/debug/spector-types.js +697 -0
  37. package/dist/context/debug/spector.d.ts +12 -8
  38. package/dist/context/debug/spector.d.ts.map +1 -1
  39. package/dist/context/debug/spector.js +23 -17
  40. package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts +9 -0
  41. package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts.map +1 -0
  42. package/dist/context/polyfills/polyfill-webgl1-extensions.js +181 -0
  43. package/dist/context/state-tracker/webgl-state-tracker.d.ts +43 -0
  44. package/dist/context/state-tracker/webgl-state-tracker.d.ts.map +1 -0
  45. package/dist/context/state-tracker/{track-context-state.js → webgl-state-tracker.js} +44 -74
  46. package/dist/context/state-tracker/with-parameters.d.ts.map +1 -1
  47. package/dist/context/state-tracker/with-parameters.js +5 -4
  48. package/dist/deprecated/accessor.d.ts.map +1 -0
  49. package/dist/{classic → deprecated}/accessor.js +36 -1
  50. package/dist/deprecated/clear.d.ts.map +1 -0
  51. package/dist/{classic → deprecated}/clear.js +2 -0
  52. package/dist/dist.dev.js +816 -642
  53. package/dist/dist.min.js +2 -2
  54. package/dist/index.cjs +815 -648
  55. package/dist/index.cjs.map +4 -4
  56. package/dist/index.d.ts +4 -2
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +4 -3
  59. package/dist/utils/fill-array.d.ts +4 -4
  60. package/dist/utils/fill-array.d.ts.map +1 -1
  61. package/dist/utils/split-uniforms-and-bindings.d.ts +1 -1
  62. package/dist/utils/split-uniforms-and-bindings.d.ts.map +1 -1
  63. package/dist/utils/uid.d.ts +7 -0
  64. package/dist/utils/uid.d.ts.map +1 -0
  65. package/dist/utils/uid.js +14 -0
  66. package/package.json +5 -5
  67. package/src/adapter/converters/device-parameters.ts +18 -12
  68. package/src/adapter/converters/texture-formats.ts +12 -20
  69. package/src/adapter/device-helpers/webgl-device-features.ts +5 -3
  70. package/src/adapter/helpers/get-shader-layout.ts +1 -3
  71. package/src/adapter/helpers/webgl-texture-utils.ts +366 -44
  72. package/src/adapter/resources/webgl-framebuffer.ts +1 -1
  73. package/src/adapter/resources/webgl-render-pass.ts +20 -7
  74. package/src/adapter/resources/webgl-render-pipeline.ts +12 -4
  75. package/src/adapter/resources/webgl-shader.ts +1 -1
  76. package/src/adapter/resources/webgl-texture.ts +76 -30
  77. package/src/adapter/resources/webgl-transform-feedback.ts +1 -1
  78. package/src/adapter/resources/webgl-vertex-array.ts +3 -0
  79. package/src/adapter/webgl-adapter.ts +113 -0
  80. package/src/adapter/webgl-device.ts +45 -139
  81. package/src/context/debug/spector-types.ts +1154 -0
  82. package/src/context/debug/spector.ts +38 -29
  83. package/src/context/polyfills/polyfill-webgl1-extensions.ts +202 -0
  84. package/src/context/state-tracker/{track-context-state.ts → webgl-state-tracker.ts} +55 -94
  85. package/src/context/state-tracker/with-parameters.ts +5 -4
  86. package/src/{classic → deprecated}/accessor.ts +44 -3
  87. package/src/{classic → deprecated}/clear.ts +3 -1
  88. package/src/index.ts +6 -8
  89. package/src/utils/fill-array.ts +4 -4
  90. package/src/utils/split-uniforms-and-bindings.ts +3 -3
  91. package/src/utils/uid.ts +16 -0
  92. package/dist/classic/accessor.d.ts.map +0 -1
  93. package/dist/classic/clear.d.ts.map +0 -1
  94. package/dist/classic/copy-and-blit.d.ts +0 -63
  95. package/dist/classic/copy-and-blit.d.ts.map +0 -1
  96. package/dist/classic/copy-and-blit.js +0 -193
  97. package/dist/classic/format-utils.d.ts.map +0 -1
  98. package/dist/classic/typed-array-utils.d.ts.map +0 -1
  99. package/dist/context/state-tracker/track-context-state.d.ts +0 -22
  100. package/dist/context/state-tracker/track-context-state.d.ts.map +0 -1
  101. package/src/classic/copy-and-blit.ts +0 -318
  102. /package/dist/{classic → adapter/helpers}/format-utils.d.ts +0 -0
  103. /package/dist/{classic → adapter/helpers}/format-utils.js +0 -0
  104. /package/dist/{classic → adapter/helpers}/typed-array-utils.d.ts +0 -0
  105. /package/dist/{classic → adapter/helpers}/typed-array-utils.js +0 -0
  106. /package/dist/{classic → deprecated}/accessor.d.ts +0 -0
  107. /package/dist/{classic → deprecated}/clear.d.ts +0 -0
  108. /package/src/{classic → adapter/helpers}/format-utils.ts +0 -0
  109. /package/src/{classic → adapter/helpers}/typed-array-utils.ts +0 -0
@@ -7,7 +7,8 @@
7
7
  //
8
8
 
9
9
  import type {ExternalImage} from '@luma.gl/core';
10
- // import {Buffer} from '@luma.gl/core';
10
+ import {Buffer, Texture, Framebuffer, FramebufferProps} from '@luma.gl/core';
11
+
11
12
  import {
12
13
  GL,
13
14
  GLTextureTarget,
@@ -18,39 +19,36 @@ import {
18
19
 
19
20
  import {TypedArray} from '@math.gl/types';
20
21
 
22
+ import {WEBGLFramebuffer} from '../resources/webgl-framebuffer';
23
+ import {getGLTypeFromTypedArray, getTypedArrayFromGLType} from './typed-array-utils';
24
+ import {glFormatToComponents, glTypeToBytes} from './format-utils';
25
+ import {WEBGLBuffer} from '../resources/webgl-buffer';
26
+ import {WEBGLTexture} from '../resources/webgl-texture';
27
+
21
28
  /** A "border" parameter is required in many WebGL texture APIs, but must always be 0... */
22
29
  const BORDER = 0;
23
30
 
31
+ /**
32
+ * Options for setting data into a texture
33
+ */
24
34
  export type WebGLSetTextureOptions = {
25
35
  dimension: '1d' | '2d' | '2d-array' | 'cube' | 'cube-array' | '3d';
26
36
  height: number;
27
37
  width: number;
28
- depth?: number;
29
- level?: number;
38
+ depth: number;
39
+ mipLevel?: number;
30
40
  glTarget: GLTextureTarget;
31
41
  glInternalFormat: GL;
32
42
  glFormat: GLTexelDataFormat;
33
43
  glType: GLPixelType;
34
44
  compressed?: boolean;
35
-
36
45
  byteOffset?: number;
37
46
  byteLength?: number;
38
47
  };
39
48
 
40
49
  /**
41
- * @param {*} pixels, data -
42
- * null - create empty texture of specified format
43
- * Typed array - init from image data in typed array
44
- * Buffer|WebGLBuffer - (WEBGL2) init from image data in WebGLBuffer
45
- * HTMLImageElement|Image - Inits with content of image. Auto width/height
46
- * HTMLCanvasElement - Inits with contents of canvas. Auto width/height
47
- * HTMLVideoElement - Creates video texture. Auto width/height
50
+ * Options for copying an image or data into a texture
48
51
  *
49
- * @param x - xOffset from where texture to be updated
50
- * @param y - yOffset from where texture to be updated
51
- * @param width - width of the sub image to be updated
52
- * @param height - height of the sub image to be updated
53
- * @param level - mip level to be updated
54
52
  * @param {GLenum} format - internal format of image data.
55
53
  * @param {GLenum} type
56
54
  * - format of array (autodetect from type) or
@@ -61,12 +59,19 @@ export type WebGLSetTextureOptions = {
61
59
  */
62
60
  export type WebGLCopyTextureOptions = {
63
61
  dimension: '1d' | '2d' | '2d-array' | 'cube' | 'cube-array' | '3d';
64
- level?: number;
65
- height: number;
62
+ /** mip level to be updated */
63
+ mipLevel?: number;
64
+ /** width of the sub image to be updated */
66
65
  width: number;
66
+ /** height of the sub image to be updated */
67
+ height: number;
68
+ /** depth of texture to be updated */
67
69
  depth?: number;
70
+ /** xOffset from where texture to be updated */
68
71
  x?: number;
72
+ /** yOffset from where texture to be updated */
69
73
  y?: number;
74
+ /** yOffset from where texture to be updated */
70
75
  z?: number;
71
76
 
72
77
  glTarget: GLTextureTarget;
@@ -74,7 +79,6 @@ export type WebGLCopyTextureOptions = {
74
79
  glFormat: GL;
75
80
  glType: GL;
76
81
  compressed?: boolean;
77
-
78
82
  byteOffset?: number;
79
83
  byteLength?: number;
80
84
  };
@@ -97,7 +101,7 @@ export function initializeTextureStorage(
97
101
  ): void {
98
102
  const {dimension, width, height, depth = 0} = options;
99
103
  const {glInternalFormat} = options;
100
- const glTarget = options.glTarget; // getCubeTargetWebGL(options.glTarget, dimension, depth);
104
+ const glTarget = options.glTarget; // getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
101
105
  switch (dimension) {
102
106
  case '2d-array':
103
107
  case '3d':
@@ -112,30 +116,34 @@ export function initializeTextureStorage(
112
116
  /**
113
117
  * Copy a region of compressed data from a GPU memory buffer into this texture.
114
118
  */
115
- export function copyCPUImageToMipLevel(
119
+ export function copyExternalImageToMipLevel(
116
120
  gl: WebGL2RenderingContext,
121
+ handle: WebGLTexture,
117
122
  image: ExternalImage,
118
123
  options: WebGLCopyTextureOptions
119
124
  ): void {
120
- const {dimension, width, height, depth = 0, level = 0} = options;
125
+ const {width, height} = options;
126
+ const {dimension, depth = 0, mipLevel = 0} = options;
121
127
  const {x = 0, y = 0, z = 0} = options;
122
128
  const {glFormat, glType} = options;
123
- const glTarget = getCubeTargetWebGL(options.glTarget, dimension, depth);
124
129
 
125
- // width = size.width,
126
- // height = size.height
130
+ const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
127
131
 
128
132
  switch (dimension) {
129
133
  case '2d-array':
130
134
  case '3d':
135
+ gl.bindTexture(glTarget, handle);
131
136
  // prettier-ignore
132
- gl.texSubImage3D(glTarget, level, x, y, z, width, height, depth, glFormat, glType, image);
137
+ gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
138
+ gl.bindTexture(glTarget, null);
133
139
  break;
134
140
 
135
141
  case '2d':
136
142
  case 'cube':
143
+ gl.bindTexture(glTarget, handle);
137
144
  // prettier-ignore
138
- gl.texSubImage2D(glTarget, level, x, y, width, height, glFormat, glType, image);
145
+ gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
146
+ gl.bindTexture(glTarget, null);
139
147
  break;
140
148
 
141
149
  default:
@@ -151,20 +159,22 @@ export function copyCPUDataToMipLevel(
151
159
  typedArray: TypedArray,
152
160
  options: WebGLCopyTextureOptions
153
161
  ): void {
154
- const {dimension, width, height, depth = 0, level = 0, byteOffset = 0} = options;
162
+ const {dimension, width, height, depth = 0, mipLevel = 0, byteOffset = 0} = options;
155
163
  const {x = 0, y = 0, z = 0} = options;
156
164
  const {glFormat, glType, compressed} = options;
157
- const glTarget = getCubeTargetWebGL(options.glTarget, dimension, depth);
165
+ const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
166
+
167
+ // gl.bindTexture(glTarget, null);
158
168
 
159
169
  switch (dimension) {
160
170
  case '2d-array':
161
171
  case '3d':
162
172
  if (compressed) {
163
173
  // prettier-ignore
164
- gl.compressedTexSubImage3D(glTarget, level, x, y, z, width, height, depth, glFormat, typedArray, byteOffset); // , byteLength
174
+ gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset); // , byteLength
165
175
  } else {
166
176
  // prettier-ignore
167
- gl.texSubImage3D(glTarget, level, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset); // , byteLength
177
+ gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset); // , byteLength
168
178
  }
169
179
  break;
170
180
 
@@ -172,10 +182,10 @@ export function copyCPUDataToMipLevel(
172
182
  case 'cube':
173
183
  if (compressed) {
174
184
  // prettier-ignore
175
- gl.compressedTexSubImage2D(glTarget, level, x, y, width, height, glFormat, typedArray, byteOffset); // , byteLength
185
+ gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset); // , byteLength
176
186
  } else {
177
187
  // prettier-ignore
178
- gl.texSubImage2D(glTarget, level, x, y, width, height, glFormat, glType, typedArray, byteOffset); // , byteLength
188
+ gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset); // , byteLength
179
189
  }
180
190
  break;
181
191
 
@@ -193,10 +203,10 @@ export function copyGPUBufferToMipLevel(
193
203
  byteLength: number,
194
204
  options: WebGLCopyTextureOptions
195
205
  ): void {
196
- const {dimension, width, height, depth = 0, level = 0, byteOffset = 0} = options;
206
+ const {dimension, width, height, depth = 0, mipLevel = 0, byteOffset = 0} = options;
197
207
  const {x = 0, y = 0, z = 0} = options;
198
208
  const {glFormat, glType, compressed} = options;
199
- const glTarget = getCubeTargetWebGL(options.glTarget, dimension, depth);
209
+ const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
200
210
 
201
211
  gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, webglBuffer);
202
212
 
@@ -207,10 +217,10 @@ export function copyGPUBufferToMipLevel(
207
217
  if (compressed) {
208
218
  // TODO enable extension?
209
219
  // prettier-ignore
210
- gl.compressedTexSubImage3D(glTarget, level, x, y, z, width, height, depth, glFormat, byteLength, byteOffset);
220
+ gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, byteLength, byteOffset);
211
221
  } else {
212
222
  // prettier-ignore
213
- gl.texSubImage3D(glTarget, level, x, y, z, width, height, depth, glFormat, glType, byteOffset);
223
+ gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, byteOffset);
214
224
  }
215
225
  break;
216
226
 
@@ -218,10 +228,10 @@ export function copyGPUBufferToMipLevel(
218
228
  case 'cube':
219
229
  if (compressed) {
220
230
  // prettier-ignore
221
- gl.compressedTexSubImage2D(glTarget, level, x, y, width, height, glFormat, byteLength, byteOffset);
231
+ gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, byteLength, byteOffset);
222
232
  } else {
223
233
  // prettier-ignore
224
- gl.texSubImage2D(glTarget, level, x, y, width, height, BORDER, glFormat, byteOffset);
234
+ gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, BORDER, glFormat, byteOffset);
225
235
  }
226
236
  break;
227
237
 
@@ -250,9 +260,10 @@ export function getWebGLTextureTarget(
250
260
 
251
261
  /**
252
262
  * In WebGL, cube maps specify faces by overriding target instead of using the depth parameter.
263
+ * @note We still bind the texture using GL.TEXTURE_CUBE_MAP, but we need to use the face-specific target when setting mip levels.
253
264
  * @returns glTarget unchanged, if dimension !== 'cube'.
254
265
  */
255
- function getCubeTargetWebGL(
266
+ export function getWebGLCubeFaceTarget(
256
267
  glTarget: GLTextureTarget,
257
268
  dimension: '1d' | '2d' | '2d-array' | 'cube' | 'cube-array' | '3d',
258
269
  level: number
@@ -269,7 +280,7 @@ function getCubeTargetWebGL(
269
280
  export function clearMipLevel(gl: WebGL2RenderingContext, options: WebGLSetTextureOptions): void {
270
281
  const {dimension, width, height, depth = 0, level = 0} = options;
271
282
  const {glInternalFormat, glFormat, glType, compressed} = options;
272
- const glTarget = getCubeTargetWebGL(options.glTarget, dimension, depth);
283
+ const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
273
284
 
274
285
  switch (dimension) {
275
286
  case '2d-array':
@@ -312,7 +323,7 @@ export function setMipLevelFromExternalImage(
312
323
  const {dimension, width, height, depth = 0, level = 0} = options;
313
324
  const {glInternalFormat, glType} = options;
314
325
 
315
- const glTarget = getCubeTargetWebGL(options.glTarget, dimension, depth);
326
+ const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
316
327
 
317
328
  // TODO - we can't change texture width (due to WebGPU limitations) -
318
329
  // and the width/heigh of an external image is implicit, so why do we need to extract it?
@@ -363,7 +374,7 @@ export function setMipLevelFromTypedArray(
363
374
  const {dimension, width, height, depth = 0, level = 0, offset = 0} = options;
364
375
  const {glInternalFormat, glFormat, glType, compressed} = options;
365
376
 
366
- const glTarget = getCubeTargetWebGL(options.glTarget, dimension, depth);
377
+ const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
367
378
 
368
379
  withGLParameters(gl, parameters, () => {
369
380
  switch (dimension) {
@@ -442,7 +453,7 @@ export function setMipLevelFromGPUBuffer(
442
453
  ): void {
443
454
  const {dimension, width, height, depth = 0, level = 0, byteOffset = 0} = options;
444
455
  const {glInternalFormat, glFormat, glType, compressed} = options;
445
- const glTarget = getCubeTargetWebGL(options.glTarget, dimension, depth);
456
+ const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
446
457
 
447
458
  const webglBuffer = buffer as WEBGLBuffer;
448
459
  const imageSize = buffer.byteLength;
@@ -479,3 +490,314 @@ export function setMipLevelFromGPUBuffer(
479
490
  gl.bindBuffer(GL.PIXEL_UNPACK_BUFFER, null);
480
491
  }
481
492
  */
493
+
494
+ /**
495
+ * Copies data from a type or a Texture object into ArrayBuffer object.
496
+ * App can provide targetPixelArray or have it auto allocated by this method
497
+ * newly allocated by this method unless provided by app.
498
+ * @deprecated Use CommandEncoder.copyTextureToBuffer and Buffer.read
499
+ * @note Slow requires roundtrip to GPU
500
+ *
501
+ * @param source
502
+ * @param options
503
+ * @returns pixel array,
504
+ */
505
+ export function readPixelsToArray(
506
+ source: Framebuffer | Texture,
507
+ options?: {
508
+ sourceX?: number;
509
+ sourceY?: number;
510
+ sourceFormat?: number;
511
+ sourceAttachment?: number;
512
+ target?: Uint8Array | Uint16Array | Float32Array;
513
+ // following parameters are auto deduced if not provided
514
+ sourceWidth?: number;
515
+ sourceHeight?: number;
516
+ sourceDepth?: number;
517
+ sourceType?: number;
518
+ }
519
+ ): Uint8Array | Uint16Array | Float32Array {
520
+ const {
521
+ sourceX = 0,
522
+ sourceY = 0,
523
+ sourceAttachment = GL.COLOR_ATTACHMENT0 // TODO - support gl.readBuffer
524
+ } = options || {};
525
+ let {
526
+ target = null,
527
+ // following parameters are auto deduced if not provided
528
+ sourceWidth,
529
+ sourceHeight,
530
+ sourceDepth,
531
+ sourceFormat,
532
+ sourceType
533
+ } = options || {};
534
+
535
+ const {framebuffer, deleteFramebuffer} = getFramebuffer(source);
536
+ // assert(framebuffer);
537
+ const {gl, handle} = framebuffer;
538
+ const attachment = sourceAttachment - GL.COLOR_ATTACHMENT0;
539
+
540
+ sourceWidth ||= framebuffer.width;
541
+ sourceHeight ||= framebuffer.height;
542
+
543
+ // TODO - Set and unset gl.readBuffer
544
+ // if (sourceAttachment === GL.COLOR_ATTACHMENT0 && handle === null) {
545
+ // sourceAttachment = GL.FRONT;
546
+ // }
547
+
548
+ sourceDepth = framebuffer.colorAttachments[attachment]?.texture?.depth || 1;
549
+
550
+ sourceFormat ||= framebuffer.colorAttachments[attachment]?.texture?.glFormat || GL.RGBA;
551
+ // Deduce the type from color attachment if not provided.
552
+ sourceType ||= framebuffer.colorAttachments[attachment]?.texture?.glType || GL.UNSIGNED_BYTE;
553
+
554
+ // Deduce type and allocated pixelArray if needed
555
+ target = getPixelArray(target, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
556
+
557
+ // Pixel array available, if necessary, deduce type from it.
558
+ sourceType = sourceType || getGLTypeFromTypedArray(target);
559
+
560
+ const prevHandle = gl.bindFramebuffer(GL.FRAMEBUFFER, handle);
561
+ gl.readPixels(sourceX, sourceY, sourceWidth, sourceHeight, sourceFormat, sourceType, target);
562
+ // @ts-expect-error
563
+ gl.bindFramebuffer(GL.FRAMEBUFFER, prevHandle || null);
564
+ if (deleteFramebuffer) {
565
+ framebuffer.destroy();
566
+ }
567
+ return target;
568
+ }
569
+
570
+ /**
571
+ * Copies data from a Framebuffer or a Texture object into a Buffer object.
572
+ * NOTE: doesn't wait for copy to be complete, it programs GPU to perform a DMA transffer.
573
+ * @deprecated Use CommandEncoder
574
+ * @param source
575
+ * @param options
576
+ */
577
+ export function readPixelsToBuffer(
578
+ source: Framebuffer | Texture,
579
+ options?: {
580
+ sourceX?: number;
581
+ sourceY?: number;
582
+ sourceFormat?: number;
583
+ target?: Buffer; // A new Buffer object is created when not provided.
584
+ targetByteOffset?: number; // byte offset in buffer object
585
+ // following parameters are auto deduced if not provided
586
+ sourceWidth?: number;
587
+ sourceHeight?: number;
588
+ sourceType?: number;
589
+ }
590
+ ): WEBGLBuffer {
591
+ const {
592
+ target,
593
+ sourceX = 0,
594
+ sourceY = 0,
595
+ sourceFormat = GL.RGBA,
596
+ targetByteOffset = 0
597
+ } = options || {};
598
+ // following parameters are auto deduced if not provided
599
+ let {sourceWidth, sourceHeight, sourceType} = options || {};
600
+ const {framebuffer, deleteFramebuffer} = getFramebuffer(source);
601
+ // assert(framebuffer);
602
+ sourceWidth = sourceWidth || framebuffer.width;
603
+ sourceHeight = sourceHeight || framebuffer.height;
604
+
605
+ // Asynchronous read (PIXEL_PACK_BUFFER) is WebGL2 only feature
606
+ const webglFramebuffer = framebuffer;
607
+
608
+ // deduce type if not available.
609
+ sourceType = sourceType || GL.UNSIGNED_BYTE;
610
+
611
+ let webglBufferTarget = target as unknown as WEBGLBuffer | undefined;
612
+ if (!webglBufferTarget) {
613
+ // Create new buffer with enough size
614
+ const components = glFormatToComponents(sourceFormat);
615
+ const byteCount = glTypeToBytes(sourceType);
616
+ const byteLength = targetByteOffset + sourceWidth * sourceHeight * components * byteCount;
617
+ webglBufferTarget = webglFramebuffer.device.createBuffer({byteLength});
618
+ }
619
+
620
+ // TODO(donmccurdy): Do we have tests to confirm this is working?
621
+ const commandEncoder = source.device.createCommandEncoder();
622
+ commandEncoder.copyTextureToBuffer({
623
+ source: source as Texture,
624
+ width: sourceWidth,
625
+ height: sourceHeight,
626
+ origin: [sourceX, sourceY],
627
+ destination: webglBufferTarget,
628
+ byteOffset: targetByteOffset
629
+ });
630
+ commandEncoder.destroy();
631
+
632
+ if (deleteFramebuffer) {
633
+ framebuffer.destroy();
634
+ }
635
+
636
+ return webglBufferTarget;
637
+ }
638
+
639
+ /**
640
+ * Copy a rectangle from a Framebuffer or Texture object into a texture (at an offset)
641
+ * @deprecated Use CommandEncoder
642
+ */
643
+ // eslint-disable-next-line complexity, max-statements
644
+ export function copyToTexture(
645
+ source: Framebuffer | Texture,
646
+ target: Texture | GL,
647
+ options?: {
648
+ sourceX?: number;
649
+ sourceY?: number;
650
+
651
+ targetX?: number;
652
+ targetY?: number;
653
+ targetZ?: number;
654
+ targetMipmaplevel?: number;
655
+ targetInternalFormat?: number;
656
+
657
+ width?: number; // defaults to target width
658
+ height?: number; // defaults to target height
659
+ }
660
+ ): Texture {
661
+ const {
662
+ sourceX = 0,
663
+ sourceY = 0,
664
+ // attachment = GL.COLOR_ATTACHMENT0, // TODO - support gl.readBuffer
665
+ targetMipmaplevel = 0,
666
+ targetInternalFormat = GL.RGBA
667
+ } = options || {};
668
+ let {
669
+ targetX,
670
+ targetY,
671
+ targetZ,
672
+ width, // defaults to target width
673
+ height // defaults to target height
674
+ } = options || {};
675
+
676
+ const {framebuffer, deleteFramebuffer} = getFramebuffer(source);
677
+ // assert(framebuffer);
678
+ const webglFramebuffer = framebuffer;
679
+ const {device, handle} = webglFramebuffer;
680
+ const isSubCopy =
681
+ typeof targetX !== 'undefined' ||
682
+ typeof targetY !== 'undefined' ||
683
+ typeof targetZ !== 'undefined';
684
+ targetX = targetX || 0;
685
+ targetY = targetY || 0;
686
+ targetZ = targetZ || 0;
687
+ const prevHandle = device.gl.bindFramebuffer(GL.FRAMEBUFFER, handle);
688
+ // TODO - support gl.readBuffer (WebGL2 only)
689
+ // const prevBuffer = gl.readBuffer(attachment);
690
+ // assert(target);
691
+ let texture: WEBGLTexture | null = null;
692
+ let textureTarget: GL;
693
+ if (target instanceof WEBGLTexture) {
694
+ texture = target;
695
+ width = Number.isFinite(width) ? width : texture.width;
696
+ height = Number.isFinite(height) ? height : texture.height;
697
+ texture?.bind(0);
698
+ // @ts-ignore
699
+ textureTarget = texture.target;
700
+ } else {
701
+ // @ts-ignore
702
+ textureTarget = target;
703
+ }
704
+
705
+ if (!isSubCopy) {
706
+ device.gl.copyTexImage2D(
707
+ textureTarget,
708
+ targetMipmaplevel,
709
+ targetInternalFormat,
710
+ sourceX,
711
+ sourceY,
712
+ width,
713
+ height,
714
+ 0 /* border must be 0 */
715
+ );
716
+ } else {
717
+ switch (textureTarget) {
718
+ case GL.TEXTURE_2D:
719
+ case GL.TEXTURE_CUBE_MAP:
720
+ device.gl.copyTexSubImage2D(
721
+ textureTarget,
722
+ targetMipmaplevel,
723
+ targetX,
724
+ targetY,
725
+ sourceX,
726
+ sourceY,
727
+ width,
728
+ height
729
+ );
730
+ break;
731
+ case GL.TEXTURE_2D_ARRAY:
732
+ case GL.TEXTURE_3D:
733
+ device.gl.copyTexSubImage3D(
734
+ textureTarget,
735
+ targetMipmaplevel,
736
+ targetX,
737
+ targetY,
738
+ targetZ,
739
+ sourceX,
740
+ sourceY,
741
+ width,
742
+ height
743
+ );
744
+ break;
745
+ default:
746
+ }
747
+ }
748
+ if (texture) {
749
+ texture.unbind();
750
+ }
751
+ // @ts-expect-error
752
+ device.gl.bindFramebuffer(GL.FRAMEBUFFER, prevHandle || null);
753
+ if (deleteFramebuffer) {
754
+ framebuffer.destroy();
755
+ }
756
+ return texture;
757
+ }
758
+
759
+ function getFramebuffer(source: Texture | Framebuffer): {
760
+ framebuffer: WEBGLFramebuffer;
761
+ deleteFramebuffer: boolean;
762
+ } {
763
+ if (!(source instanceof Framebuffer)) {
764
+ return {framebuffer: toFramebuffer(source), deleteFramebuffer: true};
765
+ }
766
+ return {framebuffer: source as WEBGLFramebuffer, deleteFramebuffer: false};
767
+ }
768
+
769
+ /**
770
+ * Wraps a given texture into a framebuffer object, that can be further used
771
+ * to read data from the texture object.
772
+ */
773
+ export function toFramebuffer(texture: Texture, props?: FramebufferProps): WEBGLFramebuffer {
774
+ const {device, width, height, id} = texture;
775
+ const framebuffer = device.createFramebuffer({
776
+ ...props,
777
+ id: `framebuffer-for-${id}`,
778
+ width,
779
+ height,
780
+ colorAttachments: [texture]
781
+ });
782
+ return framebuffer as WEBGLFramebuffer;
783
+ }
784
+
785
+ // eslint-disable-next-line max-params
786
+ function getPixelArray(
787
+ pixelArray,
788
+ type,
789
+ format,
790
+ width: number,
791
+ height: number,
792
+ depth?: number
793
+ ): Uint8Array | Uint16Array | Float32Array {
794
+ if (pixelArray) {
795
+ return pixelArray;
796
+ }
797
+ // Allocate pixel array if not already available, using supplied type
798
+ type = type || GL.UNSIGNED_BYTE;
799
+ const ArrayType = getTypedArrayFromGLType(type, {clamped: false});
800
+ const components = glFormatToComponents(format);
801
+ // TODO - check for composite type (components = 1).
802
+ return new ArrayType(width * height * components) as Uint8Array | Uint16Array | Float32Array;
803
+ }
@@ -155,7 +155,7 @@ export class WEBGLFramebuffer extends Framebuffer {
155
155
  switch (texture.glTarget) {
156
156
  case GL.TEXTURE_2D_ARRAY:
157
157
  case GL.TEXTURE_3D:
158
- gl.framebufferTextureLayer(GL.FRAMEBUFFER, attachment, texture.glTarget, level, layer);
158
+ gl.framebufferTextureLayer(GL.FRAMEBUFFER, attachment, texture.handle, level, layer);
159
159
  break;
160
160
 
161
161
  case GL.TEXTURE_CUBE_MAP:
@@ -2,13 +2,12 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import {NumericArray} from '@math.gl/types';
5
+ import {NumericArray, NumberArray4} from '@math.gl/types';
6
6
  import {RenderPass, RenderPassProps, RenderPassParameters} from '@luma.gl/core';
7
7
  import {WebGLDevice} from '../webgl-device';
8
8
  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
- import {pushContextState, popContextState} from '../../context/state-tracker/track-context-state';
12
11
  import {WEBGLQuerySet} from './webgl-query-set';
13
12
 
14
13
  // Should collapse during minification
@@ -29,16 +28,30 @@ export class WEBGLRenderPass extends RenderPass {
29
28
  super(device, props);
30
29
  this.device = device;
31
30
 
31
+ // If no viewport is provided, apply reasonably defaults
32
+ let viewport;
33
+ if (!props?.parameters?.viewport) {
34
+ if (props?.framebuffer) {
35
+ // Set the viewport to the size of the framebuffer
36
+ const {width, height} = props.framebuffer;
37
+ viewport = [0, 0, width, height];
38
+ } else {
39
+ // Instead of using our own book-keeping, we can just read the values from the WebGL context
40
+ const [width, height] = device.getCanvasContext().getDrawingBufferSize();
41
+ viewport = [0, 0, width, height];
42
+ }
43
+ }
44
+
32
45
  // TODO - do parameters (scissorRect) affect the clear operation?
33
- pushContextState(this.device.gl);
34
- this.setParameters(this.props.parameters);
46
+ this.device.pushState();
47
+ this.setParameters({viewport, ...this.props.parameters});
35
48
 
36
49
  // Hack - for now WebGL draws in "immediate mode" (instead of queueing the operations)...
37
50
  this.clear();
38
51
  }
39
52
 
40
53
  end(): void {
41
- popContextState(this.device.gl);
54
+ this.device.popState();
42
55
  // should add commands to CommandEncoder.
43
56
  }
44
57
 
@@ -72,11 +85,11 @@ export class WEBGLRenderPass extends RenderPass {
72
85
  if (parameters.viewport) {
73
86
  // WebGPU viewports are 6 coordinates (X, Y, Z)
74
87
  if (parameters.viewport.length >= 6) {
75
- glParameters.viewport = parameters.viewport.slice(0, 4);
88
+ glParameters.viewport = parameters.viewport.slice(0, 4) as NumberArray4;
76
89
  glParameters.depthRange = [parameters.viewport[4], parameters.viewport[5]];
77
90
  } else {
78
91
  // WebGL viewports are 4 coordinates (X, Y)
79
- glParameters.viewport = parameters.viewport;
92
+ glParameters.viewport = parameters.viewport as NumberArray4;
80
93
  }
81
94
  }
82
95
  if (parameters.scissorRect) {
@@ -2,9 +2,16 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
 
5
- import type {RenderPipelineProps, RenderPipelineParameters, PrimitiveTopology} from '@luma.gl/core';
6
- import type {ShaderLayout, UniformValue, Binding} from '@luma.gl/core';
7
- import type {RenderPass, VertexArray} from '@luma.gl/core';
5
+ import type {
6
+ RenderPipelineProps,
7
+ RenderPipelineParameters,
8
+ PrimitiveTopology,
9
+ ShaderLayout,
10
+ UniformValue,
11
+ Binding,
12
+ RenderPass,
13
+ VertexArray
14
+ } from '@luma.gl/core';
8
15
  import {RenderPipeline, log} from '@luma.gl/core';
9
16
  // import {getAttributeInfosFromLayouts} from '@luma.gl/core';
10
17
  import {GL} from '@luma.gl/constants';
@@ -112,7 +119,8 @@ export class WEBGLRenderPipeline extends RenderPipeline {
112
119
  .join(', ');
113
120
  if (!options?.disableWarnings) {
114
121
  log.warn(
115
- `Unknown binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`
122
+ `No binding "${name}" in render pipeline "${this.id}", expected one of ${validBindings}`,
123
+ value
116
124
  )();
117
125
  }
118
126
  continue; // eslint-disable-line no-continue
@@ -60,7 +60,7 @@ export class WEBGLShader extends Shader {
60
60
  /** Compile a shader and get compilation status */
61
61
  protected async _compile(source: string): Promise<void> {
62
62
  const addGLSLVersion = (source: string) =>
63
- source.startsWith('#version ') ? source : `#version 100\n${source}`;
63
+ source.startsWith('#version ') ? source : `#version 300 es\n${source}`;
64
64
  source = addGLSLVersion(source);
65
65
 
66
66
  const {gl} = this.device;