@luma.gl/webgpu 9.0.0-alpha.9 → 9.0.0-beta.2
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/LICENSE +3 -1
- package/dist/adapter/helpers/accessor-to-format.js.map +1 -1
- package/dist/adapter/helpers/convert-texture-format.d.ts +2 -2
- package/dist/adapter/helpers/convert-texture-format.d.ts.map +1 -1
- package/dist/adapter/helpers/convert-texture-format.js +0 -1
- package/dist/adapter/helpers/convert-texture-format.js.map +1 -1
- package/dist/adapter/helpers/generate-mipmaps.d.ts +1 -1
- package/dist/adapter/helpers/generate-mipmaps.js +20 -15
- package/dist/adapter/helpers/generate-mipmaps.js.map +1 -1
- package/dist/adapter/helpers/get-bind-group.d.ts +4 -4
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/helpers/get-bind-group.js +11 -18
- package/dist/adapter/helpers/get-bind-group.js.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts +5 -5
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.js +39 -43
- package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.d.ts +2 -2
- package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.js +14 -20
- package/dist/adapter/helpers/webgpu-parameters.js.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.d.ts +14 -5
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.js +19 -29
- package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.d.ts +7 -14
- package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.js +13 -27
- package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.d.ts +5 -5
- package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js +13 -27
- package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +4 -4
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.js +8 -13
- package/dist/adapter/resources/webgpu-compute-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-external-texture.d.ts +5 -5
- package/dist/adapter/resources/webgpu-external-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-external-texture.js +6 -14
- package/dist/adapter/resources/webgpu-external-texture.js.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.d.ts +4 -21
- package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.js +4 -105
- package/dist/adapter/resources/webgpu-framebuffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-query.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.d.ts +12 -7
- package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.js +53 -36
- package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +15 -22
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +46 -118
- package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.d.ts +5 -5
- package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.js +8 -14
- package/dist/adapter/resources/webgpu-sampler.js.map +1 -1
- package/dist/adapter/resources/webgpu-shader.d.ts +9 -9
- package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-shader.js +16 -29
- package/dist/adapter/resources/webgpu-shader.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture.d.ts +18 -8
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js +38 -33
- package/dist/adapter/resources/webgpu-texture.js.map +1 -1
- package/dist/adapter/resources/webgpu-vertex-array.d.ts +26 -0
- package/dist/adapter/resources/webgpu-vertex-array.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-vertex-array.js +45 -0
- package/dist/adapter/resources/webgpu-vertex-array.js.map +1 -0
- package/dist/adapter/webgpu-canvas-context.d.ts +17 -12
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +26 -47
- package/dist/adapter/webgpu-canvas-context.js.map +1 -1
- package/dist/adapter/webgpu-device.d.ts +34 -17
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +94 -103
- package/dist/adapter/webgpu-device.js.map +1 -1
- package/dist/adapter/webgpu-types.js.map +1 -1
- package/dist/dist.dev.js +3142 -0
- package/dist/glsl/glsllang.js +0 -1
- package/dist/glsl/glsllang.js.map +1 -1
- package/dist/index.cjs +1550 -0
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -7
- package/dist/index.js.map +1 -1
- package/dist.min.js +30 -0
- package/package.json +18 -9
- package/src/adapter/helpers/accessor-to-format.ts +1 -2
- package/src/adapter/helpers/convert-texture-format.ts +1 -1
- package/src/adapter/helpers/generate-mipmaps.ts +2 -2
- package/src/adapter/helpers/get-bind-group.ts +23 -13
- package/src/adapter/helpers/get-vertex-buffer-layout.ts +65 -39
- package/src/adapter/helpers/webgpu-parameters.ts +20 -14
- package/src/adapter/resources/webgpu-buffer.ts +63 -8
- package/src/adapter/resources/webgpu-command-encoder.ts +68 -48
- package/src/adapter/resources/webgpu-compute-pass.ts +13 -12
- package/src/adapter/resources/webgpu-compute-pipeline.ts +8 -7
- package/src/adapter/resources/webgpu-external-texture.ts +5 -5
- package/src/adapter/resources/webgpu-framebuffer.ts +8 -109
- package/src/adapter/resources/webgpu-query.ts +3 -3
- package/src/adapter/resources/webgpu-render-pass.ts +68 -15
- package/src/adapter/resources/webgpu-render-pipeline.ts +117 -97
- package/src/adapter/resources/webgpu-sampler.ts +6 -6
- package/src/adapter/resources/webgpu-shader.ts +25 -16
- package/src/adapter/resources/webgpu-texture.ts +54 -25
- package/src/adapter/resources/webgpu-vertex-array.ts +83 -0
- package/src/adapter/webgpu-canvas-context.ts +51 -26
- package/src/adapter/webgpu-device.ts +144 -48
- package/src/index.ts +7 -9
- package/dist/bundle.d.ts +0 -2
- package/dist/bundle.d.ts.map +0 -1
- package/dist/bundle.js +0 -5
- package/dist/bundle.js.map +0 -1
- package/dist/init.d.ts +0 -2
- package/dist/init.d.ts.map +0 -1
- package/dist/init.js +0 -4
- package/dist/init.js.map +0 -1
- package/src/bundle.ts +0 -4
- package/src/init.ts +0 -4
|
@@ -1,69 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// luma.gl MIT license
|
|
2
|
+
|
|
3
|
+
import type {Binding, UniformValue, RenderPass, VertexArray} from '@luma.gl/core';
|
|
4
|
+
import {RenderPipeline, RenderPipelineProps, cast, log, isObjectEmpty} from '@luma.gl/core';
|
|
3
5
|
import {applyParametersToRenderPipelineDescriptor} from '../helpers/webgpu-parameters';
|
|
4
6
|
import {getWebGPUTextureFormat} from '../helpers/convert-texture-format';
|
|
5
7
|
import {getBindGroup} from '../helpers/get-bind-group';
|
|
6
|
-
import {getVertexBufferLayout
|
|
8
|
+
import {getVertexBufferLayout} from '../helpers/get-vertex-buffer-layout';
|
|
7
9
|
// import {convertAttributesVertexBufferToLayout} from '../helpers/get-vertex-buffer-layout';
|
|
8
10
|
// import {mapAccessorToWebGPUFormat} from './helpers/accessor-to-format';
|
|
9
11
|
// import type {BufferAccessors} from './webgpu-pipeline';
|
|
10
12
|
|
|
11
|
-
import type WebGPUDevice from '../webgpu-device';
|
|
12
|
-
import type WebGPUBuffer from './webgpu-buffer';
|
|
13
|
-
import type WebGPUShader from './webgpu-shader';
|
|
14
|
-
import type WebGPURenderPass from './webgpu-render-pass';
|
|
13
|
+
import type {WebGPUDevice} from '../webgpu-device';
|
|
14
|
+
// import type {WebGPUBuffer} from './webgpu-buffer';
|
|
15
|
+
import type {WebGPUShader} from './webgpu-shader';
|
|
16
|
+
import type {WebGPURenderPass} from './webgpu-render-pass';
|
|
15
17
|
|
|
16
18
|
// RENDER PIPELINE
|
|
17
19
|
|
|
18
20
|
/** Creates a new render pipeline when parameters change */
|
|
19
|
-
export
|
|
21
|
+
export class WebGPURenderPipeline extends RenderPipeline {
|
|
20
22
|
device: WebGPUDevice;
|
|
21
23
|
handle: GPURenderPipeline;
|
|
22
24
|
|
|
23
25
|
vs: WebGPUShader;
|
|
24
26
|
fs: WebGPUShader | null = null;
|
|
25
27
|
|
|
26
|
-
private _bufferSlots: Record<string, number>;
|
|
27
|
-
private _buffers: Buffer[];
|
|
28
|
-
private _indexBuffer: WebGPUBuffer | null = null;
|
|
28
|
+
// private _bufferSlots: Record<string, number>;
|
|
29
|
+
// private _buffers: Buffer[];
|
|
29
30
|
// private _firstIndex: number;
|
|
30
31
|
// private _lastIndex: number;
|
|
31
32
|
|
|
32
33
|
/** For internal use to create BindGroups */
|
|
33
|
-
private _bindGroupLayout: GPUBindGroupLayout;
|
|
34
|
+
private _bindGroupLayout: GPUBindGroupLayout | null = null;
|
|
34
35
|
private _bindGroup: GPUBindGroup | null = null;
|
|
35
36
|
|
|
36
37
|
constructor(device: WebGPUDevice, props: RenderPipelineProps) {
|
|
37
38
|
super(device, props);
|
|
38
39
|
this.device = device;
|
|
39
|
-
this.handle =
|
|
40
|
+
this.handle = this.props.handle as GPURenderPipeline;
|
|
41
|
+
if (!this.handle) {
|
|
42
|
+
const descriptor = this._getRenderPipelineDescriptor();
|
|
43
|
+
log.groupCollapsed(1, `new WebGPURenderPipeline(${this.id})`)();
|
|
44
|
+
log.probe(1, JSON.stringify(descriptor, null, 2))();
|
|
45
|
+
log.groupEnd(1)();
|
|
46
|
+
this.handle = this.device.handle.createRenderPipeline(descriptor);
|
|
47
|
+
}
|
|
40
48
|
this.handle.label = this.props.id;
|
|
41
49
|
|
|
42
50
|
this.vs = cast<WebGPUShader>(props.vs);
|
|
43
51
|
this.fs = cast<WebGPUShader>(props.fs);
|
|
44
52
|
|
|
45
|
-
this._bufferSlots = getBufferSlots(this.props.
|
|
46
|
-
this._buffers = new Array<Buffer>(Object.keys(this._bufferSlots).length).fill(null);
|
|
47
|
-
this._bindGroupLayout = this.handle.getBindGroupLayout(0);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
protected createHandle(): GPURenderPipeline {
|
|
51
|
-
const descriptor = this._getRenderPipelineDescriptor();
|
|
52
|
-
const renderPipeline = this.device.handle.createRenderPipeline(descriptor);
|
|
53
|
-
log.groupCollapsed(1, `new WebGPRenderPipeline(${this.id})`)();
|
|
54
|
-
log.log(1, JSON.stringify(descriptor, null, 2))();
|
|
55
|
-
log.groupEnd(1)();
|
|
56
|
-
return renderPipeline;
|
|
53
|
+
// this._bufferSlots = getBufferSlots(this.props.shaderLayout, this.props.bufferLayout);
|
|
54
|
+
// this._buffers = new Array<Buffer>(Object.keys(this._bufferSlots).length).fill(null);
|
|
57
55
|
}
|
|
58
56
|
|
|
59
|
-
destroy() {
|
|
57
|
+
override destroy(): void {
|
|
60
58
|
// WebGPURenderPipeline has no destroy method.
|
|
61
59
|
}
|
|
62
60
|
|
|
63
|
-
setIndexBuffer(indexBuffer: Buffer): void {
|
|
64
|
-
|
|
65
|
-
}
|
|
61
|
+
// setIndexBuffer(indexBuffer: Buffer): void {
|
|
62
|
+
// this._indexBuffer = cast<WebGPUBuffer>(indexBuffer);
|
|
63
|
+
// }
|
|
66
64
|
|
|
65
|
+
/*
|
|
67
66
|
setAttributes(attributes: Record<string, Buffer>): void {
|
|
68
67
|
for (const [name, buffer] of Object.entries(attributes)) {
|
|
69
68
|
const bufferIndex = this._bufferSlots[name];
|
|
@@ -82,44 +81,105 @@ export default class WebGPURenderPipeline extends RenderPipeline {
|
|
|
82
81
|
// }
|
|
83
82
|
// }
|
|
84
83
|
}
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
// setConstantAttributes(attributes: Record<string, TypedArray>): void {
|
|
87
|
+
// throw new Error('not implemented');
|
|
88
|
+
// }
|
|
85
89
|
|
|
86
|
-
/** Set the bindings */
|
|
87
90
|
setBindings(bindings: Record<string, Binding>): void {
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
this.props.layout,
|
|
95
|
-
this.props.bindings
|
|
96
|
-
);
|
|
97
|
-
}
|
|
91
|
+
// if (isObjectEmpty(bindings)) {
|
|
92
|
+
// return;
|
|
93
|
+
// }
|
|
94
|
+
|
|
95
|
+
// Do we want to save things on CPU side?
|
|
96
|
+
Object.assign(this.props.bindings, bindings);
|
|
98
97
|
}
|
|
99
98
|
|
|
100
|
-
setUniforms(uniforms: Record<string,
|
|
99
|
+
setUniforms(uniforms: Record<string, UniformValue>): void {
|
|
101
100
|
if (!isObjectEmpty(uniforms)) {
|
|
102
101
|
throw new Error('WebGPU does not support uniforms');
|
|
103
102
|
}
|
|
104
103
|
}
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
draw(options: {
|
|
106
|
+
renderPass: RenderPass;
|
|
107
|
+
vertexArray: VertexArray;
|
|
108
|
+
vertexCount?: number;
|
|
109
|
+
indexCount?: number;
|
|
110
|
+
instanceCount?: number;
|
|
111
|
+
firstVertex?: number;
|
|
112
|
+
firstIndex?: number;
|
|
113
|
+
firstInstance?: number;
|
|
114
|
+
baseVertex?: number;
|
|
115
|
+
}): void {
|
|
116
|
+
const webgpuRenderPass: WebGPURenderPass =
|
|
117
|
+
cast<WebGPURenderPass>(options.renderPass) || this.device.getDefaultRenderPass();
|
|
118
|
+
|
|
119
|
+
// Set pipeline
|
|
120
|
+
webgpuRenderPass.handle.setPipeline(this.handle);
|
|
121
|
+
|
|
122
|
+
// Set bindings (uniform buffers, textures etc)
|
|
123
|
+
const bindGroup = this._getBindGroup();
|
|
124
|
+
if (bindGroup) {
|
|
125
|
+
webgpuRenderPass.handle.setBindGroup(0, bindGroup);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
// Set attributes
|
|
130
|
+
// Note: Rebinds constant attributes before each draw call
|
|
131
|
+
options.vertexArray.bindBeforeRender(options.renderPass);
|
|
132
|
+
|
|
133
|
+
// Draw
|
|
134
|
+
if (options.indexCount) {
|
|
135
|
+
webgpuRenderPass.handle.drawIndexed(
|
|
136
|
+
options.indexCount,
|
|
137
|
+
options.instanceCount,
|
|
138
|
+
options.firstIndex,
|
|
139
|
+
options.baseVertex,
|
|
140
|
+
options.firstInstance
|
|
141
|
+
);
|
|
142
|
+
} else {
|
|
143
|
+
webgpuRenderPass.handle.draw(
|
|
144
|
+
options.vertexCount || 0,
|
|
145
|
+
options.instanceCount || 1, // If 0, nothing will be drawn
|
|
146
|
+
options.firstInstance
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Note: Rebinds constant attributes before each draw call
|
|
151
|
+
options.vertexArray.unbindAfterRender(options.renderPass);
|
|
108
152
|
}
|
|
109
153
|
|
|
154
|
+
// _getBuffers() {
|
|
155
|
+
// return this._buffers;
|
|
156
|
+
// }
|
|
157
|
+
|
|
110
158
|
/** Return a bind group created by setBindings */
|
|
111
159
|
_getBindGroup() {
|
|
112
|
-
//
|
|
160
|
+
// Get hold of the bind group layout. We don't want to do this unless we know there is at least one bind group
|
|
161
|
+
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
162
|
+
|
|
163
|
+
// Set up the bindings
|
|
164
|
+
this._bindGroup = this._bindGroup || getBindGroup(
|
|
165
|
+
this.device.handle,
|
|
166
|
+
this._bindGroupLayout,
|
|
167
|
+
this.props.shaderLayout,
|
|
168
|
+
this.props.bindings
|
|
169
|
+
);
|
|
170
|
+
|
|
113
171
|
return this._bindGroup;
|
|
114
172
|
}
|
|
115
173
|
|
|
116
|
-
/**
|
|
174
|
+
/**
|
|
175
|
+
* Populate the complex WebGPU GPURenderPipelineDescriptor
|
|
176
|
+
*/
|
|
117
177
|
protected _getRenderPipelineDescriptor() {
|
|
118
178
|
// Set up the vertex stage
|
|
119
179
|
const vertex: GPUVertexState = {
|
|
120
180
|
module: cast<WebGPUShader>(this.props.vs).handle,
|
|
121
181
|
entryPoint: this.props.vsEntryPoint || 'main',
|
|
122
|
-
buffers: getVertexBufferLayout(this.props.
|
|
182
|
+
buffers: getVertexBufferLayout(this.props.shaderLayout, this.props.bufferLayout)
|
|
123
183
|
};
|
|
124
184
|
|
|
125
185
|
// Set up the fragment stage
|
|
@@ -131,7 +191,7 @@ export default class WebGPURenderPipeline extends RenderPipeline {
|
|
|
131
191
|
targets: [
|
|
132
192
|
{
|
|
133
193
|
// TODO exclamation mark hack!
|
|
134
|
-
format: getWebGPUTextureFormat(this.device?.canvasContext?.format
|
|
194
|
+
format: getWebGPUTextureFormat(this.device?.canvasContext?.format)
|
|
135
195
|
}
|
|
136
196
|
]
|
|
137
197
|
};
|
|
@@ -139,19 +199,20 @@ export default class WebGPURenderPipeline extends RenderPipeline {
|
|
|
139
199
|
|
|
140
200
|
// WebGPU has more restrictive topology support than WebGL
|
|
141
201
|
switch (this.props.topology) {
|
|
142
|
-
case 'triangle-fan':
|
|
143
|
-
case 'line-loop':
|
|
202
|
+
case 'triangle-fan-webgl':
|
|
203
|
+
case 'line-loop-webgl':
|
|
144
204
|
throw new Error(`WebGPU does not support primitive topology ${this.props.topology}`);
|
|
145
205
|
default:
|
|
146
206
|
}
|
|
147
207
|
|
|
148
208
|
// Create a partially populated descriptor
|
|
149
|
-
|
|
209
|
+
const descriptor: GPURenderPipelineDescriptor = {
|
|
150
210
|
vertex,
|
|
151
211
|
fragment,
|
|
152
212
|
primitive: {
|
|
153
213
|
topology: this.props.topology
|
|
154
|
-
}
|
|
214
|
+
},
|
|
215
|
+
layout: 'auto'
|
|
155
216
|
};
|
|
156
217
|
|
|
157
218
|
// Set parameters on the descriptor
|
|
@@ -160,49 +221,7 @@ export default class WebGPURenderPipeline extends RenderPipeline {
|
|
|
160
221
|
return descriptor;
|
|
161
222
|
}
|
|
162
223
|
|
|
163
|
-
|
|
164
|
-
renderPass?: RenderPass;
|
|
165
|
-
vertexCount?: number;
|
|
166
|
-
indexCount?: number;
|
|
167
|
-
instanceCount?: number;
|
|
168
|
-
firstVertex?: number;
|
|
169
|
-
firstIndex?: number;
|
|
170
|
-
firstInstance?: number;
|
|
171
|
-
baseVertex?: number;
|
|
172
|
-
}): void {
|
|
173
|
-
const webgpuRenderPass =
|
|
174
|
-
cast<WebGPURenderPass>(options.renderPass) || this.device.getDefaultRenderPass();
|
|
175
|
-
|
|
176
|
-
// Set pipeline
|
|
177
|
-
webgpuRenderPass.handle.setPipeline(this.handle);
|
|
178
|
-
|
|
179
|
-
// Set bindings (uniform buffers, textures etc)
|
|
180
|
-
if (this._getBindGroup()) {
|
|
181
|
-
webgpuRenderPass.handle.setBindGroup(0, this._getBindGroup());
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Set attributes
|
|
185
|
-
this._setAttributeBuffers(webgpuRenderPass);
|
|
186
|
-
|
|
187
|
-
// Draw
|
|
188
|
-
if (options.indexCount) {
|
|
189
|
-
webgpuRenderPass.handle.drawIndexed(
|
|
190
|
-
options.indexCount,
|
|
191
|
-
options.instanceCount,
|
|
192
|
-
options.firstIndex,
|
|
193
|
-
options.baseVertex,
|
|
194
|
-
options.firstInstance
|
|
195
|
-
);
|
|
196
|
-
} else {
|
|
197
|
-
webgpuRenderPass.handle.draw(
|
|
198
|
-
options.vertexCount || 0,
|
|
199
|
-
options.instanceCount,
|
|
200
|
-
options.firstIndex,
|
|
201
|
-
options.firstInstance
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
224
|
+
/**
|
|
206
225
|
_setAttributeBuffers(webgpuRenderPass: WebGPURenderPass) {
|
|
207
226
|
if (this._indexBuffer) {
|
|
208
227
|
webgpuRenderPass.handle.setIndexBuffer(this._indexBuffer.handle, this._indexBuffer.props.indexType);
|
|
@@ -212,7 +231,7 @@ export default class WebGPURenderPipeline extends RenderPipeline {
|
|
|
212
231
|
for (let i = 0; i < buffers.length; ++i) {
|
|
213
232
|
const buffer = cast<WebGPUBuffer>(buffers[i]);
|
|
214
233
|
if (!buffer) {
|
|
215
|
-
const attribute = this.props.
|
|
234
|
+
const attribute = this.props.shaderLayout.attributes.find(
|
|
216
235
|
(attribute) => attribute.location === i
|
|
217
236
|
);
|
|
218
237
|
throw new Error(
|
|
@@ -224,7 +243,7 @@ export default class WebGPURenderPipeline extends RenderPipeline {
|
|
|
224
243
|
|
|
225
244
|
// TODO - HANDLE buffer maps
|
|
226
245
|
/*
|
|
227
|
-
for (const [bufferName, attributeMapping] of Object.entries(this.props.
|
|
246
|
+
for (const [bufferName, attributeMapping] of Object.entries(this.props.bufferLayout)) {
|
|
228
247
|
const buffer = cast<WebGPUBuffer>(this.props.attributes[bufferName]);
|
|
229
248
|
if (!buffer) {
|
|
230
249
|
log.warn(`Missing buffer for buffer map ${bufferName}`)();
|
|
@@ -241,6 +260,7 @@ export default class WebGPURenderPipeline extends RenderPipeline {
|
|
|
241
260
|
}
|
|
242
261
|
}
|
|
243
262
|
}
|
|
244
|
-
|
|
263
|
+
*
|
|
245
264
|
}
|
|
265
|
+
*/
|
|
246
266
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {Sampler, SamplerProps} from '@luma.gl/
|
|
2
|
-
import type WebGPUDevice from '../webgpu-device';
|
|
1
|
+
import {Sampler, SamplerProps} from '@luma.gl/core';
|
|
2
|
+
import type {WebGPUDevice} from '../webgpu-device';
|
|
3
3
|
|
|
4
4
|
export type WebGPUSamplerProps = SamplerProps & {
|
|
5
5
|
handle?: GPUSampler;
|
|
@@ -8,7 +8,7 @@ export type WebGPUSamplerProps = SamplerProps & {
|
|
|
8
8
|
/**
|
|
9
9
|
*
|
|
10
10
|
*/
|
|
11
|
-
export
|
|
11
|
+
export class WebGPUSampler extends Sampler {
|
|
12
12
|
readonly device: WebGPUDevice;
|
|
13
13
|
readonly handle: GPUSampler;
|
|
14
14
|
|
|
@@ -17,16 +17,16 @@ export default class WebGPUSampler extends Sampler {
|
|
|
17
17
|
this.device = device;
|
|
18
18
|
|
|
19
19
|
// Prepare sampler props
|
|
20
|
-
const samplerProps = this.props;
|
|
20
|
+
const samplerProps: Partial<WebGPUSamplerProps> = {...this.props};
|
|
21
21
|
if (samplerProps.type !== 'comparison-sampler') {
|
|
22
22
|
delete samplerProps.compare;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
this.handle = this.handle || this.device.handle.createSampler(
|
|
25
|
+
this.handle = this.handle || this.device.handle.createSampler(samplerProps);
|
|
26
26
|
this.handle.label = this.props.id;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
destroy(): void {
|
|
29
|
+
override destroy(): void {
|
|
30
30
|
// this.handle.destroy();
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// luma.gl, MIT license
|
|
2
|
+
// Copyright (c) vis.gl contributors
|
|
3
|
+
|
|
4
|
+
import type {ShaderProps, CompilerMessage} from '@luma.gl/core';
|
|
5
|
+
import {Shader, log} from '@luma.gl/core';
|
|
6
|
+
import type {WebGPUDevice} from '../webgpu-device';
|
|
4
7
|
|
|
5
8
|
export type WebGPUShaderProps = ShaderProps & {
|
|
6
9
|
handle?: GPUShaderModule;
|
|
@@ -9,7 +12,7 @@ export type WebGPUShaderProps = ShaderProps & {
|
|
|
9
12
|
/**
|
|
10
13
|
* Immutable shader
|
|
11
14
|
*/
|
|
12
|
-
export
|
|
15
|
+
export class WebGPUShader extends Shader {
|
|
13
16
|
readonly device: WebGPUDevice;
|
|
14
17
|
readonly handle: GPUShaderModule;
|
|
15
18
|
|
|
@@ -25,10 +28,13 @@ export default class WebGPUShader extends Shader {
|
|
|
25
28
|
this._checkCompilationError(this.device.handle.popErrorScope());
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
async _checkCompilationError(errorScope: Promise<GPUError>): Promise<void> {
|
|
31
|
+
async _checkCompilationError(errorScope: Promise<GPUError | null>): Promise<void> {
|
|
29
32
|
const error = await errorScope as GPUValidationError;
|
|
30
33
|
if (error) {
|
|
31
|
-
|
|
34
|
+
// The `Shader` base class will determine if debug window should be opened based on props
|
|
35
|
+
this.debugShader();
|
|
36
|
+
|
|
37
|
+
const shaderLog = await this.getCompilationInfo();
|
|
32
38
|
log.error(`Shader compilation error: ${error.message}`, shaderLog)();
|
|
33
39
|
// Note: Even though this error is asynchronous and thrown after the constructor completes,
|
|
34
40
|
// it will result in a useful stack trace leading back to the constructor
|
|
@@ -36,16 +42,25 @@ export default class WebGPUShader extends Shader {
|
|
|
36
42
|
}
|
|
37
43
|
}
|
|
38
44
|
|
|
39
|
-
destroy() {
|
|
45
|
+
override destroy(): void {
|
|
46
|
+
// Note: WebGPU does not offer a method to destroy shaders
|
|
40
47
|
// this.handle.destroy();
|
|
41
48
|
}
|
|
42
49
|
|
|
50
|
+
/** Returns compilation info for this shader */
|
|
51
|
+
async getCompilationInfo(): Promise<readonly CompilerMessage[]> {
|
|
52
|
+
const compilationInfo = await this.handle.getCompilationInfo();
|
|
53
|
+
return compilationInfo.messages;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// PRIVATE METHODS
|
|
57
|
+
|
|
43
58
|
protected createHandle(): GPUShaderModule {
|
|
44
|
-
const {source} = this.props;
|
|
59
|
+
const {source, stage} = this.props;
|
|
45
60
|
|
|
46
61
|
let language = this.props.language;
|
|
47
62
|
// Compile from src
|
|
48
|
-
if (
|
|
63
|
+
if (language === 'auto') {
|
|
49
64
|
// wgsl uses C++ "auto" style arrow notation
|
|
50
65
|
language = source.includes('->') ? 'wgsl' : 'glsl';
|
|
51
66
|
}
|
|
@@ -57,16 +72,10 @@ export default class WebGPUShader extends Shader {
|
|
|
57
72
|
return this.device.handle.createShaderModule({
|
|
58
73
|
code: source,
|
|
59
74
|
// @ts-expect-error
|
|
60
|
-
transform: (glsl) => this.device.glslang.compileGLSL(glsl,
|
|
75
|
+
transform: (glsl) => this.device.glslang.compileGLSL(glsl, stage)
|
|
61
76
|
});
|
|
62
77
|
default:
|
|
63
78
|
throw new Error(language);
|
|
64
79
|
}
|
|
65
80
|
}
|
|
66
|
-
|
|
67
|
-
/** Returns compilation info for this shader */
|
|
68
|
-
async compilationInfo(): Promise<readonly CompilerMessage[]> {
|
|
69
|
-
const compilationInfo = await this.handle.compilationInfo();
|
|
70
|
-
return compilationInfo.messages;
|
|
71
|
-
}
|
|
72
81
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// luma.gl, MIT license
|
|
2
|
-
import {Texture, TextureProps, Sampler, SamplerProps
|
|
2
|
+
import {Texture, TextureProps, Sampler, SamplerProps} from '@luma.gl/core';
|
|
3
3
|
import {getWebGPUTextureFormat} from '../helpers/convert-texture-format';
|
|
4
|
-
import type WebGPUDevice from '../webgpu-device';
|
|
5
|
-
import WebGPUSampler from './webgpu-sampler';
|
|
4
|
+
import type {WebGPUDevice} from '../webgpu-device';
|
|
5
|
+
import {WebGPUSampler} from './webgpu-sampler';
|
|
6
6
|
|
|
7
7
|
const BASE_DIMENSIONS: Record<string, '1d' | '2d' | '3d'> = {
|
|
8
8
|
'1d': '1d',
|
|
@@ -13,11 +13,14 @@ const BASE_DIMENSIONS: Record<string, '1d' | '2d' | '3d'> = {
|
|
|
13
13
|
'3d': '3d'
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
export
|
|
16
|
+
export class WebGPUTexture extends Texture {
|
|
17
17
|
readonly device: WebGPUDevice;
|
|
18
18
|
readonly handle: GPUTexture;
|
|
19
19
|
readonly view: GPUTextureView;
|
|
20
|
-
sampler: WebGPUSampler
|
|
20
|
+
sampler: WebGPUSampler;
|
|
21
|
+
|
|
22
|
+
override height: number = 1;
|
|
23
|
+
override width: number = 1;
|
|
21
24
|
|
|
22
25
|
// static async createFromImageURL(src, usage = 0) {
|
|
23
26
|
// const img = document.createElement('img');
|
|
@@ -29,39 +32,57 @@ export default class WebGPUTexture extends Texture {
|
|
|
29
32
|
constructor(device: WebGPUDevice, props: TextureProps) {
|
|
30
33
|
super(device, props);
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
this.device = device;
|
|
36
|
+
|
|
37
|
+
if (props.data instanceof Promise) {
|
|
38
|
+
props.data.then(resolvedImageData => {
|
|
39
|
+
// @ts-expect-error
|
|
40
|
+
this.props = {...props, data: resolvedImageData};
|
|
41
|
+
this.initialize(this.props);
|
|
42
|
+
});
|
|
43
|
+
return;
|
|
34
44
|
}
|
|
35
45
|
|
|
36
|
-
this.
|
|
46
|
+
this.initialize(props);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
protected initialize(props: TextureProps): void {
|
|
50
|
+
// @ts-expect-error
|
|
37
51
|
this.handle = this.props.handle || this.createHandle();
|
|
52
|
+
this.handle.label ||= this.id;
|
|
38
53
|
|
|
39
54
|
if (this.props.data) {
|
|
40
|
-
this.setData({data: this.props.data}
|
|
55
|
+
this.setData({data: this.props.data});
|
|
41
56
|
}
|
|
42
57
|
|
|
58
|
+
this.width = this.handle.width;
|
|
59
|
+
this.height = this.handle.height;
|
|
60
|
+
// Why not just read all properties directly from the texture
|
|
61
|
+
// this.depthOrArrayLayers = this.handle.depthOrArrayLayers;
|
|
62
|
+
// this.mipLevelCount = this.handle.mipLevelCount;
|
|
63
|
+
// this.sampleCount = this.handle.sampleCount;
|
|
64
|
+
// this.dimension = this.handle.dimension;
|
|
65
|
+
// this.format = this.handle.format;
|
|
66
|
+
// this.usage = this.handle.usage;
|
|
67
|
+
|
|
43
68
|
// Create a default sampler. This mimics the WebGL1 API where sampler props are stored on the texture
|
|
44
69
|
// this.setSampler(props.sampler);
|
|
45
70
|
this.sampler = props.sampler instanceof WebGPUSampler ? props.sampler : new WebGPUSampler(this.device, props.sampler);
|
|
46
71
|
|
|
47
72
|
// TODO - To support texture arrays we need to create custom views...
|
|
48
73
|
// But we are not ready to expose TextureViews to the public API.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
74
|
+
// @ts-expect-error
|
|
75
|
+
this.view = this.createView();
|
|
76
|
+
// format: this.props.format,
|
|
77
|
+
// dimension: this.props.dimension,
|
|
78
|
+
// aspect = "all";
|
|
79
|
+
// baseMipLevel: 0;
|
|
80
|
+
// mipLevelCount;
|
|
81
|
+
// baseArrayLayer = 0;
|
|
82
|
+
// arrayLayerCount;
|
|
58
83
|
}
|
|
59
84
|
|
|
60
85
|
protected createHandle(): GPUTexture {
|
|
61
|
-
if (typeof this.props.format === 'number') {
|
|
62
|
-
throw new Error('number format');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
86
|
// Deduce size from data - TODO this is a hack
|
|
66
87
|
// @ts-expect-error
|
|
67
88
|
const width = this.props.width || this.props.data?.width || 1;
|
|
@@ -69,6 +90,7 @@ export default class WebGPUTexture extends Texture {
|
|
|
69
90
|
const height = this.props.height || this.props.data?.height || 1;
|
|
70
91
|
|
|
71
92
|
return this.device.handle.createTexture({
|
|
93
|
+
label: this.id,
|
|
72
94
|
size: {
|
|
73
95
|
width,
|
|
74
96
|
height,
|
|
@@ -82,7 +104,7 @@ export default class WebGPUTexture extends Texture {
|
|
|
82
104
|
});
|
|
83
105
|
}
|
|
84
106
|
|
|
85
|
-
destroy(): void {
|
|
107
|
+
override destroy(): void {
|
|
86
108
|
this.handle.destroy();
|
|
87
109
|
}
|
|
88
110
|
|
|
@@ -116,7 +138,7 @@ export default class WebGPUTexture extends Texture {
|
|
|
116
138
|
aspect?: 'all' | 'stencil-only' | 'depth-only';
|
|
117
139
|
colorSpace?: 'srgb';
|
|
118
140
|
premultipliedAlpha?: boolean;
|
|
119
|
-
}):
|
|
141
|
+
}): {width: number, height: number} {
|
|
120
142
|
const {
|
|
121
143
|
source,
|
|
122
144
|
width = options.source.width,
|
|
@@ -157,9 +179,16 @@ export default class WebGPUTexture extends Texture {
|
|
|
157
179
|
depth
|
|
158
180
|
]
|
|
159
181
|
);
|
|
160
|
-
return
|
|
182
|
+
return {width, height};
|
|
161
183
|
}
|
|
162
184
|
|
|
185
|
+
// WebGPU specific
|
|
186
|
+
|
|
187
|
+
/** TODO - intention is to expose TextureViews in the public API */
|
|
188
|
+
createView(): GPUTextureView {
|
|
189
|
+
return this.handle.createView({label: this.id});
|
|
190
|
+
}
|
|
191
|
+
|
|
163
192
|
/*
|
|
164
193
|
async readPixels() {
|
|
165
194
|
const readbackBuffer = device.createBuffer({
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// luma.gl, MIT license
|
|
2
|
+
// Copyright (c) vis.gl contributors
|
|
3
|
+
|
|
4
|
+
import type {Device, Buffer, VertexArrayProps, RenderPass, TypedArray} from '@luma.gl/core';
|
|
5
|
+
import {VertexArray, log} from '@luma.gl/core';
|
|
6
|
+
import {getBrowser} from '@probe.gl/env';
|
|
7
|
+
|
|
8
|
+
import {WebGPUDevice} from '../webgpu-device';
|
|
9
|
+
import {WebGPUBuffer} from '../resources/webgpu-buffer';
|
|
10
|
+
|
|
11
|
+
import {WebGPURenderPass} from './webgpu-render-pass';
|
|
12
|
+
|
|
13
|
+
/** VertexArrayObject wrapper */
|
|
14
|
+
export class WebGPUVertexArray extends VertexArray {
|
|
15
|
+
override get [Symbol.toStringTag](): string {
|
|
16
|
+
return 'WebGPUVertexArray';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
readonly device: WebGPUDevice;
|
|
20
|
+
/** Vertex Array is a helper class under WebGPU */
|
|
21
|
+
readonly handle: never;
|
|
22
|
+
|
|
23
|
+
/** * Attribute 0 can not be disable on most desktop OpenGL based browsers */
|
|
24
|
+
static isConstantAttributeZeroSupported(device: Device): boolean {
|
|
25
|
+
return device.info.type === 'webgl2' || getBrowser() === 'Chrome';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Create a VertexArray
|
|
29
|
+
constructor(device: WebGPUDevice, props?: VertexArrayProps) {
|
|
30
|
+
super(device, props);
|
|
31
|
+
this.device = device;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
override destroy(): void {}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Set an elements buffer, for indexed rendering.
|
|
38
|
+
* Must be a Buffer bound to buffer with usage bit Buffer.INDEX set.
|
|
39
|
+
*/
|
|
40
|
+
setIndexBuffer(buffer: Buffer | null): void {
|
|
41
|
+
// assert(!elementBuffer || elementBuffer.glTarget === GL.ELEMENT_ARRAY_BUFFER, ERR_ELEMENTS);
|
|
42
|
+
this.indexBuffer = buffer;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Set a bufferSlot in vertex attributes array to a buffer, enables the bufferSlot, sets divisor */
|
|
46
|
+
setBuffer(bufferSlot: number, buffer: Buffer): void {
|
|
47
|
+
// Sanity check target
|
|
48
|
+
// if (buffer.glUsage === GL.ELEMENT_ARRAY_BUFFER) {
|
|
49
|
+
// throw new Error('Use setIndexBuffer');
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
this.attributes[bufferSlot] = buffer;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Set a location in vertex attributes array to a constant value, disables the location */
|
|
56
|
+
override setConstant(location: number, value: TypedArray): void {
|
|
57
|
+
log.warn(`${this.id} constant attributes not supported on WebGPU`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
override bindBeforeRender(renderPass: RenderPass, firstIndex?: number, indexCount?: number): void {
|
|
61
|
+
const webgpuRenderPass = renderPass as WebGPURenderPass;
|
|
62
|
+
const webgpuIndexBuffer = this.indexBuffer as WebGPUBuffer;
|
|
63
|
+
if (webgpuIndexBuffer?.handle) {
|
|
64
|
+
// Note we can't unset an index buffer
|
|
65
|
+
log.warn('setting index buffer', webgpuIndexBuffer?.handle, webgpuIndexBuffer?.indexType)();
|
|
66
|
+
webgpuRenderPass.handle.setIndexBuffer(webgpuIndexBuffer?.handle, webgpuIndexBuffer?.indexType);
|
|
67
|
+
}
|
|
68
|
+
for (let location = 0; location < this.maxVertexAttributes; location++) {
|
|
69
|
+
const webgpuBuffer = this.attributes[location] as WebGPUBuffer;
|
|
70
|
+
if (webgpuBuffer?.handle) {
|
|
71
|
+
log.warn(`setting vertex buffer ${location}`,webgpuBuffer?.handle)();
|
|
72
|
+
webgpuRenderPass.handle.setVertexBuffer(location, webgpuBuffer?.handle);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// TODO - emit warnings/errors/throw if constants have been set on this vertex array
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
override unbindAfterRender(renderPass: RenderPass): void {
|
|
79
|
+
// On WebGPU we don't need to unbind.
|
|
80
|
+
// In fact we can't easily do it. setIndexBuffer/setVertexBuffer don't accept null.
|
|
81
|
+
// Unbinding presumably happens automatically when the render pass is ended.
|
|
82
|
+
}
|
|
83
|
+
}
|