@luma.gl/webgpu 9.1.5 → 9.1.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luma.gl/webgpu",
3
- "version": "9.1.5",
3
+ "version": "9.1.7",
4
4
  "description": "WebGPU adapter for the luma.gl core API",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -43,5 +43,5 @@
43
43
  "@probe.gl/env": "^4.0.8",
44
44
  "@webgpu/types": "^0.1.34"
45
45
  },
46
- "gitHead": "83b1bfdcca2cacd0d614982a7dd000bec80d1a6f"
46
+ "gitHead": "23516eeceec768007f63b43010657668005f8582"
47
47
  }
@@ -46,7 +46,8 @@ export function getShaderLayoutBinding(
46
46
  ): BindingDeclaration | null {
47
47
  const bindingLayout = shaderLayout.bindings.find(
48
48
  binding =>
49
- binding.name === bindingName || `${binding.name}uniforms` === bindingName.toLocaleLowerCase()
49
+ binding.name === bindingName ||
50
+ `${binding.name.toLocaleLowerCase()}uniforms` === bindingName.toLocaleLowerCase()
50
51
  );
51
52
  if (!bindingLayout) {
52
53
  log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
@@ -0,0 +1,126 @@
1
+ import {
2
+ PipelineLayout,
3
+ PipelineLayoutProps,
4
+ StorageBufferBindingLayout,
5
+ StorageTextureBindingLayout
6
+ } from '@luma.gl/core';
7
+ import {WebGPUDevice} from '../webgpu-device';
8
+
9
+ export class WebGPUPipelineLayout extends PipelineLayout {
10
+ device: WebGPUDevice;
11
+ handle: GPUPipelineLayout;
12
+
13
+ constructor(device: WebGPUDevice, props: PipelineLayoutProps) {
14
+ super(device, props);
15
+
16
+ this.device = device;
17
+
18
+ const bindGroupEntries = this.mapShaderLayoutToBindGroupEntries();
19
+
20
+ this.handle = this.device.handle.createPipelineLayout({
21
+ label: props?.id ?? 'unnamed-pipeline-layout',
22
+ bindGroupLayouts: [
23
+ // TODO (kaapp): We can cache these to re-use them across
24
+ // layers, particularly if using a separate group for injected
25
+ // bindings (e.g. project/lighting)
26
+ this.device.handle.createBindGroupLayout({
27
+ label: 'bind-group-layout',
28
+ entries: bindGroupEntries
29
+ })
30
+ ]
31
+ });
32
+ }
33
+
34
+ override destroy(): void {
35
+ // WebGPUPipelineLayout has no destroy method.
36
+ // @ts-expect-error
37
+ this.handle = null;
38
+ }
39
+
40
+ protected mapShaderLayoutToBindGroupEntries(): GPUBindGroupLayoutEntry[] {
41
+ // Set up the pipeline layout
42
+ // TODO (kaapp): This only supports the first group, but so does the rest of the code
43
+ const bindGroupEntries: GPUBindGroupLayoutEntry[] = [];
44
+
45
+ for (let i = 0; i < this.props.shaderLayout.bindings.length; i++) {
46
+ const binding = this.props.shaderLayout.bindings[i];
47
+ const bindingTypeInfo: Omit<GPUBindGroupLayoutEntry, 'binding' | 'visibility'> = {};
48
+
49
+ switch (binding.type) {
50
+ case 'uniform': {
51
+ bindingTypeInfo.buffer = {
52
+ type: 'uniform',
53
+ hasDynamicOffset: binding.hasDynamicOffset,
54
+ minBindingSize: binding.minBindingSize
55
+ };
56
+ break;
57
+ }
58
+
59
+ case 'read-only-storage': {
60
+ bindingTypeInfo.buffer = {
61
+ type: 'read-only-storage',
62
+ hasDynamicOffset: binding.hasDynamicOffset,
63
+ minBindingSize: binding.minBindingSize
64
+ };
65
+ break;
66
+ }
67
+
68
+ case 'sampler': {
69
+ bindingTypeInfo.sampler = {
70
+ type: binding.samplerType
71
+ };
72
+ break;
73
+ }
74
+
75
+ case 'storage': {
76
+ if (isStorageTextureBindingLayout(binding)) {
77
+ bindingTypeInfo.storageTexture = {
78
+ // TODO (kaapp): Not all formats in the binding layout are supported
79
+ // by WebGPU, but at least it will provide a clear error for now.
80
+ format: binding.format as GPUTextureFormat,
81
+ access: binding.access,
82
+ viewDimension: binding.viewDimension
83
+ };
84
+ } else {
85
+ bindingTypeInfo.buffer = {
86
+ type: 'storage',
87
+ hasDynamicOffset: binding.hasDynamicOffset,
88
+ minBindingSize: binding.minBindingSize
89
+ };
90
+ }
91
+ break;
92
+ }
93
+
94
+ case 'texture': {
95
+ bindingTypeInfo.texture = {
96
+ multisampled: binding.multisampled,
97
+ sampleType: binding.sampleType,
98
+ viewDimension: binding.viewDimension
99
+ };
100
+ break;
101
+ }
102
+
103
+ default: {
104
+ console.warn('unhandled binding type when creating pipeline descriptor');
105
+ }
106
+ }
107
+
108
+ const VISIBILITY_ALL =
109
+ GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;
110
+
111
+ bindGroupEntries.push({
112
+ binding: binding.location,
113
+ visibility: binding.visibility || VISIBILITY_ALL,
114
+ ...bindingTypeInfo
115
+ });
116
+ }
117
+
118
+ return bindGroupEntries;
119
+ }
120
+ }
121
+
122
+ const isStorageTextureBindingLayout = (
123
+ maybe: StorageBufferBindingLayout | StorageTextureBindingLayout
124
+ ): maybe is StorageTextureBindingLayout => {
125
+ return (maybe as StorageTextureBindingLayout).format !== undefined;
126
+ };
@@ -168,6 +168,10 @@ export class WebGPURenderPipeline extends RenderPipeline {
168
168
  ]
169
169
  };
170
170
 
171
+ const layout = this.device.createPipelineLayout({
172
+ shaderLayout: this.shaderLayout
173
+ });
174
+
171
175
  // Create a partially populated descriptor
172
176
  const descriptor: GPURenderPipelineDescriptor = {
173
177
  vertex,
@@ -175,7 +179,7 @@ export class WebGPURenderPipeline extends RenderPipeline {
175
179
  primitive: {
176
180
  topology: this.props.topology
177
181
  },
178
- layout: 'auto'
182
+ layout: layout.handle
179
183
  };
180
184
 
181
185
  if (this.props.parameters.depthWriteEnabled && this.props.parameters.depthCompare) {
@@ -28,7 +28,8 @@ import type {
28
28
  TransformFeedbackProps,
29
29
  QuerySet,
30
30
  QuerySetProps,
31
- DeviceProps
31
+ DeviceProps,
32
+ PipelineLayoutProps,
32
33
  } from '@luma.gl/core';
33
34
  import {Device, DeviceFeatures} from '@luma.gl/core';
34
35
  import {WebGPUBuffer} from './resources/webgpu-buffer';
@@ -46,6 +47,7 @@ import {WebGPUVertexArray} from './resources/webgpu-vertex-array';
46
47
 
47
48
  import {WebGPUCanvasContext} from './webgpu-canvas-context';
48
49
  import {WebGPUQuerySet} from './resources/webgpu-query-set';
50
+ import {WebGPUPipelineLayout} from './resources/webgpu-pipeline-layout';
49
51
 
50
52
  /** WebGPU Device implementation */
51
53
  export class WebGPUDevice extends Device {
@@ -194,6 +196,10 @@ export class WebGPUDevice extends Device {
194
196
  return new WebGPUCanvasContext(this, this.adapter, props);
195
197
  }
196
198
 
199
+ createPipelineLayout(props: PipelineLayoutProps): WebGPUPipelineLayout {
200
+ return new WebGPUPipelineLayout(this, props);
201
+ }
202
+
197
203
  submit(): void {
198
204
  const commandBuffer = this.commandEncoder?.finish();
199
205
  if (commandBuffer) {
@@ -205,7 +211,6 @@ export class WebGPUDevice extends Device {
205
211
  }
206
212
  });
207
213
  }
208
- this.commandEncoder = null;
209
214
  }
210
215
 
211
216
  // PRIVATE METHODS