@luma.gl/webgpu 9.1.0-beta.8 → 9.2.0-alpha.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 (71) hide show
  1. package/dist/adapter/helpers/accessor-to-format.js +1 -0
  2. package/dist/adapter/helpers/accessor-to-format.js.map +1 -1
  3. package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
  4. package/dist/adapter/helpers/get-bind-group.js +26 -10
  5. package/dist/adapter/helpers/get-bind-group.js.map +1 -1
  6. package/dist/adapter/helpers/get-vertex-buffer-layout.js +4 -4
  7. package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
  8. package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
  9. package/dist/adapter/helpers/webgpu-parameters.js +66 -68
  10. package/dist/adapter/helpers/webgpu-parameters.js.map +1 -1
  11. package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
  12. package/dist/adapter/resources/webgpu-buffer.js +12 -0
  13. package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
  14. package/dist/adapter/resources/webgpu-command-buffer.d.ts +10 -0
  15. package/dist/adapter/resources/webgpu-command-buffer.d.ts.map +1 -0
  16. package/dist/adapter/resources/webgpu-command-buffer.js +18 -0
  17. package/dist/adapter/resources/webgpu-command-buffer.js.map +1 -0
  18. package/dist/adapter/resources/webgpu-command-encoder.d.ts +12 -5
  19. package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
  20. package/dist/adapter/resources/webgpu-command-encoder.js +21 -5
  21. package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -1
  22. package/dist/adapter/resources/webgpu-compute-pass.js +1 -1
  23. package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -1
  24. package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
  25. package/dist/adapter/resources/webgpu-render-pass.js +2 -1
  26. package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
  27. package/dist/adapter/resources/webgpu-sampler.js +1 -1
  28. package/dist/adapter/resources/webgpu-sampler.js.map +1 -1
  29. package/dist/adapter/resources/webgpu-texture-view.d.ts.map +1 -1
  30. package/dist/adapter/resources/webgpu-texture-view.js +16 -10
  31. package/dist/adapter/resources/webgpu-texture-view.js.map +1 -1
  32. package/dist/adapter/resources/webgpu-texture.d.ts +4 -37
  33. package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
  34. package/dist/adapter/resources/webgpu-texture.js +98 -124
  35. package/dist/adapter/resources/webgpu-texture.js.map +1 -1
  36. package/dist/adapter/resources/webgpu-vertex-array.d.ts +2 -2
  37. package/dist/adapter/resources/webgpu-vertex-array.d.ts.map +1 -1
  38. package/dist/adapter/resources/webgpu-vertex-array.js +2 -2
  39. package/dist/adapter/resources/webgpu-vertex-array.js.map +1 -1
  40. package/dist/adapter/webgpu-adapter.d.ts +2 -3
  41. package/dist/adapter/webgpu-adapter.d.ts.map +1 -1
  42. package/dist/adapter/webgpu-adapter.js +19 -10
  43. package/dist/adapter/webgpu-adapter.js.map +1 -1
  44. package/dist/adapter/webgpu-canvas-context.d.ts +1 -7
  45. package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
  46. package/dist/adapter/webgpu-canvas-context.js +13 -18
  47. package/dist/adapter/webgpu-canvas-context.js.map +1 -1
  48. package/dist/adapter/webgpu-device.d.ts +8 -25
  49. package/dist/adapter/webgpu-device.d.ts.map +1 -1
  50. package/dist/adapter/webgpu-device.js +31 -61
  51. package/dist/adapter/webgpu-device.js.map +1 -1
  52. package/dist/dist.dev.js +1657 -1389
  53. package/dist/dist.min.js +4 -4
  54. package/dist/index.cjs +1510 -1270
  55. package/dist/index.cjs.map +4 -4
  56. package/package.json +3 -3
  57. package/src/adapter/helpers/get-bind-group.ts +28 -11
  58. package/src/adapter/helpers/get-vertex-buffer-layout.ts +4 -4
  59. package/src/adapter/helpers/webgpu-parameters.ts +88 -97
  60. package/src/adapter/resources/webgpu-buffer.ts +12 -0
  61. package/src/adapter/resources/webgpu-command-buffer.ts +24 -0
  62. package/src/adapter/resources/webgpu-command-encoder.ts +27 -4
  63. package/src/adapter/resources/webgpu-compute-pass.ts +1 -1
  64. package/src/adapter/resources/webgpu-render-pass.ts +2 -1
  65. package/src/adapter/resources/webgpu-sampler.ts +1 -1
  66. package/src/adapter/resources/webgpu-texture-view.ts +15 -8
  67. package/src/adapter/resources/webgpu-texture.ts +106 -184
  68. package/src/adapter/resources/webgpu-vertex-array.ts +2 -2
  69. package/src/adapter/webgpu-adapter.ts +27 -14
  70. package/src/adapter/webgpu-canvas-context.ts +16 -20
  71. package/src/adapter/webgpu-device.ts +38 -99
package/dist/dist.dev.js CHANGED
@@ -4,6 +4,7 @@
4
4
  else if (typeof define === 'function' && define.amd) define([], factory);
5
5
  else if (typeof exports === 'object') exports['luma'] = factory();
