@luma.gl/webgpu 9.2.6 → 9.3.0-alpha.10
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/helpers/cpu-hotspot-profiler.d.ts +54 -0
- package/dist/adapter/helpers/cpu-hotspot-profiler.d.ts.map +1 -0
- package/dist/adapter/helpers/cpu-hotspot-profiler.js +26 -0
- package/dist/adapter/helpers/cpu-hotspot-profiler.js.map +1 -0
- package/dist/adapter/helpers/generate-mipmaps-webgpu.d.ts +7 -0
- package/dist/adapter/helpers/generate-mipmaps-webgpu.d.ts.map +1 -0
- package/dist/adapter/helpers/generate-mipmaps-webgpu.js +490 -0
- package/dist/adapter/helpers/generate-mipmaps-webgpu.js.map +1 -0
- package/dist/adapter/helpers/get-bind-group.d.ts +4 -6
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/helpers/get-bind-group.js +39 -32
- package/dist/adapter/helpers/get-bind-group.js.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts +3 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.js +17 -12
- package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.js +1 -0
- package/dist/adapter/helpers/webgpu-parameters.js.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.d.ts +7 -0
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.js +58 -15
- package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-command-buffer.js +1 -1
- package/dist/adapter/resources/webgpu-command-buffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.d.ts +7 -16
- package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.js +89 -32
- package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.d.ts +3 -3
- package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js +30 -12
- package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +7 -9
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.js +30 -17
- package/dist/adapter/resources/webgpu-compute-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-fence.d.ts +13 -0
- package/dist/adapter/resources/webgpu-fence.d.ts.map +1 -0
- package/dist/adapter/resources/webgpu-fence.js +33 -0
- package/dist/adapter/resources/webgpu-fence.js.map +1 -0
- package/dist/adapter/resources/webgpu-framebuffer.d.ts +6 -0
- package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.js +16 -0
- package/dist/adapter/resources/webgpu-framebuffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.d.ts +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.js +11 -18
- package/dist/adapter/resources/webgpu-pipeline-layout.js.map +1 -1
- package/dist/adapter/resources/webgpu-query-set.d.ts +33 -4
- package/dist/adapter/resources/webgpu-query-set.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-query-set.js +145 -4
- package/dist/adapter/resources/webgpu-query-set.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.d.ts +6 -3
- package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.js +78 -34
- package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +14 -10
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +56 -35
- package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.js +4 -0
- package/dist/adapter/resources/webgpu-sampler.js.map +1 -1
- package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-shader.js +17 -1
- package/dist/adapter/resources/webgpu-shader.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture-view.d.ts +6 -0
- package/dist/adapter/resources/webgpu-texture-view.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture-view.js +47 -11
- package/dist/adapter/resources/webgpu-texture-view.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture.d.ts +25 -3
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js +211 -43
- package/dist/adapter/resources/webgpu-texture.js.map +1 -1
- package/dist/adapter/resources/webgpu-vertex-array.js +1 -1
- package/dist/adapter/resources/webgpu-vertex-array.js.map +1 -1
- package/dist/adapter/webgpu-adapter.d.ts.map +1 -1
- package/dist/adapter/webgpu-adapter.js +34 -34
- package/dist/adapter/webgpu-adapter.js.map +1 -1
- package/dist/adapter/webgpu-canvas-context.d.ts +6 -3
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +90 -30
- package/dist/adapter/webgpu-canvas-context.js.map +1 -1
- package/dist/adapter/webgpu-device.d.ts +12 -2
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +173 -16
- package/dist/adapter/webgpu-device.js.map +1 -1
- package/dist/adapter/webgpu-presentation-context.d.ts +25 -0
- package/dist/adapter/webgpu-presentation-context.d.ts.map +1 -0
- package/dist/adapter/webgpu-presentation-context.js +144 -0
- package/dist/adapter/webgpu-presentation-context.js.map +1 -0
- package/dist/dist.dev.js +8070 -547
- package/dist/dist.min.js +169 -6
- package/dist/index.cjs +1929 -410
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/wgsl/get-shader-layout-wgsl.d.ts +8 -0
- package/dist/wgsl/get-shader-layout-wgsl.d.ts.map +1 -0
- package/dist/wgsl/get-shader-layout-wgsl.js +144 -0
- package/dist/wgsl/get-shader-layout-wgsl.js.map +1 -0
- package/package.json +6 -5
- package/src/adapter/helpers/cpu-hotspot-profiler.ts +70 -0
- package/src/adapter/helpers/generate-mipmaps-webgpu.ts +583 -0
- package/src/adapter/helpers/get-bind-group.ts +52 -46
- package/src/adapter/helpers/get-vertex-buffer-layout.ts +31 -12
- package/src/adapter/helpers/webgpu-parameters.ts +2 -0
- package/src/adapter/resources/webgpu-buffer.ts +61 -15
- package/src/adapter/resources/webgpu-command-buffer.ts +1 -1
- package/src/adapter/resources/webgpu-command-encoder.ts +129 -50
- package/src/adapter/resources/webgpu-compute-pass.ts +48 -13
- package/src/adapter/resources/webgpu-compute-pipeline.ts +49 -18
- package/src/adapter/resources/webgpu-fence.ts +38 -0
- package/src/adapter/resources/webgpu-framebuffer.ts +21 -0
- package/src/adapter/resources/webgpu-pipeline-layout.ts +18 -17
- package/src/adapter/resources/webgpu-query-set.ts +185 -9
- package/src/adapter/resources/webgpu-render-pass.ts +92 -40
- package/src/adapter/resources/webgpu-render-pipeline.ts +83 -44
- package/src/adapter/resources/webgpu-sampler.ts +5 -0
- package/src/adapter/resources/webgpu-shader.ts +16 -1
- package/src/adapter/resources/webgpu-texture-view.ts +51 -11
- package/src/adapter/resources/webgpu-texture.ts +281 -101
- package/src/adapter/resources/webgpu-vertex-array.ts +1 -1
- package/src/adapter/webgpu-adapter.ts +40 -42
- package/src/adapter/webgpu-canvas-context.ts +107 -40
- package/src/adapter/webgpu-device.ts +231 -21
- package/src/adapter/webgpu-presentation-context.ts +180 -0
- package/src/index.ts +3 -0
- package/src/wgsl/get-shader-layout-wgsl.ts +165 -0
- package/dist/adapter/helpers/accessor-to-format.d.ts +0 -1
- package/dist/adapter/helpers/accessor-to-format.d.ts.map +0 -1
- package/dist/adapter/helpers/accessor-to-format.js +0 -105
- package/dist/adapter/helpers/accessor-to-format.js.map +0 -1
- package/src/adapter/helpers/accessor-to-format.ts +0 -104
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
5
|
import type {
|
|
6
|
+
CommandBufferProps,
|
|
6
7
|
RenderPassProps,
|
|
7
8
|
ComputePassProps,
|
|
9
|
+
CopyBufferToTextureOptions,
|
|
8
10
|
CopyTextureToTextureOptions,
|
|
9
11
|
CopyTextureToBufferOptions
|
|
10
12
|
} from '@luma.gl/core';
|
|
11
|
-
import {CommandEncoder, CommandEncoderProps, Buffer
|
|
13
|
+
import {CommandEncoder, CommandEncoderProps, Buffer} from '@luma.gl/core';
|
|
12
14
|
import {WebGPUDevice} from '../webgpu-device';
|
|
13
15
|
import {WebGPUCommandBuffer} from './webgpu-command-buffer';
|
|
14
16
|
import {WebGPUBuffer} from './webgpu-buffer';
|
|
@@ -34,9 +36,11 @@ export class WebGPUCommandEncoder extends CommandEncoder {
|
|
|
34
36
|
this.handle.label = this.props.id;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
|
-
override destroy(): void {
|
|
39
|
+
override destroy(): void {
|
|
40
|
+
this.destroyResource();
|
|
41
|
+
}
|
|
38
42
|
|
|
39
|
-
finish(props?:
|
|
43
|
+
finish(props?: CommandBufferProps): WebGPUCommandBuffer {
|
|
40
44
|
this.device.pushErrorScope('validation');
|
|
41
45
|
const commandBuffer = new WebGPUCommandBuffer(this, {
|
|
42
46
|
id: props?.id || 'unnamed-command-buffer'
|
|
@@ -46,6 +50,7 @@ export class WebGPUCommandEncoder extends CommandEncoder {
|
|
|
46
50
|
this.device.reportError(new Error(message), this)();
|
|
47
51
|
this.device.debug();
|
|
48
52
|
});
|
|
53
|
+
this.destroy();
|
|
49
54
|
return commandBuffer;
|
|
50
55
|
}
|
|
51
56
|
|
|
@@ -53,19 +58,26 @@ export class WebGPUCommandEncoder extends CommandEncoder {
|
|
|
53
58
|
* Allows a render pass to begin against a canvas context
|
|
54
59
|
* @todo need to support a "Framebuffer" equivalent (aka preconfigured RenderPassDescriptors?).
|
|
55
60
|
*/
|
|
56
|
-
beginRenderPass(props: RenderPassProps): WebGPURenderPass {
|
|
57
|
-
return new WebGPURenderPass(
|
|
61
|
+
beginRenderPass(props: RenderPassProps = {}): WebGPURenderPass {
|
|
62
|
+
return new WebGPURenderPass(
|
|
63
|
+
this.device,
|
|
64
|
+
this._applyTimeProfilingToPassProps(props),
|
|
65
|
+
this.handle
|
|
66
|
+
);
|
|
58
67
|
}
|
|
59
68
|
|
|
60
|
-
beginComputePass(props: ComputePassProps): WebGPUComputePass {
|
|
61
|
-
return new WebGPUComputePass(
|
|
69
|
+
beginComputePass(props: ComputePassProps = {}): WebGPUComputePass {
|
|
70
|
+
return new WebGPUComputePass(
|
|
71
|
+
this.device,
|
|
72
|
+
this._applyTimeProfilingToPassProps(props),
|
|
73
|
+
this.handle
|
|
74
|
+
);
|
|
62
75
|
}
|
|
63
76
|
|
|
64
77
|
// beginRenderPass(GPURenderPassDescriptor descriptor): GPURenderPassEncoder;
|
|
65
78
|
// beginComputePass(optional GPUComputePassDescriptor descriptor = {}): GPUComputePassEncoder;
|
|
66
79
|
|
|
67
|
-
copyBufferToBuffer(options:
|
|
68
|
-
{
|
|
80
|
+
copyBufferToBuffer(options: {
|
|
69
81
|
sourceBuffer: Buffer;
|
|
70
82
|
sourceOffset?: number;
|
|
71
83
|
destinationBuffer: Buffer;
|
|
@@ -73,74 +85,119 @@ export class WebGPUCommandEncoder extends CommandEncoder {
|
|
|
73
85
|
size?: number;
|
|
74
86
|
}): void {
|
|
75
87
|
const webgpuSourceBuffer = options.sourceBuffer as WebGPUBuffer;
|
|
76
|
-
const
|
|
88
|
+
const webgpuDestinationBuffer = options.destinationBuffer as WebGPUBuffer;
|
|
77
89
|
this.handle.copyBufferToBuffer(
|
|
78
90
|
webgpuSourceBuffer.handle,
|
|
79
91
|
options.sourceOffset ?? 0,
|
|
80
|
-
|
|
92
|
+
webgpuDestinationBuffer.handle,
|
|
81
93
|
options.destinationOffset ?? 0,
|
|
82
94
|
options.size ?? 0
|
|
83
95
|
);
|
|
84
96
|
}
|
|
85
97
|
|
|
86
|
-
copyBufferToTexture(options:
|
|
87
|
-
{
|
|
88
|
-
sourceBuffer: Buffer;
|
|
89
|
-
offset?: number;
|
|
90
|
-
bytesPerRow: number;
|
|
91
|
-
rowsPerImage: number;
|
|
92
|
-
|
|
93
|
-
destinationTexture: Texture;
|
|
94
|
-
mipLevel?: number;
|
|
95
|
-
aspect?: 'all' | 'stencil-only' | 'depth-only';
|
|
96
|
-
|
|
97
|
-
origin?: number[] | [number, number, number];
|
|
98
|
-
extent?: number[] | [number, number, number];
|
|
99
|
-
}): void {
|
|
98
|
+
copyBufferToTexture(options: CopyBufferToTextureOptions): void {
|
|
100
99
|
const webgpuSourceBuffer = options.sourceBuffer as WebGPUBuffer;
|
|
101
|
-
const
|
|
100
|
+
const webgpuDestinationTexture = options.destinationTexture as WebGPUTexture;
|
|
101
|
+
const copyOrigin = options.origin ?? [0, 0, 0];
|
|
102
|
+
const copySize = options.size;
|
|
102
103
|
this.handle.copyBufferToTexture(
|
|
103
104
|
{
|
|
104
105
|
buffer: webgpuSourceBuffer.handle,
|
|
105
|
-
offset: options.
|
|
106
|
+
offset: options.byteOffset ?? 0,
|
|
106
107
|
bytesPerRow: options.bytesPerRow,
|
|
107
108
|
rowsPerImage: options.rowsPerImage
|
|
108
109
|
},
|
|
109
110
|
{
|
|
110
|
-
texture:
|
|
111
|
+
texture: webgpuDestinationTexture.handle,
|
|
111
112
|
mipLevel: options.mipLevel ?? 0,
|
|
112
|
-
origin:
|
|
113
|
-
|
|
113
|
+
origin: {
|
|
114
|
+
x: copyOrigin[0] ?? 0,
|
|
115
|
+
y: copyOrigin[1] ?? 0,
|
|
116
|
+
z: copyOrigin[2] ?? 0
|
|
117
|
+
},
|
|
118
|
+
aspect: options.aspect
|
|
114
119
|
},
|
|
115
120
|
{
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
depthOrArrayLayers: options.extent?.[2]
|
|
121
|
+
width: copySize[0],
|
|
122
|
+
height: copySize[1],
|
|
123
|
+
depthOrArrayLayers: copySize[2]
|
|
120
124
|
}
|
|
121
125
|
);
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
copyTextureToBuffer(options: CopyTextureToBufferOptions): void {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
const {
|
|
130
|
+
sourceTexture,
|
|
131
|
+
destinationBuffer,
|
|
132
|
+
origin = [0, 0, 0],
|
|
133
|
+
byteOffset = 0,
|
|
134
|
+
width,
|
|
135
|
+
height,
|
|
136
|
+
depthOrArrayLayers,
|
|
137
|
+
mipLevel,
|
|
138
|
+
aspect
|
|
139
|
+
} = options;
|
|
140
|
+
const webgpuSourceTexture = sourceTexture as WebGPUTexture;
|
|
141
|
+
webgpuSourceTexture.copyToBuffer(
|
|
142
|
+
this.handle,
|
|
143
|
+
{
|
|
144
|
+
x: origin[0] ?? 0,
|
|
145
|
+
y: origin[1] ?? 0,
|
|
146
|
+
z: origin[2] ?? 0,
|
|
147
|
+
width,
|
|
148
|
+
height,
|
|
149
|
+
depthOrArrayLayers,
|
|
150
|
+
mipLevel,
|
|
151
|
+
aspect,
|
|
152
|
+
byteOffset,
|
|
153
|
+
bytesPerRow: options.bytesPerRow,
|
|
154
|
+
rowsPerImage: options.rowsPerImage
|
|
155
|
+
},
|
|
156
|
+
destinationBuffer
|
|
157
|
+
);
|
|
133
158
|
}
|
|
134
159
|
|
|
135
160
|
copyTextureToTexture(options: CopyTextureToTextureOptions): void {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
161
|
+
const webgpuSourceTexture = options.sourceTexture as WebGPUTexture;
|
|
162
|
+
const webgpuDestinationTexture = options.destinationTexture as WebGPUTexture;
|
|
163
|
+
const sourceRegion = webgpuSourceTexture._normalizeTextureReadOptions({
|
|
164
|
+
x: options.origin?.[0] ?? 0,
|
|
165
|
+
y: options.origin?.[1] ?? 0,
|
|
166
|
+
z: options.origin?.[2] ?? 0,
|
|
167
|
+
width: options.width,
|
|
168
|
+
height: options.height,
|
|
169
|
+
depthOrArrayLayers: options.depthOrArrayLayers,
|
|
170
|
+
mipLevel: options.mipLevel ?? 0,
|
|
171
|
+
aspect: options.aspect ?? 'all'
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
this.handle.copyTextureToTexture(
|
|
175
|
+
{
|
|
176
|
+
texture: webgpuSourceTexture.handle,
|
|
177
|
+
mipLevel: sourceRegion.mipLevel,
|
|
178
|
+
origin: {
|
|
179
|
+
x: sourceRegion.x,
|
|
180
|
+
y: sourceRegion.y,
|
|
181
|
+
z: sourceRegion.z
|
|
182
|
+
},
|
|
183
|
+
aspect: sourceRegion.aspect
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
texture: webgpuDestinationTexture.handle,
|
|
187
|
+
mipLevel: options.destinationMipLevel ?? 0,
|
|
188
|
+
origin: {
|
|
189
|
+
x: options.destinationOrigin?.[0] ?? 0,
|
|
190
|
+
y: options.destinationOrigin?.[1] ?? 0,
|
|
191
|
+
z: options.destinationOrigin?.[2] ?? 0
|
|
192
|
+
},
|
|
193
|
+
aspect: options.destinationAspect ?? sourceRegion.aspect
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
width: sourceRegion.width,
|
|
197
|
+
height: sourceRegion.height,
|
|
198
|
+
depthOrArrayLayers: sourceRegion.depthOrArrayLayers
|
|
199
|
+
}
|
|
200
|
+
);
|
|
144
201
|
}
|
|
145
202
|
|
|
146
203
|
override pushDebugGroup(groupLabel: string): void {
|
|
@@ -174,6 +231,28 @@ export class WebGPUCommandEncoder extends CommandEncoder {
|
|
|
174
231
|
options?.destinationOffset || 0
|
|
175
232
|
);
|
|
176
233
|
}
|
|
234
|
+
|
|
235
|
+
writeTimestamp(querySet: WebGPUQuerySet, queryIndex: number): void {
|
|
236
|
+
querySet._invalidateResults();
|
|
237
|
+
const writeTimestamp = (
|
|
238
|
+
this.handle as GPUCommandEncoder & {
|
|
239
|
+
writeTimestamp?: (querySet: GPUQuerySet, queryIndex: number) => void;
|
|
240
|
+
}
|
|
241
|
+
).writeTimestamp;
|
|
242
|
+
|
|
243
|
+
if (writeTimestamp) {
|
|
244
|
+
writeTimestamp.call(this.handle, querySet.handle, queryIndex);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const computePass = this.handle.beginComputePass({
|
|
249
|
+
timestampWrites: {
|
|
250
|
+
querySet: querySet.handle,
|
|
251
|
+
beginningOfPassWriteIndex: queryIndex
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
computePass.end();
|
|
255
|
+
}
|
|
177
256
|
}
|
|
178
257
|
|
|
179
258
|
/*
|
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
ComputePass,
|
|
7
|
+
ComputePassProps,
|
|
8
|
+
ComputePipeline,
|
|
9
|
+
Buffer,
|
|
10
|
+
Bindings,
|
|
11
|
+
BindingsByGroup,
|
|
12
|
+
_getDefaultBindGroupFactory
|
|
13
|
+
} from '@luma.gl/core';
|
|
6
14
|
import {WebGPUDevice} from '../webgpu-device';
|
|
7
15
|
import {WebGPUBuffer} from './webgpu-buffer';
|
|
8
16
|
import {WebGPUComputePipeline} from './webgpu-compute-pipeline';
|
|
@@ -14,53 +22,80 @@ export class WebGPUComputePass extends ComputePass {
|
|
|
14
22
|
|
|
15
23
|
_webgpuPipeline: WebGPUComputePipeline | null = null;
|
|
16
24
|
|
|
17
|
-
constructor(
|
|
25
|
+
constructor(
|
|
26
|
+
device: WebGPUDevice,
|
|
27
|
+
props: ComputePassProps = {},
|
|
28
|
+
commandEncoder: GPUCommandEncoder = device.commandEncoder.handle
|
|
29
|
+
) {
|
|
18
30
|
super(device, props);
|
|
19
31
|
this.device = device;
|
|
32
|
+
const {props: computePassProps} = this;
|
|
20
33
|
|
|
21
34
|
// Set up queries
|
|
22
35
|
let timestampWrites: GPUComputePassTimestampWrites | undefined;
|
|
23
|
-
if (
|
|
24
|
-
const webgpuQuerySet =
|
|
36
|
+
if (computePassProps.timestampQuerySet) {
|
|
37
|
+
const webgpuQuerySet = computePassProps.timestampQuerySet as WebGPUQuerySet;
|
|
25
38
|
if (webgpuQuerySet) {
|
|
39
|
+
webgpuQuerySet._invalidateResults();
|
|
26
40
|
timestampWrites = {
|
|
27
41
|
querySet: webgpuQuerySet.handle,
|
|
28
|
-
beginningOfPassWriteIndex:
|
|
29
|
-
endOfPassWriteIndex:
|
|
42
|
+
beginningOfPassWriteIndex: computePassProps.beginTimestampIndex,
|
|
43
|
+
endOfPassWriteIndex: computePassProps.endTimestampIndex
|
|
30
44
|
};
|
|
31
45
|
}
|
|
32
46
|
}
|
|
33
47
|
|
|
34
48
|
this.handle =
|
|
35
49
|
this.props.handle ||
|
|
36
|
-
|
|
50
|
+
commandEncoder.beginComputePass({
|
|
37
51
|
label: this.props.id,
|
|
38
52
|
timestampWrites
|
|
39
53
|
});
|
|
40
54
|
}
|
|
41
55
|
|
|
42
56
|
/** @note no WebGPU destroy method, just gc */
|
|
43
|
-
override destroy(): void {
|
|
57
|
+
override destroy(): void {
|
|
58
|
+
this.destroyResource();
|
|
59
|
+
}
|
|
44
60
|
|
|
45
61
|
end(): void {
|
|
62
|
+
if (this.destroyed) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
46
65
|
this.handle.end();
|
|
66
|
+
this.destroy();
|
|
47
67
|
}
|
|
48
68
|
|
|
49
69
|
setPipeline(pipeline: ComputePipeline): void {
|
|
50
70
|
const wgpuPipeline = pipeline as WebGPUComputePipeline;
|
|
51
71
|
this.handle.setPipeline(wgpuPipeline.handle);
|
|
52
72
|
this._webgpuPipeline = wgpuPipeline;
|
|
53
|
-
this.
|
|
73
|
+
const bindGroups = _getDefaultBindGroupFactory(this.device).getBindGroups(
|
|
74
|
+
this._webgpuPipeline,
|
|
75
|
+
this._webgpuPipeline._getBindingsByGroupWebGPU(),
|
|
76
|
+
this._webgpuPipeline._getBindGroupCacheKeysWebGPU()
|
|
77
|
+
);
|
|
78
|
+
for (const [group, bindGroup] of Object.entries(bindGroups)) {
|
|
79
|
+
if (bindGroup) {
|
|
80
|
+
this.handle.setBindGroup(Number(group), bindGroup as GPUBindGroup);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
54
83
|
}
|
|
55
84
|
|
|
56
85
|
/**
|
|
57
86
|
* Sets an array of bindings (uniform buffers, samplers, textures, ...)
|
|
58
87
|
* TODO - still some API confusion - does this method go here or on the pipeline?
|
|
59
88
|
*/
|
|
60
|
-
setBindings(bindings:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
89
|
+
setBindings(bindings: Bindings | BindingsByGroup): void {
|
|
90
|
+
const bindGroups =
|
|
91
|
+
(this._webgpuPipeline &&
|
|
92
|
+
_getDefaultBindGroupFactory(this.device).getBindGroups(this._webgpuPipeline, bindings)) ||
|
|
93
|
+
{};
|
|
94
|
+
for (const [group, bindGroup] of Object.entries(bindGroups)) {
|
|
95
|
+
if (bindGroup) {
|
|
96
|
+
this.handle.setBindGroup(Number(group), bindGroup as GPUBindGroup);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
64
99
|
}
|
|
65
100
|
|
|
66
101
|
/**
|
|
@@ -2,11 +2,19 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
// Copyright (c) vis.gl contributors
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import {
|
|
6
|
+
ComputePipeline,
|
|
7
|
+
ComputePipelineProps,
|
|
8
|
+
Bindings,
|
|
9
|
+
BindingsByGroup,
|
|
10
|
+
_getDefaultBindGroupFactory,
|
|
11
|
+
normalizeBindingsByGroup
|
|
12
|
+
} from '@luma.gl/core';
|
|
7
13
|
import {WebGPUDevice} from '../webgpu-device';
|
|
8
14
|
import {WebGPUShader} from './webgpu-shader';
|
|
9
15
|
|
|
16
|
+
const EMPTY_BIND_GROUPS: BindingsByGroup = {};
|
|
17
|
+
|
|
10
18
|
// COMPUTE PIPELINE
|
|
11
19
|
|
|
12
20
|
/** Creates a new compute pipeline when parameters change */
|
|
@@ -14,11 +22,8 @@ export class WebGPUComputePipeline extends ComputePipeline {
|
|
|
14
22
|
readonly device: WebGPUDevice;
|
|
15
23
|
readonly handle: GPUComputePipeline;
|
|
16
24
|
|
|
17
|
-
|
|
18
|
-
private
|
|
19
|
-
private _bindGroup: GPUBindGroup | null = null;
|
|
20
|
-
/** For internal use to create BindGroups */
|
|
21
|
-
private _bindings: Record<string, Binding> = {};
|
|
25
|
+
private _bindingsByGroup: BindingsByGroup;
|
|
26
|
+
private _bindGroupCacheKeysByGroup: Partial<Record<number, object>>;
|
|
22
27
|
|
|
23
28
|
constructor(device: WebGPUDevice, props: ComputePipelineProps) {
|
|
24
29
|
super(device, props);
|
|
@@ -37,26 +42,52 @@ export class WebGPUComputePipeline extends ComputePipeline {
|
|
|
37
42
|
},
|
|
38
43
|
layout: 'auto'
|
|
39
44
|
});
|
|
45
|
+
|
|
46
|
+
this._bindingsByGroup = EMPTY_BIND_GROUPS;
|
|
47
|
+
this._bindGroupCacheKeysByGroup = {};
|
|
40
48
|
}
|
|
41
49
|
|
|
42
50
|
/**
|
|
43
51
|
* @todo Use renderpass.setBindings() ?
|
|
44
52
|
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
45
53
|
*/
|
|
46
|
-
setBindings(bindings:
|
|
47
|
-
|
|
54
|
+
setBindings(bindings: Bindings | BindingsByGroup): void {
|
|
55
|
+
const nextBindingsByGroup = normalizeBindingsByGroup(this.shaderLayout, bindings);
|
|
56
|
+
for (const [groupKey, groupBindings] of Object.entries(nextBindingsByGroup)) {
|
|
57
|
+
const group = Number(groupKey);
|
|
58
|
+
for (const [name, binding] of Object.entries(groupBindings || {})) {
|
|
59
|
+
const currentGroupBindings = this._bindingsByGroup[group] || {};
|
|
60
|
+
if (currentGroupBindings[name] !== binding) {
|
|
61
|
+
if (
|
|
62
|
+
!this._bindingsByGroup[group] ||
|
|
63
|
+
this._bindingsByGroup[group] === currentGroupBindings
|
|
64
|
+
) {
|
|
65
|
+
this._bindingsByGroup[group] = {...currentGroupBindings};
|
|
66
|
+
}
|
|
67
|
+
this._bindingsByGroup[group][name] = binding;
|
|
68
|
+
this._bindGroupCacheKeysByGroup[group] = {};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
48
72
|
}
|
|
49
73
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
74
|
+
_getBindGroups(
|
|
75
|
+
bindings?: Bindings | BindingsByGroup,
|
|
76
|
+
bindGroupCacheKeys?: Partial<Record<number, object>>
|
|
77
|
+
): Partial<Record<number, unknown>> {
|
|
78
|
+
const hasExplicitBindings = Boolean(bindings);
|
|
79
|
+
return _getDefaultBindGroupFactory(this.device).getBindGroups(
|
|
80
|
+
this,
|
|
81
|
+
hasExplicitBindings ? bindings : this._bindingsByGroup,
|
|
82
|
+
hasExplicitBindings ? bindGroupCacheKeys : this._bindGroupCacheKeysByGroup
|
|
83
|
+
);
|
|
84
|
+
}
|
|
54
85
|
|
|
55
|
-
|
|
56
|
-
this.
|
|
57
|
-
|
|
58
|
-
getBindGroup(this.device.handle, this._bindGroupLayout, this.shaderLayout, this._bindings);
|
|
86
|
+
_getBindingsByGroupWebGPU(): BindingsByGroup {
|
|
87
|
+
return this._bindingsByGroup;
|
|
88
|
+
}
|
|
59
89
|
|
|
60
|
-
|
|
90
|
+
_getBindGroupCacheKeysWebGPU(): Partial<Record<number, object>> {
|
|
91
|
+
return this._bindGroupCacheKeysByGroup;
|
|
61
92
|
}
|
|
62
93
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// luma.gl
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
// Copyright (c) vis.gl contributors
|
|
4
|
+
|
|
5
|
+
import {Fence, type FenceProps} from '@luma.gl/core';
|
|
6
|
+
import {WebGPUDevice} from '../webgpu-device';
|
|
7
|
+
|
|
8
|
+
/** WebGPU fence implemented by waiting for submitted work */
|
|
9
|
+
export class WebGPUFence extends Fence {
|
|
10
|
+
readonly device: WebGPUDevice;
|
|
11
|
+
readonly handle: null = null;
|
|
12
|
+
readonly signaled: Promise<void>;
|
|
13
|
+
private _signaled = false;
|
|
14
|
+
|
|
15
|
+
constructor(device: WebGPUDevice, props: FenceProps = {}) {
|
|
16
|
+
super(device, {});
|
|
17
|
+
this.device = device;
|
|
18
|
+
this.signaled = device.handle.queue
|
|
19
|
+
.onSubmittedWorkDone()
|
|
20
|
+
.then(() => {
|
|
21
|
+
this._signaled = true;
|
|
22
|
+
})
|
|
23
|
+
.catch(error => {
|
|
24
|
+
if (this.device.shouldIgnoreDroppedInstanceError(error)) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
throw error;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
isSignaled(): boolean {
|
|
32
|
+
return this._signaled;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
override destroy(): void {
|
|
36
|
+
// Nothing to release for WebGPU fence
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -29,4 +29,25 @@ export class WebGPUFramebuffer extends Framebuffer {
|
|
|
29
29
|
protected updateAttachments(): void {
|
|
30
30
|
// WebGPU framebuffers are JS only objects, nothing to update
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Internal-only hook for the cached CanvasContext/PresentationContext swapchain path.
|
|
35
|
+
* Rebinds the long-lived default framebuffer wrapper to the current per-frame color view
|
|
36
|
+
* and optional depth attachment without allocating a new luma.gl Framebuffer object.
|
|
37
|
+
*/
|
|
38
|
+
_reinitialize(
|
|
39
|
+
colorAttachment: WebGPUTextureView,
|
|
40
|
+
depthStencilAttachment: WebGPUTextureView | null
|
|
41
|
+
): void {
|
|
42
|
+
this.colorAttachments[0] = colorAttachment;
|
|
43
|
+
// @ts-expect-error Internal-only canvas wrapper reuse mutates this otherwise-readonly attachment.
|
|
44
|
+
this.depthStencilAttachment = depthStencilAttachment;
|
|
45
|
+
this.width = colorAttachment.texture.width;
|
|
46
|
+
this.height = colorAttachment.texture.height;
|
|
47
|
+
|
|
48
|
+
this.props.width = this.width;
|
|
49
|
+
this.props.height = this.height;
|
|
50
|
+
this.props.colorAttachments = [colorAttachment.texture];
|
|
51
|
+
this.props.depthStencilAttachment = depthStencilAttachment?.texture || null;
|
|
52
|
+
}
|
|
32
53
|
}
|
|
@@ -20,19 +20,16 @@ export class WebGPUPipelineLayout extends PipelineLayout {
|
|
|
20
20
|
|
|
21
21
|
this.device = device;
|
|
22
22
|
|
|
23
|
-
const
|
|
23
|
+
const bindGroupEntriesByGroup = this.mapShaderLayoutToBindGroupEntriesByGroup();
|
|
24
24
|
|
|
25
25
|
this.handle = this.device.handle.createPipelineLayout({
|
|
26
26
|
label: props?.id ?? 'unnamed-pipeline-layout',
|
|
27
|
-
bindGroupLayouts:
|
|
28
|
-
// TODO (kaapp): We can cache these to re-use them across
|
|
29
|
-
// layers, particularly if using a separate group for injected
|
|
30
|
-
// bindings (e.g. project/lighting)
|
|
27
|
+
bindGroupLayouts: bindGroupEntriesByGroup.map((entries, group) =>
|
|
31
28
|
this.device.handle.createBindGroupLayout({
|
|
32
|
-
label:
|
|
33
|
-
entries
|
|
29
|
+
label: `bind-group-layout-${group}`,
|
|
30
|
+
entries
|
|
34
31
|
})
|
|
35
|
-
|
|
32
|
+
)
|
|
36
33
|
});
|
|
37
34
|
}
|
|
38
35
|
|
|
@@ -42,13 +39,17 @@ export class WebGPUPipelineLayout extends PipelineLayout {
|
|
|
42
39
|
this.handle = null;
|
|
43
40
|
}
|
|
44
41
|
|
|
45
|
-
protected
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
42
|
+
protected mapShaderLayoutToBindGroupEntriesByGroup(): GPUBindGroupLayoutEntry[][] {
|
|
43
|
+
const maxGroup = this.props.shaderLayout.bindings.reduce(
|
|
44
|
+
(highestGroup, binding) => Math.max(highestGroup, binding.group),
|
|
45
|
+
-1
|
|
46
|
+
);
|
|
47
|
+
const bindGroupEntriesByGroup: GPUBindGroupLayoutEntry[][] = Array.from(
|
|
48
|
+
{length: maxGroup + 1},
|
|
49
|
+
() => []
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
for (const binding of this.props.shaderLayout.bindings) {
|
|
52
53
|
const bindingTypeInfo: Omit<GPUBindGroupLayoutEntry, 'binding' | 'visibility'> = {};
|
|
53
54
|
|
|
54
55
|
switch (binding.type) {
|
|
@@ -113,14 +114,14 @@ export class WebGPUPipelineLayout extends PipelineLayout {
|
|
|
113
114
|
const VISIBILITY_ALL =
|
|
114
115
|
GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;
|
|
115
116
|
|
|
116
|
-
|
|
117
|
+
bindGroupEntriesByGroup[binding.group].push({
|
|
117
118
|
binding: binding.location,
|
|
118
119
|
visibility: binding.visibility || VISIBILITY_ALL,
|
|
119
120
|
...bindingTypeInfo
|
|
120
121
|
});
|
|
121
122
|
}
|
|
122
123
|
|
|
123
|
-
return
|
|
124
|
+
return bindGroupEntriesByGroup;
|
|
124
125
|
}
|
|
125
126
|
}
|
|
126
127
|
|