@luma.gl/webgl 9.0.0-alpha.44 → 9.0.0-alpha.46
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/device-helpers/device-features.js +1 -0
- package/dist/adapter/device-helpers/device-features.js.map +1 -1
- package/dist/adapter/helpers/webgl-topology-utils.d.ts +6 -1
- package/dist/adapter/helpers/webgl-topology-utils.d.ts.map +1 -1
- package/dist/adapter/helpers/webgl-topology-utils.js +40 -0
- package/dist/adapter/helpers/webgl-topology-utils.js.map +1 -1
- package/dist/adapter/resources/webgl-buffer.d.ts +1 -1
- package/dist/adapter/resources/webgl-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-buffer.js +2 -0
- package/dist/adapter/resources/webgl-buffer.js.map +1 -1
- package/dist/adapter/resources/webgl-command-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-command-buffer.js +6 -4
- package/dist/adapter/resources/webgl-command-buffer.js.map +1 -1
- package/dist/adapter/resources/webgl-render-pipeline.d.ts +2 -0
- package/dist/adapter/resources/webgl-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-render-pipeline.js +4 -44
- package/dist/adapter/resources/webgl-render-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgl-transform-feedback.d.ts +53 -0
- package/dist/adapter/resources/webgl-transform-feedback.d.ts.map +1 -0
- package/dist/adapter/resources/webgl-transform-feedback.js +161 -0
- package/dist/adapter/resources/webgl-transform-feedback.js.map +1 -0
- package/dist/adapter/resources/webgl-vertex-array.d.ts.map +1 -1
- package/dist/adapter/resources/webgl-vertex-array.js +5 -3
- package/dist/adapter/resources/webgl-vertex-array.js.map +1 -1
- package/dist/adapter/webgl-device.d.ts +4 -2
- package/dist/adapter/webgl-device.d.ts.map +1 -1
- package/dist/adapter/webgl-device.js +7 -3
- package/dist/adapter/webgl-device.js.map +1 -1
- package/dist/classic/copy-and-blit.d.ts +3 -3
- package/dist/classic/copy-and-blit.d.ts.map +1 -1
- package/dist/classic/copy-and-blit.js +12 -20
- package/dist/classic/copy-and-blit.js.map +1 -1
- package/dist/dist.dev.js +2140 -2302
- package/dist/index.cjs +645 -806
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist.min.js +23 -22
- package/package.json +5 -5
- package/src/adapter/device-helpers/device-features.ts +1 -0
- package/src/adapter/helpers/webgl-topology-utils.ts +40 -0
- package/src/adapter/resources/webgl-buffer.ts +12 -8
- package/src/adapter/resources/webgl-command-buffer.ts +7 -13
- package/src/adapter/resources/webgl-render-pipeline.ts +11 -47
- package/src/adapter/resources/webgl-transform-feedback.ts +205 -0
- package/src/adapter/resources/webgl-vertex-array.ts +11 -8
- package/src/adapter/webgl-device.ts +10 -5
- package/src/classic/copy-and-blit.ts +16 -19
- package/src/index.ts +5 -4
- package/LICENSE +0 -34
- package/dist/classic/buffer-with-accessor.d.ts +0 -82
- package/dist/classic/buffer-with-accessor.d.ts.map +0 -1
- package/dist/classic/buffer-with-accessor.js +0 -314
- package/dist/classic/buffer-with-accessor.js.map +0 -1
- package/src/classic/buffer-with-accessor.ts +0 -466
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luma.gl/webgl",
|
|
3
|
-
"version": "9.0.0-alpha.
|
|
3
|
+
"version": "9.0.0-alpha.46",
|
|
4
4
|
"description": "WebGL2 adapter for the luma.gl API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@babel/runtime": "^7.0.0",
|
|
47
|
-
"@luma.gl/constants": "9.0.0-alpha.
|
|
48
|
-
"@luma.gl/core": "9.0.0-alpha.
|
|
47
|
+
"@luma.gl/constants": "9.0.0-alpha.46",
|
|
48
|
+
"@luma.gl/core": "9.0.0-alpha.46",
|
|
49
49
|
"@probe.gl/env": "^4.0.2"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@luma.gl/test-utils": "9.0.0-alpha.
|
|
52
|
+
"@luma.gl/test-utils": "9.0.0-alpha.46"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "c1e0602fd739f8d08e6532034a02e8cf658e188a"
|
|
55
55
|
}
|
|
@@ -126,6 +126,7 @@ const WEBGL_FEATURES: Partial<Record<DeviceFeature, [boolean | string, boolean |
|
|
|
126
126
|
'webgl2': [false, true],
|
|
127
127
|
|
|
128
128
|
'timer-query-webgl': ['EXT_disjoint_timer_query', 'EXT_disjoint_timer_query_webgl2'],
|
|
129
|
+
'transform-feedback-webgl2': [false, true],
|
|
129
130
|
|
|
130
131
|
// WEBGL1 SUPPORT
|
|
131
132
|
'vertex-array-object-webgl1': ['OES_vertex_array_object', true],
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Copyright (c) vis.gl contributors
|
|
3
3
|
|
|
4
4
|
import {GL, GLPrimitiveTopology, GLPrimitive} from '@luma.gl/constants';
|
|
5
|
+
import {PrimitiveTopology} from '@luma.gl/core';
|
|
5
6
|
|
|
6
7
|
// Counts the number of complete primitives given a number of vertices and a drawMode
|
|
7
8
|
export function getPrimitiveDrawMode(drawMode: GLPrimitiveTopology): GLPrimitive {
|
|
@@ -61,3 +62,42 @@ export function getVertexCount(options: {drawMode: GLPrimitiveTopology, vertexCo
|
|
|
61
62
|
throw new Error('drawMode');
|
|
62
63
|
}
|
|
63
64
|
}
|
|
65
|
+
|
|
66
|
+
/** Get the primitive type for draw */
|
|
67
|
+
export function getGLDrawMode(
|
|
68
|
+
topology: PrimitiveTopology
|
|
69
|
+
):
|
|
70
|
+
| GL.POINTS
|
|
71
|
+
| GL.LINES
|
|
72
|
+
| GL.LINE_STRIP
|
|
73
|
+
| GL.LINE_LOOP
|
|
74
|
+
| GL.TRIANGLES
|
|
75
|
+
| GL.TRIANGLE_STRIP
|
|
76
|
+
| GL.TRIANGLE_FAN {
|
|
77
|
+
// prettier-ignore
|
|
78
|
+
switch (topology) {
|
|
79
|
+
case 'point-list': return GL.POINTS;
|
|
80
|
+
case 'line-list': return GL.LINES;
|
|
81
|
+
case 'line-strip': return GL.LINE_STRIP;
|
|
82
|
+
case 'line-loop-webgl': return GL.LINE_LOOP;
|
|
83
|
+
case 'triangle-list': return GL.TRIANGLES;
|
|
84
|
+
case 'triangle-strip': return GL.TRIANGLE_STRIP;
|
|
85
|
+
case 'triangle-fan-webgl': return GL.TRIANGLE_FAN;
|
|
86
|
+
default: throw new Error(topology);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Get the primitive type for transform feedback */
|
|
91
|
+
export function getGLPrimitive(topology: PrimitiveTopology): GL.POINTS | GL.LINES | GL.TRIANGLES {
|
|
92
|
+
// prettier-ignore
|
|
93
|
+
switch (topology) {
|
|
94
|
+
case 'point-list': return GL.POINTS;
|
|
95
|
+
case 'line-list': return GL.LINES;
|
|
96
|
+
case 'line-strip': return GL.LINES;
|
|
97
|
+
case 'line-loop-webgl': return GL.LINES;
|
|
98
|
+
case 'triangle-list': return GL.TRIANGLES;
|
|
99
|
+
case 'triangle-strip': return GL.TRIANGLES;
|
|
100
|
+
case 'triangle-fan-webgl': return GL.TRIANGLES;
|
|
101
|
+
default: throw new Error(topology);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -36,7 +36,7 @@ export class WEBGLBuffer extends Buffer {
|
|
|
36
36
|
this.gl = this.device.gl;
|
|
37
37
|
this.gl2 = this.device.gl2;
|
|
38
38
|
|
|
39
|
-
const handle = typeof props === 'object' ?
|
|
39
|
+
const handle = typeof props === 'object' ? props.handle : undefined;
|
|
40
40
|
this.handle = handle || this.gl.createBuffer();
|
|
41
41
|
device.setSpectorMetadata(this.handle, {...this.props, data: typeof this.props.data});
|
|
42
42
|
|
|
@@ -45,7 +45,7 @@ export class WEBGLBuffer extends Buffer {
|
|
|
45
45
|
// - In WebGL2, we can use GL.COPY_READ_BUFFER which avoids locking the type here
|
|
46
46
|
this.glTarget = getWebGLTarget(this.props.usage);
|
|
47
47
|
this.glUsage = getWebGLUsage(this.props.usage);
|
|
48
|
-
this.glIndexType = this.props.indexType === 'uint32' ? GL.UNSIGNED_INT :
|
|
48
|
+
this.glIndexType = this.props.indexType === 'uint32' ? GL.UNSIGNED_INT : GL.UNSIGNED_SHORT;
|
|
49
49
|
|
|
50
50
|
this.debugData = null;
|
|
51
51
|
|
|
@@ -60,7 +60,11 @@ export class WEBGLBuffer extends Buffer {
|
|
|
60
60
|
// PRIVATE METHODS
|
|
61
61
|
|
|
62
62
|
/** Allocate a new buffer and initialize to contents of typed array */
|
|
63
|
-
_initWithData(
|
|
63
|
+
_initWithData(
|
|
64
|
+
data,
|
|
65
|
+
byteOffset: number = 0,
|
|
66
|
+
byteLength: number = data.byteLength + byteOffset
|
|
67
|
+
): this {
|
|
64
68
|
assert(ArrayBuffer.isView(data));
|
|
65
69
|
|
|
66
70
|
const glTarget = this._getWriteTarget();
|
|
@@ -135,12 +139,10 @@ export class WEBGLBuffer extends Buffer {
|
|
|
135
139
|
}
|
|
136
140
|
|
|
137
141
|
/** Read data from the buffer */
|
|
138
|
-
override async readAsync(
|
|
139
|
-
byteOffset: number = 0,
|
|
140
|
-
byteLength?: number
|
|
141
|
-
): Promise<ArrayBuffer> {
|
|
142
|
+
override async readAsync(byteOffset = 0, byteLength?: number): Promise<Uint8Array> {
|
|
142
143
|
this.device.assertWebGL2();
|
|
143
144
|
|
|
145
|
+
byteLength = byteLength ?? this.byteLength;
|
|
144
146
|
const data = new Uint8Array(byteLength);
|
|
145
147
|
const dstOffset = 0;
|
|
146
148
|
|
|
@@ -183,7 +185,9 @@ export class WEBGLBuffer extends Buffer {
|
|
|
183
185
|
// static INDIRECT = 0x0100;
|
|
184
186
|
// static QUERY_RESOLVE = 0x0200;
|
|
185
187
|
|
|
186
|
-
function getWebGLTarget(
|
|
188
|
+
function getWebGLTarget(
|
|
189
|
+
usage: number
|
|
190
|
+
): GL.ARRAY_BUFFER | GL.ELEMENT_ARRAY_BUFFER | GL.UNIFORM_BUFFER {
|
|
187
191
|
if (usage & Buffer.INDEX) {
|
|
188
192
|
return GL.ELEMENT_ARRAY_BUFFER;
|
|
189
193
|
}
|
|
@@ -7,19 +7,14 @@ import type {
|
|
|
7
7
|
CopyTextureToBufferOptions,
|
|
8
8
|
CopyTextureToTextureOptions
|
|
9
9
|
} from '@luma.gl/core';
|
|
10
|
-
import {
|
|
11
|
-
CommandBuffer,
|
|
12
|
-
Texture,
|
|
13
|
-
// Buffer,
|
|
14
|
-
Framebuffer
|
|
15
|
-
} from '@luma.gl/core';
|
|
10
|
+
import {CommandBuffer, Texture, Framebuffer} from '@luma.gl/core';
|
|
16
11
|
import {GL} from '@luma.gl/constants';
|
|
17
12
|
|
|
18
|
-
// import {getTypedArrayFromGLType, getGLTypeFromTypedArray} from '../../classic/typed-array-utils';
|
|
19
13
|
import {WebGLDevice} from '../webgl-device';
|
|
20
14
|
import {WEBGLBuffer} from './webgl-buffer';
|
|
21
15
|
import {WEBGLTexture} from './webgl-texture';
|
|
22
16
|
import {WEBGLFramebuffer} from './webgl-framebuffer';
|
|
17
|
+
import {getWebGLTextureParameters} from '../converters/texture-formats';
|
|
23
18
|
|
|
24
19
|
function cast<T>(value: unknown): T {
|
|
25
20
|
return value as T;
|
|
@@ -56,7 +51,7 @@ export class WEBGLCommandBuffer extends CommandBuffer {
|
|
|
56
51
|
commands: Command[] = [];
|
|
57
52
|
|
|
58
53
|
constructor(device: WebGLDevice) {
|
|
59
|
-
super({});
|
|
54
|
+
super(device, {});
|
|
60
55
|
this.device = device;
|
|
61
56
|
}
|
|
62
57
|
|
|
@@ -158,7 +153,7 @@ function _copyTextureToBuffer(device: WebGLDevice, options: CopyTextureToBufferO
|
|
|
158
153
|
}
|
|
159
154
|
|
|
160
155
|
// TODO - mipLevels are set when attaching texture to framebuffer
|
|
161
|
-
if (mipLevel !== 0 || depthOrArrayLayers !==
|
|
156
|
+
if (mipLevel !== 0 || depthOrArrayLayers !== 0 || bytesPerRow || rowsPerImage) {
|
|
162
157
|
throw new Error('not implemented');
|
|
163
158
|
}
|
|
164
159
|
|
|
@@ -170,10 +165,9 @@ function _copyTextureToBuffer(device: WebGLDevice, options: CopyTextureToBufferO
|
|
|
170
165
|
const webglBuffer = destination as WEBGLBuffer;
|
|
171
166
|
const sourceWidth = width || framebuffer.width;
|
|
172
167
|
const sourceHeight = height || framebuffer.height;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
const sourceType = GL.UNSIGNED_BYTE;
|
|
168
|
+
const sourceParams = getWebGLTextureParameters(framebuffer.texture.format, true);
|
|
169
|
+
const sourceFormat = sourceParams.dataFormat;
|
|
170
|
+
const sourceType = sourceParams.type;
|
|
177
171
|
|
|
178
172
|
// if (!target) {
|
|
179
173
|
// // Create new buffer with enough size
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright (c) vis.gl contributors
|
|
3
3
|
|
|
4
4
|
import type {UniformValue, RenderPipelineProps, Binding} from '@luma.gl/core';
|
|
5
|
-
import type {ShaderLayout
|
|
5
|
+
import type {ShaderLayout} from '@luma.gl/core';
|
|
6
6
|
import type {RenderPass, VertexArray} from '@luma.gl/core';
|
|
7
7
|
import {RenderPipeline, cast, splitUniformsAndBindings, log} from '@luma.gl/core';
|
|
8
8
|
import {mergeShaderLayout} from '@luma.gl/core';
|
|
@@ -21,6 +21,8 @@ import {WEBGLFramebuffer} from './webgl-framebuffer';
|
|
|
21
21
|
import {WEBGLTexture} from './webgl-texture';
|
|
22
22
|
// import {WEBGLVertexArray} from './webgl-vertex-array';
|
|
23
23
|
import {WEBGLRenderPass} from './webgl-render-pass';
|
|
24
|
+
import {WEBGLTransformFeedback} from './webgl-transform-feedback';
|
|
25
|
+
import {getGLDrawMode} from '../helpers/webgl-topology-utils';
|
|
24
26
|
|
|
25
27
|
const LOG_PROGRAM_PERF_PRIORITY = 4;
|
|
26
28
|
|
|
@@ -133,7 +135,7 @@ export class WEBGLRenderPipeline extends RenderPipeline {
|
|
|
133
135
|
// This convention allows shaders to name uniform blocks as `uniform appUniforms {} app;`
|
|
134
136
|
// and reference them as `app` from both GLSL and JS.
|
|
135
137
|
// TODO - this is rather hacky - we could also remap the name directly in the shader layout.
|
|
136
|
-
const binding =
|
|
138
|
+
const binding =
|
|
137
139
|
this.shaderLayout.bindings.find(binding => binding.name === name) ||
|
|
138
140
|
this.shaderLayout.bindings.find(binding => binding.name === `${name}Uniforms`);
|
|
139
141
|
|
|
@@ -198,6 +200,7 @@ export class WEBGLRenderPipeline extends RenderPipeline {
|
|
|
198
200
|
firstIndex?: number;
|
|
199
201
|
firstInstance?: number;
|
|
200
202
|
baseVertex?: number;
|
|
203
|
+
transformFeedback?: WEBGLTransformFeedback;
|
|
201
204
|
}): boolean {
|
|
202
205
|
const {
|
|
203
206
|
renderPass,
|
|
@@ -205,10 +208,11 @@ export class WEBGLRenderPipeline extends RenderPipeline {
|
|
|
205
208
|
vertexCount,
|
|
206
209
|
// indexCount,
|
|
207
210
|
instanceCount,
|
|
208
|
-
firstVertex = 0
|
|
211
|
+
firstVertex = 0,
|
|
209
212
|
// firstIndex,
|
|
210
213
|
// firstInstance,
|
|
211
|
-
// baseVertex
|
|
214
|
+
// baseVertex,
|
|
215
|
+
transformFeedback
|
|
212
216
|
} = options;
|
|
213
217
|
|
|
214
218
|
const glDrawMode = getGLDrawMode(this.props.topology);
|
|
@@ -230,10 +234,8 @@ export class WEBGLRenderPipeline extends RenderPipeline {
|
|
|
230
234
|
// Note: Rebinds constant attributes before each draw call
|
|
231
235
|
vertexArray.bindBeforeRender(renderPass);
|
|
232
236
|
|
|
233
|
-
const primitiveMode = getGLPrimitive(this.props.topology);
|
|
234
|
-
const transformFeedback: any = null;
|
|
235
237
|
if (transformFeedback) {
|
|
236
|
-
transformFeedback.begin(
|
|
238
|
+
transformFeedback.begin(this.props.topology);
|
|
237
239
|
}
|
|
238
240
|
|
|
239
241
|
// We have to apply bindings before every draw call since other draw calls will overwrite
|
|
@@ -391,7 +393,8 @@ export class WEBGLRenderPipeline extends RenderPipeline {
|
|
|
391
393
|
let uniformBufferIndex = 0;
|
|
392
394
|
for (const binding of this.shaderLayout.bindings) {
|
|
393
395
|
// Accept both `xyz` and `xyzUniforms` as valid names for `xyzUniforms` uniform block
|
|
394
|
-
const value =
|
|
396
|
+
const value =
|
|
397
|
+
this.bindings[binding.name] || this.bindings[binding.name.replace(/Uniforms$/, '')];
|
|
395
398
|
if (!value) {
|
|
396
399
|
throw new Error(`No value for binding ${binding.name} in ${this.id}`);
|
|
397
400
|
}
|
|
@@ -472,42 +475,3 @@ export class WEBGLRenderPipeline extends RenderPipeline {
|
|
|
472
475
|
}
|
|
473
476
|
}
|
|
474
477
|
}
|
|
475
|
-
|
|
476
|
-
/** Get the primitive type for draw */
|
|
477
|
-
function getGLDrawMode(
|
|
478
|
-
topology: PrimitiveTopology
|
|
479
|
-
):
|
|
480
|
-
| GL.POINTS
|
|
481
|
-
| GL.LINES
|
|
482
|
-
| GL.LINE_STRIP
|
|
483
|
-
| GL.LINE_LOOP
|
|
484
|
-
| GL.TRIANGLES
|
|
485
|
-
| GL.TRIANGLE_STRIP
|
|
486
|
-
| GL.TRIANGLE_FAN {
|
|
487
|
-
// prettier-ignore
|
|
488
|
-
switch (topology) {
|
|
489
|
-
case 'point-list': return GL.POINTS;
|
|
490
|
-
case 'line-list': return GL.LINES;
|
|
491
|
-
case 'line-strip': return GL.LINE_STRIP;
|
|
492
|
-
case 'line-loop-webgl': return GL.LINE_LOOP;
|
|
493
|
-
case 'triangle-list': return GL.TRIANGLES;
|
|
494
|
-
case 'triangle-strip': return GL.TRIANGLE_STRIP;
|
|
495
|
-
case 'triangle-fan-webgl': return GL.TRIANGLE_FAN;
|
|
496
|
-
default: throw new Error(topology);
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
/** Get the primitive type for transform feedback */
|
|
501
|
-
function getGLPrimitive(topology: PrimitiveTopology): GL.POINTS | GL.LINES | GL.TRIANGLES {
|
|
502
|
-
// prettier-ignore
|
|
503
|
-
switch (topology) {
|
|
504
|
-
case 'point-list': return GL.POINTS;
|
|
505
|
-
case 'line-list': return GL.LINES;
|
|
506
|
-
case 'line-strip': return GL.LINES;
|
|
507
|
-
case 'line-loop-webgl': return GL.LINES;
|
|
508
|
-
case 'triangle-list': return GL.TRIANGLES;
|
|
509
|
-
case 'triangle-strip': return GL.TRIANGLES;
|
|
510
|
-
case 'triangle-fan-webgl': return GL.TRIANGLES;
|
|
511
|
-
default: throw new Error(topology);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import type {PrimitiveTopology, ShaderLayout, TransformFeedbackProps} from '@luma.gl/core';
|
|
2
|
+
import {log, TransformFeedback, Buffer} from '@luma.gl/core';
|
|
3
|
+
import {GL} from '@luma.gl/constants';
|
|
4
|
+
import {WebGLDevice} from '../webgl-device';
|
|
5
|
+
import {WEBGLBuffer} from '../..';
|
|
6
|
+
import {getGLPrimitive} from '../helpers/webgl-topology-utils';
|
|
7
|
+
|
|
8
|
+
/** For bindRange */
|
|
9
|
+
type BufferRange = {
|
|
10
|
+
buffer: Buffer;
|
|
11
|
+
byteOffset?: number;
|
|
12
|
+
byteLength?: number;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export class WEBGLTransformFeedback extends TransformFeedback {
|
|
16
|
+
readonly device: WebGLDevice;
|
|
17
|
+
readonly gl2: WebGL2RenderingContext;
|
|
18
|
+
readonly handle: WebGLTransformFeedback;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* NOTE: The Model already has this information while drawing, but
|
|
22
|
+
* TransformFeedback currently needs it internally, to look up
|
|
23
|
+
* varying information outside of a draw() call.
|
|
24
|
+
*/
|
|
25
|
+
readonly layout: ShaderLayout;
|
|
26
|
+
buffers: Record<string, BufferRange> = {};
|
|
27
|
+
unusedBuffers: Record<string, Buffer> = {};
|
|
28
|
+
/**
|
|
29
|
+
* Allows us to avoid a Chrome bug where a buffer that is already bound to a
|
|
30
|
+
* different target cannot be bound to 'TRANSFORM_FEEDBACK_BUFFER' target.
|
|
31
|
+
* This a major workaround, see: https://github.com/KhronosGroup/WebGL/issues/2346
|
|
32
|
+
*/
|
|
33
|
+
bindOnUse = true;
|
|
34
|
+
private _bound: boolean = false;
|
|
35
|
+
|
|
36
|
+
constructor(device: WebGLDevice, props: TransformFeedbackProps) {
|
|
37
|
+
super(device, props);
|
|
38
|
+
|
|
39
|
+
device.assertWebGL2();
|
|
40
|
+
this.device = device;
|
|
41
|
+
this.gl2 = device.gl2;
|
|
42
|
+
this.handle = this.props.handle || this.gl2.createTransformFeedback();
|
|
43
|
+
this.layout = this.props.layout;
|
|
44
|
+
|
|
45
|
+
if (props.buffers) {
|
|
46
|
+
this.setBuffers(props.buffers);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
Object.seal(this);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override destroy(): void {
|
|
53
|
+
this.gl2.deleteTransformFeedback(this.handle);
|
|
54
|
+
super.destroy();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
begin(topology: PrimitiveTopology = 'point-list'): void {
|
|
58
|
+
this.gl2.bindTransformFeedback(GL.TRANSFORM_FEEDBACK, this.handle);
|
|
59
|
+
if (this.bindOnUse) {
|
|
60
|
+
this._bindBuffers();
|
|
61
|
+
}
|
|
62
|
+
this.gl2.beginTransformFeedback(getGLPrimitive(topology));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
end(): void {
|
|
66
|
+
this.gl2.endTransformFeedback();
|
|
67
|
+
if (!this.bindOnUse) {
|
|
68
|
+
this._unbindBuffers();
|
|
69
|
+
}
|
|
70
|
+
this.gl2.bindTransformFeedback(GL.TRANSFORM_FEEDBACK, null);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// SUBCLASS
|
|
74
|
+
|
|
75
|
+
setBuffers(buffers: Record<string, Buffer | BufferRange>) {
|
|
76
|
+
this.buffers = {};
|
|
77
|
+
this.unusedBuffers = {};
|
|
78
|
+
|
|
79
|
+
this.bind(() => {
|
|
80
|
+
for (const bufferName in buffers) {
|
|
81
|
+
this.setBuffer(bufferName, buffers[bufferName]);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
setBuffer(locationOrName: string | number, bufferOrRange: Buffer | BufferRange) {
|
|
88
|
+
const location = this._getVaryingIndex(locationOrName);
|
|
89
|
+
const {buffer, byteLength, byteOffset} = this._getBufferRange(bufferOrRange);
|
|
90
|
+
|
|
91
|
+
if (location < 0) {
|
|
92
|
+
this.unusedBuffers[locationOrName] = buffer;
|
|
93
|
+
log.warn(`${this.id} unusedBuffers varying buffer ${locationOrName}`)();
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
this.buffers[location] = {buffer, byteLength, byteOffset};
|
|
98
|
+
|
|
99
|
+
// Need to avoid chrome bug where buffer that is already bound to a different target
|
|
100
|
+
// cannot be bound to 'TRANSFORM_FEEDBACK_BUFFER' target.
|
|
101
|
+
if (!this.bindOnUse) {
|
|
102
|
+
this._bindBuffer(location, buffer, byteOffset, byteLength);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return this;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
bind(funcOrHandle = this.handle) {
|
|
109
|
+
if (typeof funcOrHandle !== 'function') {
|
|
110
|
+
this.gl2.bindTransformFeedback(GL.TRANSFORM_FEEDBACK, funcOrHandle);
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let value: unknown;
|
|
115
|
+
|
|
116
|
+
if (!this._bound) {
|
|
117
|
+
this.gl2.bindTransformFeedback(GL.TRANSFORM_FEEDBACK, this.handle);
|
|
118
|
+
this._bound = true;
|
|
119
|
+
value = funcOrHandle();
|
|
120
|
+
this._bound = false;
|
|
121
|
+
this.gl2.bindTransformFeedback(GL.TRANSFORM_FEEDBACK, null);
|
|
122
|
+
} else {
|
|
123
|
+
value = funcOrHandle();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return value;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
unbind() {
|
|
130
|
+
this.bind(null);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// PRIVATE METHODS
|
|
134
|
+
|
|
135
|
+
/** Extract offsets for bindBufferRange */
|
|
136
|
+
protected _getBufferRange(
|
|
137
|
+
bufferOrRange: Buffer | {buffer: Buffer; byteOffset?: number; byteLength?: number}
|
|
138
|
+
): Required<BufferRange> {
|
|
139
|
+
if (bufferOrRange instanceof WEBGLBuffer) {
|
|
140
|
+
return {buffer: bufferOrRange, byteOffset: 0, byteLength: bufferOrRange.byteLength};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// To use bindBufferRange either offset or size must be specified.
|
|
144
|
+
// @ts-expect-error Must be a BufferRange.
|
|
145
|
+
const {buffer, byteOffset = 0, byteLength = bufferOrRange.buffer.byteLength} = bufferOrRange;
|
|
146
|
+
return {buffer, byteOffset, byteLength};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
protected _getVaryingIndex(locationOrName: string | number) {
|
|
150
|
+
if (isIndex(locationOrName)) {
|
|
151
|
+
return Number(locationOrName);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
for (const varying of this.layout.varyings) {
|
|
155
|
+
if (locationOrName === varying.name) {
|
|
156
|
+
return varying.location;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return -1;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Need to avoid chrome bug where buffer that is already bound to a different target
|
|
165
|
+
* cannot be bound to 'TRANSFORM_FEEDBACK_BUFFER' target.
|
|
166
|
+
*/
|
|
167
|
+
protected _bindBuffers(): void {
|
|
168
|
+
for (const bufferIndex in this.buffers) {
|
|
169
|
+
const {buffer, byteLength, byteOffset} = this._getBufferRange(this.buffers[bufferIndex]);
|
|
170
|
+
this._bindBuffer(Number(bufferIndex), buffer, byteOffset, byteLength);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
protected _unbindBuffers(): void {
|
|
175
|
+
for (const bufferIndex in this.buffers) {
|
|
176
|
+
this.gl2.bindBufferBase(GL.TRANSFORM_FEEDBACK_BUFFER, Number(bufferIndex), null);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
protected _bindBuffer(
|
|
181
|
+
index: number,
|
|
182
|
+
buffer: Buffer,
|
|
183
|
+
byteOffset = 0,
|
|
184
|
+
byteLength?: number
|
|
185
|
+
): this {
|
|
186
|
+
const handle = buffer && (buffer as WEBGLBuffer).handle;
|
|
187
|
+
if (!handle || byteLength === undefined) {
|
|
188
|
+
this.gl2.bindBufferBase(GL.TRANSFORM_FEEDBACK_BUFFER, index, handle);
|
|
189
|
+
} else {
|
|
190
|
+
this.gl2.bindBufferRange(GL.TRANSFORM_FEEDBACK_BUFFER, index, handle, byteOffset, byteLength);
|
|
191
|
+
}
|
|
192
|
+
return this;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Returns true if the given value is an integer, or a string that
|
|
198
|
+
* trivially converts to an integer (only numeric characters).
|
|
199
|
+
*/
|
|
200
|
+
function isIndex(value: string | number): boolean {
|
|
201
|
+
if (typeof value === 'number') {
|
|
202
|
+
return Number.isInteger(value);
|
|
203
|
+
}
|
|
204
|
+
return /^\d+$/.test(value);
|
|
205
|
+
}
|
|
@@ -9,7 +9,6 @@ import {getBrowser} from '@probe.gl/env';
|
|
|
9
9
|
import {WebGLDevice} from '../webgl-device';
|
|
10
10
|
import {WEBGLBuffer} from '../resources/webgl-buffer';
|
|
11
11
|
|
|
12
|
-
import {BufferWithAccessor} from '../../classic/buffer-with-accessor';
|
|
13
12
|
import {getGLFromVertexType} from '../converters/vertex-formats';
|
|
14
13
|
// import {AccessorObject} from '../..';
|
|
15
14
|
// import {getGLFromVertexType} from '../converters/vertex-formats';
|
|
@@ -24,7 +23,7 @@ export class WEBGLVertexArray extends VertexArray {
|
|
|
24
23
|
readonly handle: WebGLVertexArrayObject;
|
|
25
24
|
|
|
26
25
|
/** Attribute 0 buffer constant */
|
|
27
|
-
private buffer:
|
|
26
|
+
private buffer: WEBGLBuffer | null = null;
|
|
28
27
|
private bufferValue = null;
|
|
29
28
|
|
|
30
29
|
/** * Attribute 0 can not be disable on most desktop OpenGL based browsers */
|
|
@@ -62,7 +61,7 @@ export class WEBGLVertexArray extends VertexArray {
|
|
|
62
61
|
*/
|
|
63
62
|
setIndexBuffer(indexBuffer: Buffer | null): void {
|
|
64
63
|
const buffer = indexBuffer as WEBGLBuffer;
|
|
65
|
-
if (buffer
|
|
64
|
+
if (buffer?.glTarget !== GL.ELEMENT_ARRAY_BUFFER) {
|
|
66
65
|
throw new Error('Use .setBuffer()');
|
|
67
66
|
}
|
|
68
67
|
// In WebGL The GL.ELEMENT_ARRAY_BUFFER_BINDING is stored on the VertexArrayObject
|
|
@@ -116,7 +115,7 @@ export class WEBGLVertexArray extends VertexArray {
|
|
|
116
115
|
|
|
117
116
|
override bindBeforeRender(): void {
|
|
118
117
|
this.device.gl2.bindVertexArray(this.handle);
|
|
119
|
-
// TODO - the initial bind does not seem to take effect.
|
|
118
|
+
// TODO - the initial bind does not seem to take effect.
|
|
120
119
|
if (!this.init) {
|
|
121
120
|
// log.log(1, `Binding vertex array ${this.id}`, this.indexBuffer?.id)();
|
|
122
121
|
const webglBuffer = this.indexBuffer as WEBGLBuffer;
|
|
@@ -128,7 +127,7 @@ export class WEBGLVertexArray extends VertexArray {
|
|
|
128
127
|
|
|
129
128
|
override unbindAfterRender(): void {
|
|
130
129
|
// log.log(1, `Unbinding vertex array ${this.id}`)();
|
|
131
|
-
// TODO technically this is not necessary, but we might be interfacing
|
|
130
|
+
// TODO technically this is not necessary, but we might be interfacing
|
|
132
131
|
// with code that does not use vertex array objects
|
|
133
132
|
this.device.gl2.bindVertexArray(null);
|
|
134
133
|
// this.device.gl2.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, null);
|
|
@@ -230,10 +229,14 @@ export class WEBGLVertexArray extends VertexArray {
|
|
|
230
229
|
const byteLength = constantValue.byteLength * elementCount;
|
|
231
230
|
const length = constantValue.length * elementCount;
|
|
232
231
|
|
|
232
|
+
if (this.buffer && byteLength !== this.buffer.byteLength) {
|
|
233
|
+
throw new Error(
|
|
234
|
+
`Buffer size is immutable, byte length ${byteLength} !== ${this.buffer.byteLength}.`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
233
237
|
let updateNeeded = !this.buffer;
|
|
234
238
|
|
|
235
|
-
this.buffer = this.buffer ||
|
|
236
|
-
updateNeeded = updateNeeded || this.buffer.reallocate(byteLength);
|
|
239
|
+
this.buffer = this.buffer || this.device.createBuffer({byteLength});
|
|
237
240
|
|
|
238
241
|
// Reallocate and update contents if needed
|
|
239
242
|
updateNeeded = updateNeeded || !compareConstantArrayValues(constantValue, this.bufferValue);
|
|
@@ -242,7 +245,7 @@ export class WEBGLVertexArray extends VertexArray {
|
|
|
242
245
|
// Create a typed array that is big enough, and fill it with the required data
|
|
243
246
|
const typedArray = getScratchArray(value.constructor, length);
|
|
244
247
|
fillArray({target: typedArray, source: constantValue, start: 0, count: length});
|
|
245
|
-
this.buffer.
|
|
248
|
+
this.buffer.write(typedArray);
|
|
246
249
|
this.bufferValue = value;
|
|
247
250
|
}
|
|
248
251
|
|
|
@@ -56,10 +56,10 @@ import type {
|
|
|
56
56
|
ComputePass,
|
|
57
57
|
ComputePassProps,
|
|
58
58
|
// CommandEncoder,
|
|
59
|
-
CommandEncoderProps
|
|
59
|
+
CommandEncoderProps,
|
|
60
|
+
TransformFeedbackProps
|
|
60
61
|
} from '@luma.gl/core';
|
|
61
62
|
|
|
62
|
-
import {BufferWithAccessor} from '../classic/buffer-with-accessor';
|
|
63
63
|
import {WEBGLBuffer} from './resources/webgl-buffer';
|
|
64
64
|
import {WEBGLShader} from './resources/webgl-shader';
|
|
65
65
|
import {WEBGLSampler} from './resources/webgl-sampler';
|
|
@@ -69,6 +69,7 @@ import {WEBGLRenderPass} from './resources/webgl-render-pass';
|
|
|
69
69
|
import {WEBGLRenderPipeline} from './resources/webgl-render-pipeline';
|
|
70
70
|
import {WEBGLCommandEncoder} from './resources/webgl-command-encoder';
|
|
71
71
|
import {WEBGLVertexArray} from './resources/webgl-vertex-array';
|
|
72
|
+
import {WEBGLTransformFeedback} from './resources/webgl-transform-feedback';
|
|
72
73
|
|
|
73
74
|
const LOG_LEVEL = 1;
|
|
74
75
|
|
|
@@ -298,7 +299,7 @@ ${this.info.vendor}, ${this.info.renderer} for canvas: ${this.canvasContext.id}`
|
|
|
298
299
|
|
|
299
300
|
createBuffer(props: BufferProps | ArrayBuffer | ArrayBufferView): WEBGLBuffer {
|
|
300
301
|
const newProps = this._getBufferProps(props);
|
|
301
|
-
return new
|
|
302
|
+
return new WEBGLBuffer(this, newProps);
|
|
302
303
|
}
|
|
303
304
|
|
|
304
305
|
_createTexture(props: TextureProps): WEBGLTexture {
|
|
@@ -338,7 +339,11 @@ ${this.info.vendor}, ${this.info.renderer} for canvas: ${this.canvasContext.id}`
|
|
|
338
339
|
}
|
|
339
340
|
|
|
340
341
|
beginComputePass(props: ComputePassProps): ComputePass {
|
|
341
|
-
throw new Error('
|
|
342
|
+
throw new Error('ComputePass not supported in WebGL');
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
createTransformFeedback(props: TransformFeedbackProps): WEBGLTransformFeedback {
|
|
346
|
+
return new WEBGLTransformFeedback(this, props);
|
|
342
347
|
}
|
|
343
348
|
|
|
344
349
|
private renderPass: WEBGLRenderPass | null = null;
|
|
@@ -352,7 +357,7 @@ ${this.info.vendor}, ${this.info.renderer} for canvas: ${this.canvasContext.id}`
|
|
|
352
357
|
return this.renderPass;
|
|
353
358
|
}
|
|
354
359
|
|
|
355
|
-
override createCommandEncoder(props
|
|
360
|
+
override createCommandEncoder(props?: CommandEncoderProps): WEBGLCommandEncoder {
|
|
356
361
|
return new WEBGLCommandEncoder(this, props);
|
|
357
362
|
}
|
|
358
363
|
|