@luma.gl/webgpu 9.2.6 → 9.3.0-alpha.4

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 (52) hide show
  1. package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
  2. package/dist/adapter/helpers/get-bind-group.js +11 -5
  3. package/dist/adapter/helpers/get-bind-group.js.map +1 -1
  4. package/dist/adapter/resources/webgpu-buffer.d.ts +7 -0
  5. package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
  6. package/dist/adapter/resources/webgpu-buffer.js +39 -12
  7. package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
  8. package/dist/adapter/resources/webgpu-fence.d.ts +13 -0
  9. package/dist/adapter/resources/webgpu-fence.d.ts.map +1 -0
  10. package/dist/adapter/resources/webgpu-fence.js +25 -0
  11. package/dist/adapter/resources/webgpu-fence.js.map +1 -0
  12. package/dist/adapter/resources/webgpu-pipeline-layout.d.ts.map +1 -1
  13. package/dist/adapter/resources/webgpu-pipeline-layout.js +1 -2
  14. package/dist/adapter/resources/webgpu-pipeline-layout.js.map +1 -1
  15. package/dist/adapter/resources/webgpu-texture.d.ts +12 -3
  16. package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
  17. package/dist/adapter/resources/webgpu-texture.js +143 -26
  18. package/dist/adapter/resources/webgpu-texture.js.map +1 -1
  19. package/dist/adapter/webgpu-adapter.d.ts.map +1 -1
  20. package/dist/adapter/webgpu-adapter.js +34 -34
  21. package/dist/adapter/webgpu-adapter.js.map +1 -1
  22. package/dist/adapter/webgpu-canvas-context.d.ts +4 -3
  23. package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
  24. package/dist/adapter/webgpu-canvas-context.js +22 -21
  25. package/dist/adapter/webgpu-canvas-context.js.map +1 -1
  26. package/dist/adapter/webgpu-device.d.ts +3 -1
  27. package/dist/adapter/webgpu-device.d.ts.map +1 -1
  28. package/dist/adapter/webgpu-device.js +14 -3
  29. package/dist/adapter/webgpu-device.js.map +1 -1
  30. package/dist/dist.dev.js +6485 -293
  31. package/dist/dist.min.js +10 -6
  32. package/dist/index.cjs +398 -114
  33. package/dist/index.cjs.map +4 -4
  34. package/dist/index.d.ts +2 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +2 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/wgsl/get-shader-layout-wgsl.d.ts +8 -0
  39. package/dist/wgsl/get-shader-layout-wgsl.d.ts.map +1 -0
  40. package/dist/wgsl/get-shader-layout-wgsl.js +136 -0
  41. package/dist/wgsl/get-shader-layout-wgsl.js.map +1 -0
  42. package/package.json +6 -5
  43. package/src/adapter/helpers/get-bind-group.ts +18 -5
  44. package/src/adapter/resources/webgpu-buffer.ts +43 -12
  45. package/src/adapter/resources/webgpu-fence.ts +30 -0
  46. package/src/adapter/resources/webgpu-pipeline-layout.ts +1 -2
  47. package/src/adapter/resources/webgpu-texture.ts +202 -88
  48. package/src/adapter/webgpu-adapter.ts +40 -42
  49. package/src/adapter/webgpu-canvas-context.ts +25 -23
  50. package/src/adapter/webgpu-device.ts +19 -4
  51. package/src/index.ts +3 -0
  52. package/src/wgsl/get-shader-layout-wgsl.ts +156 -0
@@ -1,18 +1,24 @@
1
1
  // luma.gl, MIT license
