@luma.gl/webgpu 9.1.0-alpha.2 → 9.1.0-beta.1

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 (108) hide show
  1. package/dist/adapter/helpers/accessor-to-format.js +1 -0
  2. package/dist/adapter/helpers/accessor-to-format.js.map +1 -0
  3. package/dist/adapter/helpers/convert-texture-format.d.ts +0 -1
  4. package/dist/adapter/helpers/convert-texture-format.d.ts.map +1 -1
  5. package/dist/adapter/helpers/convert-texture-format.js +1 -0
  6. package/dist/adapter/helpers/convert-texture-format.js.map +1 -0
  7. package/dist/adapter/helpers/get-bind-group.d.ts +3 -2
  8. package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
  9. package/dist/adapter/helpers/get-bind-group.js +18 -4
  10. package/dist/adapter/helpers/get-bind-group.js.map +1 -0
  11. package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts +0 -1
  12. package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts.map +1 -1
  13. package/dist/adapter/helpers/get-vertex-buffer-layout.js +4 -3
  14. package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -0
  15. package/dist/adapter/helpers/webgpu-parameters.d.ts +0 -1
  16. package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
  17. package/dist/adapter/helpers/webgpu-parameters.js +1 -0
  18. package/dist/adapter/helpers/webgpu-parameters.js.map +1 -0
  19. package/dist/adapter/resources/webgpu-buffer.d.ts +0 -1
  20. package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
  21. package/dist/adapter/resources/webgpu-buffer.js +1 -0
  22. package/dist/adapter/resources/webgpu-buffer.js.map +1 -0
  23. package/dist/adapter/resources/webgpu-command-encoder.d.ts +4 -5
  24. package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgpu-command-encoder.js +22 -4
  26. package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -0
  27. package/dist/adapter/resources/webgpu-compute-pass.d.ts +0 -1
  28. package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
  29. package/dist/adapter/resources/webgpu-compute-pass.js +1 -0
  30. package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -0
  31. package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +0 -1
  32. package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
  33. package/dist/adapter/resources/webgpu-compute-pipeline.js +1 -0
  34. package/dist/adapter/resources/webgpu-compute-pipeline.js.map +1 -0
  35. package/dist/adapter/resources/webgpu-external-texture.d.ts +0 -1
  36. package/dist/adapter/resources/webgpu-external-texture.d.ts.map +1 -1
  37. package/dist/adapter/resources/webgpu-external-texture.js +1 -0
  38. package/dist/adapter/resources/webgpu-external-texture.js.map +1 -0
  39. package/dist/adapter/resources/webgpu-framebuffer.d.ts +1 -0
  40. package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
  41. package/dist/adapter/resources/webgpu-framebuffer.js +4 -0
  42. package/dist/adapter/resources/webgpu-framebuffer.js.map +1 -0
  43. package/dist/adapter/resources/webgpu-query-set.d.ts +0 -1
  44. package/dist/adapter/resources/webgpu-query-set.d.ts.map +1 -1
  45. package/dist/adapter/resources/webgpu-query-set.js +1 -0
  46. package/dist/adapter/resources/webgpu-query-set.js.map +1 -0
  47. package/dist/adapter/resources/webgpu-render-pass.d.ts +0 -1
  48. package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
  49. package/dist/adapter/resources/webgpu-render-pass.js +19 -6
  50. package/dist/adapter/resources/webgpu-render-pass.js.map +1 -0
  51. package/dist/adapter/resources/webgpu-render-pipeline.d.ts +1 -1
  52. package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
  53. package/dist/adapter/resources/webgpu-render-pipeline.js +42 -6
  54. package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -0
  55. package/dist/adapter/resources/webgpu-sampler.d.ts +1 -2
  56. package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -1
  57. package/dist/adapter/resources/webgpu-sampler.js +15 -6
  58. package/dist/adapter/resources/webgpu-sampler.js.map +1 -0
  59. package/dist/adapter/resources/webgpu-shader.d.ts +2 -3
  60. package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
  61. package/dist/adapter/resources/webgpu-shader.js +23 -19
  62. package/dist/adapter/resources/webgpu-shader.js.map +1 -0
  63. package/dist/adapter/resources/webgpu-texture-view.d.ts +0 -1
  64. package/dist/adapter/resources/webgpu-texture-view.d.ts.map +1 -1
  65. package/dist/adapter/resources/webgpu-texture-view.js +1 -0
  66. package/dist/adapter/resources/webgpu-texture-view.js.map +1 -0
  67. package/dist/adapter/resources/webgpu-texture.d.ts +3 -7
  68. package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
  69. package/dist/adapter/resources/webgpu-texture.js +26 -23
  70. package/dist/adapter/resources/webgpu-texture.js.map +1 -0
  71. package/dist/adapter/resources/webgpu-vertex-array.d.ts.map +1 -1
  72. package/dist/adapter/resources/webgpu-vertex-array.js +3 -2
  73. package/dist/adapter/resources/webgpu-vertex-array.js.map +1 -0
  74. package/dist/adapter/webgpu-adapter.d.ts +13 -0
  75. package/dist/adapter/webgpu-adapter.d.ts.map +1 -0
  76. package/dist/adapter/webgpu-adapter.js +65 -0
  77. package/dist/adapter/webgpu-adapter.js.map +1 -0
  78. package/dist/adapter/webgpu-canvas-context.d.ts +8 -10
  79. package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
  80. package/dist/adapter/webgpu-canvas-context.js +56 -60
  81. package/dist/adapter/webgpu-canvas-context.js.map +1 -0
  82. package/dist/adapter/webgpu-device.d.ts +11 -18
  83. package/dist/adapter/webgpu-device.d.ts.map +1 -1
  84. package/dist/adapter/webgpu-device.js +43 -88
  85. package/dist/adapter/webgpu-device.js.map +1 -0
  86. package/dist/dist.dev.js +317 -236
  87. package/dist/dist.min.js +5 -1
  88. package/dist/index.cjs +290 -201
  89. package/dist/index.cjs.map +4 -4
  90. package/dist/index.d.ts +2 -0
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +3 -2
  93. package/dist/index.js.map +1 -0
  94. package/package.json +3 -3
  95. package/src/adapter/helpers/get-bind-group.ts +23 -4
  96. package/src/adapter/helpers/get-vertex-buffer-layout.ts +3 -3
  97. package/src/adapter/resources/webgpu-command-encoder.ts +26 -8
  98. package/src/adapter/resources/webgpu-framebuffer.ts +4 -0
  99. package/src/adapter/resources/webgpu-render-pass.ts +29 -14
  100. package/src/adapter/resources/webgpu-render-pipeline.ts +45 -6
  101. package/src/adapter/resources/webgpu-sampler.ts +16 -6
  102. package/src/adapter/resources/webgpu-shader.ts +23 -23
  103. package/src/adapter/resources/webgpu-texture.ts +43 -57
  104. package/src/adapter/resources/webgpu-vertex-array.ts +7 -2
  105. package/src/adapter/webgpu-adapter.ts +88 -0
  106. package/src/adapter/webgpu-canvas-context.ts +67 -69
  107. package/src/adapter/webgpu-device.ts +54 -116
  108. package/src/index.ts +3 -1
