@luma.gl/webgpu 9.1.9 → 9.2.0-alpha.2

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