2
- import type {
3
- TextureProps,
4
- TextureViewProps,
5
- CopyExternalImageOptions,
6
- CopyImageDataOptions,
7
- SamplerProps
2
+ import {
3
+ type TextureProps,
4
+ type TextureViewProps,
5
+ type CopyExternalImageOptions,
6
+ type CopyImageDataOptions,
7
+ type TextureReadOptions,
8
+ type TextureWriteOptions,
9
+ type SamplerProps,
10
+ Buffer,
11
+ Texture,
12
+ log,
13
+ textureFormatDecoder
8
14
  } from '@luma.gl/core';
9
- import {Texture, log} from '@luma.gl/core';
10
15
 
11
16
  import {getWebGPUTextureFormat} from '../helpers/convert-texture-format';
12
17
  import type {WebGPUDevice} from '../webgpu-device';
13
18
  import {WebGPUSampler} from './webgpu-sampler';
14
19
  import {WebGPUTextureView} from './webgpu-texture-view';
15
20
 
21
+ /** WebGPU implementation of the luma.gl core Texture resource */
16
22
  export class WebGPUTexture extends Texture {
17
23
  readonly device: WebGPUDevice;
18
24
  readonly handle: GPUTexture;
@@ -20,13 +26,9 @@ export class WebGPUTexture extends Texture {
20
26
  view: WebGPUTextureView;
21
27
 
22
28
  constructor(device: WebGPUDevice, props: TextureProps) {
23
- super(device, props);
29
+ super(device, props, {byteAlignment: 256}); // WebGPU requires row width to be a multiple of 256 bytes
24
30
  this.device = device;
25
31
 
26
- if (this.dimension === 'cube') {
27
- this.depth = 6;
28
- }
29
-
30
32
  this.device.pushErrorScope('out-of-memory');
31
33
  this.device.pushErrorScope('validation');
32
34
 
@@ -58,7 +60,9 @@ export class WebGPUTexture extends Texture {
58
60
  // TODO - Read all properties directly from the supplied handle?
59
61
  if (this.props.handle) {
60
62
  this.handle.label ||= this.id;
63
+ // @ts-expect-error readonly
61
64
  this.width = this.handle.width;
65
+ // @ts-expect-error readonly
62
66
  this.height = this.handle.height;
63
67
  }
64
68
 
@@ -90,10 +94,43 @@ export class WebGPUTexture extends Texture {
90
94
  return new WebGPUTextureView(this.device, {...props, texture: this});
91
95
  }
92
96
 
97
+ copyExternalImage(options_: CopyExternalImageOptions): {width: number; height: number} {
98
+ const options = this._normalizeCopyExternalImageOptions(options_);
99
+
100
+ this.device.pushErrorScope('validation');
101
+ this.device.handle.queue.copyExternalImageToTexture(
102
+ // source: GPUImageCopyExternalImage
103
+ {
104
+ source: options.image,
105
+ origin: [options.sourceX, options.sourceY],
106
+ flipY: false // options.flipY
107
+ },
108
+ // destination: GPUImageCopyTextureTagged
109
+ {
110
+ texture: this.handle,
111
+ origin: [options.x, options.y, options.z],
112
+ mipLevel: options.mipLevel,
113
+ aspect: options.aspect,
114
+ colorSpace: options.colorSpace,
115
+ premultipliedAlpha: options.premultipliedAlpha
116
+ },
117
+ // copySize: GPUExtent3D
118
+ [options.width, options.height, options.depth] // depth is always 1 for 2D textures
119
+ );
120
+ this.device.popErrorScope((error: GPUError) => {
121
+ this.device.reportError(new Error(`copyExternalImage: ${error.message}`), this)();
122
+ this.device.debug();
123
+ });
124
+
125
+ // TODO - should these be clipped to the texture size minus x,y,z?
126
+ return {width: options.width, height: options.height};
127
+ }
128
+
93
129
  copyImageData(options_: CopyImageDataOptions): void {
94
130
  const {width, height, depth} = this;
95
131
  const options = this._normalizeCopyImageDataOptions(options_);
96
132
  this.device.pushErrorScope('validation');
133
+
97
134
  this.device.handle.queue.writeTexture(
98
135
  // destination: GPUImageCopyTexture
99
136
  {
@@ -121,108 +158,185 @@ export class WebGPUTexture extends Texture {
121
158
  });
122
159
  }
123
160
 
124
- copyExternalImage(options_: CopyExternalImageOptions): {width: number; height: number} {
125
- const options = this._normalizeCopyExternalImageOptions(options_);
161
+ override generateMipmapsWebGL(): void {
162
+ log.warn(`${this}: generateMipmaps not supported in WebGPU`)();
163
+ }
164
+
165
+ getImageDataLayout(options: TextureReadOptions): {
166
+ byteLength: number;
167
+ bytesPerRow: number;
168
+ rowsPerImage: number;
169
+ } {
170
+ return {
171
+ byteLength: 0,
172
+ bytesPerRow: 0,
173
+ rowsPerImage: 0
174
+ };
175
+ }
176
+
177
+ override readBuffer(options: TextureReadOptions = {}, buffer?: Buffer): Buffer {
178
+ const {
179
+ x = 0,
180
+ y = 0,
181
+ z = 0,
182
+ width = this.width,
183
+ height = this.height,
184
+ depthOrArrayLayers = this.depth,
185
+ mipLevel = 0,
186
+ aspect = 'all'
187
+ } = options;
188
+
189
+ const layout = this.computeMemoryLayout(options);
190
+
191
+ const {bytesPerRow, rowsPerImage, byteLength} = layout;
192
+
193
+ // Create a GPUBuffer to hold the copied pixel data.
194
+ const readBuffer =
195
+ buffer ||
196
+ this.device.createBuffer({
197
+ byteLength,
198
+ usage: Buffer.COPY_DST | Buffer.MAP_READ
199
+ });
200
+ const gpuReadBuffer = readBuffer.handle as GPUBuffer;
201
+
202
+ // Record commands to copy from the texture to the buffer.
203
+ const gpuDevice = this.device.handle;
126
204
 
127
205
  this.device.pushErrorScope('validation');
128
- this.device.handle.queue.copyExternalImageToTexture(
129
- // source: GPUImageCopyExternalImage
206
+ const commandEncoder = gpuDevice.createCommandEncoder();
207
+ commandEncoder.copyTextureToBuffer(
208
+ // source
130
209
  {
131
- source: options.image,
132
- origin: [options.sourceX, options.sourceY],
133
- flipY: options.flipY
210
+ texture: this.handle,
211
+ origin: {x, y, z},
212
+ // origin: [options.x, options.y, 0], // options.depth],
213
+ mipLevel,
214
+ aspect
215
+ // colorSpace: options.colorSpace,
216
+ // premultipliedAlpha: options.premultipliedAlpha
134
217
  },
135
- // destination: GPUImageCopyTextureTagged
218
+ // destination
136
219
  {
137
- texture: this.handle,
138
- origin: [options.x, options.y, 0], // options.depth],
139
- mipLevel: options.mipLevel,
140
- aspect: options.aspect,
141
- colorSpace: options.colorSpace,
142
- premultipliedAlpha: options.premultipliedAlpha
220
+ buffer: gpuReadBuffer,
221
+ offset: 0,
222
+ bytesPerRow,
223
+ rowsPerImage
143
224
  },
144
- // copySize: GPUExtent3D
145
- [options.width, options.height, 1]
225
+ // copy size
226
+ {
227
+ width,
228
+ height,
229
+ depthOrArrayLayers
230
+ }
146
231
  );
232
+
233
+ // Submit the command.
234
+ const commandBuffer = commandEncoder.finish();
235
+ this.device.handle.queue.submit([commandBuffer]);
147
236
  this.device.popErrorScope((error: GPUError) => {
148
- this.device.reportError(new Error(`copyExternalImage: ${error.message}`), this)();
237
+ this.device.reportError(new Error(`${this} readBuffer: ${error.message}`), this)();
149
238
  this.device.debug();
150
239
  });
151
240
 
152
- // TODO - should these be clipped to the texture size minus x,y,z?
153
- return {width: options.width, height: options.height};
241
+ return readBuffer;
154
242
  }
155
243
 
156
- override generateMipmapsWebGL(): void {
157
- log.warn(`${this}: generateMipmaps not supported in WebGPU`)();
244
+ override async readDataAsync(options: TextureReadOptions = {}): Promise<ArrayBuffer> {
245
+ const buffer = this.readBuffer(options);
246
+ const data = await buffer.readAsync();
247
+ buffer.destroy();
248
+ return data.buffer as ArrayBuffer;
158
249
  }
159
250
 
160
- // WebGPU specific
161
-
162
- /*
163
- async readPixels() {
164
- const readbackBuffer = device.createBuffer({
165
- usage: Buffer.COPY_DST | Buffer.MAP_READ,
166
- size: 4 * textureWidth * textureHeight,
167
- });
251
+ override writeBuffer(buffer: Buffer, options: TextureWriteOptions = {}) {
252
+ const {
253
+ x = 0,
254
+ y = 0,
255
+ z = 0,
256
+ width = this.width,
257
+ height = this.height,
258
+ depthOrArrayLayers = this.depth,
259
+ mipLevel = 0,
260
+ aspect = 'all'
261
+ } = options;
168
262
 
169
- // Copy data from the texture to the buffer.
170
- const encoder = device.createCommandEncoder();
171
- encoder.copyTextureToBuffer(
172
- { texture },
173
- { buffer, rowPitch: textureWidth * 4 },
174
- [textureWidth, textureHeight],
175
- );
176
- device.submit([encoder.finish()]);
263
+ const layout = this.computeMemoryLayout(options);
177
264
 
178
265
  // Get the data on the CPU.
179
- await buffer.mapAndReadAsync(GPUMapMode.READ);
180
- saveScreenshot(buffer.getMappedRange());
181
- buffer.unmap();
182
- }
266
+ // await buffer.mapAndReadAsync();
183
267
 
184
- setImageData(imageData, usage): this {
185
- let data = null;
186
-
187
- const bytesPerRow = Math.ceil((img.width * 4) / 256) * 256;
188
- if (bytesPerRow == img.width * 4) {
189
- data = imageData.data;
190
- } else {
191
- data = new Uint8Array(bytesPerRow * img.height);
192
- let imagePixelIndex = 0;
193
- for (let y = 0; y < img.height; ++y) {
194
- for (let x = 0; x < img.width; ++x) {
195
- const i = x * 4 + y * bytesPerRow;
196
- data[i] = imageData.data[imagePixelIndex];
197
- data[i + 1] = imageData.data[imagePixelIndex + 1];
198
- data[i + 2] = imageData.data[imagePixelIndex + 2];
199
- data[i + 3] = imageData.data[imagePixelIndex + 3];
200
- imagePixelIndex += 4;
201
- }
202
- }
203
- }
204
- return this;
205
- }
268
+ const {bytesPerRow, rowsPerImage} = layout;
269
+
270
+ const gpuDevice = this.device.handle;
206
271
 
207
- setBuffer(textureDataBuffer, {bytesPerRow}): this {
208
- const commandEncoder = this.device.handle.createCommandEncoder();
272
+ this.device.pushErrorScope('validation');
273
+ const commandEncoder = gpuDevice.createCommandEncoder();
209
274
  commandEncoder.copyBufferToTexture(
210
275
  {
211
- buffer: textureDataBuffer,
212
- bytesPerRow
276
+ buffer: buffer.handle as GPUBuffer,
277
+ offset: 0,
278
+ bytesPerRow,
279
+ rowsPerImage
213
280
  },
214
281
  {
215
- texture: this.handle
282
+ texture: this.handle,
283
+ origin: {x, y, z},
284
+ mipLevel,
285
+ aspect
216
286
  },
217
- {
218
- width,
219
- height,
220
- depth
221
- }
287
+ {width, height, depthOrArrayLayers}
222
288
  );
289
+ const commandBuffer = commandEncoder.finish();
290
+ this.device.handle.queue.submit([commandBuffer]);
291
+ this.device.popErrorScope((error: GPUError) => {
292
+ this.device.reportError(new Error(`${this} writeBuffer: ${error.message}`), this)();
293
+ this.device.debug();
294
+ });
295
+ }
223
296
 
224
- this.device.handle.defaultQueue.submit([commandEncoder.finish()]);
225
- return this;
297
+ override writeData(data: ArrayBuffer | ArrayBufferView, options: TextureWriteOptions = {}): void {
298
+ const device = this.device;
299
+
300
+ const {
301
+ x = 0,
302
+ y = 0,
303
+ z = 0,
304
+ width = this.width,
305
+ height = this.height,
306
+ depthOrArrayLayers = this.depth,
307
+ mipLevel = 0,
308
+ aspect = 'all'
309
+ } = options;
310
+
311
+ const layout = textureFormatDecoder.computeMemoryLayout({
312
+ format: this.format,
313
+ width: this.width,
314
+ height: this.height,
315
+ depth: this.depth,
316
+ byteAlignment: this.byteAlignment
317
+ });
318
+
319
+ const {bytesPerRow, rowsPerImage} = layout;
320
+
321
+ this.device.pushErrorScope('validation');
322
+ device.handle.queue.writeTexture(
323
+ {
324
+ texture: this.handle,
325
+ mipLevel,
326
+ aspect,
327
+ origin: {x, y, z}
328
+ },
329
+ data,
330
+ {
331
+ offset: 0,
332
+ bytesPerRow,
333
+ rowsPerImage
334
+ },
335
+ {width, height, depthOrArrayLayers}
336
+ );
337
+ this.device.popErrorScope((error: GPUError) => {
338
+ this.device.reportError(new Error(`${this} writeData: ${error.message}`), this)();
339
+ this.device.debug();
340
+ });
226
341
  }
227
- */
228
342
  }
@@ -35,62 +35,60 @@ export class WebGPUAdapter extends Adapter {
35
35
  throw new Error('WebGPU not available. Recent Chrome browsers should work.');
36
36
  }
37
37
 
38
- log.groupCollapsed(1, 'WebGPUDevice created')();
39
- try {
40
- const adapter = await navigator.gpu.requestAdapter({
41
- powerPreference: 'high-performance'
42
- // forceSoftware: false
43
- });
38
+ const adapter = await navigator.gpu.requestAdapter({
39
+ powerPreference: 'high-performance'
40
+ // forceSoftware: false
41
+ });
44
42
 
45
- if (!adapter) {
46
- throw new Error('Failed to request WebGPU adapter');
47
- }
43
+ if (!adapter) {
44
+ throw new Error('Failed to request WebGPU adapter');
45
+ }
48
46
 
49
- // Note: adapter.requestAdapterInfo() has been replaced with adapter.info. Fall back in case adapter.info is not available
50
- const adapterInfo =
51
- adapter.info ||
52
- // @ts-ignore
53
- (await adapter.requestAdapterInfo?.());
54
- log.probe(2, 'Adapter available', adapterInfo)();
55
-
56
- const requiredFeatures: GPUFeatureName[] = [];
57
- const requiredLimits: Record<string, number> = {};
58
-
59
- if (props._requestMaxLimits) {
60
- // Require all features
61
- requiredFeatures.push(...(Array.from(adapter.features) as GPUFeatureName[]));
62
-
63
- // Require all limits
64
- // Filter out chrome specific keys (avoid crash)
65
- const limits = Object.keys(adapter.limits).filter(
66
- key => !['minSubgroupSize', 'maxSubgroupSize'].includes(key)
67
- );
68
- for (const key of limits) {
69
- const limit = key as keyof GPUSupportedLimits;
70
- const value = adapter.limits[limit];
71
- if (typeof value === 'number') {
72
- requiredLimits[limit] = value;
73
- }
47
+ // Note: adapter.requestAdapterInfo() has been replaced with adapter.info. Fall back in case adapter.info is not available
48
+ const adapterInfo =
49
+ adapter.info ||
50
+ // @ts-ignore
51
+ (await adapter.requestAdapterInfo?.());
52
+ // log.probe(2, 'Adapter available', adapterInfo)();
53
+
54
+ const requiredFeatures: GPUFeatureName[] = [];
55
+ const requiredLimits: Record<string, number> = {};
56
+
57
+ if (props._requestMaxLimits) {
58
+ // Require all features
59
+ requiredFeatures.push(...(Array.from(adapter.features) as GPUFeatureName[]));
60
+
61
+ // Require all limits
62
+ // Filter out chrome specific keys (avoid crash)
63
+ const limits = Object.keys(adapter.limits).filter(
64
+ key => !['minSubgroupSize', 'maxSubgroupSize'].includes(key)
65
+ );
66
+ for (const key of limits) {
67
+ const limit = key as keyof GPUSupportedLimits;
68
+ const value = adapter.limits[limit];
69
+ if (typeof value === 'number') {
70
+ requiredLimits[limit] = value;
74
71
  }
75
72
  }
73
+ }
76
74
 
77
- const gpuDevice = await adapter.requestDevice({
78
- requiredFeatures,
79
- requiredLimits
80
- });
75
+ const gpuDevice = await adapter.requestDevice({
76
+ requiredFeatures,
77
+ requiredLimits
78
+ });
81
79
 
82
- log.probe(1, 'GPUDevice available')();
80
+ // log.probe(1, 'GPUDevice available')();
83
81
 
84
- const {WebGPUDevice} = await import('./webgpu-device');
82
+ const {WebGPUDevice} = await import('./webgpu-device');
85
83
 
84
+ log.groupCollapsed(1, 'WebGPUDevice created')();
85
+ try {
86
86
  const device = new WebGPUDevice(props, gpuDevice, adapter, adapterInfo);
87
-
88
87
  log.probe(
89
88
  1,
90
89
  'Device created. For more info, set chrome://flags/#enable-webgpu-developer-features'
91
90
  )();
92
91
  log.table(1, device.info)();
93
-
94
92
  return device;
95
93
  } finally {
96
94
  log.groupEnd(1)();
@@ -38,7 +38,7 @@ export class WebGPUCanvasContext extends CanvasContext {
38
38
 
39
39
  // Base class constructor cannot access derived methods/fields, so we need to call these functions in the subclass constructor
40
40
  this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
41
- this._updateDevice();
41
+ this._configureDevice();
42
42
  }
43
43
 
44
44
  /** Destroy any textures produced while configured and remove the context configuration. */
@@ -47,14 +47,34 @@ export class WebGPUCanvasContext extends CanvasContext {
47
47
  super.destroy();
48
48
  }
49
49
 
50
+ // IMPLEMENTATION OF ABSTRACT METHODS
51
+
52
+ /** @see https://www.w3.org/TR/webgpu/#canvas-configuration */
53
+ _configureDevice(): void {
54
+ if (this.depthStencilAttachment) {
55
+ this.depthStencilAttachment.destroy();
56
+ this.depthStencilAttachment = null;
57
+ }
58
+
59
+ // Reconfigure the canvas size.
60
+ this.handle.configure({
61
+ device: this.device.handle,
62
+ format: this.device.preferredColorFormat,
63
+ // Can be used to define e.g. -srgb views
64
+ // viewFormats: [...]
65
+ colorSpace: this.props.colorSpace,
66
+ alphaMode: this.props.alphaMode
67
+ });
68
+ }
69
+
50
70
  /** Update framebuffer with properly resized "swap chain" texture views */
51
- getCurrentFramebuffer(
71
+ _getCurrentFramebuffer(
52
72
  options: {depthStencilFormat?: TextureFormatDepthStencil | false} = {
53
73
  depthStencilFormat: 'depth24plus'
54
74
  }
55
75
  ): WebGPUFramebuffer {
56
76
  // Wrap the current canvas context texture in a luma.gl texture
57
- const currentColorAttachment = this.getCurrentTexture();
77
+ const currentColorAttachment = this._getCurrentTexture();
58
78
  // TODO - temporary debug code
59
79
  if (
60
80
  currentColorAttachment.width !== this.drawingBufferWidth ||
@@ -80,28 +100,10 @@ export class WebGPUCanvasContext extends CanvasContext {
80
100
  });
81
101
  }
82
102
 
83
- // IMPLEMENTATION OF ABSTRACT METHODS
84
-
85
- _updateDevice(): void {
86
- if (this.depthStencilAttachment) {
87
- this.depthStencilAttachment.destroy();
88
- this.depthStencilAttachment = null;
89
- }
90
-
91
- // Reconfigure the canvas size.
92
- // https://www.w3.org/TR/webgpu/#canvas-configuration
93
- this.handle.configure({
94
- device: this.device.handle,
95
- format: this.device.preferredColorFormat,
96
- // Can be used to define e.g. -srgb views
97
- // viewFormats: [...]
98
- colorSpace: this.props.colorSpace,
99
- alphaMode: this.props.alphaMode
100
- });
101
- }
103
+ // PRIMARY METHODS
102
104
 
103
105
  /** Wrap the current canvas context texture in a luma.gl texture */
104
- getCurrentTexture(): WebGPUTexture {
106
+ _getCurrentTexture(): WebGPUTexture {
105
107
  const handle = this.handle.getCurrentTexture();
106
108
  return this.device.createTexture({
107
109
  id: `${this.id}#color-texture`,
@@ -45,6 +45,9 @@ import {WebGPUCommandEncoder} from './resources/webgpu-command-encoder';
45
45
  import {WebGPUCommandBuffer} from './resources/webgpu-command-buffer';
46
46
  import {WebGPUQuerySet} from './resources/webgpu-query-set';
47
47
  import {WebGPUPipelineLayout} from './resources/webgpu-pipeline-layout';
48
+ import {WebGPUFence} from './resources/webgpu-fence';
49
+
50
+ import {getShaderLayoutFromWGSL} from '../wgsl/get-shader-layout-wgsl';
48
51
 
49
52
  /** WebGPU Device implementation */
50
53
  export class WebGPUDevice extends Device {
@@ -136,15 +139,15 @@ export class WebGPUDevice extends Device {
136
139
  return this._isLost;
137
140
  }
138
141
 
142
+ getShaderLayout(source: string) {
143
+ return getShaderLayoutFromWGSL(source);
144
+ }
145
+
139
146
  override isVertexFormatSupported(format: VertexFormat): boolean {
140
147
  const info = this.getVertexFormatInfo(format);
141
148
  return !info.webglOnly;
142
149
  }
143
150
 
144
- getTextureByteAlignment(): number {
145
- return 1;
146
- }
147
-
148
151
  createBuffer(props: BufferProps | ArrayBuffer | ArrayBufferView): WebGPUBuffer {
149
152
  const newProps = this._normalizeBufferProps(props);
150
153
  return new WebGPUBuffer(this, newProps);
@@ -196,6 +199,10 @@ export class WebGPUDevice extends Device {
196
199
  return new WebGPUQuerySet(this, props);
197
200
  }
198
201
 
202
+ override createFence(): WebGPUFence {
203
+ return new WebGPUFence(this);
204
+ }
205
+
199
206
  createCanvasContext(props: CanvasContextProps): WebGPUCanvasContext {
200
207
  return new WebGPUCanvasContext(this, this.adapter, props);
201
208
  }
@@ -278,6 +285,14 @@ export class WebGPUDevice extends Device {
278
285
  features.add('texture-compression-bc5-webgl');
279
286
  }
280
287
 
288
+ if (this.handle.features.has('chromium-experimental-norm16-texture-formats')) {
289
+ features.add('norm16-renderable-webgl');
290
+ }
291
+
292
+ if (this.handle.features.has('chromium-experimental-snorm16-texture-formats')) {
293
+ features.add('snorm16-renderable-webgl');
294
+ }
295
+
281
296
  const WEBGPU_ALWAYS_FEATURES: DeviceFeature[] = [
282
297
  'timer-query-webgl',
283
298
  'compilation-status-async-webgl',
package/src/index.ts CHANGED
@@ -12,3 +12,6 @@ export {WebGPUBuffer} from './adapter/resources/webgpu-buffer';
12
12
  export {WebGPUTexture} from './adapter/resources/webgpu-texture';
13
13
  export {WebGPUSampler} from './adapter/resources/webgpu-sampler';
14
14
  export {WebGPUShader} from './adapter/resources/webgpu-shader';
15
+ export {WebGPUFence} from './adapter/resources/webgpu-fence';
16
+
17
+ export {getShaderLayoutFromWGSL} from './wgsl/get-shader-layout-wgsl';