@luma.gl/webgpu 9.1.0-beta.8 → 9.1.0
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/get-bind-group.d.ts +1 -3
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/helpers/get-bind-group.js +3 -5
- package/dist/adapter/helpers/get-bind-group.js.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.js +2 -2
- package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +0 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +6 -28
- package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
- package/dist/adapter/webgpu-adapter.d.ts.map +1 -1
- package/dist/adapter/webgpu-adapter.js +3 -1
- package/dist/adapter/webgpu-adapter.js.map +1 -1
- package/dist/adapter/webgpu-canvas-context.d.ts +9 -7
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +62 -44
- package/dist/adapter/webgpu-canvas-context.js.map +1 -1
- package/dist/adapter/webgpu-device.d.ts +5 -7
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +8 -11
- package/dist/adapter/webgpu-device.js.map +1 -1
- package/dist/dist.dev.js +66 -83
- package/dist/dist.min.js +5 -5
- package/dist/index.cjs +67 -80
- package/dist/index.cjs.map +2 -2
- package/package.json +2 -2
- package/src/adapter/helpers/get-bind-group.ts +3 -6
- package/src/adapter/helpers/get-vertex-buffer-layout.ts +2 -2
- package/src/adapter/resources/webgpu-render-pipeline.ts +6 -31
- package/src/adapter/webgpu-adapter.ts +4 -1
- package/src/adapter/webgpu-canvas-context.ts +72 -55
- package/src/adapter/webgpu-device.ts +9 -15
|
@@ -42,14 +42,13 @@ export function getBindGroup(
|
|
|
42
42
|
|
|
43
43
|
export function getShaderLayoutBinding(
|
|
44
44
|
shaderLayout: ComputeShaderLayout,
|
|
45
|
-
bindingName: string
|
|
46
|
-
options?: {ignoreWarnings?: boolean}
|
|
45
|
+
bindingName: string
|
|
47
46
|
): BindingDeclaration | null {
|
|
48
47
|
const bindingLayout = shaderLayout.bindings.find(
|
|
49
48
|
binding =>
|
|
50
49
|
binding.name === bindingName || `${binding.name}uniforms` === bindingName.toLocaleLowerCase()
|
|
51
50
|
);
|
|
52
|
-
if (!bindingLayout
|
|
51
|
+
if (!bindingLayout) {
|
|
53
52
|
log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
|
|
54
53
|
}
|
|
55
54
|
return bindingLayout || null;
|
|
@@ -72,9 +71,7 @@ function getBindGroupEntries(
|
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
// TODO - hack to automatically bind samplers to supplied texture default samplers
|
|
75
|
-
bindingLayout = getShaderLayoutBinding(shaderLayout, `${bindingName}Sampler
|
|
76
|
-
ignoreWarnings: true
|
|
77
|
-
});
|
|
74
|
+
bindingLayout = getShaderLayoutBinding(shaderLayout, `${bindingName}Sampler`);
|
|
78
75
|
if (bindingLayout) {
|
|
79
76
|
entries.push(getBindGroupEntry(value, bindingLayout.location, {sampler: true}));
|
|
80
77
|
}
|
|
@@ -152,11 +152,11 @@ function findAttributeLayout(
|
|
|
152
152
|
): AttributeDeclaration | null {
|
|
153
153
|
const attribute = shaderLayout.attributes.find(attribute_ => attribute_.name === name);
|
|
154
154
|
if (!attribute) {
|
|
155
|
-
log.warn(`
|
|
155
|
+
log.warn(`Unknown attribute ${name}`)();
|
|
156
156
|
return null;
|
|
157
157
|
}
|
|
158
158
|
if (attributeNames.has(name)) {
|
|
159
|
-
throw new Error(`
|
|
159
|
+
throw new Error(`Duplicate attribute ${name}`);
|
|
160
160
|
}
|
|
161
161
|
attributeNames.add(name);
|
|
162
162
|
return attribute;
|
|
@@ -30,10 +30,6 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
30
30
|
private _bindGroupLayout: GPUBindGroupLayout | null = null;
|
|
31
31
|
private _bindGroup: GPUBindGroup | null = null;
|
|
32
32
|
|
|
33
|
-
override get [Symbol.toStringTag]() {
|
|
34
|
-
return 'WebGPURenderPipeline';
|
|
35
|
-
}
|
|
36
|
-
|
|
37
33
|
constructor(device: WebGPUDevice, props: RenderPipelineProps) {
|
|
38
34
|
super(device, props);
|
|
39
35
|
this.device = device;
|
|
@@ -72,12 +68,6 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
72
68
|
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
73
69
|
*/
|
|
74
70
|
setBindings(bindings: Record<string, Binding>): void {
|
|
75
|
-
// Invalidate the cached bind group if any value has changed
|
|
76
|
-
for (const [name, binding] of Object.entries(bindings)) {
|
|
77
|
-
if (this._bindings[name] !== binding) {
|
|
78
|
-
this._bindGroup = null;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
71
|
Object.assign(this._bindings, bindings);
|
|
82
72
|
}
|
|
83
73
|
|
|
@@ -166,22 +156,16 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
166
156
|
buffers: getVertexBufferLayout(this.shaderLayout, this.props.bufferLayout)
|
|
167
157
|
};
|
|
168
158
|
|
|
169
|
-
// Populate color targets
|
|
170
|
-
// TODO - at the moment blend and write mask are only set on the first target
|
|
171
|
-
const targets: (GPUColorTargetState | null)[] = [];
|
|
172
|
-
if (this.props.colorAttachmentFormats) {
|
|
173
|
-
for (const format of this.props.colorAttachmentFormats) {
|
|
174
|
-
targets.push(format ? {format: getWebGPUTextureFormat(format)} : null);
|
|
175
|
-
}
|
|
176
|
-
} else {
|
|
177
|
-
targets.push({format: getWebGPUTextureFormat(this.device.preferredColorFormat)});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
159
|
// Set up the fragment stage
|
|
181
160
|
const fragment: GPUFragmentState = {
|
|
182
161
|
module: (this.props.fs as WebGPUShader).handle,
|
|
183
162
|
entryPoint: this.props.fragmentEntryPoint || 'main',
|
|
184
|
-
targets
|
|
163
|
+
targets: [
|
|
164
|
+
{
|
|
165
|
+
// TODO exclamation mark hack!
|
|
166
|
+
format: getWebGPUTextureFormat(this.device.getCanvasContext().format)
|
|
167
|
+
}
|
|
168
|
+
]
|
|
185
169
|
};
|
|
186
170
|
|
|
187
171
|
// Create a partially populated descriptor
|
|
@@ -194,15 +178,6 @@ export class WebGPURenderPipeline extends RenderPipeline {
|
|
|
194
178
|
layout: 'auto'
|
|
195
179
|
};
|
|
196
180
|
|
|
197
|
-
// Set depth format if required, defaulting to the preferred depth format
|
|
198
|
-
const depthFormat = this.props.depthStencilAttachmentFormat || this.device.preferredDepthFormat;
|
|
199
|
-
|
|
200
|
-
if (this.props.parameters.depthWriteEnabled) {
|
|
201
|
-
descriptor.depthStencil = {
|
|
202
|
-
format: getWebGPUTextureFormat(depthFormat)
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
181
|
// Set parameters on the descriptor
|
|
207
182
|
applyParametersToRenderPipelineDescriptor(descriptor, this.props.parameters);
|
|
208
183
|
|
|
@@ -38,7 +38,10 @@ export class WebGPUAdapter extends Adapter {
|
|
|
38
38
|
throw new Error('Failed to request WebGPU adapter');
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const adapterInfo =
|
|
41
|
+
const adapterInfo =
|
|
42
|
+
adapter.info ||
|
|
43
|
+
// @ts-ignore Chrome has removed this function
|
|
44
|
+
(await adapter.requestAdapterInfo?.());
|
|
42
45
|
log.probe(2, 'Adapter available', adapterInfo)();
|
|
43
46
|
|
|
44
47
|
const requiredFeatures: GPUFeatureName[] = [];
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
// / <reference types="@webgpu/types" />
|
|
6
6
|
|
|
7
|
-
import type {
|
|
8
|
-
import {CanvasContext,
|
|
7
|
+
import type {Texture, TextureFormat, CanvasContextProps} from '@luma.gl/core';
|
|
8
|
+
import {CanvasContext, log} from '@luma.gl/core';
|
|
9
|
+
import {getWebGPUTextureFormat} from './helpers/convert-texture-format';
|
|
9
10
|
import {WebGPUDevice} from './webgpu-device';
|
|
10
11
|
import {WebGPUFramebuffer} from './resources/webgpu-framebuffer';
|
|
11
12
|
import {WebGPUTexture} from './resources/webgpu-texture';
|
|
@@ -17,9 +18,13 @@ import {WebGPUTexture} from './resources/webgpu-texture';
|
|
|
17
18
|
*/
|
|
18
19
|
export class WebGPUCanvasContext extends CanvasContext {
|
|
19
20
|
readonly device: WebGPUDevice;
|
|
20
|
-
readonly
|
|
21
|
+
readonly gpuCanvasContext: GPUCanvasContext;
|
|
22
|
+
/** Format of returned textures: "bgra8unorm", "rgba8unorm", "rgba16float". */
|
|
23
|
+
readonly format: TextureFormat = navigator.gpu.getPreferredCanvasFormat() as TextureFormat;
|
|
24
|
+
/** Default stencil format for depth textures */
|
|
25
|
+
readonly depthStencilFormat: TextureFormat = 'depth24plus';
|
|
21
26
|
|
|
22
|
-
private depthStencilAttachment:
|
|
27
|
+
private depthStencilAttachment: Texture | null = null;
|
|
23
28
|
|
|
24
29
|
get [Symbol.toStringTag](): string {
|
|
25
30
|
return 'WebGPUCanvasContext';
|
|
@@ -28,43 +33,44 @@ export class WebGPUCanvasContext extends CanvasContext {
|
|
|
28
33
|
constructor(device: WebGPUDevice, adapter: GPUAdapter, props: CanvasContextProps) {
|
|
29
34
|
super(props);
|
|
30
35
|
this.device = device;
|
|
36
|
+
// TODO - ugly hack to trigger first resize
|
|
37
|
+
this.width = -1;
|
|
38
|
+
this.height = -1;
|
|
31
39
|
|
|
32
|
-
// Base class constructor cannot access derived methods/fields, so we need to call these functions in the subclass constructor
|
|
33
40
|
this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
|
|
34
|
-
|
|
41
|
+
// @ts-ignore TODO - we don't handle OffscreenRenderingContext.
|
|
42
|
+
this.gpuCanvasContext = this.canvas.getContext('webgpu');
|
|
43
|
+
// TODO this has been replaced
|
|
44
|
+
// this.format = this.gpuCanvasContext.getPreferredFormat(adapter);
|
|
45
|
+
this.format = 'bgra8unorm';
|
|
35
46
|
}
|
|
36
47
|
|
|
37
48
|
/** Destroy any textures produced while configured and remove the context configuration. */
|
|
38
49
|
destroy(): void {
|
|
39
|
-
this.
|
|
50
|
+
this.gpuCanvasContext.unconfigure();
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
/** Update framebuffer with properly resized "swap chain" texture views */
|
|
43
|
-
getCurrentFramebuffer(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
54
|
+
getCurrentFramebuffer(): WebGPUFramebuffer {
|
|
55
|
+
// Ensure the canvas context size is updated
|
|
56
|
+
this.update();
|
|
57
|
+
|
|
58
|
+
// Wrap the current canvas context texture in a luma.gl texture
|
|
59
|
+
// const currentColorAttachment = this.device.createTexture({
|
|
60
|
+
// id: 'default-render-target',
|
|
61
|
+
// handle: this.gpuCanvasContext.getCurrentTexture(),
|
|
62
|
+
// format: this.format,
|
|
63
|
+
// width: this.width,
|
|
64
|
+
// height: this.height
|
|
65
|
+
// });
|
|
66
|
+
|
|
48
67
|
// Wrap the current canvas context texture in a luma.gl texture
|
|
49
68
|
const currentColorAttachment = this.getCurrentTexture();
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
currentColorAttachment.width !== this.drawingBufferWidth ||
|
|
53
|
-
currentColorAttachment.height !== this.drawingBufferHeight
|
|
54
|
-
) {
|
|
55
|
-
const [oldWidth, oldHeight] = this.getDrawingBufferSize();
|
|
56
|
-
this.drawingBufferWidth = currentColorAttachment.width;
|
|
57
|
-
this.drawingBufferHeight = currentColorAttachment.height;
|
|
58
|
-
log.log(
|
|
59
|
-
1,
|
|
60
|
-
`${this}: Resized to compensate for initial canvas size mismatch ${oldWidth}x${oldHeight} => ${this.drawingBufferWidth}x${this.drawingBufferHeight}px`
|
|
61
|
-
)();
|
|
62
|
-
}
|
|
69
|
+
this.width = currentColorAttachment.width;
|
|
70
|
+
this.height = currentColorAttachment.height;
|
|
63
71
|
|
|
64
72
|
// Resize the depth stencil attachment
|
|
65
|
-
|
|
66
|
-
this._createDepthStencilAttachment(options?.depthStencilFormat);
|
|
67
|
-
}
|
|
73
|
+
this._createDepthStencilAttachment();
|
|
68
74
|
|
|
69
75
|
return new WebGPUFramebuffer(this.device, {
|
|
70
76
|
colorAttachments: [currentColorAttachment],
|
|
@@ -73,35 +79,46 @@ export class WebGPUCanvasContext extends CanvasContext {
|
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
/** Resizes and updates render targets if necessary */
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
update() {
|
|
83
|
+
const oldWidth = this.width;
|
|
84
|
+
const oldHeight = this.height;
|
|
85
|
+
const [newWidth, newHeight] = this.getPixelSize();
|
|
86
|
+
|
|
87
|
+
const sizeChanged = newWidth !== oldWidth || newHeight !== oldHeight;
|
|
88
|
+
|
|
89
|
+
if (sizeChanged) {
|
|
90
|
+
this.width = newWidth;
|
|
91
|
+
this.height = newHeight;
|
|
92
|
+
|
|
93
|
+
if (this.depthStencilAttachment) {
|
|
94
|
+
this.depthStencilAttachment.destroy();
|
|
95
|
+
this.depthStencilAttachment = null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Reconfigure the canvas size.
|
|
99
|
+
// https://www.w3.org/TR/webgpu/#canvas-configuration
|
|
100
|
+
this.gpuCanvasContext.configure({
|
|
101
|
+
device: this.device.handle,
|
|
102
|
+
format: getWebGPUTextureFormat(this.format),
|
|
103
|
+
// Can be used to define e.g. -srgb views
|
|
104
|
+
// viewFormats: [...]
|
|
105
|
+
colorSpace: this.props.colorSpace,
|
|
106
|
+
alphaMode: this.props.alphaMode
|
|
107
|
+
});
|
|
81
108
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
this.handle.configure({
|
|
85
|
-
device: this.device.handle,
|
|
86
|
-
format: this.device.preferredColorFormat,
|
|
87
|
-
// Can be used to define e.g. -srgb views
|
|
88
|
-
// viewFormats: [...]
|
|
89
|
-
colorSpace: this.props.colorSpace,
|
|
90
|
-
alphaMode: this.props.alphaMode
|
|
91
|
-
});
|
|
109
|
+
log.log(1, `${this} Resized ${oldWidth}x${oldHeight} => ${newWidth}x${newHeight}px`)();
|
|
110
|
+
}
|
|
92
111
|
}
|
|
93
112
|
|
|
94
113
|
resize(options?: {width?: number; height?: number; useDevicePixels?: boolean | number}): void {
|
|
95
|
-
|
|
114
|
+
this.update();
|
|
96
115
|
|
|
97
|
-
if (this.
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
116
|
+
if (!this.device.handle) return;
|
|
100
117
|
|
|
101
118
|
// Resize browser context .
|
|
102
119
|
if (this.canvas) {
|
|
103
120
|
const devicePixelRatio = this.getDevicePixelRatio(options?.useDevicePixels);
|
|
104
|
-
this.
|
|
121
|
+
this.setDevicePixelRatio(devicePixelRatio, options);
|
|
105
122
|
return;
|
|
106
123
|
}
|
|
107
124
|
}
|
|
@@ -110,20 +127,20 @@ export class WebGPUCanvasContext extends CanvasContext {
|
|
|
110
127
|
getCurrentTexture(): WebGPUTexture {
|
|
111
128
|
return this.device.createTexture({
|
|
112
129
|
id: `${this.id}#color-texture`,
|
|
113
|
-
handle: this.
|
|
114
|
-
format: this.
|
|
130
|
+
handle: this.gpuCanvasContext.getCurrentTexture(),
|
|
131
|
+
format: this.format
|
|
115
132
|
});
|
|
116
133
|
}
|
|
117
134
|
|
|
118
135
|
/** We build render targets on demand (i.e. not when size changes but when about to render) */
|
|
119
|
-
_createDepthStencilAttachment(
|
|
136
|
+
_createDepthStencilAttachment() {
|
|
120
137
|
if (!this.depthStencilAttachment) {
|
|
121
138
|
this.depthStencilAttachment = this.device.createTexture({
|
|
122
139
|
id: `${this.id}#depth-stencil-texture`,
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
140
|
+
format: this.depthStencilFormat,
|
|
141
|
+
width: this.width,
|
|
142
|
+
height: this.height,
|
|
143
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT
|
|
127
144
|
});
|
|
128
145
|
}
|
|
129
146
|
return this.depthStencilAttachment;
|
|
@@ -28,7 +28,7 @@ import type {
|
|
|
28
28
|
TransformFeedbackProps,
|
|
29
29
|
QuerySet,
|
|
30
30
|
QuerySetProps,
|
|
31
|
-
DeviceProps
|
|
31
|
+
DeviceProps
|
|
32
32
|
} from '@luma.gl/core';
|
|
33
33
|
import {Device, DeviceFeatures} from '@luma.gl/core';
|
|
34
34
|
import {WebGPUBuffer} from './resources/webgpu-buffer';
|
|
@@ -49,32 +49,26 @@ import {WebGPUQuerySet} from './resources/webgpu-query-set';
|
|
|
49
49
|
|
|
50
50
|
/** WebGPU Device implementation */
|
|
51
51
|
export class WebGPUDevice extends Device {
|
|
52
|
-
/** The underlying WebGPU device */
|
|
53
|
-
readonly handle: GPUDevice;
|
|
54
52
|
/** type of this device */
|
|
55
53
|
readonly type = 'webgpu';
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
readonly
|
|
55
|
+
/** The underlying WebGPU device */
|
|
56
|
+
readonly handle: GPUDevice;
|
|
57
|
+
/* The underlying WebGPU adapter */
|
|
58
|
+
readonly adapter: GPUAdapter;
|
|
59
|
+
/* The underlying WebGPU adapter's info */
|
|
60
|
+
readonly adapterInfo: GPUAdapterInfo;
|
|
61
61
|
|
|
62
62
|
readonly features: DeviceFeatures;
|
|
63
63
|
readonly info: DeviceInfo;
|
|
64
64
|
readonly limits: DeviceLimits;
|
|
65
65
|
|
|
66
66
|
readonly lost: Promise<{reason: 'destroyed'; message: string}>;
|
|
67
|
-
|
|
68
|
-
renderPass: WebGPURenderPass | null = null;
|
|
69
|
-
override canvasContext: WebGPUCanvasContext | null;
|
|
67
|
+
canvasContext: WebGPUCanvasContext | null = null;
|
|
70
68
|
|
|
71
69
|
private _isLost: boolean = false;
|
|
72
|
-
// canvasContext: WebGPUCanvasContext | null = null;
|
|
73
70
|
commandEncoder: GPUCommandEncoder | null = null;
|
|
74
|
-
|
|
75
|
-
readonly adapter: GPUAdapter;
|
|
76
|
-
/* The underlying WebGPU adapter's info */
|
|
77
|
-
readonly adapterInfo: GPUAdapterInfo;
|
|
71
|
+
renderPass: WebGPURenderPass | null = null;
|
|
78
72
|
|
|
79
73
|
constructor(
|
|
80
74
|
props: DeviceProps,
|