package/dist/index.cjs CHANGED
@@ -2,7 +2,6 @@ var __defProp = Object.defineProperty;
2
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
4
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
5
  var __export = (target, all) => {
7
6
  for (var name in all)
8
7
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -16,10 +15,6 @@ var __copyProps = (to, from, except, desc) => {
16
15
  return to;
17
16
  };
18
17
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var __publicField = (obj, key, value) => {
20
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
21
- return value;
22
- };
23
18
 
24
19
  // dist/index.js
25
20
  var dist_exports = {};
@@ -28,10 +23,14 @@ __export(dist_exports, {
28
23
  WebGPUDevice: () => WebGPUDevice,
29
24
  WebGPUSampler: () => WebGPUSampler,
30
25
  WebGPUShader: () => WebGPUShader,
31
- WebGPUTexture: () => WebGPUTexture
26
+ WebGPUTexture: () => WebGPUTexture,
27
+ webgpuAdapter: () => webgpuAdapter
32
28
  });
33
29
  module.exports = __toCommonJS(dist_exports);
34
30
 
31
+ // dist/adapter/webgpu-adapter.js
32
+ var import_core18 = require("@luma.gl/core");
33
+
35
34
  // dist/adapter/webgpu-device.js
36
35
  var import_core17 = require("@luma.gl/core");
37
36
 
@@ -123,11 +122,17 @@ var WebGPUSampler = class extends import_core2.Sampler {
123
122
  constructor(device, props) {
124
123
  super(device, props);
125
124
  this.device = device;
126
- const samplerProps = { ...this.props };
127
- if (samplerProps.type !== "comparison-sampler") {
128
- delete samplerProps.compare;
125
+ const samplerDescriptor = {
126
+ ...this.props,
127
+ mipmapFilter: void 0
128
+ };
129
+ if (props.type !== "comparison-sampler") {
130
+ delete samplerDescriptor.compare;
129
131
  }
130
- this.handle = this.handle || this.device.handle.createSampler(samplerProps);
132
+ if (props.mipmapFilter && props.mipmapFilter !== "none") {
133
+ samplerDescriptor.mipmapFilter = props.mipmapFilter;
134
+ }
135
+ this.handle = this.handle || this.device.handle.createSampler(samplerDescriptor);
131
136
  this.handle.label = this.props.id;
132
137
  }
133
138
  destroy() {
@@ -176,27 +181,16 @@ var BASE_DIMENSIONS = {
176
181
  var WebGPUTexture = class extends import_core4.Texture {
177
182
  device;
178
183
  handle;
179
- height = 1;
180
- width = 1;
181
184
  sampler;
182
185
  view;
183
- // static async createFromImageURL(src, usage = 0) {
184
- // const img = document.createElement('img');
185
- // img.src = src;
186
- // await img.decode();
187
- // return WebGPUTexture(img, usage);
188
- // }
189
186
  constructor(device, props) {
190
187
  super(device, props);
191
188
  this.device = device;
192
- if (props.data instanceof Promise) {
193
- props.data.then((resolvedImageData) => {
194
- this.props = { ...this.props, data: resolvedImageData };
195
- this.initialize(this.props);
196
- });
197
- return;
189
+ const propsWithData = { ...this.props };
190
+ if (props.data) {
191
+ propsWithData.data = props.data;
198
192
  }
199
- this.initialize(props);
193
+ this.initialize(propsWithData);
200
194
  }
201
195
  destroy() {
202
196
  var _a;
@@ -210,7 +204,11 @@ var WebGPUTexture = class extends import_core4.Texture {
210
204
  this.handle = this.props.handle || this.createHandle();
211
205
  this.handle.label ||= this.id;
212
206
  if (this.props.data) {
213
- this.setData({ data: this.props.data });
207
+ if (import_core4.Texture.isExternalImage(this.props.data)) {
208
+ this.copyExternalImage({ image: this.props.data });
209
+ } else {
210
+ this.setData({ data: this.props.data });
211
+ }
214
212
  }
215
213
  this.width = this.handle.width;
216
214
  this.height = this.handle.height;
@@ -266,16 +264,23 @@ var WebGPUTexture = class extends import_core4.Texture {
266
264
  throw new Error("not implemented");
267
265
  }
268
266
  setData(options) {
269
- return this.setImage({ source: options.data });
267
+ if (ArrayBuffer.isView(options.data)) {
268
+ const clampedArray = new Uint8ClampedArray(options.data.buffer);
269
+ const image = new ImageData(clampedArray, this.width, this.height);
270
+ return this.copyExternalImage({ image });
271
+ }
272
+ throw new Error("Texture.setData: Use CommandEncoder to upload data to texture in WebGPU");
270
273
  }
271
- /** Set image */
272
- setImage(options) {
273
- const { source, width = options.source.width, height = options.source.height, depth = 1, sourceX = 0, sourceY = 0, mipLevel = 0, x = 0, y = 0, z = 0, aspect = "all", colorSpace = "srgb", premultipliedAlpha = false } = options;
274
+ copyExternalImage(options) {
275
+ const size = import_core4.Texture.getExternalImageSize(options.image);
276
+ const opts = { ...import_core4.Texture.defaultCopyExternalImageOptions, ...size, ...options };
277
+ const { image, sourceX, sourceY, width, height, depth, mipLevel, x, y, z, aspect, colorSpace, premultipliedAlpha, flipY } = opts;
274
278
  this.device.handle.queue.copyExternalImageToTexture(
275
279
  // source: GPUImageCopyExternalImage
276
280
  {
277
- source,
278
- origin: [sourceX, sourceY]
281
+ source: image,
282
+ origin: [sourceX, sourceY],
283
+ flipY
279
284
  },
280
285
  // destination: GPUImageCopyTextureTagged
281
286
  {
@@ -326,18 +331,31 @@ var WebGPUShader = class extends import_core6.Shader {
326
331
  constructor(device, props) {
327
332
  super(device, props);
328
333
  this.device = device;
334
+ const isGLSL = props.source.includes("#version");
335
+ if (this.props.language === "glsl" || isGLSL) {
336
+ throw new Error("GLSL shaders are not supported in WebGPU");
337
+ }
329
338
  this.device.handle.pushErrorScope("validation");
330
- this.handle = this.props.handle || this.createHandle();
339
+ this.handle = this.props.handle || this.device.handle.createShaderModule({ code: props.source });
340
+ this.device.handle.popErrorScope().then((error) => {
341
+ if (error) {
342
+ import_core6.log.error(`${this} creation failed:
343
+ "${error.message}"`, this, this.props.source)();
344
+ }
345
+ });
331
346
  this.handle.label = this.props.id;
332
- this._checkCompilationError(this.device.handle.popErrorScope());
333
- }
334
- async _checkCompilationError(errorScope) {
335
- const error = await errorScope;
336
- if (error) {
337
- this.debugShader();
338
- const shaderLog = await this.getCompilationInfo();
339
- import_core6.log.error(`Shader compilation error: ${error.message}`, shaderLog)();
340
- throw new Error(`Shader compilation error: ${error.message}`);
347
+ this._checkCompilationError();
348
+ }
349
+ get asyncCompilationStatus() {
350
+ return this.getCompilationInfo().then(() => this.compilationStatus);
351
+ }
352
+ async _checkCompilationError() {
353
+ const shaderLog = await this.getCompilationInfo();
354
+ const hasErrors = Boolean(shaderLog.find((msg) => msg.type === "error"));
355
+ this.compilationStatus = hasErrors ? "error" : "success";
356
+ this.debugShader();
357
+ if (this.compilationStatus === "error") {
358
+ import_core6.log.error(`Shader compilation error`, shaderLog)();
341
359
  }
342
360
  }
343
361
  destroy() {
@@ -348,15 +366,6 @@ var WebGPUShader = class extends import_core6.Shader {
348
366
  const compilationInfo = await this.handle.getCompilationInfo();
349
367
  return compilationInfo.messages;
350
368
  }
351
- // PRIVATE METHODS
352
- createHandle() {
353
- const { source } = this.props;
354
- const isGLSL = source.includes("#version");
355
- if (this.props.language === "glsl" || isGLSL) {
356
- throw new Error("GLSL shaders are not supported in WebGPU");
357
- }
358
- return this.device.handle.createShaderModule({ code: source });
359
- }
360
369
  };
361
370
 
362
371
  // dist/adapter/resources/webgpu-render-pipeline.js
@@ -568,9 +577,9 @@ function getBindGroup(device, bindGroupLayout, shaderLayout, bindings) {
568
577
  entries
569
578
  });
570
579
  }
571
- function getShaderLayoutBinding(shaderLayout, bindingName) {
580
+ function getShaderLayoutBinding(shaderLayout, bindingName, options) {
572
581
  const bindingLayout = shaderLayout.bindings.find((binding) => binding.name === bindingName || `${binding.name}uniforms` === bindingName.toLocaleLowerCase());
573
- if (!bindingLayout) {
582
+ if (!bindingLayout && !(options == null ? void 0 : options.ignoreWarnings)) {
574
583
  import_core7.log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
575
584
  }
576
585
  return bindingLayout || null;
@@ -578,14 +587,20 @@ function getShaderLayoutBinding(shaderLayout, bindingName) {
578
587
  function getBindGroupEntries(bindings, shaderLayout) {
579
588
  const entries = [];
580
589
  for (const [bindingName, value] of Object.entries(bindings)) {
581
- const bindingLayout = getShaderLayoutBinding(shaderLayout, bindingName);
590
+ let bindingLayout = getShaderLayoutBinding(shaderLayout, bindingName);
582
591
  if (bindingLayout) {
583
592
  entries.push(getBindGroupEntry(value, bindingLayout.location));
584
593
  }
594
+ bindingLayout = getShaderLayoutBinding(shaderLayout, `${bindingName}Sampler`, {
595
+ ignoreWarnings: true
596
+ });
597
+ if (bindingLayout) {
598
+ entries.push(getBindGroupEntry(value, bindingLayout.location, { sampler: true }));
599
+ }
585
600
  }
586
601
  return entries;
587
602
  }
588
- function getBindGroupEntry(binding, index) {
603
+ function getBindGroupEntry(binding, index, options) {
589
604
  if (binding instanceof import_core7.Buffer) {
590
605
  return {
591
606
  binding: index,
@@ -600,6 +615,12 @@ function getBindGroupEntry(binding, index) {
600
615
  resource: binding.handle
601
616
  };
602
617
  } else if (binding instanceof import_core7.Texture) {
618
+ if (options == null ? void 0 : options.sampler) {
619
+ return {
620
+ binding: index,
621
+ resource: binding.sampler.handle
622
+ };
623
+ }
603
624
  return {
604
625
  binding: index,
605
626
  resource: binding.handle.createView({ label: "bind-group-auto-created" })
@@ -675,13 +696,13 @@ function getVertexBufferLayout(shaderLayout, bufferLayout) {
675
696
  return vertexBufferLayouts;
676
697
  }
677
698
  function findAttributeLayout(shaderLayout, name, attributeNames) {
678
- const attribute = shaderLayout.attributes.find((attribute2) => attribute2.name === name);
699
+ const attribute = shaderLayout.attributes.find((attribute_) => attribute_.name === name);
679
700
  if (!attribute) {
680
- import_core8.log.warn(`Unknown attribute ${name}`)();
701
+ import_core8.log.warn(`Supplied attribute not present in shader layout: ${name}`)();
681
702
  return null;
682
703
  }
683
704
  if (attributeNames.has(name)) {
684
- throw new Error(`Duplicate attribute ${name}`);
705
+ throw new Error(`Found multiple entries for attribute: ${name}`);
685
706
  }
686
707
  attributeNames.add(name);
687
708
  return attribute;
@@ -697,6 +718,9 @@ var WebGPURenderPipeline = class extends import_core9.RenderPipeline {
697
718
  _bindings;
698
719
  _bindGroupLayout = null;
699
720
  _bindGroup = null;
721
+ get [Symbol.toStringTag]() {
722
+ return "WebGPURenderPipeline";
723
+ }
700
724
  constructor(device, props) {
701
725
  super(device, props);
702
726
  this.device = device;
@@ -706,7 +730,15 @@ var WebGPURenderPipeline = class extends import_core9.RenderPipeline {
706
730
  import_core9.log.groupCollapsed(1, `new WebGPURenderPipeline(${this.id})`)();
707
731
  import_core9.log.probe(1, JSON.stringify(descriptor, null, 2))();
708
732
  import_core9.log.groupEnd(1)();
733
+ this.device.handle.pushErrorScope("validation");
709
734
  this.handle = this.device.handle.createRenderPipeline(descriptor);
735
+ this.device.handle.popErrorScope().then((error) => {
736
+ var _a;
737
+ if (error) {
738
+ import_core9.log.error(`${this} creation failed:
739
+ "${error.message}"`, this, (_a = this.props.vs) == null ? void 0 : _a.source)();
740
+ }
741
+ });
710
742
  }
711
743
  this.handle.label = this.props.id;
712
744
  this.vs = props.vs;
@@ -721,12 +753,24 @@ var WebGPURenderPipeline = class extends import_core9.RenderPipeline {
721
753
  * @todo Do we want to expose BindGroups in the API and remove this?
722
754
  */
723
755
  setBindings(bindings) {
756
+ for (const [name, binding] of Object.entries(bindings)) {
757
+ if (this._bindings[name] !== binding) {
758
+ this._bindGroup = null;
759
+ }
760
+ }
724
761
  Object.assign(this._bindings, bindings);
725
762
  }
726
763
  /** @todo - should this be moved to renderpass? */
727
764
  draw(options) {
728
765
  const webgpuRenderPass = options.renderPass;
766
+ this.device.handle.pushErrorScope("validation");
729
767
  webgpuRenderPass.handle.setPipeline(this.handle);
768
+ this.device.handle.popErrorScope().then((error) => {
769
+ if (error) {
770
+ import_core9.log.error(`${this} setPipeline failed:
771
+ "${error.message}"`, this)();
772
+ }
773
+ });
730
774
  const bindGroup = this._getBindGroup();
731
775
  if (bindGroup) {
732
776
  webgpuRenderPass.handle.setBindGroup(0, bindGroup);
@@ -763,15 +807,18 @@ var WebGPURenderPipeline = class extends import_core9.RenderPipeline {
763
807
  entryPoint: this.props.vertexEntryPoint || "main",
764
808
  buffers: getVertexBufferLayout(this.shaderLayout, this.props.bufferLayout)
765
809
  };
810
+ const targets = [];
811
+ if (this.props.colorAttachmentFormats) {
812
+ for (const format of this.props.colorAttachmentFormats) {
813
+ targets.push(format ? { format: getWebGPUTextureFormat(format) } : null);
814
+ }
815
+ } else {
816
+ targets.push({ format: getWebGPUTextureFormat(this.device.preferredColorFormat) });
817
+ }
766
818
  const fragment = {
767
819
  module: this.props.fs.handle,
768
820
  entryPoint: this.props.fragmentEntryPoint || "main",
769
- targets: [
770
- {
771
- // TODO exclamation mark hack!
772
- format: getWebGPUTextureFormat(this.device.getCanvasContext().format)
773
- }
774
- ]
821
+ targets
775
822
  };
776
823
  const descriptor = {
777
824
  vertex,
@@ -781,6 +828,12 @@ var WebGPURenderPipeline = class extends import_core9.RenderPipeline {
781
828
  },
782
829
  layout: "auto"
783
830
  };
831
+ const depthFormat = this.props.depthStencilAttachmentFormat || this.device.preferredDepthFormat;
832
+ if (this.props.parameters.depthWriteEnabled) {
833
+ descriptor.depthStencil = {
834
+ format: getWebGPUTextureFormat(depthFormat)
835
+ };
836
+ }
784
837
  applyParametersToRenderPipelineDescriptor(descriptor, this.props.parameters);
785
838
  return descriptor;
786
839
  }
@@ -797,6 +850,8 @@ var WebGPUFramebuffer = class extends import_core10.Framebuffer {
797
850
  this.device = device;
798
851
  this.autoCreateAttachmentTextures();
799
852
  }
853
+ updateAttachments() {
854
+ }
800
855
  };
801
856
 
802
857
  // dist/adapter/resources/webgpu-compute-pipeline.js
@@ -855,9 +910,9 @@ var WebGPURenderPass = class extends import_core12.RenderPass {
855
910
  renderPassDescriptor.occlusionQuerySet = webgpuQuerySet.handle;
856
911
  }
857
912
  if (device.features.has("timestamp-query")) {
858
- const webgpuQuerySet2 = props.timestampQuerySet;
859
- renderPassDescriptor.timestampWrites = webgpuQuerySet2 ? {
860
- querySet: webgpuQuerySet2.handle,
913
+ const webgpuTSQuerySet = props.timestampQuerySet;
914
+ renderPassDescriptor.timestampWrites = webgpuTSQuerySet ? {
915
+ querySet: webgpuTSQuerySet.handle,
861
916
  beginningOfPassWriteIndex: props.beginTimestampIndex,
862
917
  endOfPassWriteIndex: props.endTimestampIndex
863
918
  } : void 0;
@@ -865,7 +920,14 @@ var WebGPURenderPass = class extends import_core12.RenderPass {
865
920
  if (!device.commandEncoder) {
866
921
  throw new Error("commandEncoder not available");
867
922
  }
923
+ this.device.handle.pushErrorScope("validation");
868
924
  this.handle = this.props.handle || device.commandEncoder.beginRenderPass(renderPassDescriptor);
925
+ this.device.handle.popErrorScope().then((error) => {
926
+ if (error) {
927
+ import_core12.log.error(`${this} creation failed:
928
+ "${error.message}"`, this)();
929
+ }
930
+ });
869
931
  this.handle.label = this.props.id;
870
932
  import_core12.log.groupCollapsed(3, `new WebGPURenderPass(${this.id})`)();
871
933
  import_core12.log.probe(3, JSON.stringify(renderPassDescriptor, null, 2))();
@@ -944,14 +1006,17 @@ var WebGPURenderPass = class extends import_core12.RenderPass {
944
1006
  const renderPassDescriptor = {
945
1007
  colorAttachments: []
946
1008
  };
947
- renderPassDescriptor.colorAttachments = framebuffer.colorAttachments.map((colorAttachment) => ({
948
- // clear values
949
- loadOp: this.props.clearColor !== false ? "clear" : "load",
950
- colorClearValue: this.props.clearColor || [0, 0, 0, 0],
951
- storeOp: this.props.discard ? "discard" : "store",
952
- // ...colorAttachment,
953
- view: colorAttachment.handle
954
- }));
1009
+ renderPassDescriptor.colorAttachments = framebuffer.colorAttachments.map((colorAttachment, index) => {
1010
+ var _a;
1011
+ return {
1012
+ // clear values
1013
+ loadOp: this.props.clearColor !== false ? "clear" : "load",
1014
+ colorClearValue: ((_a = this.props.clearColors) == null ? void 0 : _a[index]) || this.props.clearColor || import_core12.RenderPass.defaultClearColor,
1015
+ storeOp: this.props.discard ? "discard" : "store",
1016
+ // ...colorAttachment,
1017
+ view: colorAttachment.handle
1018
+ };
1019
+ });
955
1020
  if (framebuffer.depthStencilAttachment) {
956
1021
  renderPassDescriptor.depthStencilAttachment = {
957
1022
  view: framebuffer.depthStencilAttachment.handle
@@ -960,7 +1025,9 @@ var WebGPURenderPass = class extends import_core12.RenderPass {
960
1025
  if (this.props.depthReadOnly) {
961
1026
  depthStencilAttachment.depthReadOnly = true;
962
1027
  }
963
- depthStencilAttachment.depthClearValue = this.props.clearDepth || 0;
1028
+ if (this.props.clearDepth !== false) {
1029
+ depthStencilAttachment.depthClearValue = this.props.clearDepth;
1030
+ }
964
1031
  const hasDepthAspect = true;
965
1032
  if (hasDepthAspect) {
966
1033
  depthStencilAttachment.depthLoadOp = this.props.clearDepth !== false ? "clear" : "load";
@@ -1085,7 +1152,7 @@ var WebGPUVertexArray = class extends import_core14.VertexArray {
1085
1152
  const webgpuRenderPass = renderPass;
1086
1153
  const webgpuIndexBuffer = this.indexBuffer;
1087
1154
  if (webgpuIndexBuffer == null ? void 0 : webgpuIndexBuffer.handle) {
1088
- import_core14.log.warn("setting index buffer", webgpuIndexBuffer == null ? void 0 : webgpuIndexBuffer.handle, webgpuIndexBuffer == null ? void 0 : webgpuIndexBuffer.indexType)();
1155
+ import_core14.log.info(3, "setting index buffer", webgpuIndexBuffer == null ? void 0 : webgpuIndexBuffer.handle, webgpuIndexBuffer == null ? void 0 : webgpuIndexBuffer.indexType)();
1089
1156
  webgpuRenderPass.handle.setIndexBuffer(
1090
1157
  webgpuIndexBuffer == null ? void 0 : webgpuIndexBuffer.handle,
1091
1158
  // @ts-expect-error TODO - we must enforce type
@@ -1095,7 +1162,7 @@ var WebGPUVertexArray = class extends import_core14.VertexArray {
1095
1162
  for (let location = 0; location < this.maxVertexAttributes; location++) {
1096
1163
  const webgpuBuffer = this.attributes[location];
1097
1164
  if (webgpuBuffer == null ? void 0 : webgpuBuffer.handle) {
1098
- import_core14.log.warn(`setting vertex buffer ${location}`, webgpuBuffer == null ? void 0 : webgpuBuffer.handle)();
1165
+ import_core14.log.info(3, `setting vertex buffer ${location}`, webgpuBuffer == null ? void 0 : webgpuBuffer.handle)();
1099
1166
  webgpuRenderPass.handle.setVertexBuffer(location, webgpuBuffer == null ? void 0 : webgpuBuffer.handle);
1100
1167
  }
1101
1168
  }
@@ -1116,79 +1183,84 @@ var WebGPUVertexArray = class extends import_core14.VertexArray {
1116
1183
  var import_core15 = require("@luma.gl/core");
1117
1184
  var WebGPUCanvasContext = class extends import_core15.CanvasContext {
1118
1185
  device;
1119
- gpuCanvasContext;
1120
- /** Format of returned textures: "bgra8unorm", "rgba8unorm", "rgba16float". */
1121
- format = navigator.gpu.getPreferredCanvasFormat();
1122
- /** Default stencil format for depth textures */
1123
- depthStencilFormat = "depth24plus";
1186
+ handle;
1124
1187
  depthStencilAttachment = null;
1188
+ get [Symbol.toStringTag]() {
1189
+ return "WebGPUCanvasContext";
1190
+ }
1125
1191
  constructor(device, adapter, props) {
1126
1192
  super(props);
1127
1193
  this.device = device;
1128
- this.width = -1;
1129
- this.height = -1;
1130
1194
  this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
1131
- this.gpuCanvasContext = this.canvas.getContext("webgpu");
1132
- this.format = "bgra8unorm";
1195
+ this.updateSize([this.drawingBufferWidth, this.drawingBufferHeight]);
1133
1196
  }
1134
1197
  /** Destroy any textures produced while configured and remove the context configuration. */
1135
1198
  destroy() {
1136
- this.gpuCanvasContext.unconfigure();
1199
+ this.handle.unconfigure();
1137
1200
  }
1138
1201
  /** Update framebuffer with properly resized "swap chain" texture views */
1139
- getCurrentFramebuffer() {
1140
- this.update();
1202
+ getCurrentFramebuffer(options = {
1203
+ depthStencilFormat: "depth24plus"
1204
+ }) {
1141
1205
  const currentColorAttachment = this.getCurrentTexture();
1142
- this.width = currentColorAttachment.width;
1143
- this.height = currentColorAttachment.height;
1144
- this._createDepthStencilAttachment();
1206
+ if (currentColorAttachment.width !== this.drawingBufferWidth || currentColorAttachment.height !== this.drawingBufferHeight) {
1207
+ const [oldWidth, oldHeight] = this.getDrawingBufferSize();
1208
+ this.drawingBufferWidth = currentColorAttachment.width;
1209
+ this.drawingBufferHeight = currentColorAttachment.height;
1210
+ import_core15.log.log(1, `${this}: Resized to compensate for initial canvas size mismatch ${oldWidth}x${oldHeight} => ${this.drawingBufferWidth}x${this.drawingBufferHeight}px`)();
1211
+ }
1212
+ if (options == null ? void 0 : options.depthStencilFormat) {
1213
+ this._createDepthStencilAttachment(options == null ? void 0 : options.depthStencilFormat);
1214
+ }
1145
1215
  return new WebGPUFramebuffer(this.device, {
1146
1216
  colorAttachments: [currentColorAttachment],
1147
1217
  depthStencilAttachment: this.depthStencilAttachment
1148
1218
  });
1149
1219
  }
1150
1220
  /** Resizes and updates render targets if necessary */
1151
- update() {
1152
- const [width, height] = this.getPixelSize();
1153
- const sizeChanged = width !== this.width || height !== this.height;
1154
- if (sizeChanged) {
1155
- this.width = width;
1156
- this.height = height;
1157
- if (this.depthStencilAttachment) {
1158
- this.depthStencilAttachment.destroy();
1159
- this.depthStencilAttachment = null;
1160
- }
1161
- this.gpuCanvasContext.configure({
1162
- device: this.device.handle,
1163
- format: getWebGPUTextureFormat(this.format),
1164
- // Can be used to define e.g. -srgb views
1165
- // viewFormats: [...]
1166
- colorSpace: this.props.colorSpace,
1167
- alphaMode: this.props.alphaMode
1168
- });
1169
- import_core15.log.log(1, `Resized to ${this.width}x${this.height}px`)();
1221
+ updateSize(size) {
1222
+ if (this.depthStencilAttachment) {
1223
+ this.depthStencilAttachment.destroy();
1224
+ this.depthStencilAttachment = null;
1170
1225
  }
1226
+ this.handle.configure({
1227
+ device: this.device.handle,
1228
+ format: this.device.preferredColorFormat,
1229
+ // Can be used to define e.g. -srgb views
1230
+ // viewFormats: [...]
1231
+ colorSpace: this.props.colorSpace,
1232
+ alphaMode: this.props.alphaMode
1233
+ });
1171
1234
  }
1172
1235
  resize(options) {
1173
- this.update();
1236
+ if (!this.device.handle)
1237
+ return;
1238
+ if (this.props.autoResize) {
1239
+ return;
1240
+ }
1241
+ if (this.canvas) {
1242
+ const devicePixelRatio = this.getDevicePixelRatio(options == null ? void 0 : options.useDevicePixels);
1243
+ this._setDevicePixelRatio(devicePixelRatio, options);
1244
+ return;
1245
+ }
1174
1246
  }
1175
1247
  /** Wrap the current canvas context texture in a luma.gl texture */
1176
1248
  getCurrentTexture() {
1177
- return this.device._createTexture({
1249
+ return this.device.createTexture({
1178
1250
  id: `${this.id}#color-texture`,
1179
- handle: this.gpuCanvasContext.getCurrentTexture(),
1180
- format: this.format
1251
+ handle: this.handle.getCurrentTexture(),
1252
+ format: this.device.preferredColorFormat
1181
1253
  });
1182
1254
  }
1183
1255
  /** We build render targets on demand (i.e. not when size changes but when about to render) */
1184
- _createDepthStencilAttachment() {
1256
+ _createDepthStencilAttachment(depthStencilFormat) {
1185
1257
  if (!this.depthStencilAttachment) {
1186
1258
  this.depthStencilAttachment = this.device.createTexture({
1187
1259
  id: `${this.id}#depth-stencil-texture`,
1188
- format: this.depthStencilFormat,
1189
- width: this.width,
1190
- height: this.height,
1191
- usage: GPUTextureUsage.RENDER_ATTACHMENT
1260
+ usage: import_core15.Texture.RENDER_ATTACHMENT,
1261
+ format: depthStencilFormat,
1262
+ width: this.drawingBufferWidth,
1263
+ height: this.drawingBufferHeight
1192
1264
  });
1193
1265
  }
1194
1266
  return this.depthStencilAttachment;
@@ -1217,70 +1289,27 @@ var WebGPUQuerySet = class extends import_core16.QuerySet {
1217
1289
  };
1218
1290
 
1219
1291
  // dist/adapter/webgpu-device.js
1220
- var _WebGPUDevice = class extends import_core17.Device {
1221
- /** type of this device */
1222
- type = "webgpu";
1292
+ var WebGPUDevice = class extends import_core17.Device {
1223
1293
  /** The underlying WebGPU device */
1224
1294
  handle;
1225
- /* The underlying WebGPU adapter */
1226
- adapter;
1227
- /* The underlying WebGPU adapter's info */
1228
- adapterInfo;
1295
+ /** type of this device */
1296
+ type = "webgpu";
1297
+ preferredColorFormat = navigator.gpu.getPreferredCanvasFormat();
1298
+ preferredDepthFormat = "depth24plus";
1229
1299
  features;
1230
1300
  info;
1231
1301
  limits;
1232
1302
  lost;
1233
- canvasContext = null;
1303
+ renderPass = null;
1304
+ canvasContext;
1234
1305
  _isLost = false;
1306
+ // canvasContext: WebGPUCanvasContext | null = null;
1235
1307
  commandEncoder = null;
1236
- renderPass = null;
1237
- /** Check if WebGPU is available */
1238
- static isSupported() {
1239
- return Boolean(typeof navigator !== "undefined" && navigator.gpu);
1240
- }
1241
- static async create(props) {
1242
- if (!navigator.gpu) {
1243
- throw new Error("WebGPU not available. Open in Chrome Canary and turn on chrome://flags/#enable-unsafe-webgpu");
1244
- }
1245
- import_core17.log.groupCollapsed(1, "WebGPUDevice created")();
1246
- const adapter = await navigator.gpu.requestAdapter({
1247
- powerPreference: "high-performance"
1248
- // forceSoftware: false
1249
- });
1250
- if (!adapter) {
1251
- throw new Error("Failed to request WebGPU adapter");
1252
- }
1253
- const adapterInfo = await adapter.requestAdapterInfo();
1254
- import_core17.log.probe(2, "Adapter available", adapterInfo)();
1255
- const requiredFeatures = [];
1256
- const requiredLimits = {};
1257
- if (props.requestMaxLimits) {
1258
- requiredFeatures.push(...Array.from(adapter.features));
1259
- const limits = Object.keys(adapter.limits).filter((key) => !["minSubgroupSize", "maxSubgroupSize"].includes(key));
1260
- for (const key of limits) {
1261
- const limit = key;
1262
- const value = adapter.limits[limit];
1263
- if (typeof value === "number") {
1264
- requiredLimits[limit] = value;
1265
- }
1266
- }
1267
- }
1268
- const gpuDevice = await adapter.requestDevice({
1269
- requiredFeatures,
1270
- requiredLimits
1271
- });
1272
- import_core17.log.probe(1, "GPUDevice available")();
1273
- if (typeof props.canvas === "string") {
1274
- await import_core17.CanvasContext.pageLoaded;
1275
- import_core17.log.probe(1, "DOM is loaded")();
1276
- }
1277
- const device = new _WebGPUDevice(gpuDevice, adapter, adapterInfo, props);
1278
- import_core17.log.probe(1, "Device created. For more info, set chrome://flags/#enable-webgpu-developer-features")();
1279
- import_core17.log.table(1, device.info)();
1280
- import_core17.log.groupEnd(1)();
1281
- return device;
1282
- }
1283
- constructor(device, adapter, adapterInfo, props) {
1308
+ /* The underlying WebGPU adapter */
1309
+ adapter;
1310
+ /* The underlying WebGPU adapter's info */
1311
+ adapterInfo;
1312
+ constructor(props, device, adapter, adapterInfo) {
1284
1313
  super({ ...props, id: props.id || "webgpu-device" });
1285
1314
  this.handle = device;
1286
1315
  this.adapter = adapter;
@@ -1289,20 +1318,22 @@ var _WebGPUDevice = class extends import_core17.Device {
1289
1318
  this.features = this._getFeatures();
1290
1319
  this.limits = this.handle.limits;
1291
1320
  device.addEventListener("uncapturederror", (event) => {
1292
- const errorMessage = event instanceof GPUUncapturedErrorEvent ? event.error.message : "Unknown error";
1293
- this.error(new Error(errorMessage));
1321
+ const errorMessage = event instanceof GPUUncapturedErrorEvent ? event.error.message : "Unknown WebGPU error";
1322
+ this.reportError(new Error(errorMessage));
1323
+ if (this.props.debug) {
1324
+ debugger;
1325
+ }
1326
+ event.preventDefault();
1294
1327
  });
1295
1328
  this.lost = new Promise(async (resolve) => {
1296
1329
  const lostInfo = await this.handle.lost;
1297
1330
  this._isLost = true;
1298
1331
  resolve({ reason: "destroyed", message: lostInfo.message });
1299
1332
  });
1300
- this.canvasContext = new WebGPUCanvasContext(this, this.adapter, {
1301
- canvas: props.canvas,
1302
- height: props.height,
1303
- width: props.width,
1304
- container: props.container
1305
- });
1333
+ if (props.createCanvasContext) {
1334
+ const canvasContextProps = props.createCanvasContext === true ? {} : props.createCanvasContext;
1335
+ this.canvasContext = new WebGPUCanvasContext(this, this.adapter, canvasContextProps);
1336
+ }
1306
1337
  }
1307
1338
  // TODO
1308
1339
  // Load the glslang module now so that it is available synchronously when compiling shaders
@@ -1311,25 +1342,14 @@ var _WebGPUDevice = class extends import_core17.Device {
1311
1342
  destroy() {
1312
1343
  this.handle.destroy();
1313
1344
  }
1314
- isTextureFormatSupported(format) {
1315
- return !format.includes("webgl");
1316
- }
1317
- /** @todo implement proper check? */
1318
- isTextureFormatFilterable(format) {
1319
- return this.isTextureFormatSupported(format) && !format.startsWith("depth") && !format.startsWith("stencil");
1320
- }
1321
- /** @todo implement proper check? */
1322
- isTextureFormatRenderable(format) {
1323
- return this.isTextureFormatSupported(format);
1324
- }
1325
1345
  get isLost() {
1326
1346
  return this._isLost;
1327
1347
  }
1328
1348
  createBuffer(props) {
1329
- const newProps = this._getBufferProps(props);
1349
+ const newProps = this._normalizeBufferProps(props);
1330
1350
  return new WebGPUBuffer(this, newProps);
1331
1351
  }
1332
- _createTexture(props) {
1352
+ createTexture(props) {
1333
1353
  return new WebGPUTexture(this, props);
1334
1354
  }
1335
1355
  createExternalTexture(props) {
@@ -1382,7 +1402,13 @@ var _WebGPUDevice = class extends import_core17.Device {
1382
1402
  var _a;
1383
1403
  const commandBuffer = (_a = this.commandEncoder) == null ? void 0 : _a.finish();
1384
1404
  if (commandBuffer) {
1405
+ this.handle.pushErrorScope("validation");
1385
1406
  this.handle.queue.submit([commandBuffer]);
1407
+ this.handle.popErrorScope().then((error) => {
1408
+ if (error) {
1409
+ this.reportError(new Error(`WebGPU command submission failed: ${error.message}`));
1410
+ }
1411
+ });
1386
1412
  }
1387
1413
  this.commandEncoder = null;
1388
1414
  }
@@ -1430,8 +1456,17 @@ var _WebGPUDevice = class extends import_core17.Device {
1430
1456
  for (const feature of WEBGPU_ALWAYS_FEATURES) {
1431
1457
  features.add(feature);
1432
1458
  }
1433
- return new import_core17.DeviceFeatures(Array.from(features), this.props.disabledFeatures);
1459
+ return new import_core17.DeviceFeatures(Array.from(features), this.props._disabledFeatures);
1434
1460
  }
1461
+ _getDeviceSpecificTextureFormatCapabilities(capabilities) {
1462
+ const { format } = capabilities;
1463
+ if (format.includes("webgl")) {
1464
+ return { format, create: false, render: false, filter: false, blend: false, store: false };
1465
+ }
1466
+ return capabilities;
1467
+ }
1468
+ // DEPRECATED METHODS
1469
+ // @deprecated
1435
1470
  copyExternalImageToTexture(options) {
1436
1471
  var _a;
1437
1472
  const {
@@ -1472,6 +1507,60 @@ var _WebGPUDevice = class extends import_core17.Device {
1472
1507
  );
1473
1508
  }
1474
1509
  };
1475
- var WebGPUDevice = _WebGPUDevice;
1476
- __publicField(WebGPUDevice, "type", "webgpu");
1510
+
1511
+ // dist/adapter/webgpu-adapter.js
1512
+ var WebGPUAdapter = class extends import_core18.Adapter {
1513
+ /** type of device's created by this adapter */
1514
+ type = "webgpu";
1515
+ constructor() {
1516
+ super();
1517
+ WebGPUDevice.adapter = this;
1518
+ }
1519
+ /** Check if WebGPU is available */
1520
+ isSupported() {
1521
+ return Boolean(typeof navigator !== "undefined" && navigator.gpu);
1522
+ }
1523
+ async create(props) {
1524
+ if (!navigator.gpu) {
1525
+ throw new Error("WebGPU not available. Open in Chrome Canary and turn on chrome://flags/#enable-unsafe-webgpu");
1526
+ }
1527
+ import_core18.log.groupCollapsed(1, "WebGPUDevice created")();
1528
+ const adapter = await navigator.gpu.requestAdapter({
1529
+ powerPreference: "high-performance"
1530
+ // forceSoftware: false
1531
+ });
1532
+ if (!adapter) {
1533
+ throw new Error("Failed to request WebGPU adapter");
1534
+ }
1535
+ const adapterInfo = await adapter.requestAdapterInfo();
1536
+ import_core18.log.probe(2, "Adapter available", adapterInfo)();
1537
+ const requiredFeatures = [];
1538
+ const requiredLimits = {};
1539
+ if (props._requestMaxLimits) {
1540
+ requiredFeatures.push(...Array.from(adapter.features));
1541
+ const limits = Object.keys(adapter.limits).filter((key) => !["minSubgroupSize", "maxSubgroupSize"].includes(key));
1542
+ for (const key of limits) {
1543
+ const limit = key;
1544
+ const value = adapter.limits[limit];
1545
+ if (typeof value === "number") {
1546
+ requiredLimits[limit] = value;
1547
+ }
1548
+ }
1549
+ }
1550
+ const gpuDevice = await adapter.requestDevice({
1551
+ requiredFeatures,
1552
+ requiredLimits
1553
+ });
1554
+ import_core18.log.probe(1, "GPUDevice available")();
1555
+ const device = new WebGPUDevice(props, gpuDevice, adapter, adapterInfo);
1556
+ import_core18.log.probe(1, "Device created. For more info, set chrome://flags/#enable-webgpu-developer-features")();
1557
+ import_core18.log.table(1, device.info)();
1558
+ import_core18.log.groupEnd(1)();
1559
+ return device;
1560
+ }
1561
+ async attach(handle) {
1562
+ throw new Error("WebGPUAdapter.attach() not implemented");
1563
+ }
1564
+ };
1565
+ var webgpuAdapter = new WebGPUAdapter();
1477
1566
  //# sourceMappingURL=index.cjs.map