@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.
- package/dist/adapter/converters/device-parameters.d.ts.map +1 -1
- package/dist/adapter/converters/device-parameters.js +18 -11
- package/dist/adapter/converters/texture-formats.d.ts +1 -1
- package/dist/adapter/converters/texture-formats.d.ts.map +1 -1
- package/dist/adapter/converters/texture-formats.js +9 -16
- package/dist/adapter/device-helpers/webgl-device-features.d.ts.map +1 -1
- package/dist/adapter/device-helpers/webgl-device-features.js +1 -3
- package/dist/adapter/helpers/format-utils.d.ts.map +1 -0
- package/dist/adapter/helpers/get-shader-layout.d.ts.map +1 -1
- package/dist/adapter/helpers/get-shader-layout.js +1 -3
- package/dist/adapter/helpers/typed-array-utils.d.ts.map +1 -0
- package/dist/adapter/helpers/webgl-texture-utils.d.ts +89 -22
- package/dist/adapter/helpers/webgl-texture-utils.d.ts.map +1 -1
- package/dist/adapter/helpers/webgl-texture-utils.js +220 -26
- package/dist/adapter/resources/webgl-framebuffer.js +1 -1
- package/dist/adapter/resources/webgl-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pass.js +17 -4
- package/dist/adapter/resources/webgl-render-pipeline.d.ts +1 -3
- package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pipeline.js +1 -1
- package/dist/adapter/resources/webgl-shader.js +1 -1
- package/dist/adapter/resources/webgl-texture.d.ts +21 -3
- package/dist/adapter/resources/webgl-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-texture.js +49 -30
- package/dist/adapter/resources/webgl-transform-feedback.js +1 -1
- package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-vertex-array.js +3 -0
- package/dist/adapter/webgl-adapter.d.ts +21 -0
- package/dist/adapter/webgl-adapter.d.ts.map +1 -0
- package/dist/adapter/webgl-adapter.js +91 -0
- package/dist/adapter/webgl-device.d.ts +16 -29
- package/dist/adapter/webgl-device.d.ts.map +1 -1
- package/dist/adapter/webgl-device.js +34 -114
- package/dist/context/debug/spector-types.d.ts +1108 -0
- package/dist/context/debug/spector-types.d.ts.map +1 -0
- package/dist/context/debug/spector-types.js +697 -0
- package/dist/context/debug/spector.d.ts +12 -8
- package/dist/context/debug/spector.d.ts.map +1 -1
- package/dist/context/debug/spector.js +23 -17
- package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts +9 -0
- package/dist/context/polyfills/polyfill-webgl1-extensions.d.ts.map +1 -0
- package/dist/context/polyfills/polyfill-webgl1-extensions.js +181 -0
- package/dist/context/state-tracker/webgl-state-tracker.d.ts +43 -0
- package/dist/context/state-tracker/webgl-state-tracker.d.ts.map +1 -0
- package/dist/context/state-tracker/{track-context-state.js → webgl-state-tracker.js} +44 -74
- package/dist/context/state-tracker/with-parameters.d.ts.map +1 -1
- package/dist/context/state-tracker/with-parameters.js +5 -4
- package/dist/deprecated/accessor.d.ts.map +1 -0
- package/dist/{classic → deprecated}/accessor.js +36 -1
- package/dist/deprecated/clear.d.ts.map +1 -0
- package/dist/{classic → deprecated}/clear.js +2 -0
- package/dist/dist.dev.js +816 -642
- package/dist/dist.min.js +2 -2
- package/dist/index.cjs +815 -648
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/utils/fill-array.d.ts +4 -4
- package/dist/utils/fill-array.d.ts.map +1 -1
- package/dist/utils/split-uniforms-and-bindings.d.ts +1 -1
- package/dist/utils/split-uniforms-and-bindings.d.ts.map +1 -1
- package/dist/utils/uid.d.ts +7 -0
- package/dist/utils/uid.d.ts.map +1 -0
- package/dist/utils/uid.js +14 -0
- package/package.json +5 -5
- package/src/adapter/converters/device-parameters.ts +18 -12
- package/src/adapter/converters/texture-formats.ts +12 -20
- package/src/adapter/device-helpers/webgl-device-features.ts +5 -3
- package/src/adapter/helpers/get-shader-layout.ts +1 -3
- package/src/adapter/helpers/webgl-texture-utils.ts +366 -44
- package/src/adapter/resources/webgl-framebuffer.ts +1 -1
- package/src/adapter/resources/webgl-render-pass.ts +20 -7
- package/src/adapter/resources/webgl-render-pipeline.ts +12 -4
- package/src/adapter/resources/webgl-shader.ts +1 -1
- package/src/adapter/resources/webgl-texture.ts +76 -30
- package/src/adapter/resources/webgl-transform-feedback.ts +1 -1
- package/src/adapter/resources/webgl-vertex-array.ts +3 -0
- package/src/adapter/webgl-adapter.ts +113 -0
- package/src/adapter/webgl-device.ts +45 -139
- package/src/context/debug/spector-types.ts +1154 -0
- package/src/context/debug/spector.ts +38 -29
- package/src/context/polyfills/polyfill-webgl1-extensions.ts +202 -0
- package/src/context/state-tracker/{track-context-state.ts → webgl-state-tracker.ts} +55 -94
- package/src/context/state-tracker/with-parameters.ts +5 -4
- package/src/{classic → deprecated}/accessor.ts +44 -3
- package/src/{classic → deprecated}/clear.ts +3 -1
- package/src/index.ts +6 -8
- package/src/utils/fill-array.ts +4 -4
- package/src/utils/split-uniforms-and-bindings.ts +3 -3
- package/src/utils/uid.ts +16 -0
- package/dist/classic/accessor.d.ts.map +0 -1
- package/dist/classic/clear.d.ts.map +0 -1
- package/dist/classic/copy-and-blit.d.ts +0 -63
- package/dist/classic/copy-and-blit.d.ts.map +0 -1
- package/dist/classic/copy-and-blit.js +0 -193
- package/dist/classic/format-utils.d.ts.map +0 -1
- package/dist/classic/typed-array-utils.d.ts.map +0 -1
- package/dist/context/state-tracker/track-context-state.d.ts +0 -22
- package/dist/context/state-tracker/track-context-state.d.ts.map +0 -1
- package/src/classic/copy-and-blit.ts +0 -318
- /package/dist/{classic → adapter/helpers}/format-utils.d.ts +0 -0
- /package/dist/{classic → adapter/helpers}/format-utils.js +0 -0
- /package/dist/{classic → adapter/helpers}/typed-array-utils.d.ts +0 -0
- /package/dist/{classic → adapter/helpers}/typed-array-utils.js +0 -0
- /package/dist/{classic → deprecated}/accessor.d.ts +0 -0
- /package/dist/{classic → deprecated}/clear.d.ts +0 -0
- /package/src/{classic → adapter/helpers}/format-utils.ts +0 -0
- /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
|
-
|
|
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
|
|
29
|
-
|
|
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
|
-
*
|
|
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
|
|
65
|
-
|
|
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; //
|
|
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
|
|
119
|
+
export function copyExternalImageToMipLevel(
|
|
116
120
|
gl: WebGL2RenderingContext,
|
|
121
|
+
handle: WebGLTexture,
|
|
117
122
|
image: ExternalImage,
|
|
118
123
|
options: WebGLCopyTextureOptions
|
|
119
124
|
): void {
|
|
120
|
-
const {
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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 =
|
|
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,
|
|
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,
|
|
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,
|
|
185
|
+
gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset); // , byteLength
|
|
176
186
|
} else {
|
|
177
187
|
// prettier-ignore
|
|
178
|
-
gl.texSubImage2D(glTarget,
|
|
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,
|
|
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 =
|
|
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,
|
|
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,
|
|
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,
|
|
231
|
+
gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, byteLength, byteOffset);
|
|
222
232
|
} else {
|
|
223
233
|
// prettier-ignore
|
|
224
|
-
gl.texSubImage2D(glTarget,
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
`
|
|
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
|
|
63
|
+
source.startsWith('#version ') ? source : `#version 300 es\n${source}`;
|
|
64
64
|
source = addGLSLVersion(source);
|
|
65
65
|
|
|
66
66
|
const {gl} = this.device;
|