@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.
Files changed (32) hide show
  1. package/dist/adapter/helpers/get-bind-group.d.ts +1 -3
  2. package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
  3. package/dist/adapter/helpers/get-bind-group.js +3 -5
  4. package/dist/adapter/helpers/get-bind-group.js.map +1 -1
  5. package/dist/adapter/helpers/get-vertex-buffer-layout.js +2 -2
  6. package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
  7. package/dist/adapter/resources/webgpu-render-pipeline.d.ts +0 -1
  8. package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
  9. package/dist/adapter/resources/webgpu-render-pipeline.js +6 -28
  10. package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
  11. package/dist/adapter/webgpu-adapter.d.ts.map +1 -1
  12. package/dist/adapter/webgpu-adapter.js +3 -1
  13. package/dist/adapter/webgpu-adapter.js.map +1 -1
  14. package/dist/adapter/webgpu-canvas-context.d.ts +9 -7
  15. package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
  16. package/dist/adapter/webgpu-canvas-context.js +62 -44
  17. package/dist/adapter/webgpu-canvas-context.js.map +1 -1
  18. package/dist/adapter/webgpu-device.d.ts +5 -7
  19. package/dist/adapter/webgpu-device.d.ts.map +1 -1
  20. package/dist/adapter/webgpu-device.js +8 -11
  21. package/dist/adapter/webgpu-device.js.map +1 -1
  22. package/dist/dist.dev.js +66 -83
  23. package/dist/dist.min.js +5 -5
  24. package/dist/index.cjs +67 -80
  25. package/dist/index.cjs.map +2 -2
  26. package/package.json +2 -2
  27. package/src/adapter/helpers/get-bind-group.ts +3 -6
  28. package/src/adapter/helpers/get-vertex-buffer-layout.ts +2 -2
  29. package/src/adapter/resources/webgpu-render-pipeline.ts +6 -31
  30. package/src/adapter/webgpu-adapter.ts +4 -1
  31. package/src/adapter/webgpu-canvas-context.ts +72 -55
  32. 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 && !options?.ignoreWarnings) {
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(`Supplied attribute not present in shader layout: ${name}`)();
155
+ log.warn(`Unknown attribute ${name}`)();
156
156
  return null;
157
157
  }
158
158
  if (attributeNames.has(name)) {
159
- throw new Error(`Found multiple entries for attribute: ${name}`);
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 = await adapter.requestAdapterInfo();
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 {DepthStencilTextureFormat, CanvasContextProps} from '@luma.gl/core';
8
- import {CanvasContext, Texture, log} from '@luma.gl/core';
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 handle: GPUCanvasContext;
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: WebGPUTexture | null = null;
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
- this.updateSize([this.drawingBufferWidth, this.drawingBufferHeight]);
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.handle.unconfigure();
50
+ this.gpuCanvasContext.unconfigure();
40
51
  }
41
52
 
42
53
  /** Update framebuffer with properly resized "swap chain" texture views */
43
- getCurrentFramebuffer(
44
- options: {depthStencilFormat?: DepthStencilTextureFormat | false} = {
45
- depthStencilFormat: 'depth24plus'
46
- }
47
- ): WebGPUFramebuffer {
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
- // TODO - temporary debug code
51
- if (
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
- if (options?.depthStencilFormat) {
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
- updateSize(size: [newWidth: number, newHeight: number]): void {
77
- if (this.depthStencilAttachment) {
78
- this.depthStencilAttachment.destroy();
79
- this.depthStencilAttachment = null;
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
- // Reconfigure the canvas size.
83
- // https://www.w3.org/TR/webgpu/#canvas-configuration
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
- if (!this.device.handle) return;
114
+ this.update();
96
115
 
97
- if (this.props.autoResize) {
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._setDevicePixelRatio(devicePixelRatio, options);
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.handle.getCurrentTexture(),
114
- format: this.device.preferredColorFormat
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(depthStencilFormat: DepthStencilTextureFormat): WebGPUTexture {
136
+ _createDepthStencilAttachment() {
120
137
  if (!this.depthStencilAttachment) {
121
138
  this.depthStencilAttachment = this.device.createTexture({
122
139
  id: `${this.id}#depth-stencil-texture`,
123
- usage: Texture.RENDER_ATTACHMENT,
124
- format: depthStencilFormat,
125
- width: this.drawingBufferWidth,
126
- height: this.drawingBufferHeight
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
- readonly preferredColorFormat = navigator.gpu.getPreferredCanvasFormat() as
58
- | 'rgba8unorm'
59
- | 'bgra8unorm';
60
- readonly preferredDepthFormat = 'depth24plus';
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
- /* The underlying WebGPU adapter */
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,