@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
package/dist/index.cjs CHANGED
@@ -7,8 +7,8 @@ var __esm = (fn, res) => function __init() {
7
7
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
8
  };
9
9
  var __export = (target, all) => {
10
- for (var name2 in all)
11
- __defProp(target, name2, { get: all[name2], enumerable: true });
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
12
  };
13
13
  var __copyProps = (to, from, except, desc) => {
14
14
  if (from && typeof from === "object" || typeof from === "function") {
@@ -30,13 +30,15 @@ var init_webgpu_buffer = __esm({
30
30
  device;
31
31
  handle;
32
32
  byteLength;
33
+ paddedByteLength;
33
34
  constructor(device, props) {
34
35
  var _a, _b;
35
36
  super(device, props);
36
37
  this.device = device;
37
38
  this.byteLength = props.byteLength || ((_a = props.data) == null ? void 0 : _a.byteLength) || 0;
39
+ this.paddedByteLength = Math.ceil(this.byteLength / 4) * 4;
38
40
  const mappedAtCreation = Boolean(this.props.onMapped || props.data);
39
- const size = Math.ceil(this.byteLength / 4) * 4;
41
+ const size = this.paddedByteLength;
40
42
  this.device.pushErrorScope("out-of-memory");
41
43
  this.device.pushErrorScope("validation");
42
44
  this.handle = this.props.handle || this.device.handle.createBuffer({
@@ -89,18 +91,21 @@ var init_webgpu_buffer = __esm({
89
91
  });
90
92
  }
91
93
  async mapAndWriteAsync(callback, byteOffset = 0, byteLength = this.byteLength - byteOffset) {
94
+ const alignedByteLength = Math.ceil(byteLength / 4) * 4;
92
95
  const isMappable = (this.usage & import_core.Buffer.MAP_WRITE) !== 0;
93
- const mappableBuffer = !isMappable ? this._getMappableBuffer(import_core.Buffer.MAP_WRITE | import_core.Buffer.COPY_SRC, 0, this.byteLength) : null;
96
+ const mappableBuffer = !isMappable ? this._getMappableBuffer(import_core.Buffer.MAP_WRITE | import_core.Buffer.COPY_SRC, 0, this.paddedByteLength) : null;
94
97
  const writeBuffer = mappableBuffer || this;
95
98
  this.device.pushErrorScope("validation");
96
99
  try {
97
100
  await this.device.handle.queue.onSubmittedWorkDone();
98
- await writeBuffer.handle.mapAsync(GPUMapMode.WRITE, byteOffset, byteLength);
99
- const arrayBuffer = writeBuffer.handle.getMappedRange(byteOffset, byteLength);
101
+ await writeBuffer.handle.mapAsync(GPUMapMode.WRITE, byteOffset, alignedByteLength);
102
+ const mappedRange = writeBuffer.handle.getMappedRange(byteOffset, alignedByteLength);
103
+ const arrayBuffer = mappedRange.slice(0, byteLength);
100
104
  await callback(arrayBuffer, "mapped");
105
+ new Uint8Array(mappedRange).set(new Uint8Array(arrayBuffer), 0);
101
106
  writeBuffer.handle.unmap();
102
107
  if (mappableBuffer) {
103
- this._copyBuffer(mappableBuffer, byteOffset, byteLength);
108
+ this._copyBuffer(mappableBuffer, byteOffset, alignedByteLength);
104
109
  }
105
110
  } finally {
106
111
  this.device.popErrorScope((error) => {
@@ -114,24 +119,37 @@ var init_webgpu_buffer = __esm({
114
119
  return this.mapAndReadAsync((arrayBuffer) => new Uint8Array(arrayBuffer.slice(0)), byteOffset, byteLength);
115
120
  }
116
121
  async mapAndReadAsync(callback, byteOffset = 0, byteLength = this.byteLength - byteOffset) {
122
+ const requestedEnd = byteOffset + byteLength;
123
+ if (requestedEnd > this.byteLength) {
124
+ throw new Error("Mapping range exceeds buffer size");
125
+ }
126
+ let mappedByteOffset = byteOffset;
127
+ let mappedByteLength = byteLength;
128
+ let sliceByteOffset = 0;
129
+ let lifetime = "mapped";
117
130
  if (byteOffset % 8 !== 0 || byteLength % 4 !== 0) {
118
- throw new Error("byteOffset must be multiple of 8 and byteLength multiple of 4");
131
+ mappedByteOffset = Math.floor(byteOffset / 8) * 8;
132
+ const alignedEnd = Math.ceil(requestedEnd / 4) * 4;
133
+ mappedByteLength = alignedEnd - mappedByteOffset;
134
+ sliceByteOffset = byteOffset - mappedByteOffset;
135
+ lifetime = "copied";
119
136
  }
120
- if (byteOffset + byteLength > this.handle.size) {
137
+ if (mappedByteOffset + mappedByteLength > this.paddedByteLength) {
121
138
  throw new Error("Mapping range exceeds buffer size");
122
139
  }
123
140
  const isMappable = (this.usage & import_core.Buffer.MAP_READ) !== 0;
124
- const mappableBuffer = !isMappable ? this._getMappableBuffer(import_core.Buffer.MAP_READ | import_core.Buffer.COPY_DST, 0, this.byteLength) : null;
141
+ const mappableBuffer = !isMappable ? this._getMappableBuffer(import_core.Buffer.MAP_READ | import_core.Buffer.COPY_DST, 0, this.paddedByteLength) : null;
125
142
  const readBuffer = mappableBuffer || this;
126
143
  this.device.pushErrorScope("validation");
127
144
  try {
128
145
  await this.device.handle.queue.onSubmittedWorkDone();
129
146
  if (mappableBuffer) {
130
- mappableBuffer._copyBuffer(this);
147
+ mappableBuffer._copyBuffer(this, mappedByteOffset, mappedByteLength);
131
148
  }
132
- await readBuffer.handle.mapAsync(GPUMapMode.READ, byteOffset, byteLength);
133
- const arrayBuffer = readBuffer.handle.getMappedRange(byteOffset, byteLength);
134
- const result = await callback(arrayBuffer, "mapped");
149
+ await readBuffer.handle.mapAsync(GPUMapMode.READ, mappedByteOffset, mappedByteLength);
150
+ const arrayBuffer = readBuffer.handle.getMappedRange(mappedByteOffset, mappedByteLength);
151
+ const mappedRange = lifetime === "mapped" ? arrayBuffer : arrayBuffer.slice(sliceByteOffset, sliceByteOffset + byteLength);
152
+ const result = await callback(mappedRange, lifetime);
135
153
  readBuffer.handle.unmap();
136
154
  return result;
137
155
  } finally {
@@ -267,11 +285,8 @@ var init_webgpu_texture = __esm({
267
285
  sampler;
268
286
  view;
269
287
  constructor(device, props) {
270
- super(device, props);
288
+ super(device, props, { byteAlignment: 256 });
271
289
  this.device = device;
272
- if (this.dimension === "cube") {
273
- this.depth = 6;
274
- }
275
290
  this.device.pushErrorScope("out-of-memory");
276
291
  this.device.pushErrorScope("validation");
277
292
  this.handle = this.props.handle || this.device.handle.createTexture({
@@ -318,6 +333,36 @@ var init_webgpu_texture = __esm({
318
333
  createView(props) {
319
334
  return new WebGPUTextureView(this.device, { ...props, texture: this });
320
335
  }
336
+ copyExternalImage(options_) {
337
+ const options = this._normalizeCopyExternalImageOptions(options_);
338
+ this.device.pushErrorScope("validation");
339
+ this.device.handle.queue.copyExternalImageToTexture(
340
+ // source: GPUImageCopyExternalImage
341
+ {
342
+ source: options.image,
343
+ origin: [options.sourceX, options.sourceY],
344
+ flipY: false
345
+ // options.flipY
346
+ },
347
+ // destination: GPUImageCopyTextureTagged
348
+ {
349
+ texture: this.handle,
350
+ origin: [options.x, options.y, options.z],
351
+ mipLevel: options.mipLevel,
352
+ aspect: options.aspect,
353
+ colorSpace: options.colorSpace,
354
+ premultipliedAlpha: options.premultipliedAlpha
355
+ },
356
+ // copySize: GPUExtent3D
357
+ [options.width, options.height, options.depth]
358
+ // depth is always 1 for 2D textures
359
+ );
360
+ this.device.popErrorScope((error) => {
361
+ this.device.reportError(new Error(`copyExternalImage: ${error.message}`), this)();
362
+ this.device.debug();
363
+ });
364
+ return { width: options.width, height: options.height };
365
+ }
321
366
  copyImageData(options_) {
322
367
  const { width, height, depth } = this;
323
368
  const options = this._normalizeCopyImageDataOptions(options_);
@@ -348,37 +393,118 @@ var init_webgpu_texture = __esm({
348
393
  this.device.debug();
349
394
  });
350
395
  }
351
- copyExternalImage(options_) {
352
- const options = this._normalizeCopyExternalImageOptions(options_);
396
+ generateMipmapsWebGL() {
397
+ import_core4.log.warn(`${this}: generateMipmaps not supported in WebGPU`)();
398
+ }
399
+ getImageDataLayout(options) {
400
+ return {
401
+ byteLength: 0,
402
+ bytesPerRow: 0,
403
+ rowsPerImage: 0
404
+ };
405
+ }
406
+ readBuffer(options = {}, buffer) {
407
+ const { x = 0, y = 0, z = 0, width = this.width, height = this.height, depthOrArrayLayers = this.depth, mipLevel = 0, aspect = "all" } = options;
408
+ const layout = this.computeMemoryLayout(options);
409
+ const { bytesPerRow, rowsPerImage, byteLength } = layout;
410
+ const readBuffer = buffer || this.device.createBuffer({
411
+ byteLength,
412
+ usage: import_core4.Buffer.COPY_DST | import_core4.Buffer.MAP_READ
413
+ });
414
+ const gpuReadBuffer = readBuffer.handle;
415
+ const gpuDevice = this.device.handle;
353
416
  this.device.pushErrorScope("validation");
354
- this.device.handle.queue.copyExternalImageToTexture(
355
- // source: GPUImageCopyExternalImage
417
+ const commandEncoder = gpuDevice.createCommandEncoder();
418
+ commandEncoder.copyTextureToBuffer(
419
+ // source
356
420
  {
357
- source: options.image,
358
- origin: [options.sourceX, options.sourceY],
359
- flipY: options.flipY
421
+ texture: this.handle,
422
+ origin: { x, y, z },
423
+ // origin: [options.x, options.y, 0], // options.depth],
424
+ mipLevel,
425
+ aspect
426
+ // colorSpace: options.colorSpace,
427
+ // premultipliedAlpha: options.premultipliedAlpha
360
428
  },
361
- // destination: GPUImageCopyTextureTagged
429
+ // destination
362
430
  {
363
- texture: this.handle,
364
- origin: [options.x, options.y, 0],
365
- // options.depth],
366
- mipLevel: options.mipLevel,
367
- aspect: options.aspect,
368
- colorSpace: options.colorSpace,
369
- premultipliedAlpha: options.premultipliedAlpha
431
+ buffer: gpuReadBuffer,
432
+ offset: 0,
433
+ bytesPerRow,
434
+ rowsPerImage
370
435
  },
371
- // copySize: GPUExtent3D
372
- [options.width, options.height, 1]
436
+ // copy size
437
+ {
438
+ width,
439
+ height,
440
+ depthOrArrayLayers
441
+ }
373
442
  );
443
+ const commandBuffer = commandEncoder.finish();
444
+ this.device.handle.queue.submit([commandBuffer]);
374
445
  this.device.popErrorScope((error) => {
375
- this.device.reportError(new Error(`copyExternalImage: ${error.message}`), this)();
446
+ this.device.reportError(new Error(`${this} readBuffer: ${error.message}`), this)();
447
+ this.device.debug();
448
+ });
449
+ return readBuffer;
450
+ }
451
+ async readDataAsync(options = {}) {
452
+ const buffer = this.readBuffer(options);
453
+ const data = await buffer.readAsync();
454
+ buffer.destroy();
455
+ return data.buffer;
456
+ }
457
+ writeBuffer(buffer, options = {}) {
458
+ const { x = 0, y = 0, z = 0, width = this.width, height = this.height, depthOrArrayLayers = this.depth, mipLevel = 0, aspect = "all" } = options;
459
+ const layout = this.computeMemoryLayout(options);
460
+ const { bytesPerRow, rowsPerImage } = layout;
461
+ const gpuDevice = this.device.handle;
462
+ this.device.pushErrorScope("validation");
463
+ const commandEncoder = gpuDevice.createCommandEncoder();
464
+ commandEncoder.copyBufferToTexture({
465
+ buffer: buffer.handle,
466
+ offset: 0,
467
+ bytesPerRow,
468
+ rowsPerImage
469
+ }, {
470
+ texture: this.handle,
471
+ origin: { x, y, z },
472
+ mipLevel,
473
+ aspect
474
+ }, { width, height, depthOrArrayLayers });
475
+ const commandBuffer = commandEncoder.finish();
476
+ this.device.handle.queue.submit([commandBuffer]);
477
+ this.device.popErrorScope((error) => {
478
+ this.device.reportError(new Error(`${this} writeBuffer: ${error.message}`), this)();
376
479
  this.device.debug();
377
480
  });
378
- return { width: options.width, height: options.height };
379
481
  }
380
- generateMipmapsWebGL() {
381
- import_core4.log.warn(`${this}: generateMipmaps not supported in WebGPU`)();
482
+ writeData(data, options = {}) {
483
+ const device = this.device;
484
+ const { x = 0, y = 0, z = 0, width = this.width, height = this.height, depthOrArrayLayers = this.depth, mipLevel = 0, aspect = "all" } = options;
485
+ const layout = import_core4.textureFormatDecoder.computeMemoryLayout({
486
+ format: this.format,
487
+ width: this.width,
488
+ height: this.height,
489
+ depth: this.depth,
490
+ byteAlignment: this.byteAlignment
491
+ });
492
+ const { bytesPerRow, rowsPerImage } = layout;
493
+ this.device.pushErrorScope("validation");
494
+ device.handle.queue.writeTexture({
495
+ texture: this.handle,
496
+ mipLevel,
497
+ aspect,
498
+ origin: { x, y, z }
499
+ }, data, {
500
+ offset: 0,
501
+ bytesPerRow,
502
+ rowsPerImage
503
+ }, { width, height, depthOrArrayLayers });
504
+ this.device.popErrorScope((error) => {
505
+ this.device.reportError(new Error(`${this} writeData: ${error.message}`), this)();
506
+ this.device.debug();
507
+ });
382
508
  }
383
509
  };
384
510
  }
@@ -716,7 +842,7 @@ function getBindGroupEntries(bindings, shaderLayout) {
716
842
  for (const [bindingName, value] of Object.entries(bindings)) {
717
843
  let bindingLayout = getShaderLayoutBinding(shaderLayout, bindingName);
718
844
  if (bindingLayout) {
719
- const entry = getBindGroupEntry(value, bindingLayout.location);
845
+ const entry = getBindGroupEntry(value, bindingLayout.location, void 0, bindingName);
720
846
  if (entry) {
721
847
  entries.push(entry);
722
848
  }
@@ -726,7 +852,7 @@ function getBindGroupEntries(bindings, shaderLayout) {
726
852
  ignoreWarnings: true
727
853
  });
728
854
  if (bindingLayout) {
729
- const entry = getBindGroupEntry(value, bindingLayout.location, { sampler: true });
855
+ const entry = getBindGroupEntry(value, bindingLayout.location, { sampler: true }, bindingName);
730
856
  if (entry) {
731
857
  entries.push(entry);
732
858
  }
@@ -735,7 +861,7 @@ function getBindGroupEntries(bindings, shaderLayout) {
735
861
  }
736
862
  return entries;
737
863
  }
738
- function getBindGroupEntry(binding, index, options) {
864
+ function getBindGroupEntry(binding, index, options, bindingName = "unknown") {
739
865
  if (binding instanceof import_core8.Buffer) {
740
866
  return {
741
867
  binding: index,
@@ -750,6 +876,12 @@ function getBindGroupEntry(binding, index, options) {
750
876
  resource: binding.handle
751
877
  };
752
878
  }
879
+ if (binding instanceof import_core8.TextureView) {
880
+ return {
881
+ binding: index,
882
+ resource: binding.handle
883
+ };
884
+ }
753
885
  if (binding instanceof import_core8.Texture) {
754
886
  if (options == null ? void 0 : options.sampler) {
755
887
  return {
@@ -762,7 +894,7 @@ function getBindGroupEntry(binding, index, options) {
762
894
  resource: binding.view.handle
763
895
  };
764
896
  }
765
- import_core8.log.warn(`invalid binding ${name}`, binding);
897
+ import_core8.log.warn(`invalid binding ${bindingName}`, binding);
766
898
  return null;
767
899
  }
768
900
  var import_core8;
@@ -844,17 +976,17 @@ function getVertexBufferLayout(shaderLayout, bufferLayout) {
844
976
  });
845
977
  return vertexBufferLayouts;
846
978
  }
847
- function findAttributeLayout(shaderLayout, name2, attributeNames) {
848
- const attribute = shaderLayout.attributes.find((attribute_) => attribute_.name === name2);
979
+ function findAttributeLayout(shaderLayout, name, attributeNames) {
980
+ const attribute = shaderLayout.attributes.find((attribute_) => attribute_.name === name);
849
981
  if (!attribute) {
850
- import_core9.log.warn(`Supplied attribute not present in shader layout: ${name2}`)();
982
+ import_core9.log.warn(`Supplied attribute not present in shader layout: ${name}`)();
851
983
  return null;
852
984
  }
853
985
  if (attributeNames) {
854
- if (attributeNames.has(name2)) {
855
- throw new Error(`Found multiple entries for attribute: ${name2}`);
986
+ if (attributeNames.has(name)) {
987
+ throw new Error(`Found multiple entries for attribute: ${name}`);
856
988
  }
857
- attributeNames.add(name2);
989
+ attributeNames.add(name);
858
990
  }
859
991
  return attribute;
860
992
  }
@@ -918,8 +1050,8 @@ var init_webgpu_render_pipeline = __esm({
918
1050
  * @todo Do we want to expose BindGroups in the API and remove this?
919
1051
  */
920
1052
  setBindings(bindings) {
921
- for (const [name2, binding] of Object.entries(bindings)) {
922
- if (this._bindings[name2] !== binding) {
1053
+ for (const [name, binding] of Object.entries(bindings)) {
1054
+ if (this._bindings[name] !== binding) {
923
1055
  this._bindGroup = null;
924
1056
  }
925
1057
  }
@@ -1164,18 +1296,34 @@ var init_webgpu_canvas_context = __esm({
1164
1296
  this.device = device;
1165
1297
  this.handle = context;
1166
1298
  this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
1167
- this._updateDevice();
1299
+ this._configureDevice();
1168
1300
  }
1169
1301
  /** Destroy any textures produced while configured and remove the context configuration. */
1170
1302
  destroy() {
1171
1303
  this.handle.unconfigure();
1172
1304
  super.destroy();
1173
1305
  }
1306
+ // IMPLEMENTATION OF ABSTRACT METHODS
1307
+ /** @see https://www.w3.org/TR/webgpu/#canvas-configuration */
1308
+ _configureDevice() {
1309
+ if (this.depthStencilAttachment) {
1310
+ this.depthStencilAttachment.destroy();
1311
+ this.depthStencilAttachment = null;
1312
+ }
1313
+ this.handle.configure({
1314
+ device: this.device.handle,
1315
+ format: this.device.preferredColorFormat,
1316
+ // Can be used to define e.g. -srgb views
1317
+ // viewFormats: [...]
1318
+ colorSpace: this.props.colorSpace,
1319
+ alphaMode: this.props.alphaMode
1320
+ });
1321
+ }
1174
1322
  /** Update framebuffer with properly resized "swap chain" texture views */
1175
- getCurrentFramebuffer(options = {
1323
+ _getCurrentFramebuffer(options = {
1176
1324
  depthStencilFormat: "depth24plus"
1177
1325
  }) {
1178
- const currentColorAttachment = this.getCurrentTexture();
1326
+ const currentColorAttachment = this._getCurrentTexture();
1179
1327
  if (currentColorAttachment.width !== this.drawingBufferWidth || currentColorAttachment.height !== this.drawingBufferHeight) {
1180
1328
  const [oldWidth, oldHeight] = this.getDrawingBufferSize();
1181
1329
  this.drawingBufferWidth = currentColorAttachment.width;
@@ -1190,23 +1338,9 @@ var init_webgpu_canvas_context = __esm({
1190
1338
  depthStencilAttachment: this.depthStencilAttachment
1191
1339
  });
1192
1340
  }
1193
- // IMPLEMENTATION OF ABSTRACT METHODS
1194
- _updateDevice() {
1195
- if (this.depthStencilAttachment) {
1196
- this.depthStencilAttachment.destroy();
1197
- this.depthStencilAttachment = null;
1198
- }
1199
- this.handle.configure({
1200
- device: this.device.handle,
1201
- format: this.device.preferredColorFormat,
1202
- // Can be used to define e.g. -srgb views
1203
- // viewFormats: [...]
1204
- colorSpace: this.props.colorSpace,
1205
- alphaMode: this.props.alphaMode
1206
- });
1207
- }
1341
+ // PRIMARY METHODS
1208
1342
  /** Wrap the current canvas context texture in a luma.gl texture */
1209
- getCurrentTexture() {
1343
+ _getCurrentTexture() {
1210
1344
  const handle = this.handle.getCurrentTexture();
1211
1345
  return this.device.createTexture({
1212
1346
  id: `${this.id}#color-texture`,
@@ -1653,8 +1787,7 @@ var init_webgpu_pipeline_layout = __esm({
1653
1787
  }
1654
1788
  mapShaderLayoutToBindGroupEntries() {
1655
1789
  const bindGroupEntries = [];
1656
- for (let i = 0; i < this.props.shaderLayout.bindings.length; i++) {
1657
- const binding = this.props.shaderLayout.bindings[i];
1790
+ for (const binding of this.props.shaderLayout.bindings) {
1658
1791
  const bindingTypeInfo = {};
1659
1792
  switch (binding.type) {
1660
1793
  case "uniform": {
@@ -1725,16 +1858,154 @@ var init_webgpu_pipeline_layout = __esm({
1725
1858
  }
1726
1859
  });
1727
1860
 
1861
+ // dist/adapter/resources/webgpu-fence.js
1862
+ var import_core21, WebGPUFence;
1863
+ var init_webgpu_fence = __esm({
1864
+ "dist/adapter/resources/webgpu-fence.js"() {
1865
+ "use strict";
1866
+ import_core21 = require("@luma.gl/core");
1867
+ WebGPUFence = class extends import_core21.Fence {
1868
+ device;
1869
+ handle = null;
1870
+ signaled;
1871
+ _signaled = false;
1872
+ constructor(device, props = {}) {
1873
+ super(device, {});
1874
+ this.device = device;
1875
+ this.signaled = device.handle.queue.onSubmittedWorkDone().then(() => {
1876
+ this._signaled = true;
1877
+ });
1878
+ }
1879
+ isSignaled() {
1880
+ return this._signaled;
1881
+ }
1882
+ destroy() {
1883
+ }
1884
+ };
1885
+ }
1886
+ });
1887
+
1888
+ // dist/wgsl/get-shader-layout-wgsl.js
1889
+ function getShaderLayoutFromWGSL(source) {
1890
+ var _a;
1891
+ const shaderLayout = { attributes: [], bindings: [] };
1892
+ let parsedWGSL;
1893
+ try {
1894
+ parsedWGSL = parseWGSL(source);
1895
+ } catch (error) {
1896
+ import_core22.log.error(error.message)();
1897
+ return shaderLayout;
1898
+ }
1899
+ for (const uniform of parsedWGSL.uniforms) {
1900
+ const members = [];
1901
+ for (const attribute of ((_a = uniform.type) == null ? void 0 : _a.members) || []) {
1902
+ members.push({
1903
+ name: attribute.name,
1904
+ type: getType(attribute.type)
1905
+ });
1906
+ }
1907
+ shaderLayout.bindings.push({
1908
+ type: "uniform",
1909
+ name: uniform.name,
1910
+ group: uniform.group,
1911
+ location: uniform.binding,
1912
+ // @ts-expect-error TODO - unused for now but needs fixing
1913
+ members
1914
+ });
1915
+ }
1916
+ for (const texture of parsedWGSL.textures) {
1917
+ const bindingDeclaration = {
1918
+ type: "texture",
1919
+ name: texture.name,
1920
+ group: texture.group,
1921
+ location: texture.binding,
1922
+ ...getTextureBindingFromReflect(texture)
1923
+ };
1924
+ shaderLayout.bindings.push(bindingDeclaration);
1925
+ }
1926
+ for (const sampler of parsedWGSL.samplers) {
1927
+ shaderLayout.bindings.push({
1928
+ type: "sampler",
1929
+ name: sampler.name,
1930
+ group: sampler.group,
1931
+ location: sampler.binding
1932
+ });
1933
+ }
1934
+ const vertex = parsedWGSL.entry.vertex[0];
1935
+ const attributeCount = (vertex == null ? void 0 : vertex.inputs.length) || 0;
1936
+ for (let i = 0; i < attributeCount; i++) {
1937
+ const wgslAttribute = vertex.inputs[i];
1938
+ if (wgslAttribute.locationType === "location") {
1939
+ const type = getType(wgslAttribute.type);
1940
+ shaderLayout.attributes.push({
1941
+ name: wgslAttribute.name,
1942
+ location: Number(wgslAttribute.location),
1943
+ type
1944
+ });
1945
+ }
1946
+ }
1947
+ return shaderLayout;
1948
+ }
1949
+ function getType(type) {
1950
+ return (type == null ? void 0 : type.format) ? `${type.name}<${type.format.name}>` : type.name;
1951
+ }
1952
+ function parseWGSL(source) {
1953
+ try {
1954
+ return new import_wgsl_reflect.WgslReflect(source);
1955
+ } catch (error) {
1956
+ if (error instanceof Error) {
1957
+ throw error;
1958
+ }
1959
+ let message = "WGSL parse error";
1960
+ if (typeof error === "object" && (error == null ? void 0 : error.message)) {
1961
+ message += `: ${error.message} `;
1962
+ }
1963
+ if (typeof error === "object" && (error == null ? void 0 : error.token)) {
1964
+ message += error.token.line || "";
1965
+ }
1966
+ throw new Error(message, { cause: error });
1967
+ }
1968
+ }
1969
+ function getTextureBindingFromReflect(v, opts) {
1970
+ var _a;
1971
+ if (v.resourceType !== import_wgsl_reflect.ResourceType.Texture) {
1972
+ throw new Error("Not a texture binding");
1973
+ }
1974
+ const typeName = v.type.name;
1975
+ const component = (_a = v.type.format) == null ? void 0 : _a.name;
1976
+ const viewDimension = typeName.includes("cube_array") ? "cube-array" : typeName.includes("cube") ? "cube" : typeName.includes("2d_array") ? "2d-array" : typeName.includes("3d") ? "3d" : typeName.includes("1d") ? "1d" : "2d";
1977
+ const multisampled = typeName === "texture_multisampled_2d";
1978
+ let sampleType;
1979
+ if (typeName.startsWith("texture_depth")) {
1980
+ sampleType = "depth";
1981
+ } else if (component === "i32") {
1982
+ sampleType = "sint";
1983
+ } else if (component === "u32") {
1984
+ sampleType = "uint";
1985
+ } else {
1986
+ sampleType = "float";
1987
+ }
1988
+ return { viewDimension, sampleType, multisampled };
1989
+ }
1990
+ var import_core22, import_wgsl_reflect;
1991
+ var init_get_shader_layout_wgsl = __esm({
1992
+ "dist/wgsl/get-shader-layout-wgsl.js"() {
1993
+ "use strict";
1994
+ import_core22 = require("@luma.gl/core");
1995
+ import_wgsl_reflect = require("wgsl_reflect");
1996
+ }
1997
+ });
1998
+
1728
1999
  // dist/adapter/webgpu-device.js
1729
2000
  var webgpu_device_exports = {};
1730
2001
  __export(webgpu_device_exports, {
1731
2002
  WebGPUDevice: () => WebGPUDevice
1732
2003
  });
1733
- var import_core21, WebGPUDevice;
2004
+ var import_core23, WebGPUDevice;
1734
2005
  var init_webgpu_device = __esm({
1735
2006
  "dist/adapter/webgpu-device.js"() {
1736
2007
  "use strict";
1737
- import_core21 = require("@luma.gl/core");
2008
+ import_core23 = require("@luma.gl/core");
1738
2009
  init_webgpu_buffer();
1739
2010
  init_webgpu_texture();
1740
2011
  init_webgpu_external_texture();
@@ -1748,7 +2019,9 @@ var init_webgpu_device = __esm({
1748
2019
  init_webgpu_command_encoder();
1749
2020
  init_webgpu_query_set();
1750
2021
  init_webgpu_pipeline_layout();
1751
- WebGPUDevice = class extends import_core21.Device {
2022
+ init_webgpu_fence();
2023
+ init_get_shader_layout_wgsl();
2024
+ WebGPUDevice = class extends import_core23.Device {
1752
2025
  /** The underlying WebGPU device */
1753
2026
  handle;
1754
2027
  /* The underlying WebGPU adapter */
@@ -1791,7 +2064,7 @@ var init_webgpu_device = __esm({
1791
2064
  this._isLost = true;
1792
2065
  resolve({ reason: "destroyed", message: lostInfo.message });
1793
2066
  });
1794
- const canvasContextProps = import_core21.Device._getCanvasContextProps(props);
2067
+ const canvasContextProps = import_core23.Device._getCanvasContextProps(props);
1795
2068
  if (canvasContextProps) {
1796
2069
  this.canvasContext = new WebGPUCanvasContext(this, this.adapter, canvasContextProps);
1797
2070
  }
@@ -1807,13 +2080,13 @@ var init_webgpu_device = __esm({
1807
2080
  get isLost() {
1808
2081
  return this._isLost;
1809
2082
  }
2083
+ getShaderLayout(source) {
2084
+ return getShaderLayoutFromWGSL(source);
2085
+ }
1810
2086
  isVertexFormatSupported(format) {
1811
2087
  const info = this.getVertexFormatInfo(format);
1812
2088
  return !info.webglOnly;
1813
2089
  }
1814
- getTextureByteAlignment() {
1815
- return 1;
1816
- }
1817
2090
  createBuffer(props) {
1818
2091
  const newProps = this._normalizeBufferProps(props);
1819
2092
  return new WebGPUBuffer(this, newProps);
@@ -1852,6 +2125,9 @@ var init_webgpu_device = __esm({
1852
2125
  createQuerySet(props) {
1853
2126
  return new WebGPUQuerySet(this, props);
1854
2127
  }
2128
+ createFence() {
2129
+ return new WebGPUFence(this);
2130
+ }
1855
2131
  createCanvasContext(props) {
1856
2132
  return new WebGPUCanvasContext(this, this.adapter, props);
1857
2133
  }
@@ -1914,6 +2190,12 @@ var init_webgpu_device = __esm({
1914
2190
  if (features.has("texture-compression-bc")) {
1915
2191
  features.add("texture-compression-bc5-webgl");
1916
2192
  }
2193
+ if (this.handle.features.has("chromium-experimental-norm16-texture-formats")) {
2194
+ features.add("norm16-renderable-webgl");
2195
+ }
2196
+ if (this.handle.features.has("chromium-experimental-snorm16-texture-formats")) {
2197
+ features.add("snorm16-renderable-webgl");
2198
+ }
1917
2199
  const WEBGPU_ALWAYS_FEATURES = [
1918
2200
  "timer-query-webgl",
1919
2201
  "compilation-status-async-webgl",
@@ -1926,7 +2208,7 @@ var init_webgpu_device = __esm({
1926
2208
  for (const feature of WEBGPU_ALWAYS_FEATURES) {
1927
2209
  features.add(feature);
1928
2210
  }
1929
- return new import_core21.DeviceFeatures(Array.from(features), this.props._disabledFeatures);
2211
+ return new import_core23.DeviceFeatures(Array.from(features), this.props._disabledFeatures);
1930
2212
  }
1931
2213
  _getDeviceSpecificTextureFormatCapabilities(capabilities) {
1932
2214
  const { format } = capabilities;
@@ -1944,16 +2226,18 @@ var dist_exports = {};
1944
2226
  __export(dist_exports, {
1945
2227
  WebGPUBuffer: () => WebGPUBuffer,
1946
2228
  WebGPUDevice: () => WebGPUDevice,
2229
+ WebGPUFence: () => WebGPUFence,
1947
2230
  WebGPUSampler: () => WebGPUSampler,
1948
2231
  WebGPUShader: () => WebGPUShader,
1949
2232
  WebGPUTexture: () => WebGPUTexture,
2233
+ getShaderLayoutFromWGSL: () => getShaderLayoutFromWGSL,
1950
2234
  webgpuAdapter: () => webgpuAdapter
1951
2235
  });
1952
2236
  module.exports = __toCommonJS(dist_exports);
1953
2237
 
1954
2238
  // dist/adapter/webgpu-adapter.js
1955
- var import_core22 = require("@luma.gl/core");
1956
- var WebGPUAdapter = class extends import_core22.Adapter {
2239
+ var import_core24 = require("@luma.gl/core");
2240
+ var WebGPUAdapter = class extends import_core24.Adapter {
1957
2241
  /** type of device's created by this adapter */
1958
2242
  type = "webgpu";
1959
2243
  isSupported() {
@@ -1973,43 +2257,41 @@ var WebGPUAdapter = class extends import_core22.Adapter {
1973
2257
  if (!navigator.gpu) {
1974
2258
  throw new Error("WebGPU not available. Recent Chrome browsers should work.");
1975
2259
  }
1976
- import_core22.log.groupCollapsed(1, "WebGPUDevice created")();
1977
- try {
1978
- const adapter = await navigator.gpu.requestAdapter({
1979
- powerPreference: "high-performance"
1980
- // forceSoftware: false
1981
- });
1982
- if (!adapter) {
1983
- throw new Error("Failed to request WebGPU adapter");
1984
- }
1985
- const adapterInfo = adapter.info || // @ts-ignore
1986
- await ((_a = adapter.requestAdapterInfo) == null ? void 0 : _a.call(adapter));
1987
- import_core22.log.probe(2, "Adapter available", adapterInfo)();
1988
- const requiredFeatures = [];
1989
- const requiredLimits = {};
1990
- if (props._requestMaxLimits) {
1991
- requiredFeatures.push(...Array.from(adapter.features));
1992
- const limits = Object.keys(adapter.limits).filter((key) => !["minSubgroupSize", "maxSubgroupSize"].includes(key));
1993
- for (const key of limits) {
1994
- const limit = key;
1995
- const value = adapter.limits[limit];
1996
- if (typeof value === "number") {
1997
- requiredLimits[limit] = value;
1998
- }
2260
+ const adapter = await navigator.gpu.requestAdapter({
2261
+ powerPreference: "high-performance"
2262
+ // forceSoftware: false
2263
+ });
2264
+ if (!adapter) {
2265
+ throw new Error("Failed to request WebGPU adapter");
2266
+ }
2267
+ const adapterInfo = adapter.info || // @ts-ignore
2268
+ await ((_a = adapter.requestAdapterInfo) == null ? void 0 : _a.call(adapter));
2269
+ const requiredFeatures = [];
2270
+ const requiredLimits = {};
2271
+ if (props._requestMaxLimits) {
2272
+ requiredFeatures.push(...Array.from(adapter.features));
2273
+ const limits = Object.keys(adapter.limits).filter((key) => !["minSubgroupSize", "maxSubgroupSize"].includes(key));
2274
+ for (const key of limits) {
2275
+ const limit = key;
2276
+ const value = adapter.limits[limit];
2277
+ if (typeof value === "number") {
2278
+ requiredLimits[limit] = value;
1999
2279
  }
2000
2280
  }
2001
- const gpuDevice = await adapter.requestDevice({
2002
- requiredFeatures,
2003
- requiredLimits
2004
- });
2005
- import_core22.log.probe(1, "GPUDevice available")();
2006
- const { WebGPUDevice: WebGPUDevice2 } = await Promise.resolve().then(() => (init_webgpu_device(), webgpu_device_exports));
2281
+ }
2282
+ const gpuDevice = await adapter.requestDevice({
2283
+ requiredFeatures,
2284
+ requiredLimits
2285
+ });
2286
+ const { WebGPUDevice: WebGPUDevice2 } = await Promise.resolve().then(() => (init_webgpu_device(), webgpu_device_exports));
2287
+ import_core24.log.groupCollapsed(1, "WebGPUDevice created")();
2288
+ try {
2007
2289
  const device = new WebGPUDevice2(props, gpuDevice, adapter, adapterInfo);
2008
- import_core22.log.probe(1, "Device created. For more info, set chrome://flags/#enable-webgpu-developer-features")();
2009
- import_core22.log.table(1, device.info)();
2290
+ import_core24.log.probe(1, "Device created. For more info, set chrome://flags/#enable-webgpu-developer-features")();
2291
+ import_core24.log.table(1, device.info)();
2010
2292
  return device;
2011
2293
  } finally {
2012
- import_core22.log.groupEnd(1)();
2294
+ import_core24.log.groupEnd(1)();
2013
2295
  }
2014
2296
  }
2015
2297
  async attach(handle) {
@@ -2024,4 +2306,6 @@ init_webgpu_buffer();
2024
2306
  init_webgpu_texture();
2025
2307
  init_webgpu_sampler();
2026
2308
  init_webgpu_shader();
2309
+ init_webgpu_fence();
2310
+ init_get_shader_layout_wgsl();
2027
2311
  //# sourceMappingURL=index.cjs.map