6
6
  else root['luma'] = factory();})(globalThis, function () {
7
+ "use strict";
7
8
  var __exports__ = (() => {
8
9
  var __create = Object.create;
9
10
  var __defProp = Object.defineProperty;
@@ -11,12 +12,15 @@ var __exports__ = (() => {
11
12
  var __getOwnPropNames = Object.getOwnPropertyNames;
12
13
  var __getProtoOf = Object.getPrototypeOf;
13
14
  var __hasOwnProp = Object.prototype.hasOwnProperty;
15
+ var __esm = (fn, res) => function __init() {
16
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
17
+ };
14
18
  var __commonJS = (cb, mod) => function __require() {
15
19
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
16
20
  };
17
21
  var __export = (target, all) => {
18
- for (var name in all)
19
- __defProp(target, name, { get: all[name], enumerable: true });
22
+ for (var name2 in all)
23
+ __defProp(target, name2, { get: all[name2], enumerable: true });
20
24
  };
21
25
  var __copyProps = (to, from, except, desc) => {
22
26
  if (from && typeof from === "object" || typeof from === "function") {
@@ -44,99 +48,96 @@ var __exports__ = (() => {
44
48
  }
45
49
  });
46
50
 
47
- // bundle.ts
48
- var bundle_exports = {};
49
- __export(bundle_exports, {
50
- WebGPUBuffer: () => WebGPUBuffer,
51
- WebGPUDevice: () => WebGPUDevice,
52
- WebGPUSampler: () => WebGPUSampler,
53
- WebGPUShader: () => WebGPUShader,
54
- WebGPUTexture: () => WebGPUTexture,
55
- webgpuAdapter: () => webgpuAdapter
56
- });
57
- __reExport(bundle_exports, __toESM(require_core(), 1));
58
-
59
- // src/adapter/webgpu-adapter.ts
60
- var import_core18 = __toESM(require_core(), 1);
61
-
62
- // src/adapter/webgpu-device.ts
63
- var import_core17 = __toESM(require_core(), 1);
64
-
65
51
  // src/adapter/resources/webgpu-buffer.ts
66
- var import_core = __toESM(require_core(), 1);
67
52
  function getByteLength(props) {
68
53
  return props.byteLength || props.data?.byteLength || 0;
69
54
  }
70
- var WebGPUBuffer = class extends import_core.Buffer {
71
- device;
72
- handle;
73
- byteLength;
74
- constructor(device, props) {
75
- super(device, props);
76
- this.device = device;
77
- this.byteLength = getByteLength(props);
78
- const mapBuffer = Boolean(props.data);
79
- const size = Math.ceil(this.byteLength / 4) * 4;
80
- this.handle = this.props.handle || this.device.handle.createBuffer({
81
- size,
82
- // usage defaults to vertex
83
- usage: this.props.usage || GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
84
- mappedAtCreation: this.props.mappedAtCreation || mapBuffer,
85
- label: this.props.id
86
- });
87
- if (props.data) {
88
- this._writeMapped(props.data);
89
- }
90
- if (mapBuffer && !props.mappedAtCreation) {
91
- this.handle.unmap();
92
- }
93
- }
94
- destroy() {
95
- this.handle?.destroy();
96
- this.handle = null;
97
- }
98
- // WebGPU provides multiple ways to write a buffer...
99
- write(data, byteOffset = 0) {
100
- this.device.handle.queue.writeBuffer(
101
- this.handle,
102
- byteOffset,
103
- data.buffer,
104
- data.byteOffset,
105
- data.byteLength
106
- );
107
- }
108
- async readAsync(byteOffset = 0, byteLength = this.byteLength) {
109
- const tempBuffer = new WebGPUBuffer(this.device, {
110
- usage: import_core.Buffer.MAP_READ | import_core.Buffer.COPY_DST,
111
- byteLength
112
- });
113
- const commandEncoder = this.device.handle.createCommandEncoder();
114
- commandEncoder.copyBufferToBuffer(this.handle, byteOffset, tempBuffer.handle, 0, byteLength);
115
- this.device.handle.queue.submit([commandEncoder.finish()]);
116
- await tempBuffer.handle.mapAsync(GPUMapMode.READ, byteOffset, byteLength);
117
- const arrayBuffer = tempBuffer.handle.getMappedRange().slice(0);
118
- tempBuffer.handle.unmap();
119
- tempBuffer.destroy();
120
- return new Uint8Array(arrayBuffer);
121
- }
122
- _writeMapped(typedArray) {
123
- const arrayBuffer = this.handle.getMappedRange();
124
- new typedArray.constructor(arrayBuffer).set(typedArray);
125
- }
126
- // WEBGPU API
127
- mapAsync(mode, offset = 0, size) {
128
- return this.handle.mapAsync(mode, offset, size);
129
- }
130
- getMappedRange(offset = 0, size) {
131
- return this.handle.getMappedRange(offset, size);
132
- }
133
- unmap() {
134
- this.handle.unmap();
55
+ var import_core, WebGPUBuffer;
56
+ var init_webgpu_buffer = __esm({
57
+ "src/adapter/resources/webgpu-buffer.ts"() {
58
+ "use strict";
59
+ import_core = __toESM(require_core(), 1);
60
+ WebGPUBuffer = class extends import_core.Buffer {
61
+ device;
62
+ handle;
63
+ byteLength;
64
+ constructor(device, props) {
65
+ super(device, props);
66
+ this.device = device;
67
+ this.byteLength = getByteLength(props);
68
+ const mapBuffer = Boolean(props.data);
69
+ const size = Math.ceil(this.byteLength / 4) * 4;
70
+ this.device.handle.pushErrorScope("out-of-memory");
71
+ this.device.handle.pushErrorScope("validation");
72
+ this.handle = this.props.handle || this.device.handle.createBuffer({
73
+ size,
74
+ // usage defaults to vertex
75
+ usage: this.props.usage || GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
76
+ mappedAtCreation: this.props.mappedAtCreation || mapBuffer,
77
+ label: this.props.id
78
+ });
79
+ this.device.handle.popErrorScope().then((error) => {
80
+ if (error) {
81
+ this.device.reportError(new Error(`Buffer validation failed: ${error.message}`), this);
82
+ }
83
+ });
84
+ this.device.handle.popErrorScope().then((error) => {
85
+ if (error) {
86
+ this.device.reportError(new Error(`Buffer out of memory: ${error.message}`), this);
87
+ }
88
+ });
89
+ if (props.data) {
90
+ this._writeMapped(props.data);
91
+ }
92
+ if (mapBuffer && !props.mappedAtCreation) {
93
+ this.handle.unmap();
94
+ }
95
+ }
96
+ destroy() {
97
+ this.handle?.destroy();
98
+ this.handle = null;
99
+ }
100
+ // WebGPU provides multiple ways to write a buffer...
101
+ write(data, byteOffset = 0) {
102
+ this.device.handle.queue.writeBuffer(
103
+ this.handle,
104
+ byteOffset,
105
+ data.buffer,
106
+ data.byteOffset,
107
+ data.byteLength
108
+ );
109
+ }
110
+ async readAsync(byteOffset = 0, byteLength = this.byteLength) {
111
+ const tempBuffer = new WebGPUBuffer(this.device, {
112
+ usage: import_core.Buffer.MAP_READ | import_core.Buffer.COPY_DST,
113
+ byteLength
114
+ });
115
+ const commandEncoder = this.device.handle.createCommandEncoder();
116
+ commandEncoder.copyBufferToBuffer(this.handle, byteOffset, tempBuffer.handle, 0, byteLength);
117
+ this.device.handle.queue.submit([commandEncoder.finish()]);
118
+ await tempBuffer.handle.mapAsync(GPUMapMode.READ, byteOffset, byteLength);
119
+ const arrayBuffer = tempBuffer.handle.getMappedRange().slice(0);
120
+ tempBuffer.handle.unmap();
121
+ tempBuffer.destroy();
122
+ return new Uint8Array(arrayBuffer);
123
+ }
124
+ _writeMapped(typedArray) {
125
+ const arrayBuffer = this.handle.getMappedRange();
126
+ new typedArray.constructor(arrayBuffer).set(typedArray);
127
+ }
128
+ // WEBGPU API
129
+ mapAsync(mode, offset = 0, size) {
130
+ return this.handle.mapAsync(mode, offset, size);
131
+ }
132
+ getMappedRange(offset = 0, size) {
133
+ return this.handle.getMappedRange(offset, size);
134
+ }
135
+ unmap() {
136
+ this.handle.unmap();
137
+ }
138
+ };
135
139
  }
136
- };
137
-
138
- // src/adapter/resources/webgpu-texture.ts
139
- var import_core4 = __toESM(require_core(), 1);
140
+ });
140
141
 
141
142
  // src/adapter/helpers/convert-texture-format.ts
142
143
  function getWebGPUTextureFormat(format) {
@@ -145,343 +146,365 @@ var __exports__ = (() => {
145
146
  }
146
147
  return format;
147
148
  }
149
+ var init_convert_texture_format = __esm({
150
+ "src/adapter/helpers/convert-texture-format.ts"() {
151
+ "use strict";
152
+ }
153
+ });
148
154
 
149
155
  // src/adapter/resources/webgpu-sampler.ts
150
- var import_core2 = __toESM(require_core(), 1);
151
- var WebGPUSampler = class extends import_core2.Sampler {
152
- device;
153
- handle;
154
- constructor(device, props) {
155
- super(device, props);
156
- this.device = device;
157
- const samplerDescriptor = {
158
- ...this.props,
159
- mipmapFilter: void 0
156
+ var import_core2, WebGPUSampler;
157
+ var init_webgpu_sampler = __esm({
158
+ "src/adapter/resources/webgpu-sampler.ts"() {
159
+ "use strict";
160
+ import_core2 = __toESM(require_core(), 1);
161
+ WebGPUSampler = class extends import_core2.Sampler {
162
+ device;
163
+ handle;
164
+ constructor(device, props) {
165
+ super(device, props);
166
+ this.device = device;
167
+ const samplerDescriptor = {
168
+ ...this.props,
169
+ mipmapFilter: void 0
170
+ };
171
+ if (props.type !== "comparison-sampler") {
172
+ delete samplerDescriptor.compare;
173
+ }
174
+ if (props.mipmapFilter && props.mipmapFilter !== "none") {
175
+ samplerDescriptor.mipmapFilter = props.mipmapFilter;
176
+ }
177
+ this.handle = props.handle || this.device.handle.createSampler(samplerDescriptor);
178
+ this.handle.label = this.props.id;
179
+ }
180
+ destroy() {
181
+ this.handle = null;
182
+ }
160
183
  };
161
- if (props.type !== "comparison-sampler") {
162
- delete samplerDescriptor.compare;
163
- }
164
- if (props.mipmapFilter && props.mipmapFilter !== "none") {
165
- samplerDescriptor.mipmapFilter = props.mipmapFilter;
166
- }
167
- this.handle = this.handle || this.device.handle.createSampler(samplerDescriptor);
168
- this.handle.label = this.props.id;
169
184
  }
170
- destroy() {
171
- this.handle = null;
172
- }
173
- };
185
+ });
174
186
 
175
187
  // src/adapter/resources/webgpu-texture-view.ts
176
- var import_core3 = __toESM(require_core(), 1);
177
- var WebGPUTextureView = class extends import_core3.TextureView {
178
- device;
179
- handle;
180
- texture;
181
- constructor(device, props) {
182
- super(device, props);
183
- this.device = device;
184
- this.texture = props.texture;
185
- this.handle = this.handle || this.texture.handle.createView({
186
- format: props.format || this.texture.format,
187
- dimension: props.dimension || this.texture.dimension,
188
- aspect: props.aspect,
189
- baseMipLevel: props.baseMipLevel,
190
- mipLevelCount: props.mipLevelCount,
191
- // GPUIntegerCoordinate;
192
- baseArrayLayer: props.baseArrayLayer,
193
- // GPUIntegerCoordinate;
194
- arrayLayerCount: props.arrayLayerCount
195
- // GPUIntegerCoordinate;
196
- });
197
- this.handle.label = this.props.id;
198
- }
199
- destroy() {
200
- this.handle = null;
188
+ var import_core3, WebGPUTextureView;
189
+ var init_webgpu_texture_view = __esm({
190
+ "src/adapter/resources/webgpu-texture-view.ts"() {
191
+ "use strict";
192
+ import_core3 = __toESM(require_core(), 1);
193
+ WebGPUTextureView = class extends import_core3.TextureView {
194
+ device;
195
+ handle;
196
+ texture;
197
+ constructor(device, props) {
198
+ super(device, props);
199
+ this.device = device;
200
+ this.texture = props.texture;
201
+ this.device.pushErrorScope("validation");
202
+ this.handle = // props.handle ||
203
+ this.texture.handle.createView({
204
+ format: this.props.format || this.texture.format,
205
+ dimension: this.props.dimension || this.texture.dimension,
206
+ aspect: this.props.aspect,
207
+ baseMipLevel: this.props.baseMipLevel,
208
+ mipLevelCount: this.props.mipLevelCount,
209
+ baseArrayLayer: this.props.baseArrayLayer,
210
+ arrayLayerCount: this.props.arrayLayerCount
211
+ });
212
+ this.device.handle.popErrorScope().then((error) => {
213
+ if (error) {
214
+ this.device.reportError(new Error(`TextureView validation failed: ${error.message}`), this);
215
+ }
216
+ });
217
+ this.handle.label = this.props.id;
218
+ }
219
+ destroy() {
220
+ this.handle = null;
221
+ }
222
+ };
201
223
  }
202
- };
224
+ });
203
225
 
204
226
  // src/adapter/resources/webgpu-texture.ts
205
- var BASE_DIMENSIONS = {
206
- "1d": "1d",
207
- "2d": "2d",
208
- "2d-array": "2d",
209
- cube: "2d",
210
- "cube-array": "2d",
211
- "3d": "3d"
212
- };
213
- var WebGPUTexture = class extends import_core4.Texture {
214
- device;
215
- handle;
216
- sampler;
217
- view;
218
- constructor(device, props) {
219
- super(device, props);
220
- this.device = device;
221
- const propsWithData = { ...this.props };
222
- if (props.data) {
223
- propsWithData.data = props.data;
224
- }
225
- this.initialize(propsWithData);
226
- }
227
- destroy() {
228
- this.handle?.destroy();
229
- this.handle = null;
230
- }
231
- createView(props) {
232
- return new WebGPUTextureView(this.device, { ...props, texture: this });
233
- }
234
- initialize(props) {
235
- this.handle = this.props.handle || this.createHandle();
236
- this.handle.label ||= this.id;
237
- if (this.props.data) {
238
- if (import_core4.Texture.isExternalImage(this.props.data)) {
239
- this.copyExternalImage({ image: this.props.data });
240
- } else {
241
- this.setData({ data: this.props.data });
242
- }
243
- }
244
- this.width = this.handle.width;
245
- this.height = this.handle.height;
246
- this.sampler = props.sampler instanceof WebGPUSampler ? props.sampler : new WebGPUSampler(this.device, props.sampler || {});
247
- this.view = new WebGPUTextureView(this.device, { ...this.props, texture: this });
248
- }
249
- createHandle() {
250
- const width = this.props.width || this.props.data?.width || 1;
251
- const height = this.props.height || this.props.data?.height || 1;
252
- return this.device.handle.createTexture({
253
- label: this.id,
254
- size: {
255
- width,
256
- height,
257
- depthOrArrayLayers: this.depth
258
- },
259
- usage: this.props.usage || import_core4.Texture.TEXTURE | import_core4.Texture.COPY_DST,
260
- dimension: BASE_DIMENSIONS[this.dimension],
261
- format: getWebGPUTextureFormat(this.format),
262
- mipLevelCount: this.mipLevels,
263
- sampleCount: this.props.samples
264
- });
265
- }
266
- /** @deprecated - intention is to use the createView public API */
267
- createGPUTextureView() {
268
- return this.handle.createView({ label: this.id });
269
- }
270
- /**
271
- * Set default sampler
272
- * Accept a sampler instance or set of props;
273
- */
274
- setSampler(sampler) {
275
- this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
276
- return this;
277
- }
278
- setTexture1DData(data) {
279
- throw new Error("not implemented");
280
- }
281
- setTexture2DData(lodData, depth, target) {
282
- throw new Error("not implemented");
283
- }
284
- setTexture3DData(lodData, depth, target) {
285
- throw new Error("not implemented");
286
- }
287
- setTextureCubeData(data, depth) {
288
- throw new Error("not implemented");
289
- }
290
- setTextureArrayData(data) {
291
- throw new Error("not implemented");
292
- }
293
- setTextureCubeArrayData(data) {
294
- throw new Error("not implemented");
295
- }
296
- setData(options) {
297
- if (ArrayBuffer.isView(options.data)) {
298
- const clampedArray = new Uint8ClampedArray(options.data.buffer);
299
- const image = new ImageData(clampedArray, this.width, this.height);
300
- return this.copyExternalImage({ image });
301
- }
302
- throw new Error("Texture.setData: Use CommandEncoder to upload data to texture in WebGPU");
303
- }
304
- copyExternalImage(options) {
305
- const size = import_core4.Texture.getExternalImageSize(options.image);
306
- const opts = { ...import_core4.Texture.defaultCopyExternalImageOptions, ...size, ...options };
307
- const {
308
- image,
309
- sourceX,
310
- sourceY,
311
- width,
312
- height,
313
- depth,
314
- mipLevel,
315
- x,
316
- y,
317
- z,
318
- aspect,
319
- colorSpace,
320
- premultipliedAlpha,
321
- flipY
322
- } = opts;
323
- this.device.handle.queue.copyExternalImageToTexture(
324
- // source: GPUImageCopyExternalImage
325
- {
326
- source: image,
327
- origin: [sourceX, sourceY],
328
- flipY
329
- },
330
- // destination: GPUImageCopyTextureTagged
331
- {
332
- texture: this.handle,
333
- origin: [x, y, z],
334
- mipLevel,
335
- aspect,
336
- colorSpace,
337
- premultipliedAlpha
338
- },
339
- // copySize: GPUExtent3D
340
- [width, height, depth]
341
- );
342
- return { width, height };
343
- }
344
- // WebGPU specific
345
- /*
346
- async readPixels() {
347
- const readbackBuffer = device.createBuffer({
348
- usage: Buffer.COPY_DST | Buffer.MAP_READ,
349
- size: 4 * textureWidth * textureHeight,
350
- });
351
-
352
- // Copy data from the texture to the buffer.
353
- const encoder = device.createCommandEncoder();
354
- encoder.copyTextureToBuffer(
355
- { texture },
356
- { buffer, rowPitch: textureWidth * 4 },
357
- [textureWidth, textureHeight],
358
- );
359
- device.submit([encoder.finish()]);
360
-
361
- // Get the data on the CPU.
362
- await buffer.mapAsync(GPUMapMode.READ);
363
- saveScreenshot(buffer.getMappedRange());
364
- buffer.unmap();
365
- }
366
-
367
- setImageData(imageData, usage): this {
368
- let data = null;
369
-
370
- const bytesPerRow = Math.ceil((img.width * 4) / 256) * 256;
371
- if (bytesPerRow == img.width * 4) {
372
- data = imageData.data;
373
- } else {
374
- data = new Uint8Array(bytesPerRow * img.height);
375
- let imagePixelIndex = 0;
376
- for (let y = 0; y < img.height; ++y) {
377
- for (let x = 0; x < img.width; ++x) {
378
- const i = x * 4 + y * bytesPerRow;
379
- data[i] = imageData.data[imagePixelIndex];
380
- data[i + 1] = imageData.data[imagePixelIndex + 1];
381
- data[i + 2] = imageData.data[imagePixelIndex + 2];
382
- data[i + 3] = imageData.data[imagePixelIndex + 3];
383
- imagePixelIndex += 4;
227
+ var import_core4, WebGPUTexture;
228
+ var init_webgpu_texture = __esm({
229
+ "src/adapter/resources/webgpu-texture.ts"() {
230
+ "use strict";
231
+ import_core4 = __toESM(require_core(), 1);
232
+ init_convert_texture_format();
233
+ init_webgpu_sampler();
234
+ init_webgpu_texture_view();
235
+ WebGPUTexture = class extends import_core4.Texture {
236
+ device;
237
+ handle;
238
+ sampler;
239
+ view;
240
+ constructor(device, props) {
241
+ super(device, props);
242
+ this.device = device;
243
+ if (this.dimension === "cube") {
244
+ this.depth = 6;
245
+ }
246
+ this.device.handle.pushErrorScope("out-of-memory");
247
+ this.device.handle.pushErrorScope("validation");
248
+ this.handle = this.props.handle || this.device.handle.createTexture({
249
+ label: this.id,
250
+ size: {
251
+ width: this.width,
252
+ height: this.height,
253
+ depthOrArrayLayers: this.depth
254
+ },
255
+ usage: this.props.usage || import_core4.Texture.TEXTURE | import_core4.Texture.COPY_DST,
256
+ dimension: this.baseDimension,
257
+ format: getWebGPUTextureFormat(this.format),
258
+ mipLevelCount: this.mipLevels,
259
+ sampleCount: this.props.samples
260
+ });
261
+ this.device.handle.popErrorScope().then((error) => {
262
+ if (error) {
263
+ this.device.reportError(new Error(`Texture validation failed: ${error.message}`), this);
384
264
  }
265
+ });
266
+ this.device.handle.popErrorScope().then((error) => {
267
+ if (error) {
268
+ this.device.reportError(new Error(`Texture out of memory: ${error.message}`), this);
269
+ }
270
+ });
271
+ if (this.props.handle) {
272
+ this.handle.label ||= this.id;
273
+ this.width = this.handle.width;
274
+ this.height = this.handle.height;
385
275
  }
276
+ this.sampler = props.sampler instanceof WebGPUSampler ? props.sampler : new WebGPUSampler(this.device, props.sampler || {});
277
+ this.view = new WebGPUTextureView(this.device, {
278
+ ...this.props,
279
+ texture: this,
280
+ mipLevelCount: this.mipLevels,
281
+ arrayLayerCount: this.depth
282
+ });
283
+ this._initializeData(props.data);
386
284
  }
387
- return this;
388
- }
389
-
390
- setBuffer(textureDataBuffer, {bytesPerRow}): this {
391
- const commandEncoder = this.device.handle.createCommandEncoder();
392
- commandEncoder.copyBufferToTexture(
393
- {
394
- buffer: textureDataBuffer,
395
- bytesPerRow
396
- },
397
- {
398
- texture: this.handle
399
- },
400
- {
401
- width,
402
- height,
403
- depth
285
+ destroy() {
286
+ this.handle?.destroy();
287
+ this.handle = null;
288
+ }
289
+ createView(props) {
290
+ return new WebGPUTextureView(this.device, { ...props, texture: this });
291
+ }
292
+ copyImageData(options_) {
293
+ const { width, height, depth } = this;
294
+ const options = this._normalizeCopyImageDataOptions(options_);
295
+ this.device.handle.pushErrorScope("validation");
296
+ this.device.handle.queue.writeTexture(
297
+ // destination: GPUImageCopyTexture
298
+ {
299
+ // texture subresource
300
+ texture: this.handle,
301
+ mipLevel: options.mipLevel,
302
+ aspect: options.aspect,
303
+ // origin to write to
304
+ origin: [options.x, options.y, options.z]
305
+ },
306
+ // data
307
+ options.data,
308
+ // dataLayout: GPUImageDataLayout
309
+ {
310
+ offset: options.byteOffset,
311
+ bytesPerRow: options.bytesPerRow,
312
+ rowsPerImage: options.rowsPerImage
313
+ },
314
+ // size: GPUExtent3D - extents of the content to write
315
+ [width, height, depth]
316
+ );
317
+ this.device.handle.popErrorScope().then((error) => {
318
+ if (error) {
319
+ this.device.reportError(new Error(`copyImageData validation failed: ${error.message}`));
320
+ }
321
+ });
322
+ }
323
+ copyExternalImage(options_) {
324
+ const options = this._normalizeCopyExternalImageOptions(options_);
325
+ this.device.handle.pushErrorScope("validation");
326
+ this.device.handle.queue.copyExternalImageToTexture(
327
+ // source: GPUImageCopyExternalImage
328
+ {
329
+ source: options.image,
330
+ origin: [options.sourceX, options.sourceY],
331
+ flipY: options.flipY
332
+ },
333
+ // destination: GPUImageCopyTextureTagged
334
+ {
335
+ texture: this.handle,
336
+ origin: [options.x, options.y, options.depth],
337
+ mipLevel: options.mipLevel,
338
+ aspect: options.aspect,
339
+ colorSpace: options.colorSpace,
340
+ premultipliedAlpha: options.premultipliedAlpha
341
+ },
342
+ // copySize: GPUExtent3D
343
+ [options.width, options.height, 1]
344
+ );
345
+ this.device.handle.popErrorScope().then((error) => {
346
+ if (error) {
347
+ this.device.reportError(new Error(`copyExternalImage validation failed: ${error.message}`));
348
+ }
349
+ });
350
+ return { width: options.width, height: options.height };
351
+ }
352
+ generateMipmapsWebGL() {
353
+ import_core4.log.warn(`${this}: generateMipmaps not supported in WebGPU`)();
354
+ }
355
+ // WebGPU specific
356
+ /*
357
+ async readPixels() {
358
+ const readbackBuffer = device.createBuffer({
359
+ usage: Buffer.COPY_DST | Buffer.MAP_READ,
360
+ size: 4 * textureWidth * textureHeight,
361
+ });
362
+
363
+ // Copy data from the texture to the buffer.
364
+ const encoder = device.createCommandEncoder();
365
+ encoder.copyTextureToBuffer(
366
+ { texture },
367
+ { buffer, rowPitch: textureWidth * 4 },
368
+ [textureWidth, textureHeight],
369
+ );
370
+ device.submit([encoder.finish()]);
371
+
372
+ // Get the data on the CPU.
373
+ await buffer.mapAsync(GPUMapMode.READ);
374
+ saveScreenshot(buffer.getMappedRange());
375
+ buffer.unmap();
404
376
  }
405
- );
406
-
407
- this.device.handle.defaultQueue.submit([commandEncoder.finish()]);
408
- return this;
409
- }
410
- */
411
- };
377
+
378
+ setImageData(imageData, usage): this {
379
+ let data = null;
380
+
381
+ const bytesPerRow = Math.ceil((img.width * 4) / 256) * 256;
382
+ if (bytesPerRow == img.width * 4) {
383
+ data = imageData.data;
384
+ } else {
385
+ data = new Uint8Array(bytesPerRow * img.height);
386
+ let imagePixelIndex = 0;
387
+ for (let y = 0; y < img.height; ++y) {
388
+ for (let x = 0; x < img.width; ++x) {
389
+ const i = x * 4 + y * bytesPerRow;
390
+ data[i] = imageData.data[imagePixelIndex];
391
+ data[i + 1] = imageData.data[imagePixelIndex + 1];
392
+ data[i + 2] = imageData.data[imagePixelIndex + 2];
393
+ data[i + 3] = imageData.data[imagePixelIndex + 3];
394
+ imagePixelIndex += 4;
395
+ }
396
+ }
397
+ }
398
+ return this;
399
+ }
400
+
401
+ setBuffer(textureDataBuffer, {bytesPerRow}): this {
402
+ const commandEncoder = this.device.handle.createCommandEncoder();
403
+ commandEncoder.copyBufferToTexture(
404
+ {
405
+ buffer: textureDataBuffer,
406
+ bytesPerRow
407
+ },
408
+ {
409
+ texture: this.handle
410
+ },
411
+ {
412
+ width,
413
+ height,
414
+ depth
415
+ }
416
+ );
417
+
418
+ this.device.handle.defaultQueue.submit([commandEncoder.finish()]);
419
+ return this;
420
+ }
421
+ */
422
+ };
423
+ }
424
+ });
412
425
 
413
426
  // src/adapter/resources/webgpu-external-texture.ts
414
- var import_core5 = __toESM(require_core(), 1);
415
- var WebGPUExternalTexture = class extends import_core5.ExternalTexture {
416
- device;
417
- handle;
418
- sampler;
419
- constructor(device, props) {
420
- super(device, props);
421
- this.device = device;
422
- this.handle = this.props.handle || this.device.handle.importExternalTexture({
423
- source: props.source,
424
- colorSpace: props.colorSpace
425
- });
426
- this.sampler = null;
427
- }
428
- destroy() {
429
- this.handle = null;
430
- }
431
- /** Set default sampler */
432
- setSampler(sampler) {
433
- this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
434
- return this;
427
+ var import_core5, WebGPUExternalTexture;
428
+ var init_webgpu_external_texture = __esm({
429
+ "src/adapter/resources/webgpu-external-texture.ts"() {
430
+ "use strict";
431
+ import_core5 = __toESM(require_core(), 1);
432
+ init_webgpu_sampler();
433
+ WebGPUExternalTexture = class extends import_core5.ExternalTexture {
434
+ device;
435
+ handle;
436
+ sampler;
437
+ constructor(device, props) {
438
+ super(device, props);
439
+ this.device = device;
440
+ this.handle = this.props.handle || this.device.handle.importExternalTexture({
441
+ source: props.source,
442
+ colorSpace: props.colorSpace
443
+ });
444
+ this.sampler = null;
445
+ }
446
+ destroy() {
447
+ this.handle = null;
448
+ }
449
+ /** Set default sampler */
450
+ setSampler(sampler) {
451
+ this.sampler = sampler instanceof WebGPUSampler ? sampler : new WebGPUSampler(this.device, sampler);
452
+ return this;
453
+ }
454
+ };
435
455
  }
436
- };
456
+ });
437
457
 
438
458
  // src/adapter/resources/webgpu-shader.ts
439
- var import_core6 = __toESM(require_core(), 1);
440
- var WebGPUShader = class extends import_core6.Shader {
441
- device;
442
- handle;
443
- constructor(device, props) {
444
- super(device, props);
445
- this.device = device;
446
- const isGLSL = props.source.includes("#version");
447
- if (this.props.language === "glsl" || isGLSL) {
448
- throw new Error("GLSL shaders are not supported in WebGPU");
449
- }
450
- this.device.handle.pushErrorScope("validation");
451
- this.handle = this.props.handle || this.device.handle.createShaderModule({ code: props.source });
452
- this.device.handle.popErrorScope().then((error) => {
453
- if (error) {
454
- import_core6.log.error(`${this} creation failed:
459
+ var import_core6, WebGPUShader;
460
+ var init_webgpu_shader = __esm({
461
+ "src/adapter/resources/webgpu-shader.ts"() {
462
+ "use strict";
463
+ import_core6 = __toESM(require_core(), 1);
464
+ WebGPUShader = class extends import_core6.Shader {
465
+ device;
466
+ handle;
467
+ constructor(device, props) {
468
+ super(device, props);
469
+ this.device = device;
470
+ const isGLSL = props.source.includes("#version");
471
+ if (this.props.language === "glsl" || isGLSL) {
472
+ throw new Error("GLSL shaders are not supported in WebGPU");
473
+ }
474
+ this.device.handle.pushErrorScope("validation");
475
+ this.handle = this.props.handle || this.device.handle.createShaderModule({ code: props.source });
476
+ this.device.handle.popErrorScope().then((error) => {
477
+ if (error) {
478
+ import_core6.log.error(`${this} creation failed:
455
479
  "${error.message}"`, this, this.props.source)();
480
+ }
481
+ });
482
+ this.handle.label = this.props.id;
483
+ this._checkCompilationError();
456
484
  }
457
- });
458
- this.handle.label = this.props.id;
459
- this._checkCompilationError();
460
- }
461
- get asyncCompilationStatus() {
462
- return this.getCompilationInfo().then(() => this.compilationStatus);
463
- }
464
- async _checkCompilationError() {
465
- const shaderLog = await this.getCompilationInfo();
466
- const hasErrors = Boolean(shaderLog.find((msg) => msg.type === "error"));
467
- this.compilationStatus = hasErrors ? "error" : "success";
468
- this.debugShader();
469
- if (this.compilationStatus === "error") {
470
- import_core6.log.error(`Shader compilation error`, shaderLog)();
471
- }
472
- }
473
- destroy() {
474
- this.handle = null;
475
- }
476
- /** Returns compilation info for this shader */
477
- async getCompilationInfo() {
478
- const compilationInfo = await this.handle.getCompilationInfo();
479
- return compilationInfo.messages;
485
+ get asyncCompilationStatus() {
486
+ return this.getCompilationInfo().then(() => this.compilationStatus);
487
+ }
488
+ async _checkCompilationError() {
489
+ const shaderLog = await this.getCompilationInfo();
490
+ const hasErrors = Boolean(shaderLog.find((msg) => msg.type === "error"));
491
+ this.compilationStatus = hasErrors ? "error" : "success";
492
+ this.debugShader();
493
+ if (this.compilationStatus === "error") {
494
+ import_core6.log.error(`Shader compilation error`, shaderLog)();
495
+ }
496
+ }
497
+ destroy() {
498
+ this.handle = null;
499
+ }
500
+ /** Returns compilation info for this shader */
501
+ async getCompilationInfo() {
502
+ const compilationInfo = await this.handle.getCompilationInfo();
503
+ return compilationInfo.messages;
504
+ }
505
+ };
480
506
  }
481
- };
482
-
483
- // src/adapter/resources/webgpu-render-pipeline.ts
484
- var import_core9 = __toESM(require_core(), 1);
507
+ });
485
508
 
486
509
  // src/adapter/helpers/webgpu-parameters.ts
487
510
  function addDepthStencil(descriptor) {
@@ -504,157 +527,6 @@ var __exports__ = (() => {
504
527
  const depthStencil = addDepthStencil(descriptor);
505
528
  return depthStencil.stencilBack;
506
529
  }
507
- var PARAMETER_TABLE = {
508
- // RASTERIZATION PARAMETERS
509
- cullMode: (parameter, value, descriptor) => {
510
- descriptor.primitive = descriptor.primitive || {};
511
- descriptor.primitive.cullMode = value;
512
- },
513
- frontFace: (parameter, value, descriptor) => {
514
- descriptor.primitive = descriptor.primitive || {};
515
- descriptor.primitive.frontFace = value;
516
- },
517
- // DEPTH
518
- depthWriteEnabled: (parameter, value, descriptor) => {
519
- const depthStencil = addDepthStencil(descriptor);
520
- depthStencil.depthWriteEnabled = value;
521
- },
522
- depthCompare: (parameter, value, descriptor) => {
523
- const depthStencil = addDepthStencil(descriptor);
524
- depthStencil.depthCompare = value;
525
- },
526
- depthFormat: (parameter, value, descriptor) => {
527
- const depthStencil = addDepthStencil(descriptor);
528
- depthStencil.format = value;
529
- },
530
- depthBias: (parameter, value, descriptor) => {
531
- const depthStencil = addDepthStencil(descriptor);
532
- depthStencil.depthBias = value;
533
- },
534
- depthBiasSlopeScale: (parameter, value, descriptor) => {
535
- const depthStencil = addDepthStencil(descriptor);
536
- depthStencil.depthBiasSlopeScale = value;
537
- },
538
- depthBiasClamp: (parameter, value, descriptor) => {
539
- const depthStencil = addDepthStencil(descriptor);
540
- depthStencil.depthBiasClamp = value;
541
- },
542
- // STENCIL
543
- stencilReadMask: (parameter, value, descriptor) => {
544
- const depthStencil = addDepthStencil(descriptor);
545
- depthStencil.stencilReadMask = value;
546
- },
547
- stencilWriteMask: (parameter, value, descriptor) => {
548
- const depthStencil = addDepthStencil(descriptor);
549
- depthStencil.stencilWriteMask = value;
550
- },
551
- stencilCompare: (parameter, value, descriptor) => {
552
- const stencilFront = addDepthStencilFront(descriptor);
553
- const stencilBack = addDepthStencilBack(descriptor);
554
- stencilFront.compare = value;
555
- stencilBack.compare = value;
556
- },
557
- stencilPassOperation: (parameter, value, descriptor) => {
558
- const stencilFront = addDepthStencilFront(descriptor);
559
- const stencilBack = addDepthStencilBack(descriptor);
560
- stencilFront.passOp = value;
561
- stencilBack.passOp = value;
562
- },
563
- stencilFailOperation: (parameter, value, descriptor) => {
564
- const stencilFront = addDepthStencilFront(descriptor);
565
- const stencilBack = addDepthStencilBack(descriptor);
566
- stencilFront.failOp = value;
567
- stencilBack.failOp = value;
568
- },
569
- stencilDepthFailOperation: (parameter, value, descriptor) => {
570
- const stencilFront = addDepthStencilFront(descriptor);
571
- const stencilBack = addDepthStencilBack(descriptor);
572
- stencilFront.depthFailOp = value;
573
- stencilBack.depthFailOp = value;
574
- },
575
- // MULTISAMPLE
576
- sampleCount: (parameter, value, descriptor) => {
577
- descriptor.multisample = descriptor.multisample || {};
578
- descriptor.multisample.count = value;
579
- },
580
- sampleMask: (parameter, value, descriptor) => {
581
- descriptor.multisample = descriptor.multisample || {};
582
- descriptor.multisample.mask = value;
583
- },
584
- sampleAlphaToCoverageEnabled: (parameter, value, descriptor) => {
585
- descriptor.multisample = descriptor.multisample || {};
586
- descriptor.multisample.alphaToCoverageEnabled = value;
587
- },
588
- // COLOR
589
- colorMask: (parameter, value, descriptor) => {
590
- const targets = addColorState(descriptor);
591
- targets[0].writeMask = value;
592
- },
593
- blendColorOperation: (parameter, value, descriptor) => {
594
- addColorState(descriptor);
595
- }
596
- /*
597
- blendColorSrcTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
598
- addColorState(descriptor);
599
- targets[0].blend = targets[0].blend || {};
600
- targets[0].blend.color = targets[0].blend.color || {};
601
- targets[0].blend.color.srcTarget = value;
602
- },
603
-
604
- blendColorDstTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
605
- addColorState(descriptor);
606
- targets[0].blend = targets[0].blend || {};
607
- targets[0].blend.color = targets[0].blend.color || {};
608
- targets[0].blend.color.dstTarget = value;
609
- },
610
-
611
- blendAlphaOperation: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
612
- addColorState(descriptor);
613
- targets[0].blend = targets[0].blend || {};
614
- targets[0].blend.alpha = targets[0].blend.alpha || {};
615
- targets[0].blend.alpha.operation = value;
616
- },
617
-
618
- blendAlphaSrcTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
619
- addColorState(descriptor);
620
- targets[0].blend = targets[0].blend || {};
621
- targets[0].blend.alpha = targets[0].blend.alpha || {};
622
- targets[0].blend.alpha.srcTarget = value;
623
- },
624
-
625
- blendAlphaDstTarget: (parameter, value, descriptor: GPURenderPipelineDescriptor) => {
626
- addColorState(descriptor);
627
- targets[0].blend = targets[0].blend || {};
628
- targets[0].blend.alpha = targets[0].blend.alpha || {};
629
- targets[0].blend.alpha.dstTarget = value;
630
- },
631
- */
632
- };
633
- var DEFAULT_PIPELINE_DESCRIPTOR = {
634
- // depthStencil: {
635
- // stencilFront: {},
636
- // stencilBack: {},
637
- // // depthWriteEnabled: true,
638
- // // depthCompare: 'less',
639
- // // format: 'depth24plus-stencil8',
640
- // },
641
- primitive: {
642
- cullMode: "back",
643
- topology: "triangle-list"
644
- },
645
- vertex: {
646
- module: void 0,
647
- entryPoint: "main"
648
- },
649
- fragment: {
650
- module: void 0,
651
- entryPoint: "main",
652
- targets: [
653
- // { format: props.color0Format || 'bgra8unorm' }
654
- ]
655
- },
656
- layout: "auto"
657
- };
658
530
  function applyParametersToRenderPipelineDescriptor(pipelineDescriptor, parameters = {}) {
659
531
  Object.assign(pipelineDescriptor, { ...DEFAULT_PIPELINE_DESCRIPTOR, ...pipelineDescriptor });
660
532
  setParameters(pipelineDescriptor, parameters);
@@ -668,7 +540,7 @@ var __exports__ = (() => {
668
540
  setterFunction(key, value, pipelineDescriptor);
669
541
  }
670
542
  }
671
- function addColorState(descriptor) {
543
+ function addColorState(descriptor, attachment) {
672
544
  descriptor.fragment.targets = descriptor.fragment?.targets || [];
673
545
  if (!Array.isArray(descriptor.fragment?.targets)) {
674
546
  throw new Error("colorstate");
@@ -676,17 +548,182 @@ var __exports__ = (() => {
676
548
  if (descriptor.fragment?.targets?.length === 0) {
677
549
  descriptor.fragment.targets?.push({});
678
550
  }
679
- return descriptor.fragment?.targets;
551
+ return descriptor.fragment?.targets[0];
680
552
  }
553
+ function addBlendState(descriptor, attachment) {
554
+ const target = addColorState(descriptor, attachment);
555
+ target.blend = target.blend || { color: {}, alpha: {} };
556
+ return target.blend;
557
+ }
558
+ var PARAMETER_TABLE, DEFAULT_PIPELINE_DESCRIPTOR;
559
+ var init_webgpu_parameters = __esm({
560
+ "src/adapter/helpers/webgpu-parameters.ts"() {
561
+ "use strict";
562
+ PARAMETER_TABLE = {
563
+ // RASTERIZATION PARAMETERS
564
+ cullMode: (_, value, descriptor) => {
565
+ descriptor.primitive = descriptor.primitive || {};
566
+ descriptor.primitive.cullMode = value;
567
+ },
568
+ frontFace: (_, value, descriptor) => {
569
+ descriptor.primitive = descriptor.primitive || {};
570
+ descriptor.primitive.frontFace = value;
571
+ },
572
+ // DEPTH
573
+ depthWriteEnabled: (_, value, descriptor) => {
574
+ if (value) {
575
+ const depthStencil = addDepthStencil(descriptor);
576
+ depthStencil.depthWriteEnabled = value;
577
+ }
578
+ },
579
+ depthCompare: (_, value, descriptor) => {
580
+ const depthStencil = addDepthStencil(descriptor);
581
+ depthStencil.depthCompare = value;
582
+ },
583
+ depthFormat: (_, value, descriptor) => {
584
+ const depthStencil = addDepthStencil(descriptor);
585
+ depthStencil.format = value;
586
+ },
587
+ depthBias: (_, value, descriptor) => {
588
+ const depthStencil = addDepthStencil(descriptor);
589
+ depthStencil.depthBias = value;
590
+ },
591
+ depthBiasSlopeScale: (_, value, descriptor) => {
592
+ const depthStencil = addDepthStencil(descriptor);
593
+ depthStencil.depthBiasSlopeScale = value;
594
+ },
595
+ depthBiasClamp: (_, value, descriptor) => {
596
+ const depthStencil = addDepthStencil(descriptor);
597
+ depthStencil.depthBiasClamp = value;
598
+ },
599
+ // STENCIL
600
+ stencilReadMask: (_, value, descriptor) => {
601
+ const depthStencil = addDepthStencil(descriptor);
602
+ depthStencil.stencilReadMask = value;
603
+ },
604
+ stencilWriteMask: (_, value, descriptor) => {
605
+ const depthStencil = addDepthStencil(descriptor);
606
+ depthStencil.stencilWriteMask = value;
607
+ },
608
+ stencilCompare: (_, value, descriptor) => {
609
+ const stencilFront = addDepthStencilFront(descriptor);
610
+ const stencilBack = addDepthStencilBack(descriptor);
611
+ stencilFront.compare = value;
612
+ stencilBack.compare = value;
613
+ },
614
+ stencilPassOperation: (_, value, descriptor) => {
615
+ const stencilFront = addDepthStencilFront(descriptor);
616
+ const stencilBack = addDepthStencilBack(descriptor);
617
+ stencilFront.passOp = value;
618
+ stencilBack.passOp = value;
619
+ },
620
+ stencilFailOperation: (_, value, descriptor) => {
621
+ const stencilFront = addDepthStencilFront(descriptor);
622
+ const stencilBack = addDepthStencilBack(descriptor);
623
+ stencilFront.failOp = value;
624
+ stencilBack.failOp = value;
625
+ },
626
+ stencilDepthFailOperation: (_, value, descriptor) => {
627
+ const stencilFront = addDepthStencilFront(descriptor);
628
+ const stencilBack = addDepthStencilBack(descriptor);
629
+ stencilFront.depthFailOp = value;
630
+ stencilBack.depthFailOp = value;
631
+ },
632
+ // MULTISAMPLE
633
+ sampleCount: (_, value, descriptor) => {
634
+ descriptor.multisample = descriptor.multisample || {};
635
+ descriptor.multisample.count = value;
636
+ },
637
+ sampleMask: (_, value, descriptor) => {
638
+ descriptor.multisample = descriptor.multisample || {};
639
+ descriptor.multisample.mask = value;
640
+ },
641
+ sampleAlphaToCoverageEnabled: (_, value, descriptor) => {
642
+ descriptor.multisample = descriptor.multisample || {};
643
+ descriptor.multisample.alphaToCoverageEnabled = value;
644
+ },
645
+ // COLOR
646
+ colorMask: (_, value, descriptor) => {
647
+ const target = addColorState(descriptor, 0);
648
+ target.writeMask = value;
649
+ },
650
+ blend: (_, value, descriptor) => {
651
+ if (value) {
652
+ addBlendState(descriptor, 0);
653
+ }
654
+ },
655
+ blendColorOperation: (_, value, descriptor) => {
656
+ const blend = addBlendState(descriptor, 0);
657
+ blend.color = blend.color || {};
658
+ blend.color.operation = value;
659
+ },
660
+ blendColorSrcFactor: (_, value, descriptor) => {
661
+ const blend = addBlendState(descriptor, 0);
662
+ blend.color = blend.color || {};
663
+ blend.color.srcFactor = value;
664
+ },
665
+ blendColorDstFactor: (_, value, descriptor) => {
666
+ const blend = addBlendState(descriptor, 0);
667
+ blend.color.dstFactor = value;
668
+ },
669
+ blendAlphaOperation: (_, value, descriptor) => {
670
+ const blend = addBlendState(descriptor, 0);
671
+ blend.alpha = blend.alpha || {};
672
+ blend.alpha.operation = value;
673
+ },
674
+ blendAlphaSrcFactor: (_, value, descriptor) => {
675
+ const blend = addBlendState(descriptor, 0);
676
+ blend.alpha = blend.alpha || {};
677
+ blend.alpha.srcFactor = value;
678
+ },
679
+ blendAlphaDstFactor: (_, value, descriptor) => {
680
+ const blend = addBlendState(descriptor, 0);
681
+ blend.alpha = blend.alpha || {};
682
+ blend.alpha.dstFactor = value;
683
+ }
684
+ };
685
+ DEFAULT_PIPELINE_DESCRIPTOR = {
686
+ // depthStencil: {
687
+ // stencilFront: {},
688
+ // stencilBack: {},
689
+ // // depthWriteEnabled: true,
690
+ // // depthCompare: 'less',
691
+ // // format: 'depth24plus-stencil8',
692
+ // },
693
+ primitive: {
694
+ cullMode: "back",
695
+ topology: "triangle-list"
696
+ },
697
+ vertex: {
698
+ module: void 0,
699
+ entryPoint: "main"
700
+ },
701
+ fragment: {
702
+ module: void 0,
703
+ entryPoint: "main",
704
+ targets: [
705
+ // { format: props.color0Format || 'bgra8unorm' }
706
+ ]
707
+ },
708
+ layout: "auto"
709
+ };
710
+ }
711
+ });
681
712
 
682
713
  // src/adapter/helpers/get-bind-group.ts
683
- var import_core7 = __toESM(require_core(), 1);
684
714
  function getBindGroup(device, bindGroupLayout, shaderLayout, bindings) {
685
715
  const entries = getBindGroupEntries(bindings, shaderLayout);
686
- return device.createBindGroup({
716
+ device.pushErrorScope("validation");
717
+ const bindGroup = device.createBindGroup({
687
718
  layout: bindGroupLayout,
688
719
  entries
689
720
  });
721
+ device.popErrorScope().then((error) => {
722
+ if (error) {
723
+ import_core7.log.error(`createBindGroup validation failed: ${error.message}`)();
724
+ }
725
+ });
726
+ return bindGroup;
690
727
  }
691
728
  function getShaderLayoutBinding(shaderLayout, bindingName, options) {
692
729
  const bindingLayout = shaderLayout.bindings.find(
@@ -702,13 +739,21 @@ var __exports__ = (() => {
702
739
  for (const [bindingName, value] of Object.entries(bindings)) {
703
740
  let bindingLayout = getShaderLayoutBinding(shaderLayout, bindingName);
704
741
  if (bindingLayout) {
705
- entries.push(getBindGroupEntry(value, bindingLayout.location));
742
+ const entry = getBindGroupEntry(value, bindingLayout.location);
743
+ if (entry) {
744
+ entries.push(entry);
745
+ }
706
746
  }
707
- bindingLayout = getShaderLayoutBinding(shaderLayout, `${bindingName}Sampler`, {
708
- ignoreWarnings: true
709
- });
710
- if (bindingLayout) {
711
- entries.push(getBindGroupEntry(value, bindingLayout.location, { sampler: true }));
747
+ if (value instanceof import_core7.Texture) {
748
+ bindingLayout = getShaderLayoutBinding(shaderLayout, `${bindingName}Sampler`, {
749
+ ignoreWarnings: true
750
+ });
751
+ if (bindingLayout) {
752
+ const entry = getBindGroupEntry(value, bindingLayout.location, { sampler: true });
753
+ if (entry) {
754
+ entries.push(entry);
755
+ }
756
+ }
712
757
  }
713
758
  }
714
759
  return entries;
@@ -727,7 +772,8 @@ var __exports__ = (() => {
727
772
  binding: index,
728
773
  resource: binding.handle
729
774
  };
730
- } else if (binding instanceof import_core7.Texture) {
775
+ }
776
+ if (binding instanceof import_core7.Texture) {
731
777
  if (options?.sampler) {
732
778
  return {
733
779
  binding: index,
@@ -736,14 +782,21 @@ var __exports__ = (() => {
736
782
  }
737
783
  return {
738
784
  binding: index,
739
- resource: binding.handle.createView({ label: "bind-group-auto-created" })
785
+ resource: binding.view.handle
740
786
  };
741
787
  }
742
- throw new Error("invalid binding");
788
+ import_core7.log.warn(`invalid binding ${name}`, binding);
789
+ return null;
743
790
  }
791
+ var import_core7;
792
+ var init_get_bind_group = __esm({
793
+ "src/adapter/helpers/get-bind-group.ts"() {
794
+ "use strict";
795
+ import_core7 = __toESM(require_core(), 1);
796
+ }
797
+ });
744
798
 
745
799
  // src/adapter/helpers/get-vertex-buffer-layout.ts
746
- var import_core8 = __toESM(require_core(), 1);
747
800
  function getWebGPUVertexFormat(format) {
748
801
  if (format.endsWith("-webgl")) {
749
802
  throw new Error(`WebGPU does not support vertex format ${format}`);
@@ -769,14 +822,14 @@ var __exports__ = (() => {
769
822
  offset: attributeMapping.byteOffset,
770
823
  shaderLocation: location
771
824
  });
772
- byteStride += (0, import_core8.decodeVertexFormat)(format).byteLength;
825
+ byteStride += (0, import_core8.getVertexFormatInfo)(format).byteLength;
773
826
  }
774
827
  } else {
775
828
  const attributeLayout = findAttributeLayout(shaderLayout, mapping.name, usedAttributes);
776
829
  if (!attributeLayout) {
777
830
  continue;
778
831
  }
779
- byteStride = (0, import_core8.decodeVertexFormat)(format).byteLength;
832
+ byteStride = (0, import_core8.getVertexFormatInfo)(format).byteLength;
780
833
  stepMode = attributeLayout.stepMode || (attributeLayout.name.startsWith("instance") ? "instance" : "vertex");
781
834
  vertexAttributes.push({
782
835
  format: getWebGPUVertexFormat(format),
@@ -794,7 +847,7 @@ var __exports__ = (() => {
794
847
  for (const attribute of shaderLayout.attributes) {
795
848
  if (!usedAttributes.has(attribute.name)) {
796
849
  vertexBufferLayouts.push({
797
- arrayStride: (0, import_core8.decodeVertexFormat)("float32x3").byteLength,
850
+ arrayStride: (0, import_core8.getVertexFormatInfo)("float32x3").byteLength,
798
851
  stepMode: attribute.stepMode || (attribute.name.startsWith("instance") ? "instance" : "vertex"),
799
852
  attributes: [
800
853
  {
@@ -808,459 +861,250 @@ var __exports__ = (() => {
808
861
  }
809
862
  return vertexBufferLayouts;
810
863
  }
811
- function findAttributeLayout(shaderLayout, name, attributeNames) {
812
- const attribute = shaderLayout.attributes.find((attribute_) => attribute_.name === name);
864
+ function findAttributeLayout(shaderLayout, name2, attributeNames) {
865
+ const attribute = shaderLayout.attributes.find((attribute_) => attribute_.name === name2);
813
866
  if (!attribute) {
814
- import_core8.log.warn(`Supplied attribute not present in shader layout: ${name}`)();
867
+ import_core8.log.warn(`Supplied attribute not present in shader layout: ${name2}`)();
815
868
  return null;
816
869
  }
817
- if (attributeNames.has(name)) {
818
- throw new Error(`Found multiple entries for attribute: ${name}`);
870
+ if (attributeNames.has(name2)) {
871
+ throw new Error(`Found multiple entries for attribute: ${name2}`);
819
872
  }
820
- attributeNames.add(name);
873
+ attributeNames.add(name2);
821
874
  return attribute;
822
875
  }
876
+ var import_core8;
877
+ var init_get_vertex_buffer_layout = __esm({
878
+ "src/adapter/helpers/get-vertex-buffer-layout.ts"() {
879
+ "use strict";
880
+ import_core8 = __toESM(require_core(), 1);
881
+ }
882
+ });
823
883
 
824
884
  // src/adapter/resources/webgpu-render-pipeline.ts
825
- var WebGPURenderPipeline = class extends import_core9.RenderPipeline {
826
- device;
827
- handle;
828
- vs;
829
- fs = null;
830
- /** For internal use to create BindGroups */
831
- _bindings;
832
- _bindGroupLayout = null;
833
- _bindGroup = null;
834
- get [Symbol.toStringTag]() {
835
- return "WebGPURenderPipeline";
836
- }
837
- constructor(device, props) {
838
- super(device, props);
839
- this.device = device;
840
- this.handle = this.props.handle;
841
- if (!this.handle) {
842
- const descriptor = this._getRenderPipelineDescriptor();
843
- import_core9.log.groupCollapsed(1, `new WebGPURenderPipeline(${this.id})`)();
844
- import_core9.log.probe(1, JSON.stringify(descriptor, null, 2))();
845
- import_core9.log.groupEnd(1)();
846
- this.device.handle.pushErrorScope("validation");
847
- this.handle = this.device.handle.createRenderPipeline(descriptor);
848
- this.device.handle.popErrorScope().then((error) => {
849
- if (error) {
850
- import_core9.log.error(`${this} creation failed:
885
+ var import_core9, WebGPURenderPipeline;
886
+ var init_webgpu_render_pipeline = __esm({
887
+ "src/adapter/resources/webgpu-render-pipeline.ts"() {
888
+ "use strict";
889
+ import_core9 = __toESM(require_core(), 1);
890
+ init_webgpu_parameters();
891
+ init_convert_texture_format();
892
+ init_get_bind_group();
893
+ init_get_vertex_buffer_layout();
894
+ WebGPURenderPipeline = class extends import_core9.RenderPipeline {
895
+ device;
896
+ handle;
897
+ vs;
898
+ fs = null;
899
+ /** For internal use to create BindGroups */
900
+ _bindings;
901
+ _bindGroupLayout = null;
902
+ _bindGroup = null;
903
+ get [Symbol.toStringTag]() {
904
+ return "WebGPURenderPipeline";
905
+ }
906
+ constructor(device, props) {
907
+ super(device, props);
908
+ this.device = device;
909
+ this.handle = this.props.handle;
910
+ if (!this.handle) {
911
+ const descriptor = this._getRenderPipelineDescriptor();
912
+ import_core9.log.groupCollapsed(1, `new WebGPURenderPipeline(${this.id})`)();
913
+ import_core9.log.probe(1, JSON.stringify(descriptor, null, 2))();
914
+ import_core9.log.groupEnd(1)();
915
+ this.device.handle.pushErrorScope("validation");
916
+ this.handle = this.device.handle.createRenderPipeline(descriptor);
917
+ this.device.handle.popErrorScope().then((error) => {
918
+ if (error) {
919
+ import_core9.log.error(`${this} creation failed:
851
920
  "${error.message}"`, this, this.props.vs?.source)();
921
+ }
922
+ });
852
923
  }
853
- });
854
- }
855
- this.handle.label = this.props.id;
856
- this.vs = props.vs;
857
- this.fs = props.fs;
858
- this._bindings = { ...this.props.bindings };
859
- }
860
- destroy() {
861
- this.handle = null;
862
- }
863
- /**
864
- * @todo Use renderpass.setBindings() ?
865
- * @todo Do we want to expose BindGroups in the API and remove this?
866
- */
867
- setBindings(bindings) {
868
- for (const [name, binding] of Object.entries(bindings)) {
869
- if (this._bindings[name] !== binding) {
870
- this._bindGroup = null;
924
+ this.handle.label = this.props.id;
925
+ this.vs = props.vs;
926
+ this.fs = props.fs;
927
+ this._bindings = { ...this.props.bindings };
871
928
  }
872
- }
873
- Object.assign(this._bindings, bindings);
874
- }
875
- /** @todo - should this be moved to renderpass? */
876
- draw(options) {
877
- const webgpuRenderPass = options.renderPass;
878
- this.device.handle.pushErrorScope("validation");
879
- webgpuRenderPass.handle.setPipeline(this.handle);
880
- this.device.handle.popErrorScope().then((error) => {
881
- if (error) {
882
- import_core9.log.error(`${this} setPipeline failed:
929
+ destroy() {
930
+ this.handle = null;
931
+ }
932
+ /**
933
+ * @todo Use renderpass.setBindings() ?
934
+ * @todo Do we want to expose BindGroups in the API and remove this?
935
+ */
936
+ setBindings(bindings) {
937
+ for (const [name2, binding] of Object.entries(bindings)) {
938
+ if (this._bindings[name2] !== binding) {
939
+ this._bindGroup = null;
940
+ }
941
+ }
942
+ Object.assign(this._bindings, bindings);
943
+ }
944
+ /** @todo - should this be moved to renderpass? */
945
+ draw(options) {
946
+ const webgpuRenderPass = options.renderPass;
947
+ this.device.handle.pushErrorScope("validation");
948
+ webgpuRenderPass.handle.setPipeline(this.handle);
949
+ this.device.handle.popErrorScope().then((error) => {
950
+ if (error) {
951
+ import_core9.log.error(`${this} setPipeline failed:
883
952
  "${error.message}"`, this)();
953
+ }
954
+ });
955
+ const bindGroup = this._getBindGroup();
956
+ if (bindGroup) {
957
+ webgpuRenderPass.handle.setBindGroup(0, bindGroup);
958
+ }
959
+ options.vertexArray.bindBeforeRender(options.renderPass);
960
+ if (options.indexCount) {
961
+ webgpuRenderPass.handle.drawIndexed(
962
+ options.indexCount,
963
+ options.instanceCount,
964
+ options.firstIndex,
965
+ options.baseVertex,
966
+ options.firstInstance
967
+ );
968
+ } else {
969
+ webgpuRenderPass.handle.draw(
970
+ options.vertexCount || 0,
971
+ options.instanceCount || 1,
972
+ // If 0, nothing will be drawn
973
+ options.firstInstance
974
+ );
975
+ }
976
+ options.vertexArray.unbindAfterRender(options.renderPass);
977
+ return true;
884
978
  }
885
- });
886
- const bindGroup = this._getBindGroup();
887
- if (bindGroup) {
888
- webgpuRenderPass.handle.setBindGroup(0, bindGroup);
889
- }
890
- options.vertexArray.bindBeforeRender(options.renderPass);
891
- if (options.indexCount) {
892
- webgpuRenderPass.handle.drawIndexed(
893
- options.indexCount,
894
- options.instanceCount,
895
- options.firstIndex,
896
- options.baseVertex,
897
- options.firstInstance
898
- );
899
- } else {
900
- webgpuRenderPass.handle.draw(
901
- options.vertexCount || 0,
902
- options.instanceCount || 1,
903
- // If 0, nothing will be drawn
904
- options.firstInstance
905
- );
906
- }
907
- options.vertexArray.unbindAfterRender(options.renderPass);
908
- return true;
909
- }
910
- /** Return a bind group created by setBindings */
911
- _getBindGroup() {
912
- if (this.shaderLayout.bindings.length === 0) {
913
- return null;
914
- }
915
- this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
916
- this._bindGroup = this._bindGroup || getBindGroup(this.device.handle, this._bindGroupLayout, this.shaderLayout, this._bindings);
917
- return this._bindGroup;
918
- }
919
- /**
920
- * Populate the complex WebGPU GPURenderPipelineDescriptor
921
- */
922
- _getRenderPipelineDescriptor() {
923
- const vertex = {
924
- module: this.props.vs.handle,
925
- entryPoint: this.props.vertexEntryPoint || "main",
926
- buffers: getVertexBufferLayout(this.shaderLayout, this.props.bufferLayout)
927
- };
928
- const targets = [];
929
- if (this.props.colorAttachmentFormats) {
930
- for (const format of this.props.colorAttachmentFormats) {
931
- targets.push(format ? { format: getWebGPUTextureFormat(format) } : null);
979
+ /** Return a bind group created by setBindings */
980
+ _getBindGroup() {
981
+ if (this.shaderLayout.bindings.length === 0) {
982
+ return null;
983
+ }
984
+ this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
985
+ this._bindGroup = this._bindGroup || getBindGroup(this.device.handle, this._bindGroupLayout, this.shaderLayout, this._bindings);
986
+ return this._bindGroup;
987
+ }
988
+ /**
989
+ * Populate the complex WebGPU GPURenderPipelineDescriptor
990
+ */
991
+ _getRenderPipelineDescriptor() {
992
+ const vertex = {
993
+ module: this.props.vs.handle,
994
+ entryPoint: this.props.vertexEntryPoint || "main",
995
+ buffers: getVertexBufferLayout(this.shaderLayout, this.props.bufferLayout)
996
+ };
997
+ const targets = [];
998
+ if (this.props.colorAttachmentFormats) {
999
+ for (const format of this.props.colorAttachmentFormats) {
1000
+ targets.push(format ? { format: getWebGPUTextureFormat(format) } : null);
1001
+ }
1002
+ } else {
1003
+ targets.push({ format: getWebGPUTextureFormat(this.device.preferredColorFormat) });
1004
+ }
1005
+ const fragment = {
1006
+ module: this.props.fs.handle,
1007
+ entryPoint: this.props.fragmentEntryPoint || "main",
1008
+ targets
1009
+ };
1010
+ const descriptor = {
1011
+ vertex,
1012
+ fragment,
1013
+ primitive: {
1014
+ topology: this.props.topology
1015
+ },
1016
+ layout: "auto"
1017
+ };
1018
+ const depthFormat = this.props.depthStencilAttachmentFormat || this.device.preferredDepthFormat;
1019
+ if (this.props.parameters.depthWriteEnabled) {
1020
+ descriptor.depthStencil = {
1021
+ format: getWebGPUTextureFormat(depthFormat)
1022
+ };
1023
+ }
1024
+ applyParametersToRenderPipelineDescriptor(descriptor, this.props.parameters);
1025
+ return descriptor;
932
1026
  }
933
- } else {
934
- targets.push({ format: getWebGPUTextureFormat(this.device.preferredColorFormat) });
935
- }
936
- const fragment = {
937
- module: this.props.fs.handle,
938
- entryPoint: this.props.fragmentEntryPoint || "main",
939
- targets
940
- };
941
- const descriptor = {
942
- vertex,
943
- fragment,
944
- primitive: {
945
- topology: this.props.topology
946
- },
947
- layout: "auto"
948
1027
  };
949
- const depthFormat = this.props.depthStencilAttachmentFormat || this.device.preferredDepthFormat;
950
- if (this.props.parameters.depthWriteEnabled) {
951
- descriptor.depthStencil = {
952
- format: getWebGPUTextureFormat(depthFormat)
953
- };
954
- }
955
- applyParametersToRenderPipelineDescriptor(descriptor, this.props.parameters);
956
- return descriptor;
957
1028
  }
958
- };
1029
+ });
959
1030
 
960
1031
  // src/adapter/resources/webgpu-framebuffer.ts
961
- var import_core10 = __toESM(require_core(), 1);
962
- var WebGPUFramebuffer = class extends import_core10.Framebuffer {
963
- device;
964
- colorAttachments = [];
965
- depthStencilAttachment = null;
966
- constructor(device, props) {
967
- super(device, props);
968
- this.device = device;
969
- this.autoCreateAttachmentTextures();
970
- }
971
- updateAttachments() {
1032
+ var import_core10, WebGPUFramebuffer;
1033
+ var init_webgpu_framebuffer = __esm({
1034
+ "src/adapter/resources/webgpu-framebuffer.ts"() {
1035
+ "use strict";
1036
+ import_core10 = __toESM(require_core(), 1);
1037
+ WebGPUFramebuffer = class extends import_core10.Framebuffer {
1038
+ device;
1039
+ colorAttachments = [];
1040
+ depthStencilAttachment = null;
1041
+ constructor(device, props) {
1042
+ super(device, props);
1043
+ this.device = device;
1044
+ this.autoCreateAttachmentTextures();
1045
+ }
1046
+ updateAttachments() {
1047
+ }
1048
+ };
972
1049
  }
973
- };
1050
+ });
974
1051
 
975
1052
  // src/adapter/resources/webgpu-compute-pipeline.ts
976
- var import_core11 = __toESM(require_core(), 1);
977
- var WebGPUComputePipeline = class extends import_core11.ComputePipeline {
978
- device;
979
- handle;
980
- /** For internal use to create BindGroups */
981
- _bindGroupLayout = null;
982
- _bindGroup = null;
983
- /** For internal use to create BindGroups */
984
- _bindings = {};
985
- constructor(device, props) {
986
- super(device, props);
987
- this.device = device;
988
- const webgpuShader = this.props.shader;
989
- this.handle = this.props.handle || this.device.handle.createComputePipeline({
990
- label: this.props.id,
991
- compute: {
992
- module: webgpuShader.handle,
993
- entryPoint: this.props.entryPoint,
994
- constants: this.props.constants
995
- },
996
- layout: "auto"
997
- });
998
- }
999
- /**
1000
- * @todo Use renderpass.setBindings() ?
1001
- * @todo Do we want to expose BindGroups in the API and remove this?
1002
- */
1003
- setBindings(bindings) {
1004
- Object.assign(this._bindings, bindings);
1005
- }
1006
- /** Return a bind group created by setBindings */
1007
- _getBindGroup() {
1008
- this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
1009
- this._bindGroup = this._bindGroup || getBindGroup(this.device.handle, this._bindGroupLayout, this.shaderLayout, this._bindings);
1010
- return this._bindGroup;
1011
- }
1012
- };
1013
-
1014
- // src/adapter/resources/webgpu-render-pass.ts
1015
- var import_core12 = __toESM(require_core(), 1);
1016
- var WebGPURenderPass = class extends import_core12.RenderPass {
1017
- device;
1018
- handle;
1019
- /** Active pipeline */
1020
- pipeline = null;
1021
- constructor(device, props = {}) {
1022
- super(device, props);
1023
- this.device = device;
1024
- const framebuffer = props.framebuffer || device.getCanvasContext().getCurrentFramebuffer();
1025
- const renderPassDescriptor = this.getRenderPassDescriptor(framebuffer);
1026
- const webgpuQuerySet = props.timestampQuerySet;
1027
- if (webgpuQuerySet) {
1028
- renderPassDescriptor.occlusionQuerySet = webgpuQuerySet.handle;
1029
- }
1030
- if (device.features.has("timestamp-query")) {
1031
- const webgpuTSQuerySet = props.timestampQuerySet;
1032
- renderPassDescriptor.timestampWrites = webgpuTSQuerySet ? {
1033
- querySet: webgpuTSQuerySet.handle,
1034
- beginningOfPassWriteIndex: props.beginTimestampIndex,
1035
- endOfPassWriteIndex: props.endTimestampIndex
1036
- } : void 0;
1037
- }
1038
- if (!device.commandEncoder) {
1039
- throw new Error("commandEncoder not available");
1040
- }
1041
- this.device.handle.pushErrorScope("validation");
1042
- this.handle = this.props.handle || device.commandEncoder.beginRenderPass(renderPassDescriptor);
1043
- this.device.handle.popErrorScope().then((error) => {
1044
- if (error) {
1045
- import_core12.log.error(`${this} creation failed:
1046
- "${error.message}"`, this)();
1047
- }
1048
- });
1049
- this.handle.label = this.props.id;
1050
- import_core12.log.groupCollapsed(3, `new WebGPURenderPass(${this.id})`)();
1051
- import_core12.log.probe(3, JSON.stringify(renderPassDescriptor, null, 2))();
1052
- import_core12.log.groupEnd(3)();
1053
- }
1054
- destroy() {
1055
- }
1056
- end() {
1057
- this.handle.end();
1058
- }
1059
- setPipeline(pipeline) {
1060
- this.pipeline = pipeline;
1061
- this.handle.setPipeline(this.pipeline.handle);
1062
- }
1063
- /** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
1064
- setBindings(bindings) {
1065
- this.pipeline?.setBindings(bindings);
1066
- const bindGroup = this.pipeline?._getBindGroup();
1067
- if (bindGroup) {
1068
- this.handle.setBindGroup(0, bindGroup);
1069
- }
1070
- }
1071
- setIndexBuffer(buffer, indexFormat, offset = 0, size) {
1072
- this.handle.setIndexBuffer(buffer.handle, indexFormat, offset, size);
1073
- }
1074
- setVertexBuffer(slot, buffer, offset = 0) {
1075
- this.handle.setVertexBuffer(slot, buffer.handle, offset);
1076
- }
1077
- draw(options) {
1078
- if (options.indexCount) {
1079
- this.handle.drawIndexed(
1080
- options.indexCount,
1081
- options.instanceCount,
1082
- options.firstIndex,
1083
- options.baseVertex,
1084
- options.firstInstance
1085
- );
1086
- } else {
1087
- this.handle.draw(
1088
- options.vertexCount || 0,
1089
- options.instanceCount || 1,
1090
- options.firstIndex,
1091
- options.firstInstance
1092
- );
1093
- }
1094
- }
1095
- drawIndirect() {
1096
- }
1097
- setParameters(parameters) {
1098
- const { blendConstant, stencilReference, scissorRect, viewport } = parameters;
1099
- if (blendConstant) {
1100
- this.handle.setBlendConstant(blendConstant);
1101
- }
1102
- if (stencilReference) {
1103
- this.handle.setStencilReference(stencilReference);
1104
- }
1105
- if (scissorRect) {
1106
- this.handle.setScissorRect(scissorRect[0], scissorRect[1], scissorRect[2], scissorRect[3]);
1107
- }
1108
- if (viewport) {
1109
- this.handle.setViewport(
1110
- viewport[0],
1111
- viewport[1],
1112
- viewport[2],
1113
- viewport[3],
1114
- viewport[4],
1115
- viewport[5]
1116
- );
1117
- }
1118
- }
1119
- pushDebugGroup(groupLabel) {
1120
- this.handle.pushDebugGroup(groupLabel);
1121
- }
1122
- popDebugGroup() {
1123
- this.handle.popDebugGroup();
1124
- }
1125
- insertDebugMarker(markerLabel) {
1126
- this.handle.insertDebugMarker(markerLabel);
1127
- }
1128
- beginOcclusionQuery(queryIndex) {
1129
- this.handle.beginOcclusionQuery(queryIndex);
1130
- }
1131
- endOcclusionQuery() {
1132
- this.handle.endOcclusionQuery();
1133
- }
1134
- // executeBundles(bundles: Iterable<GPURenderBundle>): void;
1135
- // INTERNAL
1136
- /**
1137
- * Partial render pass descriptor. Used by WebGPURenderPass.
1138
- * @returns attachments fields of a renderpass descriptor.
1139
- */
1140
- getRenderPassDescriptor(framebuffer) {
1141
- const renderPassDescriptor = {
1142
- colorAttachments: []
1143
- };
1144
- renderPassDescriptor.colorAttachments = framebuffer.colorAttachments.map(
1145
- (colorAttachment, index) => ({
1146
- // clear values
1147
- loadOp: this.props.clearColor !== false ? "clear" : "load",
1148
- colorClearValue: this.props.clearColors?.[index] || this.props.clearColor || import_core12.RenderPass.defaultClearColor,
1149
- storeOp: this.props.discard ? "discard" : "store",
1150
- // ...colorAttachment,
1151
- view: colorAttachment.handle
1152
- })
1153
- );
1154
- if (framebuffer.depthStencilAttachment) {
1155
- renderPassDescriptor.depthStencilAttachment = {
1156
- view: framebuffer.depthStencilAttachment.handle
1157
- };
1158
- const { depthStencilAttachment } = renderPassDescriptor;
1159
- if (this.props.depthReadOnly) {
1160
- depthStencilAttachment.depthReadOnly = true;
1161
- }
1162
- if (this.props.clearDepth !== false) {
1163
- depthStencilAttachment.depthClearValue = this.props.clearDepth;
1164
- }
1165
- const hasDepthAspect = true;
1166
- if (hasDepthAspect) {
1167
- depthStencilAttachment.depthLoadOp = this.props.clearDepth !== false ? "clear" : "load";
1168
- depthStencilAttachment.depthStoreOp = "store";
1053
+ var import_core11, WebGPUComputePipeline;
1054
+ var init_webgpu_compute_pipeline = __esm({
1055
+ "src/adapter/resources/webgpu-compute-pipeline.ts"() {
1056
+ "use strict";
1057
+ import_core11 = __toESM(require_core(), 1);
1058
+ init_get_bind_group();
1059
+ WebGPUComputePipeline = class extends import_core11.ComputePipeline {
1060
+ device;
1061
+ handle;
1062
+ /** For internal use to create BindGroups */
1063
+ _bindGroupLayout = null;
1064
+ _bindGroup = null;
1065
+ /** For internal use to create BindGroups */
1066
+ _bindings = {};
1067
+ constructor(device, props) {
1068
+ super(device, props);
1069
+ this.device = device;
1070
+ const webgpuShader = this.props.shader;
1071
+ this.handle = this.props.handle || this.device.handle.createComputePipeline({
1072
+ label: this.props.id,
1073
+ compute: {
1074
+ module: webgpuShader.handle,
1075
+ entryPoint: this.props.entryPoint,
1076
+ constants: this.props.constants
1077
+ },
1078
+ layout: "auto"
1079
+ });
1169
1080
  }
1170
- const hasStencilAspect = false;
1171
- if (hasStencilAspect) {
1172
- depthStencilAttachment.stencilLoadOp = this.props.clearStencil !== false ? "clear" : "load";
1173
- depthStencilAttachment.stencilStoreOp = "store";
1081
+ /**
1082
+ * @todo Use renderpass.setBindings() ?
1083
+ * @todo Do we want to expose BindGroups in the API and remove this?
1084
+ */
1085
+ setBindings(bindings) {
1086
+ Object.assign(this._bindings, bindings);
1174
1087
  }
1175
- }
1176
- return renderPassDescriptor;
1177
- }
1178
- };
1179
-
1180
- // src/adapter/resources/webgpu-compute-pass.ts
1181
- var import_core13 = __toESM(require_core(), 1);
1182
- var WebGPUComputePass = class extends import_core13.ComputePass {
1183
- device;
1184
- handle;
1185
- _webgpuPipeline = null;
1186
- constructor(device, props) {
1187
- super(device, props);
1188
- this.device = device;
1189
- let timestampWrites;
1190
- if (device.features.has("timestamp-query")) {
1191
- const webgpuQuerySet = props.timestampQuerySet;
1192
- if (webgpuQuerySet) {
1193
- timestampWrites = {
1194
- querySet: webgpuQuerySet.handle,
1195
- beginningOfPassWriteIndex: props.beginTimestampIndex,
1196
- endOfPassWriteIndex: props.endTimestampIndex
1197
- };
1088
+ /** Return a bind group created by setBindings */
1089
+ _getBindGroup() {
1090
+ this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
1091
+ this._bindGroup = this._bindGroup || getBindGroup(this.device.handle, this._bindGroupLayout, this.shaderLayout, this._bindings);
1092
+ return this._bindGroup;
1198
1093
  }
1199
- }
1200
- this.handle = this.props.handle || device.commandEncoder?.beginComputePass({
1201
- label: this.props.id,
1202
- timestampWrites
1203
- });
1204
- }
1205
- /** @note no WebGPU destroy method, just gc */
1206
- destroy() {
1207
- }
1208
- end() {
1209
- this.handle.end();
1210
- }
1211
- setPipeline(pipeline) {
1212
- const wgpuPipeline = pipeline;
1213
- this.handle.setPipeline(wgpuPipeline.handle);
1214
- this._webgpuPipeline = wgpuPipeline;
1215
- this.setBindings([]);
1216
- }
1217
- /**
1218
- * Sets an array of bindings (uniform buffers, samplers, textures, ...)
1219
- * TODO - still some API confusion - does this method go here or on the pipeline?
1220
- */
1221
- setBindings(bindings) {
1222
- const bindGroup = this._webgpuPipeline._getBindGroup();
1223
- this.handle.setBindGroup(0, bindGroup);
1224
- }
1225
- /**
1226
- * Dispatch work to be performed with the current ComputePipeline.
1227
- * @param x X dimension of the grid of work groups to dispatch.
1228
- * @param y Y dimension of the grid of work groups to dispatch.
1229
- * @param z Z dimension of the grid of work groups to dispatch.
1230
- */
1231
- dispatch(x, y, z) {
1232
- this.handle.dispatchWorkgroups(x, y, z);
1233
- }
1234
- /**
1235
- * Dispatch work to be performed with the current ComputePipeline.
1236
- *
1237
- * Buffer must be a tightly packed block of three 32-bit unsigned integer values (12 bytes total), given in the same order as the arguments for dispatch()
1238
- * @param indirectBuffer
1239
- * @param indirectOffset offset in buffer to the beginning of the dispatch data.
1240
- */
1241
- dispatchIndirect(indirectBuffer, indirectByteOffset = 0) {
1242
- const webgpuBuffer = indirectBuffer;
1243
- this.handle.dispatchWorkgroupsIndirect(webgpuBuffer.handle, indirectByteOffset);
1244
- }
1245
- pushDebugGroup(groupLabel) {
1246
- this.handle.pushDebugGroup(groupLabel);
1247
- }
1248
- popDebugGroup() {
1249
- this.handle.popDebugGroup();
1250
- }
1251
- insertDebugMarker(markerLabel) {
1252
- this.handle.insertDebugMarker(markerLabel);
1094
+ };
1253
1095
  }
1254
- };
1255
-
1256
- // src/adapter/resources/webgpu-vertex-array.ts
1257
- var import_core14 = __toESM(require_core(), 1);
1096
+ });
1258
1097
 
1259
1098
  // ../../node_modules/@probe.gl/env/dist/lib/globals.js
1260
- var document_ = globalThis.document || {};
1261
- var process_ = globalThis.process || {};
1262
- var console_ = globalThis.console;
1263
- var navigator_ = globalThis.navigator || {};
1099
+ var document_, process_, console_, navigator_;
1100
+ var init_globals = __esm({
1101
+ "../../node_modules/@probe.gl/env/dist/lib/globals.js"() {
1102
+ document_ = globalThis.document || {};
1103
+ process_ = globalThis.process || {};
1104
+ console_ = globalThis.console;
1105
+ navigator_ = globalThis.navigator || {};
1106
+ }
1107
+ });
1264
1108
 
1265
1109
  // ../../node_modules/@probe.gl/env/dist/lib/is-electron.js
1266
1110
  function isElectron(mockUserAgent) {
@@ -1274,6 +1118,10 @@ var __exports__ = (() => {
1274
1118
  const userAgent = mockUserAgent || realUserAgent;
1275
1119
  return Boolean(userAgent && userAgent.indexOf("Electron") >= 0);
1276
1120
  }
1121
+ var init_is_electron = __esm({
1122
+ "../../node_modules/@probe.gl/env/dist/lib/is-electron.js"() {
1123
+ }
1124
+ });
1277
1125
 
1278
1126
  // ../../node_modules/@probe.gl/env/dist/lib/is-browser.js
1279
1127
  function isBrowser() {
@@ -1283,6 +1131,11 @@ var __exports__ = (() => {
1283
1131
  );
1284
1132
  return !isNode || isElectron();
1285
1133
  }
1134
+ var init_is_browser = __esm({
1135
+ "../../node_modules/@probe.gl/env/dist/lib/is-browser.js"() {
1136
+ init_is_electron();
1137
+ }
1138
+ });
1286
1139
 
1287
1140
  // ../../node_modules/@probe.gl/env/dist/lib/get-browser.js
1288
1141
  function getBrowser(mockUserAgent) {
@@ -1307,417 +1160,823 @@ var __exports__ = (() => {
1307
1160
  }
1308
1161
  return "Unknown";
1309
1162
  }
1310
-
1311
- // src/adapter/resources/webgpu-vertex-array.ts
1312
- var WebGPUVertexArray = class extends import_core14.VertexArray {
1313
- get [Symbol.toStringTag]() {
1314
- return "WebGPUVertexArray";
1315
- }
1316
- device;
1317
- /** Vertex Array is a helper class under WebGPU */
1318
- handle;
1319
- // Create a VertexArray
1320
- constructor(device, props) {
1321
- super(device, props);
1322
- this.device = device;
1323
- }
1324
- destroy() {
1163
+ var init_get_browser = __esm({
1164
+ "../../node_modules/@probe.gl/env/dist/lib/get-browser.js"() {
1165
+ init_is_browser();
1166
+ init_is_electron();
1167
+ init_globals();
1325
1168
  }
1326
- /**
1327
- * Set an elements buffer, for indexed rendering.
1328
- * Must be a Buffer bound to buffer with usage bit Buffer.INDEX set.
1329
- */
1330
- setIndexBuffer(buffer) {
1331
- this.indexBuffer = buffer;
1332
- }
1333
- /** Set a bufferSlot in vertex attributes array to a buffer, enables the bufferSlot, sets divisor */
1334
- setBuffer(bufferSlot, buffer) {
1335
- this.attributes[bufferSlot] = buffer;
1169
+ });
1170
+
1171
+ // ../../node_modules/@probe.gl/env/dist/index.js
1172
+ var init_dist = __esm({
1173
+ "../../node_modules/@probe.gl/env/dist/index.js"() {
1174
+ init_get_browser();
1336
1175
  }
1337
- bindBeforeRender(renderPass, firstIndex, indexCount) {
1338
- const webgpuRenderPass = renderPass;
1339
- const webgpuIndexBuffer = this.indexBuffer;
1340
- if (webgpuIndexBuffer?.handle) {
1341
- import_core14.log.info(
1342
- 3,
1343
- "setting index buffer",
1344
- webgpuIndexBuffer?.handle,
1345
- webgpuIndexBuffer?.indexType
1346
- )();
1347
- webgpuRenderPass.handle.setIndexBuffer(
1348
- webgpuIndexBuffer?.handle,
1349
- // @ts-expect-error TODO - we must enforce type
1350
- webgpuIndexBuffer?.indexType
1351
- );
1352
- }
1353
- for (let location = 0; location < this.maxVertexAttributes; location++) {
1354
- const webgpuBuffer = this.attributes[location];
1355
- if (webgpuBuffer?.handle) {
1356
- import_core14.log.info(3, `setting vertex buffer ${location}`, webgpuBuffer?.handle)();
1357
- webgpuRenderPass.handle.setVertexBuffer(location, webgpuBuffer?.handle);
1176
+ });
1177
+
1178
+ // src/adapter/resources/webgpu-vertex-array.ts
1179
+ var import_core12, WebGPUVertexArray;
1180
+ var init_webgpu_vertex_array = __esm({
1181
+ "src/adapter/resources/webgpu-vertex-array.ts"() {
1182
+ "use strict";
1183
+ import_core12 = __toESM(require_core(), 1);
1184
+ init_dist();
1185
+ WebGPUVertexArray = class extends import_core12.VertexArray {
1186
+ get [Symbol.toStringTag]() {
1187
+ return "WebGPUVertexArray";
1358
1188
  }
1359
- }
1360
- }
1361
- unbindAfterRender(renderPass) {
1362
- }
1363
- // DEPRECATED METHODS
1364
- /**
1365
- * @deprecated is this even an issue for WebGPU?
1366
- * Attribute 0 can not be disable on most desktop OpenGL based browsers
1367
- */
1368
- static isConstantAttributeZeroSupported(device) {
1369
- return getBrowser() === "Chrome";
1189
+ device;
1190
+ /** Vertex Array is just a helper class under WebGPU */
1191
+ handle = null;
1192
+ // Create a VertexArray
1193
+ constructor(device, props) {
1194
+ super(device, props);
1195
+ this.device = device;
1196
+ }
1197
+ destroy() {
1198
+ }
1199
+ /**
1200
+ * Set an elements buffer, for indexed rendering.
1201
+ * Must be a Buffer bound to buffer with usage bit Buffer.INDEX set.
1202
+ */
1203
+ setIndexBuffer(buffer) {
1204
+ this.indexBuffer = buffer;
1205
+ }
1206
+ /** Set a bufferSlot in vertex attributes array to a buffer, enables the bufferSlot, sets divisor */
1207
+ setBuffer(bufferSlot, buffer) {
1208
+ this.attributes[bufferSlot] = buffer;
1209
+ }
1210
+ bindBeforeRender(renderPass, firstIndex, indexCount) {
1211
+ const webgpuRenderPass = renderPass;
1212
+ const webgpuIndexBuffer = this.indexBuffer;
1213
+ if (webgpuIndexBuffer?.handle) {
1214
+ import_core12.log.info(
1215
+ 3,
1216
+ "setting index buffer",
1217
+ webgpuIndexBuffer?.handle,
1218
+ webgpuIndexBuffer?.indexType
1219
+ )();
1220
+ webgpuRenderPass.handle.setIndexBuffer(
1221
+ webgpuIndexBuffer?.handle,
1222
+ // @ts-expect-error TODO - we must enforce type
1223
+ webgpuIndexBuffer?.indexType
1224
+ );
1225
+ }
1226
+ for (let location = 0; location < this.maxVertexAttributes; location++) {
1227
+ const webgpuBuffer = this.attributes[location];
1228
+ if (webgpuBuffer?.handle) {
1229
+ import_core12.log.info(3, `setting vertex buffer ${location}`, webgpuBuffer?.handle)();
1230
+ webgpuRenderPass.handle.setVertexBuffer(location, webgpuBuffer?.handle);
1231
+ }
1232
+ }
1233
+ }
1234
+ unbindAfterRender(renderPass) {
1235
+ }
1236
+ // DEPRECATED METHODS
1237
+ /**
1238
+ * @deprecated is this even an issue for WebGPU?
1239
+ * Attribute 0 can not be disable on most desktop OpenGL based browsers
1240
+ */
1241
+ static isConstantAttributeZeroSupported(device) {
1242
+ return getBrowser() === "Chrome";
1243
+ }
1244
+ };
1370
1245
  }
1371
- };
1246
+ });
1372
1247
 
1373
1248
  // src/adapter/webgpu-canvas-context.ts
1374
- var import_core15 = __toESM(require_core(), 1);
1375
- var WebGPUCanvasContext = class extends import_core15.CanvasContext {
1376
- device;
1377
- handle;
1378
- depthStencilAttachment = null;
1379
- get [Symbol.toStringTag]() {
1380
- return "WebGPUCanvasContext";
1381
- }
1382
- constructor(device, adapter, props) {
1383
- super(props);
1384
- this.device = device;
1385
- this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
1386
- this.updateSize([this.drawingBufferWidth, this.drawingBufferHeight]);
1387
- }
1388
- /** Destroy any textures produced while configured and remove the context configuration. */
1389
- destroy() {
1390
- this.handle.unconfigure();
1391
- }
1392
- /** Update framebuffer with properly resized "swap chain" texture views */
1393
- getCurrentFramebuffer(options = {
1394
- depthStencilFormat: "depth24plus"
1395
- }) {
1396
- const currentColorAttachment = this.getCurrentTexture();
1397
- if (currentColorAttachment.width !== this.drawingBufferWidth || currentColorAttachment.height !== this.drawingBufferHeight) {
1398
- const [oldWidth, oldHeight] = this.getDrawingBufferSize();
1399
- this.drawingBufferWidth = currentColorAttachment.width;
1400
- this.drawingBufferHeight = currentColorAttachment.height;
1401
- import_core15.log.log(
1402
- 1,
1403
- `${this}: Resized to compensate for initial canvas size mismatch ${oldWidth}x${oldHeight} => ${this.drawingBufferWidth}x${this.drawingBufferHeight}px`
1404
- )();
1405
- }
1406
- if (options?.depthStencilFormat) {
1407
- this._createDepthStencilAttachment(options?.depthStencilFormat);
1408
- }
1409
- return new WebGPUFramebuffer(this.device, {
1410
- colorAttachments: [currentColorAttachment],
1411
- depthStencilAttachment: this.depthStencilAttachment
1412
- });
1249
+ var import_core13, WebGPUCanvasContext;
1250
+ var init_webgpu_canvas_context = __esm({
1251
+ "src/adapter/webgpu-canvas-context.ts"() {
1252
+ "use strict";
1253
+ import_core13 = __toESM(require_core(), 1);
1254
+ init_webgpu_framebuffer();
1255
+ WebGPUCanvasContext = class extends import_core13.CanvasContext {
1256
+ device;
1257
+ handle;
1258
+ depthStencilAttachment = null;
1259
+ get [Symbol.toStringTag]() {
1260
+ return "WebGPUCanvasContext";
1261
+ }
1262
+ constructor(device, adapter, props) {
1263
+ super(props);
1264
+ const context = this.canvas.getContext("webgpu");
1265
+ if (!context) {
1266
+ throw new Error(`${this}: Failed to create WebGPU canvas context`);
1267
+ }
1268
+ this.device = device;
1269
+ this.handle = context;
1270
+ this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
1271
+ this._updateDevice();
1272
+ }
1273
+ /** Destroy any textures produced while configured and remove the context configuration. */
1274
+ destroy() {
1275
+ this.handle.unconfigure();
1276
+ }
1277
+ /** Update framebuffer with properly resized "swap chain" texture views */
1278
+ getCurrentFramebuffer(options = {
1279
+ depthStencilFormat: "depth24plus"
1280
+ }) {
1281
+ const currentColorAttachment = this.getCurrentTexture();
1282
+ if (currentColorAttachment.width !== this.drawingBufferWidth || currentColorAttachment.height !== this.drawingBufferHeight) {
1283
+ const [oldWidth, oldHeight] = this.getDrawingBufferSize();
1284
+ this.drawingBufferWidth = currentColorAttachment.width;
1285
+ this.drawingBufferHeight = currentColorAttachment.height;
1286
+ import_core13.log.log(
1287
+ 1,
1288
+ `${this}: Resized to compensate for initial canvas size mismatch ${oldWidth}x${oldHeight} => ${this.drawingBufferWidth}x${this.drawingBufferHeight}px`
1289
+ )();
1290
+ }
1291
+ if (options?.depthStencilFormat) {
1292
+ this._createDepthStencilAttachment(options?.depthStencilFormat);
1293
+ }
1294
+ return new WebGPUFramebuffer(this.device, {
1295
+ colorAttachments: [currentColorAttachment],
1296
+ depthStencilAttachment: this.depthStencilAttachment
1297
+ });
1298
+ }
1299
+ // IMPLEMENTATION OF ABSTRACT METHODS
1300
+ _updateDevice() {
1301
+ if (this.depthStencilAttachment) {
1302
+ this.depthStencilAttachment.destroy();
1303
+ this.depthStencilAttachment = null;
1304
+ }
1305
+ this.handle.configure({
1306
+ device: this.device.handle,
1307
+ format: this.device.preferredColorFormat,
1308
+ // Can be used to define e.g. -srgb views
1309
+ // viewFormats: [...]
1310
+ colorSpace: this.props.colorSpace,
1311
+ alphaMode: this.props.alphaMode
1312
+ });
1313
+ }
1314
+ /** Wrap the current canvas context texture in a luma.gl texture */
1315
+ getCurrentTexture() {
1316
+ const handle = this.handle.getCurrentTexture();
1317
+ return this.device.createTexture({
1318
+ id: `${this.id}#color-texture`,
1319
+ handle,
1320
+ format: this.device.preferredColorFormat,
1321
+ width: handle.width,
1322
+ height: handle.height
1323
+ });
1324
+ }
1325
+ /** We build render targets on demand (i.e. not when size changes but when about to render) */
1326
+ _createDepthStencilAttachment(depthStencilFormat) {
1327
+ if (!this.depthStencilAttachment) {
1328
+ this.depthStencilAttachment = this.device.createTexture({
1329
+ id: `${this.id}#depth-stencil-texture`,
1330
+ usage: import_core13.Texture.RENDER_ATTACHMENT,
1331
+ format: depthStencilFormat,
1332
+ width: this.drawingBufferWidth,
1333
+ height: this.drawingBufferHeight
1334
+ });
1335
+ }
1336
+ return this.depthStencilAttachment;
1337
+ }
1338
+ };
1413
1339
  }
1414
- /** Resizes and updates render targets if necessary */
1415
- updateSize(size) {
1416
- if (this.depthStencilAttachment) {
1417
- this.depthStencilAttachment.destroy();
1418
- this.depthStencilAttachment = null;
1419
- }
1420
- this.handle.configure({
1421
- device: this.device.handle,
1422
- format: this.device.preferredColorFormat,
1423
- // Can be used to define e.g. -srgb views
1424
- // viewFormats: [...]
1425
- colorSpace: this.props.colorSpace,
1426
- alphaMode: this.props.alphaMode
1427
- });
1340
+ });
1341
+
1342
+ // src/adapter/resources/webgpu-command-buffer.ts
1343
+ var import_core14, WebGPUCommandBuffer;
1344
+ var init_webgpu_command_buffer = __esm({
1345
+ "src/adapter/resources/webgpu-command-buffer.ts"() {
1346
+ "use strict";
1347
+ import_core14 = __toESM(require_core(), 1);
1348
+ WebGPUCommandBuffer = class extends import_core14.CommandBuffer {
1349
+ device;
1350
+ handle;
1351
+ constructor(commandEncoder, props) {
1352
+ super(commandEncoder.device, {});
1353
+ this.device = commandEncoder.device;
1354
+ this.handle = this.props.handle || commandEncoder.handle.finish({
1355
+ label: props?.id || "unnamed-command-buffer"
1356
+ });
1357
+ }
1358
+ };
1428
1359
  }
1429
- resize(options) {
1430
- if (!this.device.handle)
1431
- return;
1432
- if (this.props.autoResize) {
1433
- return;
1434
- }
1435
- if (this.canvas) {
1436
- const devicePixelRatio = this.getDevicePixelRatio(options?.useDevicePixels);
1437
- this._setDevicePixelRatio(devicePixelRatio, options);
1438
- return;
1439
- }
1360
+ });
1361
+
1362
+ // src/adapter/resources/webgpu-render-pass.ts
1363
+ var import_core15, WebGPURenderPass;
1364
+ var init_webgpu_render_pass = __esm({
1365
+ "src/adapter/resources/webgpu-render-pass.ts"() {
1366
+ "use strict";
1367
+ import_core15 = __toESM(require_core(), 1);
1368
+ WebGPURenderPass = class extends import_core15.RenderPass {
1369
+ device;
1370
+ handle;
1371
+ /** Active pipeline */
1372
+ pipeline = null;
1373
+ constructor(device, props = {}) {
1374
+ super(device, props);
1375
+ this.device = device;
1376
+ const framebuffer = props.framebuffer || device.getCanvasContext().getCurrentFramebuffer();
1377
+ const renderPassDescriptor = this.getRenderPassDescriptor(framebuffer);
1378
+ const webgpuQuerySet = props.timestampQuerySet;
1379
+ if (webgpuQuerySet) {
1380
+ renderPassDescriptor.occlusionQuerySet = webgpuQuerySet.handle;
1381
+ }
1382
+ if (device.features.has("timestamp-query")) {
1383
+ const webgpuTSQuerySet = props.timestampQuerySet;
1384
+ renderPassDescriptor.timestampWrites = webgpuTSQuerySet ? {
1385
+ querySet: webgpuTSQuerySet.handle,
1386
+ beginningOfPassWriteIndex: props.beginTimestampIndex,
1387
+ endOfPassWriteIndex: props.endTimestampIndex
1388
+ } : void 0;
1389
+ }
1390
+ if (!device.commandEncoder) {
1391
+ throw new Error("commandEncoder not available");
1392
+ }
1393
+ this.device.handle.pushErrorScope("validation");
1394
+ this.handle = this.props.handle || device.commandEncoder.handle.beginRenderPass(renderPassDescriptor);
1395
+ this.device.handle.popErrorScope().then((error) => {
1396
+ if (error) {
1397
+ import_core15.log.error(`${this} creation failed:
1398
+ "${error.message}"`, this)();
1399
+ }
1400
+ });
1401
+ this.handle.label = this.props.id;
1402
+ import_core15.log.groupCollapsed(3, `new WebGPURenderPass(${this.id})`)();
1403
+ import_core15.log.probe(3, JSON.stringify(renderPassDescriptor, null, 2))();
1404
+ import_core15.log.groupEnd(3)();
1405
+ }
1406
+ destroy() {
1407
+ }
1408
+ end() {
1409
+ this.handle.end();
1410
+ }
1411
+ setPipeline(pipeline) {
1412
+ this.pipeline = pipeline;
1413
+ this.handle.setPipeline(this.pipeline.handle);
1414
+ }
1415
+ /** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
1416
+ setBindings(bindings) {
1417
+ this.pipeline?.setBindings(bindings);
1418
+ const bindGroup = this.pipeline?._getBindGroup();
1419
+ if (bindGroup) {
1420
+ this.handle.setBindGroup(0, bindGroup);
1421
+ }
1422
+ }
1423
+ setIndexBuffer(buffer, indexFormat, offset = 0, size) {
1424
+ this.handle.setIndexBuffer(buffer.handle, indexFormat, offset, size);
1425
+ }
1426
+ setVertexBuffer(slot, buffer, offset = 0) {
1427
+ this.handle.setVertexBuffer(slot, buffer.handle, offset);
1428
+ }
1429
+ draw(options) {
1430
+ if (options.indexCount) {
1431
+ this.handle.drawIndexed(
1432
+ options.indexCount,
1433
+ options.instanceCount,
1434
+ options.firstIndex,
1435
+ options.baseVertex,
1436
+ options.firstInstance
1437
+ );
1438
+ } else {
1439
+ this.handle.draw(
1440
+ options.vertexCount || 0,
1441
+ options.instanceCount || 1,
1442
+ options.firstIndex,
1443
+ options.firstInstance
1444
+ );
1445
+ }
1446
+ }
1447
+ drawIndirect() {
1448
+ }
1449
+ setParameters(parameters) {
1450
+ const { blendConstant, stencilReference, scissorRect, viewport } = parameters;
1451
+ if (blendConstant) {
1452
+ this.handle.setBlendConstant(blendConstant);
1453
+ }
1454
+ if (stencilReference) {
1455
+ this.handle.setStencilReference(stencilReference);
1456
+ }
1457
+ if (scissorRect) {
1458
+ this.handle.setScissorRect(scissorRect[0], scissorRect[1], scissorRect[2], scissorRect[3]);
1459
+ }
1460
+ if (viewport) {
1461
+ this.handle.setViewport(
1462
+ viewport[0],
1463
+ viewport[1],
1464
+ viewport[2],
1465
+ viewport[3],
1466
+ viewport[4],
1467
+ viewport[5]
1468
+ );
1469
+ }
1470
+ }
1471
+ pushDebugGroup(groupLabel) {
1472
+ this.handle.pushDebugGroup(groupLabel);
1473
+ }
1474
+ popDebugGroup() {
1475
+ this.handle.popDebugGroup();
1476
+ }
1477
+ insertDebugMarker(markerLabel) {
1478
+ this.handle.insertDebugMarker(markerLabel);
1479
+ }
1480
+ beginOcclusionQuery(queryIndex) {
1481
+ this.handle.beginOcclusionQuery(queryIndex);
1482
+ }
1483
+ endOcclusionQuery() {
1484
+ this.handle.endOcclusionQuery();
1485
+ }
1486
+ // executeBundles(bundles: Iterable<GPURenderBundle>): void;
1487
+ // INTERNAL
1488
+ /**
1489
+ * Partial render pass descriptor. Used by WebGPURenderPass.
1490
+ * @returns attachments fields of a renderpass descriptor.
1491
+ */
1492
+ getRenderPassDescriptor(framebuffer) {
1493
+ const renderPassDescriptor = {
1494
+ colorAttachments: []
1495
+ };
1496
+ renderPassDescriptor.colorAttachments = framebuffer.colorAttachments.map(
1497
+ (colorAttachment, index) => ({
1498
+ // clear values
1499
+ loadOp: this.props.clearColor !== false ? "clear" : "load",
1500
+ colorClearValue: this.props.clearColors?.[index] || this.props.clearColor || import_core15.RenderPass.defaultClearColor,
1501
+ storeOp: this.props.discard ? "discard" : "store",
1502
+ // ...colorAttachment,
1503
+ view: colorAttachment.handle
1504
+ })
1505
+ );
1506
+ if (framebuffer.depthStencilAttachment) {
1507
+ renderPassDescriptor.depthStencilAttachment = {
1508
+ view: framebuffer.depthStencilAttachment.handle
1509
+ };
1510
+ const { depthStencilAttachment } = renderPassDescriptor;
1511
+ if (this.props.depthReadOnly) {
1512
+ depthStencilAttachment.depthReadOnly = true;
1513
+ }
1514
+ if (this.props.clearDepth !== false) {
1515
+ depthStencilAttachment.depthClearValue = this.props.clearDepth;
1516
+ }
1517
+ const hasDepthAspect = true;
1518
+ if (hasDepthAspect) {
1519
+ depthStencilAttachment.depthLoadOp = this.props.clearDepth !== false ? "clear" : "load";
1520
+ depthStencilAttachment.depthStoreOp = "store";
1521
+ }
1522
+ const hasStencilAspect = false;
1523
+ if (hasStencilAspect) {
1524
+ depthStencilAttachment.stencilLoadOp = this.props.clearStencil !== false ? "clear" : "load";
1525
+ depthStencilAttachment.stencilStoreOp = "store";
1526
+ }
1527
+ }
1528
+ return renderPassDescriptor;
1529
+ }
1530
+ };
1440
1531
  }
1441
- /** Wrap the current canvas context texture in a luma.gl texture */
1442
- getCurrentTexture() {
1443
- return this.device.createTexture({
1444
- id: `${this.id}#color-texture`,
1445
- handle: this.handle.getCurrentTexture(),
1446
- format: this.device.preferredColorFormat
1447
- });
1532
+ });
1533
+
1534
+ // src/adapter/resources/webgpu-compute-pass.ts
1535
+ var import_core16, WebGPUComputePass;
1536
+ var init_webgpu_compute_pass = __esm({
1537
+ "src/adapter/resources/webgpu-compute-pass.ts"() {
1538
+ "use strict";
1539
+ import_core16 = __toESM(require_core(), 1);
1540
+ WebGPUComputePass = class extends import_core16.ComputePass {
1541
+ device;
1542
+ handle;
1543
+ _webgpuPipeline = null;
1544
+ constructor(device, props) {
1545
+ super(device, props);
1546
+ this.device = device;
1547
+ let timestampWrites;
1548
+ if (device.features.has("timestamp-query")) {
1549
+ const webgpuQuerySet = props.timestampQuerySet;
1550
+ if (webgpuQuerySet) {
1551
+ timestampWrites = {
1552
+ querySet: webgpuQuerySet.handle,
1553
+ beginningOfPassWriteIndex: props.beginTimestampIndex,
1554
+ endOfPassWriteIndex: props.endTimestampIndex
1555
+ };
1556
+ }
1557
+ }
1558
+ this.handle = this.props.handle || device.commandEncoder.handle.beginComputePass({
1559
+ label: this.props.id,
1560
+ timestampWrites
1561
+ });
1562
+ }
1563
+ /** @note no WebGPU destroy method, just gc */
1564
+ destroy() {
1565
+ }
1566
+ end() {
1567
+ this.handle.end();
1568
+ }
1569
+ setPipeline(pipeline) {
1570
+ const wgpuPipeline = pipeline;
1571
+ this.handle.setPipeline(wgpuPipeline.handle);
1572
+ this._webgpuPipeline = wgpuPipeline;
1573
+ this.setBindings([]);
1574
+ }
1575
+ /**
1576
+ * Sets an array of bindings (uniform buffers, samplers, textures, ...)
1577
+ * TODO - still some API confusion - does this method go here or on the pipeline?
1578
+ */
1579
+ setBindings(bindings) {
1580
+ const bindGroup = this._webgpuPipeline._getBindGroup();
1581
+ this.handle.setBindGroup(0, bindGroup);
1582
+ }
1583
+ /**
1584
+ * Dispatch work to be performed with the current ComputePipeline.
1585
+ * @param x X dimension of the grid of work groups to dispatch.
1586
+ * @param y Y dimension of the grid of work groups to dispatch.
1587
+ * @param z Z dimension of the grid of work groups to dispatch.
1588
+ */
1589
+ dispatch(x, y, z) {
1590
+ this.handle.dispatchWorkgroups(x, y, z);
1591
+ }
1592
+ /**
1593
+ * Dispatch work to be performed with the current ComputePipeline.
1594
+ *
1595
+ * Buffer must be a tightly packed block of three 32-bit unsigned integer values (12 bytes total), given in the same order as the arguments for dispatch()
1596
+ * @param indirectBuffer
1597
+ * @param indirectOffset offset in buffer to the beginning of the dispatch data.
1598
+ */
1599
+ dispatchIndirect(indirectBuffer, indirectByteOffset = 0) {
1600
+ const webgpuBuffer = indirectBuffer;
1601
+ this.handle.dispatchWorkgroupsIndirect(webgpuBuffer.handle, indirectByteOffset);
1602
+ }
1603
+ pushDebugGroup(groupLabel) {
1604
+ this.handle.pushDebugGroup(groupLabel);
1605
+ }
1606
+ popDebugGroup() {
1607
+ this.handle.popDebugGroup();
1608
+ }
1609
+ insertDebugMarker(markerLabel) {
1610
+ this.handle.insertDebugMarker(markerLabel);
1611
+ }
1612
+ };
1448
1613
  }
1449
- /** We build render targets on demand (i.e. not when size changes but when about to render) */
1450
- _createDepthStencilAttachment(depthStencilFormat) {
1451
- if (!this.depthStencilAttachment) {
1452
- this.depthStencilAttachment = this.device.createTexture({
1453
- id: `${this.id}#depth-stencil-texture`,
1454
- usage: import_core15.Texture.RENDER_ATTACHMENT,
1455
- format: depthStencilFormat,
1456
- width: this.drawingBufferWidth,
1457
- height: this.drawingBufferHeight
1458
- });
1459
- }
1460
- return this.depthStencilAttachment;
1614
+ });
1615
+
1616
+ // src/adapter/resources/webgpu-command-encoder.ts
1617
+ var import_core17, WebGPUCommandEncoder;
1618
+ var init_webgpu_command_encoder = __esm({
1619
+ "src/adapter/resources/webgpu-command-encoder.ts"() {
1620
+ "use strict";
1621
+ import_core17 = __toESM(require_core(), 1);
1622
+ init_webgpu_command_buffer();
1623
+ init_webgpu_render_pass();
1624
+ init_webgpu_compute_pass();
1625
+ WebGPUCommandEncoder = class extends import_core17.CommandEncoder {
1626
+ device;
1627
+ handle;
1628
+ constructor(device, props = {}) {
1629
+ super(device, props);
1630
+ this.device = device;
1631
+ this.handle = props.handle || this.device.handle.createCommandEncoder({
1632
+ label: this.props.id
1633
+ // TODO was this removed in standard?
1634
+ // measureExecutionTime: this.props.measureExecutionTime
1635
+ });
1636
+ this.handle.label = this.props.id;
1637
+ }
1638
+ destroy() {
1639
+ }
1640
+ finish(props) {
1641
+ return new WebGPUCommandBuffer(this, {
1642
+ id: props?.id || "unnamed-command-buffer"
1643
+ });
1644
+ }
1645
+ /**
1646
+ * Allows a render pass to begin against a canvas context
1647
+ * @todo need to support a "Framebuffer" equivalent (aka preconfigured RenderPassDescriptors?).
1648
+ */
1649
+ beginRenderPass(props) {
1650
+ return new WebGPURenderPass(this.device, props);
1651
+ }
1652
+ beginComputePass(props) {
1653
+ return new WebGPUComputePass(this.device, props);
1654
+ }
1655
+ // beginRenderPass(GPURenderPassDescriptor descriptor): GPURenderPassEncoder;
1656
+ // beginComputePass(optional GPUComputePassDescriptor descriptor = {}): GPUComputePassEncoder;
1657
+ copyBufferToBuffer(options) {
1658
+ const webgpuSourceBuffer = options.sourceBuffer;
1659
+ const WebGPUDestinationBuffer = options.destinationBuffer;
1660
+ this.handle.copyBufferToBuffer(
1661
+ webgpuSourceBuffer.handle,
1662
+ options.sourceOffset ?? 0,
1663
+ WebGPUDestinationBuffer.handle,
1664
+ options.destinationOffset ?? 0,
1665
+ options.size ?? 0
1666
+ );
1667
+ }
1668
+ copyBufferToTexture(options) {
1669
+ const webgpuSourceBuffer = options.sourceBuffer;
1670
+ const WebGPUDestinationTexture = options.destinationTexture;
1671
+ this.handle.copyBufferToTexture(
1672
+ {
1673
+ buffer: webgpuSourceBuffer.handle,
1674
+ offset: options.offset ?? 0,
1675
+ bytesPerRow: options.bytesPerRow,
1676
+ rowsPerImage: options.rowsPerImage
1677
+ },
1678
+ {
1679
+ texture: WebGPUDestinationTexture.handle,
1680
+ mipLevel: options.mipLevel ?? 0,
1681
+ origin: options.origin ?? {}
1682
+ // aspect: options.aspect
1683
+ },
1684
+ {
1685
+ // @ts-ignore
1686
+ width: options.extent?.[0],
1687
+ height: options.extent?.[1],
1688
+ depthOrArrayLayers: options.extent?.[2]
1689
+ }
1690
+ );
1691
+ }
1692
+ copyTextureToBuffer(options) {
1693
+ }
1694
+ copyTextureToTexture(options) {
1695
+ }
1696
+ pushDebugGroup(groupLabel) {
1697
+ this.handle.pushDebugGroup(groupLabel);
1698
+ }
1699
+ popDebugGroup() {
1700
+ this.handle.popDebugGroup();
1701
+ }
1702
+ insertDebugMarker(markerLabel) {
1703
+ this.handle.insertDebugMarker(markerLabel);
1704
+ }
1705
+ resolveQuerySet(querySet, destination, options) {
1706
+ const webgpuQuerySet = querySet;
1707
+ const webgpuBuffer = destination;
1708
+ this.handle.resolveQuerySet(
1709
+ webgpuQuerySet.handle,
1710
+ options?.firstQuery || 0,
1711
+ options?.queryCount || querySet.props.count - (options?.firstQuery || 0),
1712
+ webgpuBuffer.handle,
1713
+ options?.destinationOffset || 0
1714
+ );
1715
+ }
1716
+ };
1461
1717
  }
1462
- };
1718
+ });
1463
1719
 
1464
1720
  // src/adapter/resources/webgpu-query-set.ts
1465
- var import_core16 = __toESM(require_core(), 1);
1466
- var WebGPUQuerySet = class extends import_core16.QuerySet {
1467
- device;
1468
- handle;
1469
- constructor(device, props) {
1470
- super(device, props);
1471
- this.device = device;
1472
- this.handle = this.props.handle || this.device.handle.createQuerySet({
1473
- type: this.props.type,
1474
- count: this.props.count
1475
- });
1476
- this.handle.label = this.props.id;
1477
- }
1478
- destroy() {
1479
- this.handle?.destroy();
1480
- this.handle = null;
1721
+ var import_core18, WebGPUQuerySet;
1722
+ var init_webgpu_query_set = __esm({
1723
+ "src/adapter/resources/webgpu-query-set.ts"() {
1724
+ "use strict";
1725
+ import_core18 = __toESM(require_core(), 1);
1726
+ WebGPUQuerySet = class extends import_core18.QuerySet {
1727
+ device;
1728
+ handle;
1729
+ constructor(device, props) {
1730
+ super(device, props);
1731
+ this.device = device;
1732
+ this.handle = this.props.handle || this.device.handle.createQuerySet({
1733
+ type: this.props.type,
1734
+ count: this.props.count
1735
+ });
1736
+ this.handle.label = this.props.id;
1737
+ }
1738
+ destroy() {
1739
+ this.handle?.destroy();
1740
+ this.handle = null;
1741
+ }
1742
+ };
1481
1743
  }
1482
- };
1744
+ });
1483
1745
 
1484
1746
  // src/adapter/webgpu-device.ts
1485
- var WebGPUDevice = class extends import_core17.Device {
1486
- /** The underlying WebGPU device */
1487
- handle;
1488
- /** type of this device */
1489
- type = "webgpu";
1490
- preferredColorFormat = navigator.gpu.getPreferredCanvasFormat();
1491
- preferredDepthFormat = "depth24plus";
1492
- features;
1493
- info;
1494
- limits;
1495
- lost;
1496
- renderPass = null;
1497
- canvasContext;
1498
- _isLost = false;
1499
- // canvasContext: WebGPUCanvasContext | null = null;
1500
- commandEncoder = null;
1501
- /* The underlying WebGPU adapter */
1502
- adapter;
1503
- /* The underlying WebGPU adapter's info */
1504
- adapterInfo;
1505
- constructor(props, device, adapter, adapterInfo) {
1506
- super({ ...props, id: props.id || "webgpu-device" });
1507
- this.handle = device;
1508
- this.adapter = adapter;
1509
- this.adapterInfo = adapterInfo;
1510
- this.info = this._getInfo();
1511
- this.features = this._getFeatures();
1512
- this.limits = this.handle.limits;
1513
- device.addEventListener("uncapturederror", (event) => {
1514
- const errorMessage = event instanceof GPUUncapturedErrorEvent ? event.error.message : "Unknown WebGPU error";
1515
- this.reportError(new Error(errorMessage));
1516
- if (this.props.debug) {
1517
- debugger;
1518
- }
1519
- event.preventDefault();
1520
- });
1521
- this.lost = new Promise(async (resolve) => {
1522
- const lostInfo = await this.handle.lost;
1523
- this._isLost = true;
1524
- resolve({ reason: "destroyed", message: lostInfo.message });
1525
- });
1526
- if (props.createCanvasContext) {
1527
- const canvasContextProps = props.createCanvasContext === true ? {} : props.createCanvasContext;
1528
- this.canvasContext = new WebGPUCanvasContext(this, this.adapter, canvasContextProps);
1529
- }
1530
- }
1531
- // TODO
1532
- // Load the glslang module now so that it is available synchronously when compiling shaders
1533
- // const {glsl = true} = props;
1534
- // this.glslang = glsl && await loadGlslangModule();
1535
- destroy() {
1536
- this.handle.destroy();
1537
- }
1538
- get isLost() {
1539
- return this._isLost;
1540
- }
1541
- createBuffer(props) {
1542
- const newProps = this._normalizeBufferProps(props);
1543
- return new WebGPUBuffer(this, newProps);
1544
- }
1545
- createTexture(props) {
1546
- return new WebGPUTexture(this, props);
1547
- }
1548
- createExternalTexture(props) {
1549
- return new WebGPUExternalTexture(this, props);
1550
- }
1551
- createShader(props) {
1552
- return new WebGPUShader(this, props);
1553
- }
1554
- createSampler(props) {
1555
- return new WebGPUSampler(this, props);
1556
- }
1557
- createRenderPipeline(props) {
1558
- return new WebGPURenderPipeline(this, props);
1559
- }
1560
- createFramebuffer(props) {
1561
- return new WebGPUFramebuffer(this, props);
1562
- }
1563
- createComputePipeline(props) {
1564
- return new WebGPUComputePipeline(this, props);
1565
- }
1566
- createVertexArray(props) {
1567
- return new WebGPUVertexArray(this, props);
1568
- }
1569
- // WebGPU specifics
1570
- /**
1571
- * Allows a render pass to begin against a canvas context
1572
- * @todo need to support a "Framebuffer" equivalent (aka preconfigured RenderPassDescriptors?).
1573
- */
1574
- beginRenderPass(props) {
1575
- this.commandEncoder = this.commandEncoder || this.handle.createCommandEncoder();
1576
- return new WebGPURenderPass(this, props);
1577
- }
1578
- beginComputePass(props) {
1579
- this.commandEncoder = this.commandEncoder || this.handle.createCommandEncoder();
1580
- return new WebGPUComputePass(this, props);
1581
- }
1582
- // createCommandEncoder(props: CommandEncoderProps): WebGPUCommandEncoder {
1583
- // return new WebGPUCommandEncoder(this, props);
1584
- // }
1585
- createTransformFeedback(props) {
1586
- throw new Error("Transform feedback not supported in WebGPU");
1587
- }
1588
- createQuerySet(props) {
1589
- return new WebGPUQuerySet(this, props);
1590
- }
1591
- createCanvasContext(props) {
1592
- return new WebGPUCanvasContext(this, this.adapter, props);
1593
- }
1594
- submit() {
1595
- const commandBuffer = this.commandEncoder?.finish();
1596
- if (commandBuffer) {
1597
- this.handle.pushErrorScope("validation");
1598
- this.handle.queue.submit([commandBuffer]);
1599
- this.handle.popErrorScope().then((error) => {
1600
- if (error) {
1601
- this.reportError(new Error(`WebGPU command submission failed: ${error.message}`));
1747
+ var webgpu_device_exports = {};
1748
+ __export(webgpu_device_exports, {
1749
+ WebGPUDevice: () => WebGPUDevice
1750
+ });
1751
+ var import_core19, WebGPUDevice;
1752
+ var init_webgpu_device = __esm({
1753
+ "src/adapter/webgpu-device.ts"() {
1754
+ "use strict";
1755
+ import_core19 = __toESM(require_core(), 1);
1756
+ init_webgpu_buffer();
1757
+ init_webgpu_texture();
1758
+ init_webgpu_external_texture();
1759
+ init_webgpu_sampler();
1760
+ init_webgpu_shader();
1761
+ init_webgpu_render_pipeline();
1762
+ init_webgpu_framebuffer();
1763
+ init_webgpu_compute_pipeline();
1764
+ init_webgpu_vertex_array();
1765
+ init_webgpu_canvas_context();
1766
+ init_webgpu_command_encoder();
1767
+ init_webgpu_query_set();
1768
+ WebGPUDevice = class extends import_core19.Device {
1769
+ /** The underlying WebGPU device */
1770
+ handle;
1771
+ /** type of this device */
1772
+ type = "webgpu";
1773
+ preferredColorFormat = navigator.gpu.getPreferredCanvasFormat();
1774
+ preferredDepthFormat = "depth24plus";
1775
+ features;
1776
+ info;
1777
+ limits;
1778
+ lost;
1779
+ canvasContext = null;
1780
+ _isLost = false;
1781
+ commandEncoder;
1782
+ /* The underlying WebGPU adapter */
1783
+ adapter;
1784
+ /* The underlying WebGPU adapter's info */
1785
+ adapterInfo;
1786
+ constructor(props, device, adapter, adapterInfo) {
1787
+ super({ ...props, id: props.id || "webgpu-device" });
1788
+ this.handle = device;
1789
+ this.adapter = adapter;
1790
+ this.adapterInfo = adapterInfo;
1791
+ this.info = this._getInfo();
1792
+ this.features = this._getFeatures();
1793
+ this.limits = this.handle.limits;
1794
+ device.addEventListener("uncapturederror", (event) => {
1795
+ event.preventDefault();
1796
+ const errorMessage = event instanceof GPUUncapturedErrorEvent ? event.error.message : "Unknown WebGPU error";
1797
+ this.reportError(new Error(errorMessage));
1798
+ if (this.props.debug) {
1799
+ debugger;
1800
+ }
1801
+ });
1802
+ this.lost = new Promise(async (resolve) => {
1803
+ const lostInfo = await this.handle.lost;
1804
+ this._isLost = true;
1805
+ resolve({ reason: "destroyed", message: lostInfo.message });
1806
+ });
1807
+ if (props.createCanvasContext) {
1808
+ const canvasContextProps = props.createCanvasContext === true ? {} : props.createCanvasContext;
1809
+ this.canvasContext = new WebGPUCanvasContext(this, this.adapter, canvasContextProps);
1602
1810
  }
1603
- });
1604
- }
1605
- this.commandEncoder = null;
1606
- }
1607
- // PRIVATE METHODS
1608
- _getInfo() {
1609
- const [driver, driverVersion] = (this.adapterInfo.driver || "").split(" Version ");
1610
- const vendor = this.adapterInfo.vendor || this.adapter.__brand || "unknown";
1611
- const renderer = driver || "";
1612
- const version = driverVersion || "";
1613
- const gpu = vendor === "apple" ? "apple" : "unknown";
1614
- const gpuArchitecture = this.adapterInfo.architecture || "unknown";
1615
- const gpuBackend = this.adapterInfo.backend || "unknown";
1616
- const gpuType = (this.adapterInfo.type || "").split(" ")[0].toLowerCase() || "unknown";
1617
- return {
1618
- type: "webgpu",
1619
- vendor,
1620
- renderer,
1621
- version,
1622
- gpu,
1623
- gpuType,
1624
- gpuBackend,
1625
- gpuArchitecture,
1626
- shadingLanguage: "wgsl",
1627
- shadingLanguageVersion: 100
1811
+ this.commandEncoder = this.createCommandEncoder({});
1812
+ }
1813
+ // TODO
1814
+ // Load the glslang module now so that it is available synchronously when compiling shaders
1815
+ // const {glsl = true} = props;
1816
+ // this.glslang = glsl && await loadGlslangModule();
1817
+ destroy() {
1818
+ this.handle.destroy();
1819
+ }
1820
+ get isLost() {
1821
+ return this._isLost;
1822
+ }
1823
+ createBuffer(props) {
1824
+ const newProps = this._normalizeBufferProps(props);
1825
+ return new WebGPUBuffer(this, newProps);
1826
+ }
1827
+ createTexture(props) {
1828
+ return new WebGPUTexture(this, props);
1829
+ }
1830
+ createExternalTexture(props) {
1831
+ return new WebGPUExternalTexture(this, props);
1832
+ }
1833
+ createShader(props) {
1834
+ return new WebGPUShader(this, props);
1835
+ }
1836
+ createSampler(props) {
1837
+ return new WebGPUSampler(this, props);
1838
+ }
1839
+ createRenderPipeline(props) {
1840
+ return new WebGPURenderPipeline(this, props);
1841
+ }
1842
+ createFramebuffer(props) {
1843
+ return new WebGPUFramebuffer(this, props);
1844
+ }
1845
+ createComputePipeline(props) {
1846
+ return new WebGPUComputePipeline(this, props);
1847
+ }
1848
+ createVertexArray(props) {
1849
+ return new WebGPUVertexArray(this, props);
1850
+ }
1851
+ createCommandEncoder(props) {
1852
+ return new WebGPUCommandEncoder(this, props);
1853
+ }
1854
+ // WebGPU specifics
1855
+ createTransformFeedback(props) {
1856
+ throw new Error("Transform feedback not supported in WebGPU");
1857
+ }
1858
+ createQuerySet(props) {
1859
+ return new WebGPUQuerySet(this, props);
1860
+ }
1861
+ createCanvasContext(props) {
1862
+ return new WebGPUCanvasContext(this, this.adapter, props);
1863
+ }
1864
+ submit(commandBuffer) {
1865
+ if (!commandBuffer) {
1866
+ commandBuffer = this.commandEncoder.finish();
1867
+ this.commandEncoder.destroy();
1868
+ this.commandEncoder = this.createCommandEncoder({ id: `${this.id}-default-encoder` });
1869
+ }
1870
+ this.handle.pushErrorScope("validation");
1871
+ this.handle.queue.submit([commandBuffer.handle]);
1872
+ this.handle.popErrorScope().then((error) => {
1873
+ if (error) {
1874
+ this.reportError(new Error(`WebGPU command submission failed: ${error.message}`));
1875
+ }
1876
+ });
1877
+ }
1878
+ // WebGPU specific
1879
+ pushErrorScope(scope) {
1880
+ this.handle.pushErrorScope(scope);
1881
+ }
1882
+ popErrorScope(handler) {
1883
+ this.handle.popErrorScope().then((error) => {
1884
+ if (error) {
1885
+ handler(error.message);
1886
+ }
1887
+ });
1888
+ }
1889
+ // PRIVATE METHODS
1890
+ _getInfo() {
1891
+ const [driver, driverVersion] = (this.adapterInfo.driver || "").split(" Version ");
1892
+ const vendor = this.adapterInfo.vendor || this.adapter.__brand || "unknown";
1893
+ const renderer = driver || "";
1894
+ const version = driverVersion || "";
1895
+ const gpu = vendor === "apple" ? "apple" : "unknown";
1896
+ const gpuArchitecture = this.adapterInfo.architecture || "unknown";
1897
+ const gpuBackend = this.adapterInfo.backend || "unknown";
1898
+ const gpuType = (this.adapterInfo.type || "").split(" ")[0].toLowerCase() || "unknown";
1899
+ return {
1900
+ type: "webgpu",
1901
+ vendor,
1902
+ renderer,
1903
+ version,
1904
+ gpu,
1905
+ gpuType,
1906
+ gpuBackend,
1907
+ gpuArchitecture,
1908
+ shadingLanguage: "wgsl",
1909
+ shadingLanguageVersion: 100
1910
+ };
1911
+ }
1912
+ _getFeatures() {
1913
+ const features = new Set(this.handle.features);
1914
+ if (features.has("depth-clamping")) {
1915
+ features.delete("depth-clamping");
1916
+ features.add("depth-clip-control");
1917
+ }
1918
+ if (features.has("texture-compression-bc")) {
1919
+ features.add("texture-compression-bc5-webgl");
1920
+ }
1921
+ const WEBGPU_ALWAYS_FEATURES = [
1922
+ "timer-query-webgl",
1923
+ "compilation-status-async-webgl",
1924
+ "float32-renderable-webgl",
1925
+ "float16-renderable-webgl",
1926
+ "norm16-renderable-webgl",
1927
+ "texture-filterable-anisotropic-webgl",
1928
+ "shader-noperspective-interpolation-webgl"
1929
+ ];
1930
+ for (const feature of WEBGPU_ALWAYS_FEATURES) {
1931
+ features.add(feature);
1932
+ }
1933
+ return new import_core19.DeviceFeatures(Array.from(features), this.props._disabledFeatures);
1934
+ }
1935
+ _getDeviceSpecificTextureFormatCapabilities(capabilities) {
1936
+ const { format } = capabilities;
1937
+ if (format.includes("webgl")) {
1938
+ return { format, create: false, render: false, filter: false, blend: false, store: false };
1939
+ }
1940
+ return capabilities;
1941
+ }
1628
1942
  };
1629
1943
  }
1630
- _getFeatures() {
1631
- const features = new Set(this.handle.features);
1632
- if (features.has("depth-clamping")) {
1633
- features.delete("depth-clamping");
1634
- features.add("depth-clip-control");
1635
- }
1636
- if (features.has("texture-compression-bc")) {
1637
- features.add("texture-compression-bc5-webgl");
1638
- }
1639
- const WEBGPU_ALWAYS_FEATURES = [
1640
- "timer-query-webgl",
1641
- "compilation-status-async-webgl",
1642
- "float32-renderable-webgl",
1643
- "float16-renderable-webgl",
1644
- "norm16-renderable-webgl",
1645
- "texture-filterable-anisotropic-webgl",
1646
- "shader-noperspective-interpolation-webgl"
1647
- ];
1648
- for (const feature of WEBGPU_ALWAYS_FEATURES) {
1649
- features.add(feature);
1650
- }
1651
- return new import_core17.DeviceFeatures(Array.from(features), this.props._disabledFeatures);
1652
- }
1653
- _getDeviceSpecificTextureFormatCapabilities(capabilities) {
1654
- const { format } = capabilities;
1655
- if (format.includes("webgl")) {
1656
- return { format, create: false, render: false, filter: false, blend: false, store: false };
1657
- }
1658
- return capabilities;
1659
- }
1660
- // DEPRECATED METHODS
1661
- // @deprecated
1662
- copyExternalImageToTexture(options) {
1663
- const {
1664
- source,
1665
- sourceX = 0,
1666
- sourceY = 0,
1667
- texture,
1668
- mipLevel = 0,
1669
- aspect = "all",
1670
- colorSpace = "display-p3",
1671
- premultipliedAlpha = false,
1672
- // destinationX,
1673
- // destinationY,
1674
- // desitnationZ,
1675
- width = texture.width,
1676
- height = texture.height,
1677
- depth = 1
1678
- } = options;
1679
- const webGpuTexture = texture;
1680
- this.handle?.queue.copyExternalImageToTexture(
1681
- // source: GPUImageCopyExternalImage
1682
- {
1683
- source,
1684
- origin: [sourceX, sourceY]
1685
- },
1686
- // destination: GPUImageCopyTextureTagged
1687
- {
1688
- texture: webGpuTexture.handle,
1689
- origin: [0, 0, 0],
1690
- // [x, y, z],
1691
- mipLevel,
1692
- aspect,
1693
- colorSpace,
1694
- premultipliedAlpha
1695
- },
1696
- // copySize: GPUExtent3D
1697
- [width, height, depth]
1698
- );
1699
- }
1700
- };
1944
+ });
1945
+
1946
+ // bundle.ts
1947
+ var bundle_exports = {};
1948
+ __export(bundle_exports, {
1949
+ WebGPUBuffer: () => WebGPUBuffer,
1950
+ WebGPUDevice: () => WebGPUDevice,
1951
+ WebGPUSampler: () => WebGPUSampler,
1952
+ WebGPUShader: () => WebGPUShader,
1953
+ WebGPUTexture: () => WebGPUTexture,
1954
+ webgpuAdapter: () => webgpuAdapter
1955
+ });
1956
+ __reExport(bundle_exports, __toESM(require_core(), 1));
1701
1957
 
1702
1958
  // src/adapter/webgpu-adapter.ts
1703
- var WebGPUAdapter = class extends import_core18.Adapter {
1959
+ var import_core20 = __toESM(require_core(), 1);
1960
+ var WebGPUAdapter = class extends import_core20.Adapter {
1704
1961
  /** type of device's created by this adapter */
1705
1962
  type = "webgpu";
1706
- constructor() {
1707
- super();
1708
- WebGPUDevice.adapter = this;
1709
- }
1710
- /** Check if WebGPU is available */
1711
1963
  isSupported() {
1712
1964
  return Boolean(typeof navigator !== "undefined" && navigator.gpu);
1713
1965
  }
1966
+ isDeviceHandle(handle) {
1967
+ if (typeof GPUDevice !== "undefined" && handle instanceof GPUDevice) {
1968
+ return true;
1969
+ }
1970
+ if (handle?.queue) {
1971
+ return true;
1972
+ }
1973
+ return false;
1974
+ }
1714
1975
  async create(props) {
1715
1976
  if (!navigator.gpu) {
1716
- throw new Error(
1717
- "WebGPU not available. Open in Chrome Canary and turn on chrome://flags/#enable-unsafe-webgpu"
1718
- );
1977
+ throw new Error("WebGPU not available. Recent Chrome browsers should work.");
1719
1978
  }
1720
- import_core18.log.groupCollapsed(1, "WebGPUDevice created")();
1979
+ import_core20.log.groupCollapsed(1, "WebGPUDevice created")();
1721
1980
  const adapter = await navigator.gpu.requestAdapter({
1722
1981
  powerPreference: "high-performance"
1723
1982
  // forceSoftware: false
@@ -1725,8 +1984,9 @@ var __exports__ = (() => {
1725
1984
  if (!adapter) {
1726
1985
  throw new Error("Failed to request WebGPU adapter");
1727
1986
  }
1728
- const adapterInfo = await adapter.requestAdapterInfo();
1729
- import_core18.log.probe(2, "Adapter available", adapterInfo)();
1987
+ const adapterInfo = adapter.info || // @ts-ignore
1988
+ await adapter.requestAdapterInfo?.();
1989
+ import_core20.log.probe(2, "Adapter available", adapterInfo)();
1730
1990
  const requiredFeatures = [];
1731
1991
  const requiredLimits = {};
1732
1992
  if (props._requestMaxLimits) {
@@ -1746,14 +2006,15 @@ var __exports__ = (() => {
1746
2006
  requiredFeatures,
1747
2007
  requiredLimits
1748
2008
  });
1749
- import_core18.log.probe(1, "GPUDevice available")();
1750
- const device = new WebGPUDevice(props, gpuDevice, adapter, adapterInfo);
1751
- import_core18.log.probe(
2009
+ import_core20.log.probe(1, "GPUDevice available")();
2010
+ const { WebGPUDevice: WebGPUDevice2 } = await Promise.resolve().then(() => (init_webgpu_device(), webgpu_device_exports));
2011
+ const device = new WebGPUDevice2(props, gpuDevice, adapter, adapterInfo);
2012
+ import_core20.log.probe(
1752
2013
  1,
1753
2014
  "Device created. For more info, set chrome://flags/#enable-webgpu-developer-features"
1754
2015
  )();
1755
- import_core18.log.table(1, device.info)();
1756
- import_core18.log.groupEnd(1)();
2016
+ import_core20.log.table(1, device.info)();
2017
+ import_core20.log.groupEnd(1)();
1757
2018
  return device;
1758
2019
  }
1759
2020
  async attach(handle) {
@@ -1761,6 +2022,13 @@ var __exports__ = (() => {
1761
2022
  }
1762
2023
  };
1763
2024
  var webgpuAdapter = new WebGPUAdapter();
2025
+
2026
+ // src/index.ts
2027
+ init_webgpu_device();
2028
+ init_webgpu_buffer();
2029
+ init_webgpu_texture();
2030
+ init_webgpu_sampler();
2031
+ init_webgpu_shader();
1764
2032
  return __toCommonJS(bundle_exports);
1765
2033
  })();
1766
2034
  return __exports__;