@luma.gl/webgpu 9.3.0-alpha.4 → 9.3.0-alpha.8
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.
- package/dist/adapter/helpers/cpu-hotspot-profiler.d.ts +54 -0
- package/dist/adapter/helpers/cpu-hotspot-profiler.d.ts.map +1 -0
- package/dist/adapter/helpers/cpu-hotspot-profiler.js +26 -0
- package/dist/adapter/helpers/cpu-hotspot-profiler.js.map +1 -0
- package/dist/adapter/helpers/generate-mipmaps-webgpu.d.ts +7 -0
- package/dist/adapter/helpers/generate-mipmaps-webgpu.d.ts.map +1 -0
- package/dist/adapter/helpers/generate-mipmaps-webgpu.js +490 -0
- package/dist/adapter/helpers/generate-mipmaps-webgpu.js.map +1 -0
- package/dist/adapter/helpers/get-bind-group.d.ts +4 -6
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/helpers/get-bind-group.js +31 -30
- package/dist/adapter/helpers/get-bind-group.js.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts +3 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.d.ts.map +1 -1
- package/dist/adapter/helpers/get-vertex-buffer-layout.js +17 -12
- package/dist/adapter/helpers/get-vertex-buffer-layout.js.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.d.ts.map +1 -1
- package/dist/adapter/helpers/webgpu-parameters.js +1 -0
- package/dist/adapter/helpers/webgpu-parameters.js.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-buffer.js +19 -3
- package/dist/adapter/resources/webgpu-buffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-command-buffer.js +1 -1
- package/dist/adapter/resources/webgpu-command-buffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.d.ts +7 -16
- package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.js +89 -32
- package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.d.ts +3 -3
- package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js +30 -12
- package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts +7 -9
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.js +30 -17
- package/dist/adapter/resources/webgpu-compute-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-fence.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-fence.js +9 -1
- package/dist/adapter/resources/webgpu-fence.js.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.d.ts +6 -0
- package/dist/adapter/resources/webgpu-framebuffer.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-framebuffer.js +16 -0
- package/dist/adapter/resources/webgpu-framebuffer.js.map +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.d.ts +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-pipeline-layout.js +10 -16
- package/dist/adapter/resources/webgpu-pipeline-layout.js.map +1 -1
- package/dist/adapter/resources/webgpu-query-set.d.ts +33 -4
- package/dist/adapter/resources/webgpu-query-set.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-query-set.js +145 -4
- package/dist/adapter/resources/webgpu-query-set.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.d.ts +6 -3
- package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.js +78 -34
- package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +14 -10
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +56 -35
- package/dist/adapter/resources/webgpu-render-pipeline.js.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-sampler.js +4 -0
- package/dist/adapter/resources/webgpu-sampler.js.map +1 -1
- package/dist/adapter/resources/webgpu-shader.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-shader.js +17 -1
- package/dist/adapter/resources/webgpu-shader.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture-view.d.ts +6 -0
- package/dist/adapter/resources/webgpu-texture-view.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture-view.js +47 -11
- package/dist/adapter/resources/webgpu-texture-view.js.map +1 -1
- package/dist/adapter/resources/webgpu-texture.d.ts +18 -5
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js +148 -97
- package/dist/adapter/resources/webgpu-texture.js.map +1 -1
- package/dist/adapter/resources/webgpu-vertex-array.js +1 -1
- package/dist/adapter/resources/webgpu-vertex-array.js.map +1 -1
- package/dist/adapter/webgpu-canvas-context.d.ts +2 -0
- package/dist/adapter/webgpu-canvas-context.d.ts.map +1 -1
- package/dist/adapter/webgpu-canvas-context.js +78 -19
- package/dist/adapter/webgpu-canvas-context.js.map +1 -1
- package/dist/adapter/webgpu-device.d.ts +10 -2
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +159 -13
- package/dist/adapter/webgpu-device.js.map +1 -1
- package/dist/adapter/webgpu-presentation-context.d.ts +25 -0
- package/dist/adapter/webgpu-presentation-context.d.ts.map +1 -0
- package/dist/adapter/webgpu-presentation-context.js +144 -0
- package/dist/adapter/webgpu-presentation-context.js.map +1 -0
- package/dist/dist.dev.js +3180 -1849
- package/dist/dist.min.js +168 -9
- package/dist/index.cjs +1640 -405
- package/dist/index.cjs.map +4 -4
- package/dist/wgsl/get-shader-layout-wgsl.d.ts.map +1 -1
- package/dist/wgsl/get-shader-layout-wgsl.js +8 -0
- package/dist/wgsl/get-shader-layout-wgsl.js.map +1 -1
- package/package.json +5 -5
- package/src/adapter/helpers/cpu-hotspot-profiler.ts +70 -0
- package/src/adapter/helpers/generate-mipmaps-webgpu.ts +583 -0
- package/src/adapter/helpers/get-bind-group.ts +42 -49
- package/src/adapter/helpers/get-vertex-buffer-layout.ts +31 -12
- package/src/adapter/helpers/webgpu-parameters.ts +2 -0
- package/src/adapter/resources/webgpu-buffer.ts +18 -3
- package/src/adapter/resources/webgpu-command-buffer.ts +1 -1
- package/src/adapter/resources/webgpu-command-encoder.ts +129 -50
- package/src/adapter/resources/webgpu-compute-pass.ts +48 -13
- package/src/adapter/resources/webgpu-compute-pipeline.ts +49 -18
- package/src/adapter/resources/webgpu-fence.ts +11 -3
- package/src/adapter/resources/webgpu-framebuffer.ts +21 -0
- package/src/adapter/resources/webgpu-pipeline-layout.ts +16 -14
- package/src/adapter/resources/webgpu-query-set.ts +185 -9
- package/src/adapter/resources/webgpu-render-pass.ts +92 -40
- package/src/adapter/resources/webgpu-render-pipeline.ts +83 -44
- package/src/adapter/resources/webgpu-sampler.ts +5 -0
- package/src/adapter/resources/webgpu-shader.ts +16 -1
- package/src/adapter/resources/webgpu-texture-view.ts +51 -11
- package/src/adapter/resources/webgpu-texture.ts +198 -132
- package/src/adapter/resources/webgpu-vertex-array.ts +1 -1
- package/src/adapter/webgpu-canvas-context.ts +91 -26
- package/src/adapter/webgpu-device.ts +212 -17
- package/src/adapter/webgpu-presentation-context.ts +180 -0
- package/src/wgsl/get-shader-layout-wgsl.ts +9 -0
- package/dist/adapter/helpers/accessor-to-format.d.ts +0 -1
- package/dist/adapter/helpers/accessor-to-format.d.ts.map +0 -1
- package/dist/adapter/helpers/accessor-to-format.js +0 -105
- package/dist/adapter/helpers/accessor-to-format.js.map +0 -1
- package/src/adapter/helpers/accessor-to-format.ts +0 -104
package/dist/index.cjs
CHANGED
|
@@ -74,11 +74,24 @@ var init_webgpu_buffer = __esm({
|
|
|
74
74
|
this.device.reportError(new Error(`${this} creation failed ${error.message}`), this)();
|
|
75
75
|
this.device.debug();
|
|
76
76
|
});
|
|
77
|
+
if (!this.props.handle) {
|
|
78
|
+
this.trackAllocatedMemory(size);
|
|
79
|
+
} else {
|
|
80
|
+
this.trackReferencedMemory(size, "Buffer");
|
|
81
|
+
}
|
|
77
82
|
}
|
|
78
83
|
destroy() {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
84
|
+
if (!this.destroyed && this.handle) {
|
|
85
|
+
this.removeStats();
|
|
86
|
+
if (!this.props.handle) {
|
|
87
|
+
this.trackDeallocatedMemory();
|
|
88
|
+
this.handle.destroy();
|
|
89
|
+
} else {
|
|
90
|
+
this.trackDeallocatedReferencedMemory("Buffer");
|
|
91
|
+
}
|
|
92
|
+
this.destroyed = true;
|
|
93
|
+
this.handle = null;
|
|
94
|
+
}
|
|
82
95
|
}
|
|
83
96
|
write(data, byteOffset = 0) {
|
|
84
97
|
const arrayBuffer = ArrayBuffer.isView(data) ? data.buffer : data;
|
|
@@ -226,18 +239,47 @@ var init_webgpu_sampler = __esm({
|
|
|
226
239
|
this.handle.label = this.props.id;
|
|
227
240
|
}
|
|
228
241
|
destroy() {
|
|
242
|
+
if (this.destroyed) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
this.destroyResource();
|
|
229
246
|
this.handle = null;
|
|
230
247
|
}
|
|
231
248
|
};
|
|
232
249
|
}
|
|
233
250
|
});
|
|
234
251
|
|
|
252
|
+
// dist/adapter/helpers/cpu-hotspot-profiler.js
|
|
253
|
+
function getCpuHotspotProfiler(owner) {
|
|
254
|
+
const profiler = owner.userData[CPU_HOTSPOT_PROFILER_MODULE];
|
|
255
|
+
return (profiler == null ? void 0 : profiler.enabled) ? profiler : null;
|
|
256
|
+
}
|
|
257
|
+
function getCpuHotspotSubmitReason(owner) {
|
|
258
|
+
return owner.userData[CPU_HOTSPOT_SUBMIT_REASON] || null;
|
|
259
|
+
}
|
|
260
|
+
function setCpuHotspotSubmitReason(owner, submitReason) {
|
|
261
|
+
owner.userData[CPU_HOTSPOT_SUBMIT_REASON] = submitReason;
|
|
262
|
+
}
|
|
263
|
+
function getTimestamp() {
|
|
264
|
+
var _a, _b;
|
|
265
|
+
return ((_b = (_a = globalThis.performance) == null ? void 0 : _a.now) == null ? void 0 : _b.call(_a)) ?? Date.now();
|
|
266
|
+
}
|
|
267
|
+
var CPU_HOTSPOT_PROFILER_MODULE, CPU_HOTSPOT_SUBMIT_REASON;
|
|
268
|
+
var init_cpu_hotspot_profiler = __esm({
|
|
269
|
+
"dist/adapter/helpers/cpu-hotspot-profiler.js"() {
|
|
270
|
+
"use strict";
|
|
271
|
+
CPU_HOTSPOT_PROFILER_MODULE = "cpu-hotspot-profiler";
|
|
272
|
+
CPU_HOTSPOT_SUBMIT_REASON = "cpu-hotspot-submit-reason";
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
|
|
235
276
|
// dist/adapter/resources/webgpu-texture-view.js
|
|
236
277
|
var import_core3, WebGPUTextureView;
|
|
237
278
|
var init_webgpu_texture_view = __esm({
|
|
238
279
|
"dist/adapter/resources/webgpu-texture-view.js"() {
|
|
239
280
|
"use strict";
|
|
240
281
|
import_core3 = require("@luma.gl/core");
|
|
282
|
+
init_cpu_hotspot_profiler();
|
|
241
283
|
WebGPUTextureView = class extends import_core3.TextureView {
|
|
242
284
|
device;
|
|
243
285
|
handle;
|
|
@@ -247,8 +289,7 @@ var init_webgpu_texture_view = __esm({
|
|
|
247
289
|
this.device = device;
|
|
248
290
|
this.texture = props.texture;
|
|
249
291
|
this.device.pushErrorScope("validation");
|
|
250
|
-
this.handle =
|
|
251
|
-
this.texture.handle.createView({
|
|
292
|
+
this.handle = this.texture.handle.createView({
|
|
252
293
|
format: this.props.format || this.texture.format,
|
|
253
294
|
dimension: this.props.dimension || this.texture.dimension,
|
|
254
295
|
aspect: this.props.aspect,
|
|
@@ -264,8 +305,42 @@ var init_webgpu_texture_view = __esm({
|
|
|
264
305
|
this.handle.label = this.props.id;
|
|
265
306
|
}
|
|
266
307
|
destroy() {
|
|
308
|
+
if (this.destroyed) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
this.destroyResource();
|
|
267
312
|
this.handle = null;
|
|
268
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Internal-only hook for the cached CanvasContext/PresentationContext swapchain path.
|
|
316
|
+
* Rebuilds the default view when the per-frame canvas texture handle changes, without
|
|
317
|
+
* replacing the long-lived luma.gl wrapper object.
|
|
318
|
+
*/
|
|
319
|
+
_reinitialize(texture) {
|
|
320
|
+
this.texture = texture;
|
|
321
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
322
|
+
this.device.pushErrorScope("validation");
|
|
323
|
+
const createViewStartTime = profiler ? getTimestamp() : 0;
|
|
324
|
+
const handle = this.texture.handle.createView({
|
|
325
|
+
format: this.props.format || this.texture.format,
|
|
326
|
+
dimension: this.props.dimension || this.texture.dimension,
|
|
327
|
+
aspect: this.props.aspect,
|
|
328
|
+
baseMipLevel: this.props.baseMipLevel,
|
|
329
|
+
mipLevelCount: this.props.mipLevelCount,
|
|
330
|
+
baseArrayLayer: this.props.baseArrayLayer,
|
|
331
|
+
arrayLayerCount: this.props.arrayLayerCount
|
|
332
|
+
});
|
|
333
|
+
if (profiler) {
|
|
334
|
+
profiler.textureViewReinitializeCount = (profiler.textureViewReinitializeCount || 0) + 1;
|
|
335
|
+
profiler.textureViewReinitializeTimeMs = (profiler.textureViewReinitializeTimeMs || 0) + (getTimestamp() - createViewStartTime);
|
|
336
|
+
}
|
|
337
|
+
this.device.popErrorScope((error) => {
|
|
338
|
+
this.device.reportError(new Error(`TextureView constructor: ${error.message}`), this)();
|
|
339
|
+
this.device.debug();
|
|
340
|
+
});
|
|
341
|
+
handle.label = this.props.id;
|
|
342
|
+
this.handle = handle;
|
|
343
|
+
}
|
|
269
344
|
};
|
|
270
345
|
}
|
|
271
346
|
});
|
|
@@ -284,9 +359,18 @@ var init_webgpu_texture = __esm({
|
|
|
284
359
|
handle;
|
|
285
360
|
sampler;
|
|
286
361
|
view;
|
|
362
|
+
_allocatedByteLength = 0;
|
|
287
363
|
constructor(device, props) {
|
|
288
364
|
super(device, props, { byteAlignment: 256 });
|
|
289
365
|
this.device = device;
|
|
366
|
+
if (props.sampler instanceof WebGPUSampler) {
|
|
367
|
+
this.sampler = props.sampler;
|
|
368
|
+
} else if (props.sampler === void 0) {
|
|
369
|
+
this.sampler = this.device.getDefaultSampler();
|
|
370
|
+
} else {
|
|
371
|
+
this.sampler = new WebGPUSampler(this.device, props.sampler || {});
|
|
372
|
+
this.attachResource(this.sampler);
|
|
373
|
+
}
|
|
290
374
|
this.device.pushErrorScope("out-of-memory");
|
|
291
375
|
this.device.pushErrorScope("validation");
|
|
292
376
|
this.handle = this.props.handle || this.device.handle.createTexture({
|
|
@@ -315,7 +399,6 @@ var init_webgpu_texture = __esm({
|
|
|
315
399
|
this.width = this.handle.width;
|
|
316
400
|
this.height = this.handle.height;
|
|
317
401
|
}
|
|
318
|
-
this.sampler = props.sampler instanceof WebGPUSampler ? props.sampler : new WebGPUSampler(this.device, props.sampler || {});
|
|
319
402
|
this.view = new WebGPUTextureView(this.device, {
|
|
320
403
|
...this.props,
|
|
321
404
|
texture: this,
|
|
@@ -323,11 +406,26 @@ var init_webgpu_texture = __esm({
|
|
|
323
406
|
// Note: arrayLayerCount controls the view of array textures, but does not apply to 3d texture depths
|
|
324
407
|
arrayLayerCount: this.dimension !== "3d" ? this.depth : 1
|
|
325
408
|
});
|
|
409
|
+
this.attachResource(this.view);
|
|
326
410
|
this._initializeData(props.data);
|
|
411
|
+
this._allocatedByteLength = this.getAllocatedByteLength();
|
|
412
|
+
if (!this.props.handle) {
|
|
413
|
+
this.trackAllocatedMemory(this._allocatedByteLength, "Texture");
|
|
414
|
+
} else {
|
|
415
|
+
this.trackReferencedMemory(this._allocatedByteLength, "Texture");
|
|
416
|
+
}
|
|
327
417
|
}
|
|
328
418
|
destroy() {
|
|
329
|
-
|
|
330
|
-
|
|
419
|
+
if (this.destroyed) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if (!this.props.handle && this.handle) {
|
|
423
|
+
this.trackDeallocatedMemory("Texture");
|
|
424
|
+
this.handle.destroy();
|
|
425
|
+
} else if (this.handle) {
|
|
426
|
+
this.trackDeallocatedReferencedMemory("Texture");
|
|
427
|
+
}
|
|
428
|
+
this.destroyResource();
|
|
331
429
|
this.handle = null;
|
|
332
430
|
}
|
|
333
431
|
createView(props) {
|
|
@@ -363,36 +461,6 @@ var init_webgpu_texture = __esm({
|
|
|
363
461
|
});
|
|
364
462
|
return { width: options.width, height: options.height };
|
|
365
463
|
}
|
|
366
|
-
copyImageData(options_) {
|
|
367
|
-
const { width, height, depth } = this;
|
|
368
|
-
const options = this._normalizeCopyImageDataOptions(options_);
|
|
369
|
-
this.device.pushErrorScope("validation");
|
|
370
|
-
this.device.handle.queue.writeTexture(
|
|
371
|
-
// destination: GPUImageCopyTexture
|
|
372
|
-
{
|
|
373
|
-
// texture subresource
|
|
374
|
-
texture: this.handle,
|
|
375
|
-
mipLevel: options.mipLevel,
|
|
376
|
-
aspect: options.aspect,
|
|
377
|
-
// origin to write to
|
|
378
|
-
origin: [options.x, options.y, options.z]
|
|
379
|
-
},
|
|
380
|
-
// data
|
|
381
|
-
options.data,
|
|
382
|
-
// dataLayout: GPUImageDataLayout
|
|
383
|
-
{
|
|
384
|
-
offset: options.byteOffset,
|
|
385
|
-
bytesPerRow: options.bytesPerRow,
|
|
386
|
-
rowsPerImage: options.rowsPerImage
|
|
387
|
-
},
|
|
388
|
-
// size: GPUExtent3D - extents of the content to write
|
|
389
|
-
[width, height, depth]
|
|
390
|
-
);
|
|
391
|
-
this.device.popErrorScope((error) => {
|
|
392
|
-
this.device.reportError(new Error(`copyImageData: ${error.message}`), this)();
|
|
393
|
-
this.device.debug();
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
464
|
generateMipmapsWebGL() {
|
|
397
465
|
import_core4.log.warn(`${this}: generateMipmaps not supported in WebGPU`)();
|
|
398
466
|
}
|
|
@@ -404,66 +472,63 @@ var init_webgpu_texture = __esm({
|
|
|
404
472
|
};
|
|
405
473
|
}
|
|
406
474
|
readBuffer(options = {}, buffer) {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
}
|
|
414
|
-
|
|
475
|
+
if (!buffer) {
|
|
476
|
+
throw new Error(`${this} readBuffer requires a destination buffer`);
|
|
477
|
+
}
|
|
478
|
+
const { x, y, z, width, height, depthOrArrayLayers, mipLevel, aspect } = this._getSupportedColorReadOptions(options);
|
|
479
|
+
const byteOffset = options.byteOffset ?? 0;
|
|
480
|
+
const layout = this.computeMemoryLayout({ width, height, depthOrArrayLayers, mipLevel });
|
|
481
|
+
const { byteLength } = layout;
|
|
482
|
+
if (buffer.byteLength < byteOffset + byteLength) {
|
|
483
|
+
throw new Error(`${this} readBuffer target is too small (${buffer.byteLength} < ${byteOffset + byteLength})`);
|
|
484
|
+
}
|
|
415
485
|
const gpuDevice = this.device.handle;
|
|
416
486
|
this.device.pushErrorScope("validation");
|
|
417
487
|
const commandEncoder = gpuDevice.createCommandEncoder();
|
|
418
|
-
|
|
419
|
-
// source
|
|
420
|
-
{
|
|
421
|
-
texture: this.handle,
|
|
422
|
-
origin: { x, y, z },
|
|
423
|
-
// origin: [options.x, options.y, 0], // options.depth],
|
|
424
|
-
mipLevel,
|
|
425
|
-
aspect
|
|
426
|
-
// colorSpace: options.colorSpace,
|
|
427
|
-
// premultipliedAlpha: options.premultipliedAlpha
|
|
428
|
-
},
|
|
429
|
-
// destination
|
|
430
|
-
{
|
|
431
|
-
buffer: gpuReadBuffer,
|
|
432
|
-
offset: 0,
|
|
433
|
-
bytesPerRow,
|
|
434
|
-
rowsPerImage
|
|
435
|
-
},
|
|
436
|
-
// copy size
|
|
437
|
-
{
|
|
438
|
-
width,
|
|
439
|
-
height,
|
|
440
|
-
depthOrArrayLayers
|
|
441
|
-
}
|
|
442
|
-
);
|
|
488
|
+
this.copyToBuffer(commandEncoder, { x, y, z, width, height, depthOrArrayLayers, mipLevel, aspect, byteOffset }, buffer);
|
|
443
489
|
const commandBuffer = commandEncoder.finish();
|
|
444
490
|
this.device.handle.queue.submit([commandBuffer]);
|
|
445
491
|
this.device.popErrorScope((error) => {
|
|
446
492
|
this.device.reportError(new Error(`${this} readBuffer: ${error.message}`), this)();
|
|
447
493
|
this.device.debug();
|
|
448
494
|
});
|
|
449
|
-
return
|
|
495
|
+
return buffer;
|
|
450
496
|
}
|
|
451
497
|
async readDataAsync(options = {}) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
const
|
|
459
|
-
const
|
|
460
|
-
const
|
|
498
|
+
throw new Error(`${this} readDataAsync is deprecated; use readBuffer() with an explicit destination buffer or DynamicTexture.readAsync()`);
|
|
499
|
+
}
|
|
500
|
+
copyToBuffer(commandEncoder, options = {}, buffer) {
|
|
501
|
+
const { byteOffset = 0, bytesPerRow: requestedBytesPerRow, rowsPerImage: requestedRowsPerImage, ...textureReadOptions } = options;
|
|
502
|
+
const { x, y, z, width, height, depthOrArrayLayers, mipLevel, aspect } = this._getSupportedColorReadOptions(textureReadOptions);
|
|
503
|
+
const layout = this.computeMemoryLayout({ width, height, depthOrArrayLayers, mipLevel });
|
|
504
|
+
const effectiveBytesPerRow = requestedBytesPerRow ?? layout.bytesPerRow;
|
|
505
|
+
const effectiveRowsPerImage = requestedRowsPerImage ?? layout.rowsPerImage;
|
|
506
|
+
const webgpuBuffer = buffer;
|
|
507
|
+
commandEncoder.copyTextureToBuffer({
|
|
508
|
+
texture: this.handle,
|
|
509
|
+
origin: { x, y, z },
|
|
510
|
+
mipLevel,
|
|
511
|
+
aspect
|
|
512
|
+
}, {
|
|
513
|
+
buffer: webgpuBuffer.handle,
|
|
514
|
+
offset: byteOffset,
|
|
515
|
+
bytesPerRow: effectiveBytesPerRow,
|
|
516
|
+
rowsPerImage: effectiveRowsPerImage
|
|
517
|
+
}, {
|
|
518
|
+
width,
|
|
519
|
+
height,
|
|
520
|
+
depthOrArrayLayers
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
writeBuffer(buffer, options_ = {}) {
|
|
524
|
+
const options = this._normalizeTextureWriteOptions(options_);
|
|
525
|
+
const { x, y, z, width, height, depthOrArrayLayers, mipLevel, aspect, byteOffset, bytesPerRow, rowsPerImage } = options;
|
|
461
526
|
const gpuDevice = this.device.handle;
|
|
462
527
|
this.device.pushErrorScope("validation");
|
|
463
528
|
const commandEncoder = gpuDevice.createCommandEncoder();
|
|
464
529
|
commandEncoder.copyBufferToTexture({
|
|
465
530
|
buffer: buffer.handle,
|
|
466
|
-
offset:
|
|
531
|
+
offset: byteOffset,
|
|
467
532
|
bytesPerRow,
|
|
468
533
|
rowsPerImage
|
|
469
534
|
}, {
|
|
@@ -479,33 +544,88 @@ var init_webgpu_texture = __esm({
|
|
|
479
544
|
this.device.debug();
|
|
480
545
|
});
|
|
481
546
|
}
|
|
482
|
-
writeData(data,
|
|
547
|
+
writeData(data, options_ = {}) {
|
|
483
548
|
const device = this.device;
|
|
484
|
-
const
|
|
485
|
-
const
|
|
549
|
+
const options = this._normalizeTextureWriteOptions(options_);
|
|
550
|
+
const { x, y, z, width, height, depthOrArrayLayers, mipLevel, aspect, byteOffset } = options;
|
|
551
|
+
const source = data;
|
|
552
|
+
const formatInfo = this.device.getTextureFormatInfo(this.format);
|
|
553
|
+
const packedSourceLayout = import_core4.textureFormatDecoder.computeMemoryLayout({
|
|
486
554
|
format: this.format,
|
|
487
|
-
width
|
|
488
|
-
height
|
|
489
|
-
depth:
|
|
490
|
-
byteAlignment:
|
|
555
|
+
width,
|
|
556
|
+
height,
|
|
557
|
+
depth: depthOrArrayLayers,
|
|
558
|
+
byteAlignment: 1
|
|
491
559
|
});
|
|
492
|
-
const
|
|
560
|
+
const bytesPerRow = options_.bytesPerRow ?? packedSourceLayout.bytesPerRow;
|
|
561
|
+
const rowsPerImage = options_.rowsPerImage ?? packedSourceLayout.rowsPerImage;
|
|
562
|
+
let copyWidth = width;
|
|
563
|
+
let copyHeight = height;
|
|
564
|
+
if (formatInfo.compressed) {
|
|
565
|
+
const blockWidth = formatInfo.blockWidth || 1;
|
|
566
|
+
const blockHeight = formatInfo.blockHeight || 1;
|
|
567
|
+
copyWidth = Math.ceil(width / blockWidth) * blockWidth;
|
|
568
|
+
copyHeight = Math.ceil(height / blockHeight) * blockHeight;
|
|
569
|
+
}
|
|
493
570
|
this.device.pushErrorScope("validation");
|
|
494
571
|
device.handle.queue.writeTexture({
|
|
495
572
|
texture: this.handle,
|
|
496
573
|
mipLevel,
|
|
497
574
|
aspect,
|
|
498
575
|
origin: { x, y, z }
|
|
499
|
-
},
|
|
500
|
-
offset:
|
|
576
|
+
}, source, {
|
|
577
|
+
offset: byteOffset,
|
|
501
578
|
bytesPerRow,
|
|
502
579
|
rowsPerImage
|
|
503
|
-
}, { width, height, depthOrArrayLayers });
|
|
580
|
+
}, { width: copyWidth, height: copyHeight, depthOrArrayLayers });
|
|
504
581
|
this.device.popErrorScope((error) => {
|
|
505
582
|
this.device.reportError(new Error(`${this} writeData: ${error.message}`), this)();
|
|
506
583
|
this.device.debug();
|
|
507
584
|
});
|
|
508
585
|
}
|
|
586
|
+
/**
|
|
587
|
+
* Internal-only hook for the cached CanvasContext/PresentationContext swapchain path.
|
|
588
|
+
* Rebinds this handle-backed texture wrapper to the current per-frame canvas texture
|
|
589
|
+
* without allocating a new luma.gl Texture or TextureView wrapper.
|
|
590
|
+
*/
|
|
591
|
+
_reinitialize(handle, props) {
|
|
592
|
+
const nextWidth = (props == null ? void 0 : props.width) ?? handle.width ?? this.width;
|
|
593
|
+
const nextHeight = (props == null ? void 0 : props.height) ?? handle.height ?? this.height;
|
|
594
|
+
const nextDepth = (props == null ? void 0 : props.depth) ?? this.depth;
|
|
595
|
+
const nextFormat = (props == null ? void 0 : props.format) ?? this.format;
|
|
596
|
+
const allocationMayHaveChanged = nextWidth !== this.width || nextHeight !== this.height || nextDepth !== this.depth || nextFormat !== this.format;
|
|
597
|
+
handle.label ||= this.id;
|
|
598
|
+
this.handle = handle;
|
|
599
|
+
this.width = nextWidth;
|
|
600
|
+
this.height = nextHeight;
|
|
601
|
+
if ((props == null ? void 0 : props.depth) !== void 0) {
|
|
602
|
+
this.depth = nextDepth;
|
|
603
|
+
}
|
|
604
|
+
if ((props == null ? void 0 : props.format) !== void 0) {
|
|
605
|
+
this.format = nextFormat;
|
|
606
|
+
}
|
|
607
|
+
this.props.handle = handle;
|
|
608
|
+
if ((props == null ? void 0 : props.width) !== void 0) {
|
|
609
|
+
this.props.width = props.width;
|
|
610
|
+
}
|
|
611
|
+
if ((props == null ? void 0 : props.height) !== void 0) {
|
|
612
|
+
this.props.height = props.height;
|
|
613
|
+
}
|
|
614
|
+
if ((props == null ? void 0 : props.depth) !== void 0) {
|
|
615
|
+
this.props.depth = props.depth;
|
|
616
|
+
}
|
|
617
|
+
if ((props == null ? void 0 : props.format) !== void 0) {
|
|
618
|
+
this.props.format = props.format;
|
|
619
|
+
}
|
|
620
|
+
if (allocationMayHaveChanged) {
|
|
621
|
+
const nextAllocation = this.getAllocatedByteLength();
|
|
622
|
+
if (nextAllocation !== this._allocatedByteLength) {
|
|
623
|
+
this._allocatedByteLength = nextAllocation;
|
|
624
|
+
this.trackReferencedMemory(nextAllocation, "Texture");
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
this.view._reinitialize(this);
|
|
628
|
+
}
|
|
509
629
|
};
|
|
510
630
|
}
|
|
511
631
|
});
|
|
@@ -586,7 +706,19 @@ var init_webgpu_shader = __esm({
|
|
|
586
706
|
}
|
|
587
707
|
/** Returns compilation info for this shader */
|
|
588
708
|
async getCompilationInfo() {
|
|
589
|
-
const
|
|
709
|
+
const handle = this.handle;
|
|
710
|
+
if (!handle) {
|
|
711
|
+
return [];
|
|
712
|
+
}
|
|
713
|
+
let compilationInfo;
|
|
714
|
+
try {
|
|
715
|
+
compilationInfo = await handle.getCompilationInfo();
|
|
716
|
+
} catch (error) {
|
|
717
|
+
if (this.device.shouldIgnoreDroppedInstanceError(error, "getCompilationInfo")) {
|
|
718
|
+
return [];
|
|
719
|
+
}
|
|
720
|
+
throw error;
|
|
721
|
+
}
|
|
590
722
|
return compilationInfo.messages;
|
|
591
723
|
}
|
|
592
724
|
};
|
|
@@ -677,6 +809,7 @@ var init_webgpu_parameters = __esm({
|
|
|
677
809
|
const depthStencil = addDepthStencil(descriptor);
|
|
678
810
|
depthStencil.format = value;
|
|
679
811
|
},
|
|
812
|
+
clearDepth: notSupported,
|
|
680
813
|
depthBias: (_, value, descriptor) => {
|
|
681
814
|
const depthStencil = addDepthStencil(descriptor);
|
|
682
815
|
depthStencil.depthBias = value;
|
|
@@ -815,96 +948,6 @@ var init_webgpu_parameters = __esm({
|
|
|
815
948
|
}
|
|
816
949
|
});
|
|
817
950
|
|
|
818
|
-
// dist/adapter/helpers/get-bind-group.js
|
|
819
|
-
function getBindGroup(device, bindGroupLayout, shaderLayout, bindings) {
|
|
820
|
-
const entries = getBindGroupEntries(bindings, shaderLayout);
|
|
821
|
-
device.pushErrorScope("validation");
|
|
822
|
-
const bindGroup = device.createBindGroup({
|
|
823
|
-
layout: bindGroupLayout,
|
|
824
|
-
entries
|
|
825
|
-
});
|
|
826
|
-
device.popErrorScope().then((error) => {
|
|
827
|
-
if (error) {
|
|
828
|
-
import_core8.log.error(`bindGroup creation: ${error.message}`, bindGroup)();
|
|
829
|
-
}
|
|
830
|
-
});
|
|
831
|
-
return bindGroup;
|
|
832
|
-
}
|
|
833
|
-
function getShaderLayoutBinding(shaderLayout, bindingName, options) {
|
|
834
|
-
const bindingLayout = shaderLayout.bindings.find((binding) => binding.name === bindingName || `${binding.name.toLocaleLowerCase()}uniforms` === bindingName.toLocaleLowerCase());
|
|
835
|
-
if (!bindingLayout && !(options == null ? void 0 : options.ignoreWarnings)) {
|
|
836
|
-
import_core8.log.warn(`Binding ${bindingName} not set: Not found in shader layout.`)();
|
|
837
|
-
}
|
|
838
|
-
return bindingLayout || null;
|
|
839
|
-
}
|
|
840
|
-
function getBindGroupEntries(bindings, shaderLayout) {
|
|
841
|
-
const entries = [];
|
|
842
|
-
for (const [bindingName, value] of Object.entries(bindings)) {
|
|
843
|
-
let bindingLayout = getShaderLayoutBinding(shaderLayout, bindingName);
|
|
844
|
-
if (bindingLayout) {
|
|
845
|
-
const entry = getBindGroupEntry(value, bindingLayout.location, void 0, bindingName);
|
|
846
|
-
if (entry) {
|
|
847
|
-
entries.push(entry);
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
if (value instanceof import_core8.Texture) {
|
|
851
|
-
bindingLayout = getShaderLayoutBinding(shaderLayout, `${bindingName}Sampler`, {
|
|
852
|
-
ignoreWarnings: true
|
|
853
|
-
});
|
|
854
|
-
if (bindingLayout) {
|
|
855
|
-
const entry = getBindGroupEntry(value, bindingLayout.location, { sampler: true }, bindingName);
|
|
856
|
-
if (entry) {
|
|
857
|
-
entries.push(entry);
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
return entries;
|
|
863
|
-
}
|
|
864
|
-
function getBindGroupEntry(binding, index, options, bindingName = "unknown") {
|
|
865
|
-
if (binding instanceof import_core8.Buffer) {
|
|
866
|
-
return {
|
|
867
|
-
binding: index,
|
|
868
|
-
resource: {
|
|
869
|
-
buffer: binding.handle
|
|
870
|
-
}
|
|
871
|
-
};
|
|
872
|
-
}
|
|
873
|
-
if (binding instanceof import_core8.Sampler) {
|
|
874
|
-
return {
|
|
875
|
-
binding: index,
|
|
876
|
-
resource: binding.handle
|
|
877
|
-
};
|
|
878
|
-
}
|
|
879
|
-
if (binding instanceof import_core8.TextureView) {
|
|
880
|
-
return {
|
|
881
|
-
binding: index,
|
|
882
|
-
resource: binding.handle
|
|
883
|
-
};
|
|
884
|
-
}
|
|
885
|
-
if (binding instanceof import_core8.Texture) {
|
|
886
|
-
if (options == null ? void 0 : options.sampler) {
|
|
887
|
-
return {
|
|
888
|
-
binding: index,
|
|
889
|
-
resource: binding.sampler.handle
|
|
890
|
-
};
|
|
891
|
-
}
|
|
892
|
-
return {
|
|
893
|
-
binding: index,
|
|
894
|
-
resource: binding.view.handle
|
|
895
|
-
};
|
|
896
|
-
}
|
|
897
|
-
import_core8.log.warn(`invalid binding ${bindingName}`, binding);
|
|
898
|
-
return null;
|
|
899
|
-
}
|
|
900
|
-
var import_core8;
|
|
901
|
-
var init_get_bind_group = __esm({
|
|
902
|
-
"dist/adapter/helpers/get-bind-group.js"() {
|
|
903
|
-
"use strict";
|
|
904
|
-
import_core8 = require("@luma.gl/core");
|
|
905
|
-
}
|
|
906
|
-
});
|
|
907
|
-
|
|
908
951
|
// dist/adapter/helpers/get-vertex-buffer-layout.js
|
|
909
952
|
function getWebGPUVertexFormat(format) {
|
|
910
953
|
if (format.endsWith("-webgl")) {
|
|
@@ -912,9 +955,10 @@ function getWebGPUVertexFormat(format) {
|
|
|
912
955
|
}
|
|
913
956
|
return format;
|
|
914
957
|
}
|
|
915
|
-
function getVertexBufferLayout(shaderLayout, bufferLayout) {
|
|
958
|
+
function getVertexBufferLayout(shaderLayout, bufferLayout, options) {
|
|
916
959
|
const vertexBufferLayouts = [];
|
|
917
960
|
const usedAttributes = /* @__PURE__ */ new Set();
|
|
961
|
+
const shaderAttributes = shaderLayout.attributes || [];
|
|
918
962
|
for (const mapping of bufferLayout) {
|
|
919
963
|
const vertexAttributes = [];
|
|
920
964
|
let stepMode = "vertex";
|
|
@@ -923,7 +967,7 @@ function getVertexBufferLayout(shaderLayout, bufferLayout) {
|
|
|
923
967
|
if (mapping.attributes) {
|
|
924
968
|
for (const attributeMapping of mapping.attributes) {
|
|
925
969
|
const attributeName = attributeMapping.attribute;
|
|
926
|
-
const attributeLayout = findAttributeLayout(shaderLayout, attributeName, usedAttributes);
|
|
970
|
+
const attributeLayout = findAttributeLayout(shaderLayout, attributeName, usedAttributes, options);
|
|
927
971
|
const location = attributeLayout == null ? void 0 : attributeLayout.location;
|
|
928
972
|
format = attributeMapping.format || mapping.format;
|
|
929
973
|
stepMode = (attributeLayout == null ? void 0 : attributeLayout.stepMode) || ((attributeLayout == null ? void 0 : attributeLayout.name.startsWith("instance")) ? "instance" : "vertex");
|
|
@@ -932,14 +976,14 @@ function getVertexBufferLayout(shaderLayout, bufferLayout) {
|
|
|
932
976
|
offset: attributeMapping.byteOffset,
|
|
933
977
|
shaderLocation: location
|
|
934
978
|
});
|
|
935
|
-
byteStride +=
|
|
979
|
+
byteStride += import_core8.vertexFormatDecoder.getVertexFormatInfo(format).byteLength;
|
|
936
980
|
}
|
|
937
981
|
} else {
|
|
938
|
-
const attributeLayout = findAttributeLayout(shaderLayout, mapping.name, usedAttributes);
|
|
982
|
+
const attributeLayout = findAttributeLayout(shaderLayout, mapping.name, usedAttributes, options);
|
|
939
983
|
if (!attributeLayout) {
|
|
940
984
|
continue;
|
|
941
985
|
}
|
|
942
|
-
byteStride =
|
|
986
|
+
byteStride = import_core8.vertexFormatDecoder.getVertexFormatInfo(format).byteLength;
|
|
943
987
|
stepMode = attributeLayout.stepMode || (attributeLayout.name.startsWith("instance") ? "instance" : "vertex");
|
|
944
988
|
vertexAttributes.push({
|
|
945
989
|
format: getWebGPUVertexFormat(format),
|
|
@@ -954,10 +998,10 @@ function getVertexBufferLayout(shaderLayout, bufferLayout) {
|
|
|
954
998
|
attributes: vertexAttributes
|
|
955
999
|
});
|
|
956
1000
|
}
|
|
957
|
-
for (const attribute of
|
|
1001
|
+
for (const attribute of shaderAttributes) {
|
|
958
1002
|
if (!usedAttributes.has(attribute.name)) {
|
|
959
1003
|
vertexBufferLayouts.push({
|
|
960
|
-
arrayStride:
|
|
1004
|
+
arrayStride: import_core8.vertexFormatDecoder.getVertexFormatInfo("float32x3").byteLength,
|
|
961
1005
|
stepMode: attribute.stepMode || (attribute.name.startsWith("instance") ? "instance" : "vertex"),
|
|
962
1006
|
attributes: [
|
|
963
1007
|
{
|
|
@@ -976,10 +1020,12 @@ function getVertexBufferLayout(shaderLayout, bufferLayout) {
|
|
|
976
1020
|
});
|
|
977
1021
|
return vertexBufferLayouts;
|
|
978
1022
|
}
|
|
979
|
-
function findAttributeLayout(shaderLayout, name, attributeNames) {
|
|
980
|
-
|
|
1023
|
+
function findAttributeLayout(shaderLayout, name, attributeNames, options) {
|
|
1024
|
+
var _a;
|
|
1025
|
+
const attribute = (_a = shaderLayout.attributes) == null ? void 0 : _a.find((attribute_) => attribute_.name === name);
|
|
981
1026
|
if (!attribute) {
|
|
982
|
-
|
|
1027
|
+
const pipelineContext = (options == null ? void 0 : options.pipelineId) ? `RenderPipeline(${options.pipelineId})` : "RenderPipeline";
|
|
1028
|
+
import_core8.log.warn(`${pipelineContext}: Ignoring "${name}" attribute, since it is not present in shader layout.`)();
|
|
983
1029
|
return null;
|
|
984
1030
|
}
|
|
985
1031
|
if (attributeNames) {
|
|
@@ -990,45 +1036,58 @@ function findAttributeLayout(shaderLayout, name, attributeNames) {
|
|
|
990
1036
|
}
|
|
991
1037
|
return attribute;
|
|
992
1038
|
}
|
|
993
|
-
var
|
|
1039
|
+
var import_core8;
|
|
994
1040
|
var init_get_vertex_buffer_layout = __esm({
|
|
995
1041
|
"dist/adapter/helpers/get-vertex-buffer-layout.js"() {
|
|
996
1042
|
"use strict";
|
|
997
|
-
|
|
1043
|
+
import_core8 = require("@luma.gl/core");
|
|
998
1044
|
}
|
|
999
1045
|
});
|
|
1000
1046
|
|
|
1001
1047
|
// dist/adapter/resources/webgpu-render-pipeline.js
|
|
1002
|
-
|
|
1048
|
+
function createBindGroupCacheKeys(bindingsByGroup) {
|
|
1049
|
+
const bindGroupCacheKeys = {};
|
|
1050
|
+
for (const [groupKey, groupBindings] of Object.entries(bindingsByGroup)) {
|
|
1051
|
+
if (groupBindings && Object.keys(groupBindings).length > 0) {
|
|
1052
|
+
bindGroupCacheKeys[Number(groupKey)] = {};
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
return bindGroupCacheKeys;
|
|
1056
|
+
}
|
|
1057
|
+
var import_core9, WebGPURenderPipeline;
|
|
1003
1058
|
var init_webgpu_render_pipeline = __esm({
|
|
1004
1059
|
"dist/adapter/resources/webgpu-render-pipeline.js"() {
|
|
1005
1060
|
"use strict";
|
|
1006
|
-
|
|
1061
|
+
import_core9 = require("@luma.gl/core");
|
|
1007
1062
|
init_webgpu_parameters();
|
|
1008
1063
|
init_convert_texture_format();
|
|
1009
|
-
init_get_bind_group();
|
|
1010
1064
|
init_get_vertex_buffer_layout();
|
|
1011
|
-
WebGPURenderPipeline = class extends
|
|
1065
|
+
WebGPURenderPipeline = class extends import_core9.RenderPipeline {
|
|
1012
1066
|
device;
|
|
1013
1067
|
handle;
|
|
1068
|
+
descriptor;
|
|
1014
1069
|
vs;
|
|
1015
1070
|
fs = null;
|
|
1016
|
-
/**
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
_bindGroup = null;
|
|
1071
|
+
/** Compatibility path for direct pipeline.setBindings() usage */
|
|
1072
|
+
_bindingsByGroup;
|
|
1073
|
+
_bindGroupCacheKeysByGroup = {};
|
|
1020
1074
|
get [Symbol.toStringTag]() {
|
|
1021
1075
|
return "WebGPURenderPipeline";
|
|
1022
1076
|
}
|
|
1023
1077
|
constructor(device, props) {
|
|
1024
1078
|
super(device, props);
|
|
1025
1079
|
this.device = device;
|
|
1080
|
+
this.shaderLayout ||= this.device.getShaderLayout(props.vs.source) || {
|
|
1081
|
+
attributes: [],
|
|
1082
|
+
bindings: []
|
|
1083
|
+
};
|
|
1026
1084
|
this.handle = this.props.handle;
|
|
1085
|
+
let descriptor = null;
|
|
1027
1086
|
if (!this.handle) {
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1087
|
+
descriptor = this._getRenderPipelineDescriptor();
|
|
1088
|
+
import_core9.log.groupCollapsed(1, `new WebGPURenderPipeline(${this.id})`)();
|
|
1089
|
+
import_core9.log.probe(1, JSON.stringify(descriptor, null, 2))();
|
|
1090
|
+
import_core9.log.groupEnd(1)();
|
|
1032
1091
|
this.device.pushErrorScope("validation");
|
|
1033
1092
|
this.handle = this.device.handle.createRenderPipeline(descriptor);
|
|
1034
1093
|
this.device.popErrorScope((error) => {
|
|
@@ -1037,29 +1096,40 @@ var init_webgpu_render_pipeline = __esm({
|
|
|
1037
1096
|
this.device.debug();
|
|
1038
1097
|
});
|
|
1039
1098
|
}
|
|
1099
|
+
this.descriptor = descriptor;
|
|
1040
1100
|
this.handle.label = this.props.id;
|
|
1041
1101
|
this.vs = props.vs;
|
|
1042
1102
|
this.fs = props.fs;
|
|
1043
|
-
this.
|
|
1103
|
+
this._bindingsByGroup = props.bindGroups || (0, import_core9.normalizeBindingsByGroup)(this.shaderLayout, props.bindings);
|
|
1104
|
+
this._bindGroupCacheKeysByGroup = createBindGroupCacheKeys(this._bindingsByGroup);
|
|
1044
1105
|
}
|
|
1045
1106
|
destroy() {
|
|
1046
1107
|
this.handle = null;
|
|
1047
1108
|
}
|
|
1048
1109
|
/**
|
|
1049
|
-
*
|
|
1050
|
-
*
|
|
1110
|
+
* Compatibility shim for code paths that still set bindings on the pipeline.
|
|
1111
|
+
* The shared-model path passes bindings per draw and does not rely on this state.
|
|
1051
1112
|
*/
|
|
1052
1113
|
setBindings(bindings) {
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1114
|
+
const nextBindingsByGroup = (0, import_core9.normalizeBindingsByGroup)(this.shaderLayout, bindings);
|
|
1115
|
+
for (const [groupKey, groupBindings] of Object.entries(nextBindingsByGroup)) {
|
|
1116
|
+
const group = Number(groupKey);
|
|
1117
|
+
for (const [name, binding] of Object.entries(groupBindings || {})) {
|
|
1118
|
+
const currentGroupBindings = this._bindingsByGroup[group] || {};
|
|
1119
|
+
if (currentGroupBindings[name] !== binding) {
|
|
1120
|
+
if (!this._bindingsByGroup[group] || this._bindingsByGroup[group] === currentGroupBindings) {
|
|
1121
|
+
this._bindingsByGroup[group] = { ...currentGroupBindings };
|
|
1122
|
+
}
|
|
1123
|
+
this._bindingsByGroup[group][name] = binding;
|
|
1124
|
+
this._bindGroupCacheKeysByGroup[group] = {};
|
|
1125
|
+
}
|
|
1056
1126
|
}
|
|
1057
1127
|
}
|
|
1058
|
-
Object.assign(this._bindings, bindings);
|
|
1059
1128
|
}
|
|
1060
1129
|
/** @todo - should this be moved to renderpass? */
|
|
1061
1130
|
draw(options) {
|
|
1062
1131
|
const webgpuRenderPass = options.renderPass;
|
|
1132
|
+
const instanceCount = options.instanceCount && options.instanceCount > 0 ? options.instanceCount : 1;
|
|
1063
1133
|
this.device.pushErrorScope("validation");
|
|
1064
1134
|
webgpuRenderPass.handle.setPipeline(this.handle);
|
|
1065
1135
|
this.device.popErrorScope((error) => {
|
|
@@ -1067,32 +1137,27 @@ var init_webgpu_render_pipeline = __esm({
|
|
|
1067
1137
|
"${error.message}"`), this)();
|
|
1068
1138
|
this.device.debug();
|
|
1069
1139
|
});
|
|
1070
|
-
const
|
|
1071
|
-
|
|
1072
|
-
|
|
1140
|
+
const hasExplicitBindings = Boolean(options.bindGroups || options.bindings);
|
|
1141
|
+
const bindGroups = (0, import_core9._getDefaultBindGroupFactory)(this.device).getBindGroups(this, hasExplicitBindings ? options.bindGroups || options.bindings : this._bindingsByGroup, hasExplicitBindings ? options._bindGroupCacheKeys : this._bindGroupCacheKeysByGroup);
|
|
1142
|
+
for (const [group, bindGroup] of Object.entries(bindGroups)) {
|
|
1143
|
+
if (bindGroup) {
|
|
1144
|
+
webgpuRenderPass.handle.setBindGroup(Number(group), bindGroup);
|
|
1145
|
+
}
|
|
1073
1146
|
}
|
|
1074
1147
|
options.vertexArray.bindBeforeRender(options.renderPass);
|
|
1075
1148
|
if (options.indexCount) {
|
|
1076
|
-
webgpuRenderPass.handle.drawIndexed(options.indexCount,
|
|
1149
|
+
webgpuRenderPass.handle.drawIndexed(options.indexCount, instanceCount, options.firstIndex || 0, options.baseVertex || 0, options.firstInstance || 0);
|
|
1077
1150
|
} else {
|
|
1078
|
-
webgpuRenderPass.handle.draw(
|
|
1079
|
-
options.vertexCount || 0,
|
|
1080
|
-
options.instanceCount || 1,
|
|
1081
|
-
// If 0, nothing will be drawn
|
|
1082
|
-
options.firstInstance
|
|
1083
|
-
);
|
|
1151
|
+
webgpuRenderPass.handle.draw(options.vertexCount || 0, instanceCount, options.firstVertex || 0, options.firstInstance || 0);
|
|
1084
1152
|
}
|
|
1085
1153
|
options.vertexArray.unbindAfterRender(options.renderPass);
|
|
1086
1154
|
return true;
|
|
1087
1155
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
1094
|
-
this._bindGroup = this._bindGroup || getBindGroup(this.device.handle, this._bindGroupLayout, this.shaderLayout, this._bindings);
|
|
1095
|
-
return this._bindGroup;
|
|
1156
|
+
_getBindingsByGroupWebGPU() {
|
|
1157
|
+
return this._bindingsByGroup;
|
|
1158
|
+
}
|
|
1159
|
+
_getBindGroupCacheKeysWebGPU() {
|
|
1160
|
+
return this._bindGroupCacheKeysByGroup;
|
|
1096
1161
|
}
|
|
1097
1162
|
/**
|
|
1098
1163
|
* Populate the complex WebGPU GPURenderPipelineDescriptor
|
|
@@ -1101,7 +1166,9 @@ var init_webgpu_render_pipeline = __esm({
|
|
|
1101
1166
|
const vertex = {
|
|
1102
1167
|
module: this.props.vs.handle,
|
|
1103
1168
|
entryPoint: this.props.vertexEntryPoint || "main",
|
|
1104
|
-
buffers: getVertexBufferLayout(this.shaderLayout, this.props.bufferLayout
|
|
1169
|
+
buffers: getVertexBufferLayout(this.shaderLayout, this.props.bufferLayout, {
|
|
1170
|
+
pipelineId: this.id
|
|
1171
|
+
})
|
|
1105
1172
|
};
|
|
1106
1173
|
const targets = [];
|
|
1107
1174
|
if (this.props.colorAttachmentFormats) {
|
|
@@ -1141,12 +1208,12 @@ var init_webgpu_render_pipeline = __esm({
|
|
|
1141
1208
|
});
|
|
1142
1209
|
|
|
1143
1210
|
// dist/adapter/resources/webgpu-framebuffer.js
|
|
1144
|
-
var
|
|
1211
|
+
var import_core10, WebGPUFramebuffer;
|
|
1145
1212
|
var init_webgpu_framebuffer = __esm({
|
|
1146
1213
|
"dist/adapter/resources/webgpu-framebuffer.js"() {
|
|
1147
1214
|
"use strict";
|
|
1148
|
-
|
|
1149
|
-
WebGPUFramebuffer = class extends
|
|
1215
|
+
import_core10 = require("@luma.gl/core");
|
|
1216
|
+
WebGPUFramebuffer = class extends import_core10.Framebuffer {
|
|
1150
1217
|
device;
|
|
1151
1218
|
handle = null;
|
|
1152
1219
|
colorAttachments = [];
|
|
@@ -1158,25 +1225,37 @@ var init_webgpu_framebuffer = __esm({
|
|
|
1158
1225
|
}
|
|
1159
1226
|
updateAttachments() {
|
|
1160
1227
|
}
|
|
1228
|
+
/**
|
|
1229
|
+
* Internal-only hook for the cached CanvasContext/PresentationContext swapchain path.
|
|
1230
|
+
* Rebinds the long-lived default framebuffer wrapper to the current per-frame color view
|
|
1231
|
+
* and optional depth attachment without allocating a new luma.gl Framebuffer object.
|
|
1232
|
+
*/
|
|
1233
|
+
_reinitialize(colorAttachment, depthStencilAttachment) {
|
|
1234
|
+
this.colorAttachments[0] = colorAttachment;
|
|
1235
|
+
this.depthStencilAttachment = depthStencilAttachment;
|
|
1236
|
+
this.width = colorAttachment.texture.width;
|
|
1237
|
+
this.height = colorAttachment.texture.height;
|
|
1238
|
+
this.props.width = this.width;
|
|
1239
|
+
this.props.height = this.height;
|
|
1240
|
+
this.props.colorAttachments = [colorAttachment.texture];
|
|
1241
|
+
this.props.depthStencilAttachment = (depthStencilAttachment == null ? void 0 : depthStencilAttachment.texture) || null;
|
|
1242
|
+
}
|
|
1161
1243
|
};
|
|
1162
1244
|
}
|
|
1163
1245
|
});
|
|
1164
1246
|
|
|
1165
1247
|
// dist/adapter/resources/webgpu-compute-pipeline.js
|
|
1166
|
-
var
|
|
1248
|
+
var import_core11, EMPTY_BIND_GROUPS, WebGPUComputePipeline;
|
|
1167
1249
|
var init_webgpu_compute_pipeline = __esm({
|
|
1168
1250
|
"dist/adapter/resources/webgpu-compute-pipeline.js"() {
|
|
1169
1251
|
"use strict";
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
WebGPUComputePipeline = class extends
|
|
1252
|
+
import_core11 = require("@luma.gl/core");
|
|
1253
|
+
EMPTY_BIND_GROUPS = {};
|
|
1254
|
+
WebGPUComputePipeline = class extends import_core11.ComputePipeline {
|
|
1173
1255
|
device;
|
|
1174
1256
|
handle;
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
_bindGroup = null;
|
|
1178
|
-
/** For internal use to create BindGroups */
|
|
1179
|
-
_bindings = {};
|
|
1257
|
+
_bindingsByGroup;
|
|
1258
|
+
_bindGroupCacheKeysByGroup;
|
|
1180
1259
|
constructor(device, props) {
|
|
1181
1260
|
super(device, props);
|
|
1182
1261
|
this.device = device;
|
|
@@ -1190,34 +1269,53 @@ var init_webgpu_compute_pipeline = __esm({
|
|
|
1190
1269
|
},
|
|
1191
1270
|
layout: "auto"
|
|
1192
1271
|
});
|
|
1272
|
+
this._bindingsByGroup = EMPTY_BIND_GROUPS;
|
|
1273
|
+
this._bindGroupCacheKeysByGroup = {};
|
|
1193
1274
|
}
|
|
1194
1275
|
/**
|
|
1195
1276
|
* @todo Use renderpass.setBindings() ?
|
|
1196
1277
|
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
1197
1278
|
*/
|
|
1198
1279
|
setBindings(bindings) {
|
|
1199
|
-
|
|
1280
|
+
const nextBindingsByGroup = (0, import_core11.normalizeBindingsByGroup)(this.shaderLayout, bindings);
|
|
1281
|
+
for (const [groupKey, groupBindings] of Object.entries(nextBindingsByGroup)) {
|
|
1282
|
+
const group = Number(groupKey);
|
|
1283
|
+
for (const [name, binding] of Object.entries(groupBindings || {})) {
|
|
1284
|
+
const currentGroupBindings = this._bindingsByGroup[group] || {};
|
|
1285
|
+
if (currentGroupBindings[name] !== binding) {
|
|
1286
|
+
if (!this._bindingsByGroup[group] || this._bindingsByGroup[group] === currentGroupBindings) {
|
|
1287
|
+
this._bindingsByGroup[group] = { ...currentGroupBindings };
|
|
1288
|
+
}
|
|
1289
|
+
this._bindingsByGroup[group][name] = binding;
|
|
1290
|
+
this._bindGroupCacheKeysByGroup[group] = {};
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1200
1294
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
this.
|
|
1204
|
-
|
|
1205
|
-
|
|
1295
|
+
_getBindGroups(bindings, bindGroupCacheKeys) {
|
|
1296
|
+
const hasExplicitBindings = Boolean(bindings);
|
|
1297
|
+
return (0, import_core11._getDefaultBindGroupFactory)(this.device).getBindGroups(this, hasExplicitBindings ? bindings : this._bindingsByGroup, hasExplicitBindings ? bindGroupCacheKeys : this._bindGroupCacheKeysByGroup);
|
|
1298
|
+
}
|
|
1299
|
+
_getBindingsByGroupWebGPU() {
|
|
1300
|
+
return this._bindingsByGroup;
|
|
1301
|
+
}
|
|
1302
|
+
_getBindGroupCacheKeysWebGPU() {
|
|
1303
|
+
return this._bindGroupCacheKeysByGroup;
|
|
1206
1304
|
}
|
|
1207
1305
|
};
|
|
1208
1306
|
}
|
|
1209
1307
|
});
|
|
1210
1308
|
|
|
1211
1309
|
// dist/adapter/resources/webgpu-vertex-array.js
|
|
1212
|
-
var
|
|
1310
|
+
var import_core12, import_env, WebGPUVertexArray;
|
|
1213
1311
|
var init_webgpu_vertex_array = __esm({
|
|
1214
1312
|
"dist/adapter/resources/webgpu-vertex-array.js"() {
|
|
1215
1313
|
"use strict";
|
|
1216
|
-
|
|
1314
|
+
import_core12 = require("@luma.gl/core");
|
|
1217
1315
|
import_env = require("@probe.gl/env");
|
|
1218
|
-
WebGPUVertexArray = class extends
|
|
1316
|
+
WebGPUVertexArray = class extends import_core12.VertexArray {
|
|
1219
1317
|
get [Symbol.toStringTag]() {
|
|
1220
|
-
return "
|
|
1318
|
+
return "VertexArray";
|
|
1221
1319
|
}
|
|
1222
1320
|
device;
|
|
1223
1321
|
/** Vertex Array is just a helper class under WebGPU */
|
|
@@ -1244,7 +1342,7 @@ var init_webgpu_vertex_array = __esm({
|
|
|
1244
1342
|
const webgpuRenderPass = renderPass;
|
|
1245
1343
|
const webgpuIndexBuffer = this.indexBuffer;
|
|
1246
1344
|
if (webgpuIndexBuffer == null ? void 0 : webgpuIndexBuffer.handle) {
|
|
1247
|
-
|
|
1345
|
+
import_core12.log.info(3, "setting index buffer", webgpuIndexBuffer == null ? void 0 : webgpuIndexBuffer.handle, webgpuIndexBuffer == null ? void 0 : webgpuIndexBuffer.indexType)();
|
|
1248
1346
|
webgpuRenderPass.handle.setIndexBuffer(
|
|
1249
1347
|
webgpuIndexBuffer == null ? void 0 : webgpuIndexBuffer.handle,
|
|
1250
1348
|
// @ts-expect-error TODO - we must enforce type
|
|
@@ -1254,7 +1352,7 @@ var init_webgpu_vertex_array = __esm({
|
|
|
1254
1352
|
for (let location = 0; location < this.maxVertexAttributes; location++) {
|
|
1255
1353
|
const webgpuBuffer = this.attributes[location];
|
|
1256
1354
|
if (webgpuBuffer == null ? void 0 : webgpuBuffer.handle) {
|
|
1257
|
-
|
|
1355
|
+
import_core12.log.info(3, `setting vertex buffer ${location}`, webgpuBuffer == null ? void 0 : webgpuBuffer.handle)();
|
|
1258
1356
|
webgpuRenderPass.handle.setVertexBuffer(location, webgpuBuffer == null ? void 0 : webgpuBuffer.handle);
|
|
1259
1357
|
}
|
|
1260
1358
|
}
|
|
@@ -1274,16 +1372,19 @@ var init_webgpu_vertex_array = __esm({
|
|
|
1274
1372
|
});
|
|
1275
1373
|
|
|
1276
1374
|
// dist/adapter/webgpu-canvas-context.js
|
|
1277
|
-
var
|
|
1375
|
+
var import_core13, WebGPUCanvasContext;
|
|
1278
1376
|
var init_webgpu_canvas_context = __esm({
|
|
1279
1377
|
"dist/adapter/webgpu-canvas-context.js"() {
|
|
1280
1378
|
"use strict";
|
|
1281
|
-
|
|
1379
|
+
import_core13 = require("@luma.gl/core");
|
|
1282
1380
|
init_webgpu_framebuffer();
|
|
1283
|
-
|
|
1381
|
+
init_cpu_hotspot_profiler();
|
|
1382
|
+
WebGPUCanvasContext = class extends import_core13.CanvasContext {
|
|
1284
1383
|
device;
|
|
1285
1384
|
handle;
|
|
1385
|
+
colorAttachment = null;
|
|
1286
1386
|
depthStencilAttachment = null;
|
|
1387
|
+
framebuffer = null;
|
|
1287
1388
|
get [Symbol.toStringTag]() {
|
|
1288
1389
|
return "WebGPUCanvasContext";
|
|
1289
1390
|
}
|
|
@@ -1297,9 +1398,22 @@ var init_webgpu_canvas_context = __esm({
|
|
|
1297
1398
|
this.handle = context;
|
|
1298
1399
|
this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
|
|
1299
1400
|
this._configureDevice();
|
|
1401
|
+
this._startObservers();
|
|
1300
1402
|
}
|
|
1301
1403
|
/** Destroy any textures produced while configured and remove the context configuration. */
|
|
1302
1404
|
destroy() {
|
|
1405
|
+
if (this.framebuffer) {
|
|
1406
|
+
this.framebuffer.destroy();
|
|
1407
|
+
this.framebuffer = null;
|
|
1408
|
+
}
|
|
1409
|
+
if (this.colorAttachment) {
|
|
1410
|
+
this.colorAttachment.destroy();
|
|
1411
|
+
this.colorAttachment = null;
|
|
1412
|
+
}
|
|
1413
|
+
if (this.depthStencilAttachment) {
|
|
1414
|
+
this.depthStencilAttachment.destroy();
|
|
1415
|
+
this.depthStencilAttachment = null;
|
|
1416
|
+
}
|
|
1303
1417
|
this.handle.unconfigure();
|
|
1304
1418
|
super.destroy();
|
|
1305
1419
|
}
|
|
@@ -1318,44 +1432,81 @@ var init_webgpu_canvas_context = __esm({
|
|
|
1318
1432
|
colorSpace: this.props.colorSpace,
|
|
1319
1433
|
alphaMode: this.props.alphaMode
|
|
1320
1434
|
});
|
|
1435
|
+
this._createDepthStencilAttachment(this.device.preferredDepthFormat);
|
|
1321
1436
|
}
|
|
1322
1437
|
/** Update framebuffer with properly resized "swap chain" texture views */
|
|
1323
1438
|
_getCurrentFramebuffer(options = {
|
|
1324
1439
|
depthStencilFormat: "depth24plus"
|
|
1325
1440
|
}) {
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1441
|
+
var _a;
|
|
1442
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
1443
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
1444
|
+
if (profiler) {
|
|
1445
|
+
profiler.framebufferAcquireCount = (profiler.framebufferAcquireCount || 0) + 1;
|
|
1446
|
+
profiler.activeDefaultFramebufferAcquireDepth = (profiler.activeDefaultFramebufferAcquireDepth || 0) + 1;
|
|
1447
|
+
}
|
|
1448
|
+
try {
|
|
1449
|
+
const currentColorAttachment = this._getCurrentTexture();
|
|
1450
|
+
if (currentColorAttachment.width !== this.drawingBufferWidth || currentColorAttachment.height !== this.drawingBufferHeight) {
|
|
1451
|
+
const [oldWidth, oldHeight] = this.getDrawingBufferSize();
|
|
1452
|
+
this.drawingBufferWidth = currentColorAttachment.width;
|
|
1453
|
+
this.drawingBufferHeight = currentColorAttachment.height;
|
|
1454
|
+
import_core13.log.log(1, `${this}: Resized to compensate for initial canvas size mismatch ${oldWidth}x${oldHeight} => ${this.drawingBufferWidth}x${this.drawingBufferHeight}px`)();
|
|
1455
|
+
}
|
|
1456
|
+
if (options == null ? void 0 : options.depthStencilFormat) {
|
|
1457
|
+
this._createDepthStencilAttachment(options == null ? void 0 : options.depthStencilFormat);
|
|
1458
|
+
}
|
|
1459
|
+
this.framebuffer ||= new WebGPUFramebuffer(this.device, {
|
|
1460
|
+
id: `${this.id}#framebuffer`,
|
|
1461
|
+
colorAttachments: [currentColorAttachment],
|
|
1462
|
+
depthStencilAttachment: null
|
|
1463
|
+
});
|
|
1464
|
+
this.framebuffer._reinitialize(currentColorAttachment.view, (options == null ? void 0 : options.depthStencilFormat) ? ((_a = this.depthStencilAttachment) == null ? void 0 : _a.view) || null : null);
|
|
1465
|
+
return this.framebuffer;
|
|
1466
|
+
} finally {
|
|
1467
|
+
if (profiler) {
|
|
1468
|
+
profiler.activeDefaultFramebufferAcquireDepth = (profiler.activeDefaultFramebufferAcquireDepth || 1) - 1;
|
|
1469
|
+
profiler.framebufferAcquireTimeMs = (profiler.framebufferAcquireTimeMs || 0) + (getTimestamp() - startTime);
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1340
1472
|
}
|
|
1341
1473
|
// PRIMARY METHODS
|
|
1342
1474
|
/** Wrap the current canvas context texture in a luma.gl texture */
|
|
1343
1475
|
_getCurrentTexture() {
|
|
1476
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
1477
|
+
const currentTextureStartTime = profiler ? getTimestamp() : 0;
|
|
1344
1478
|
const handle = this.handle.getCurrentTexture();
|
|
1345
|
-
|
|
1346
|
-
|
|
1479
|
+
if (profiler) {
|
|
1480
|
+
profiler.currentTextureAcquireCount = (profiler.currentTextureAcquireCount || 0) + 1;
|
|
1481
|
+
profiler.currentTextureAcquireTimeMs = (profiler.currentTextureAcquireTimeMs || 0) + (getTimestamp() - currentTextureStartTime);
|
|
1482
|
+
}
|
|
1483
|
+
if (!this.colorAttachment) {
|
|
1484
|
+
this.colorAttachment = this.device.createTexture({
|
|
1485
|
+
id: `${this.id}#color-texture`,
|
|
1486
|
+
handle,
|
|
1487
|
+
format: this.device.preferredColorFormat,
|
|
1488
|
+
width: handle.width,
|
|
1489
|
+
height: handle.height
|
|
1490
|
+
});
|
|
1491
|
+
return this.colorAttachment;
|
|
1492
|
+
}
|
|
1493
|
+
this.colorAttachment._reinitialize(handle, {
|
|
1347
1494
|
handle,
|
|
1348
1495
|
format: this.device.preferredColorFormat,
|
|
1349
1496
|
width: handle.width,
|
|
1350
1497
|
height: handle.height
|
|
1351
1498
|
});
|
|
1499
|
+
return this.colorAttachment;
|
|
1352
1500
|
}
|
|
1353
1501
|
/** We build render targets on demand (i.e. not when size changes but when about to render) */
|
|
1354
1502
|
_createDepthStencilAttachment(depthStencilFormat) {
|
|
1355
|
-
|
|
1503
|
+
var _a;
|
|
1504
|
+
const needsNewDepthStencilAttachment = !this.depthStencilAttachment || this.depthStencilAttachment.width !== this.drawingBufferWidth || this.depthStencilAttachment.height !== this.drawingBufferHeight || this.depthStencilAttachment.format !== depthStencilFormat;
|
|
1505
|
+
if (needsNewDepthStencilAttachment) {
|
|
1506
|
+
(_a = this.depthStencilAttachment) == null ? void 0 : _a.destroy();
|
|
1356
1507
|
this.depthStencilAttachment = this.device.createTexture({
|
|
1357
1508
|
id: `${this.id}#depth-stencil-texture`,
|
|
1358
|
-
usage:
|
|
1509
|
+
usage: import_core13.Texture.RENDER_ATTACHMENT,
|
|
1359
1510
|
format: depthStencilFormat,
|
|
1360
1511
|
width: this.drawingBufferWidth,
|
|
1361
1512
|
height: this.drawingBufferHeight
|
|
@@ -1367,76 +1518,246 @@ var init_webgpu_canvas_context = __esm({
|
|
|
1367
1518
|
}
|
|
1368
1519
|
});
|
|
1369
1520
|
|
|
1370
|
-
// dist/adapter/
|
|
1371
|
-
var
|
|
1372
|
-
var
|
|
1373
|
-
"dist/adapter/
|
|
1521
|
+
// dist/adapter/webgpu-presentation-context.js
|
|
1522
|
+
var import_core14, WebGPUPresentationContext;
|
|
1523
|
+
var init_webgpu_presentation_context = __esm({
|
|
1524
|
+
"dist/adapter/webgpu-presentation-context.js"() {
|
|
1374
1525
|
"use strict";
|
|
1375
|
-
|
|
1376
|
-
|
|
1526
|
+
import_core14 = require("@luma.gl/core");
|
|
1527
|
+
init_webgpu_framebuffer();
|
|
1528
|
+
init_cpu_hotspot_profiler();
|
|
1529
|
+
WebGPUPresentationContext = class extends import_core14.PresentationContext {
|
|
1377
1530
|
device;
|
|
1378
1531
|
handle;
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
});
|
|
1532
|
+
colorAttachment = null;
|
|
1533
|
+
depthStencilAttachment = null;
|
|
1534
|
+
framebuffer = null;
|
|
1535
|
+
get [Symbol.toStringTag]() {
|
|
1536
|
+
return "WebGPUPresentationContext";
|
|
1385
1537
|
}
|
|
1386
|
-
};
|
|
1387
|
-
}
|
|
1388
|
-
});
|
|
1389
|
-
|
|
1390
|
-
// dist/adapter/resources/webgpu-render-pass.js
|
|
1391
|
-
function convertColor(color) {
|
|
1392
|
-
return { r: color[0], g: color[1], b: color[2], a: color[3] };
|
|
1393
|
-
}
|
|
1394
|
-
var import_core16, WebGPURenderPass;
|
|
1395
|
-
var init_webgpu_render_pass = __esm({
|
|
1396
|
-
"dist/adapter/resources/webgpu-render-pass.js"() {
|
|
1397
|
-
"use strict";
|
|
1398
|
-
import_core16 = require("@luma.gl/core");
|
|
1399
|
-
WebGPURenderPass = class extends import_core16.RenderPass {
|
|
1400
|
-
device;
|
|
1401
|
-
handle;
|
|
1402
|
-
/** Active pipeline */
|
|
1403
|
-
pipeline = null;
|
|
1404
1538
|
constructor(device, props = {}) {
|
|
1405
|
-
super(
|
|
1539
|
+
super(props);
|
|
1540
|
+
const contextLabel = `${this[Symbol.toStringTag]}(${this.id})`;
|
|
1541
|
+
const context = this.canvas.getContext("webgpu");
|
|
1542
|
+
if (!context) {
|
|
1543
|
+
throw new Error(`${contextLabel}: Failed to create WebGPU presentation context`);
|
|
1544
|
+
}
|
|
1406
1545
|
this.device = device;
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
if (
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
querySet: webgpuTSQuerySet.handle,
|
|
1417
|
-
beginningOfPassWriteIndex: props.beginTimestampIndex,
|
|
1418
|
-
endOfPassWriteIndex: props.endTimestampIndex
|
|
1419
|
-
} : void 0;
|
|
1420
|
-
}
|
|
1421
|
-
if (!device.commandEncoder) {
|
|
1422
|
-
throw new Error("commandEncoder not available");
|
|
1546
|
+
this.handle = context;
|
|
1547
|
+
this._setAutoCreatedCanvasId(`${this.device.id}-presentation-canvas`);
|
|
1548
|
+
this._configureDevice();
|
|
1549
|
+
this._startObservers();
|
|
1550
|
+
}
|
|
1551
|
+
destroy() {
|
|
1552
|
+
if (this.framebuffer) {
|
|
1553
|
+
this.framebuffer.destroy();
|
|
1554
|
+
this.framebuffer = null;
|
|
1423
1555
|
}
|
|
1424
|
-
this.
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
this.
|
|
1556
|
+
if (this.colorAttachment) {
|
|
1557
|
+
this.colorAttachment.destroy();
|
|
1558
|
+
this.colorAttachment = null;
|
|
1559
|
+
}
|
|
1560
|
+
if (this.depthStencilAttachment) {
|
|
1561
|
+
this.depthStencilAttachment.destroy();
|
|
1562
|
+
this.depthStencilAttachment = null;
|
|
1563
|
+
}
|
|
1564
|
+
this.handle.unconfigure();
|
|
1565
|
+
super.destroy();
|
|
1566
|
+
}
|
|
1567
|
+
present() {
|
|
1568
|
+
this.device.submit();
|
|
1569
|
+
}
|
|
1570
|
+
_configureDevice() {
|
|
1571
|
+
if (this.depthStencilAttachment) {
|
|
1572
|
+
this.depthStencilAttachment.destroy();
|
|
1573
|
+
this.depthStencilAttachment = null;
|
|
1574
|
+
}
|
|
1575
|
+
this.handle.configure({
|
|
1576
|
+
device: this.device.handle,
|
|
1577
|
+
format: this.device.preferredColorFormat,
|
|
1578
|
+
colorSpace: this.props.colorSpace,
|
|
1579
|
+
alphaMode: this.props.alphaMode
|
|
1580
|
+
});
|
|
1581
|
+
this._createDepthStencilAttachment(this.device.preferredDepthFormat);
|
|
1582
|
+
}
|
|
1583
|
+
_getCurrentFramebuffer(options = {
|
|
1584
|
+
depthStencilFormat: "depth24plus"
|
|
1585
|
+
}) {
|
|
1586
|
+
var _a;
|
|
1587
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
1588
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
1589
|
+
if (profiler) {
|
|
1590
|
+
profiler.framebufferAcquireCount = (profiler.framebufferAcquireCount || 0) + 1;
|
|
1591
|
+
}
|
|
1592
|
+
try {
|
|
1593
|
+
const currentColorAttachment = this._getCurrentTexture();
|
|
1594
|
+
if (currentColorAttachment.width !== this.drawingBufferWidth || currentColorAttachment.height !== this.drawingBufferHeight) {
|
|
1595
|
+
const [oldWidth, oldHeight] = this.getDrawingBufferSize();
|
|
1596
|
+
this.drawingBufferWidth = currentColorAttachment.width;
|
|
1597
|
+
this.drawingBufferHeight = currentColorAttachment.height;
|
|
1598
|
+
import_core14.log.log(1, `${this[Symbol.toStringTag]}(${this.id}): Resized to compensate for initial canvas size mismatch ${oldWidth}x${oldHeight} => ${this.drawingBufferWidth}x${this.drawingBufferHeight}px`)();
|
|
1599
|
+
}
|
|
1600
|
+
if (options == null ? void 0 : options.depthStencilFormat) {
|
|
1601
|
+
this._createDepthStencilAttachment(options.depthStencilFormat);
|
|
1602
|
+
}
|
|
1603
|
+
this.framebuffer ||= new WebGPUFramebuffer(this.device, {
|
|
1604
|
+
id: `${this.id}#framebuffer`,
|
|
1605
|
+
colorAttachments: [currentColorAttachment],
|
|
1606
|
+
depthStencilAttachment: null
|
|
1607
|
+
});
|
|
1608
|
+
this.framebuffer._reinitialize(currentColorAttachment.view, (options == null ? void 0 : options.depthStencilFormat) ? ((_a = this.depthStencilAttachment) == null ? void 0 : _a.view) || null : null);
|
|
1609
|
+
return this.framebuffer;
|
|
1610
|
+
} finally {
|
|
1611
|
+
if (profiler) {
|
|
1612
|
+
profiler.framebufferAcquireTimeMs = (profiler.framebufferAcquireTimeMs || 0) + (getTimestamp() - startTime);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
_getCurrentTexture() {
|
|
1617
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
1618
|
+
const currentTextureStartTime = profiler ? getTimestamp() : 0;
|
|
1619
|
+
const handle = this.handle.getCurrentTexture();
|
|
1620
|
+
if (profiler) {
|
|
1621
|
+
profiler.currentTextureAcquireCount = (profiler.currentTextureAcquireCount || 0) + 1;
|
|
1622
|
+
profiler.currentTextureAcquireTimeMs = (profiler.currentTextureAcquireTimeMs || 0) + (getTimestamp() - currentTextureStartTime);
|
|
1623
|
+
}
|
|
1624
|
+
if (!this.colorAttachment) {
|
|
1625
|
+
this.colorAttachment = this.device.createTexture({
|
|
1626
|
+
id: `${this.id}#color-texture`,
|
|
1627
|
+
handle,
|
|
1628
|
+
format: this.device.preferredColorFormat,
|
|
1629
|
+
width: handle.width,
|
|
1630
|
+
height: handle.height
|
|
1631
|
+
});
|
|
1632
|
+
return this.colorAttachment;
|
|
1633
|
+
}
|
|
1634
|
+
this.colorAttachment._reinitialize(handle, {
|
|
1635
|
+
handle,
|
|
1636
|
+
format: this.device.preferredColorFormat,
|
|
1637
|
+
width: handle.width,
|
|
1638
|
+
height: handle.height
|
|
1639
|
+
});
|
|
1640
|
+
return this.colorAttachment;
|
|
1641
|
+
}
|
|
1642
|
+
_createDepthStencilAttachment(depthStencilFormat) {
|
|
1643
|
+
var _a;
|
|
1644
|
+
const needsNewDepthStencilAttachment = !this.depthStencilAttachment || this.depthStencilAttachment.width !== this.drawingBufferWidth || this.depthStencilAttachment.height !== this.drawingBufferHeight || this.depthStencilAttachment.format !== depthStencilFormat;
|
|
1645
|
+
if (needsNewDepthStencilAttachment) {
|
|
1646
|
+
(_a = this.depthStencilAttachment) == null ? void 0 : _a.destroy();
|
|
1647
|
+
this.depthStencilAttachment = this.device.createTexture({
|
|
1648
|
+
id: `${this.id}#depth-stencil-texture`,
|
|
1649
|
+
usage: import_core14.Texture.RENDER_ATTACHMENT,
|
|
1650
|
+
format: depthStencilFormat,
|
|
1651
|
+
width: this.drawingBufferWidth,
|
|
1652
|
+
height: this.drawingBufferHeight
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
return this.depthStencilAttachment;
|
|
1656
|
+
}
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
});
|
|
1660
|
+
|
|
1661
|
+
// dist/adapter/resources/webgpu-command-buffer.js
|
|
1662
|
+
var import_core15, WebGPUCommandBuffer;
|
|
1663
|
+
var init_webgpu_command_buffer = __esm({
|
|
1664
|
+
"dist/adapter/resources/webgpu-command-buffer.js"() {
|
|
1665
|
+
"use strict";
|
|
1666
|
+
import_core15 = require("@luma.gl/core");
|
|
1667
|
+
WebGPUCommandBuffer = class extends import_core15.CommandBuffer {
|
|
1668
|
+
device;
|
|
1669
|
+
handle;
|
|
1670
|
+
constructor(commandEncoder, props) {
|
|
1671
|
+
super(commandEncoder.device, props);
|
|
1672
|
+
this.device = commandEncoder.device;
|
|
1673
|
+
this.handle = this.props.handle || commandEncoder.handle.finish({
|
|
1674
|
+
label: (props == null ? void 0 : props.id) || "unnamed-command-buffer"
|
|
1430
1675
|
});
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1676
|
+
}
|
|
1677
|
+
};
|
|
1678
|
+
}
|
|
1679
|
+
});
|
|
1680
|
+
|
|
1681
|
+
// dist/adapter/resources/webgpu-render-pass.js
|
|
1682
|
+
function convertColor(color) {
|
|
1683
|
+
return { r: color[0], g: color[1], b: color[2], a: color[3] };
|
|
1684
|
+
}
|
|
1685
|
+
var import_core16, WebGPURenderPass;
|
|
1686
|
+
var init_webgpu_render_pass = __esm({
|
|
1687
|
+
"dist/adapter/resources/webgpu-render-pass.js"() {
|
|
1688
|
+
"use strict";
|
|
1689
|
+
import_core16 = require("@luma.gl/core");
|
|
1690
|
+
init_cpu_hotspot_profiler();
|
|
1691
|
+
WebGPURenderPass = class extends import_core16.RenderPass {
|
|
1692
|
+
device;
|
|
1693
|
+
handle;
|
|
1694
|
+
framebuffer;
|
|
1695
|
+
/** Active pipeline */
|
|
1696
|
+
pipeline = null;
|
|
1697
|
+
/** Latest bindings applied to this pass */
|
|
1698
|
+
bindings = {};
|
|
1699
|
+
constructor(device, props = {}, commandEncoder = device.commandEncoder.handle) {
|
|
1700
|
+
super(device, props);
|
|
1701
|
+
this.device = device;
|
|
1702
|
+
const { props: renderPassProps } = this;
|
|
1703
|
+
this.framebuffer = renderPassProps.framebuffer || device.getCanvasContext().getCurrentFramebuffer();
|
|
1704
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
1705
|
+
if (profiler) {
|
|
1706
|
+
const counterName = renderPassProps.framebuffer ? "explicitFramebufferRenderPassCount" : "defaultFramebufferRenderPassCount";
|
|
1707
|
+
profiler[counterName] = (profiler[counterName] || 0) + 1;
|
|
1708
|
+
}
|
|
1709
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
1710
|
+
try {
|
|
1711
|
+
const descriptorAssemblyStartTime = profiler ? getTimestamp() : 0;
|
|
1712
|
+
const renderPassDescriptor = this.getRenderPassDescriptor(this.framebuffer);
|
|
1713
|
+
if (renderPassProps.occlusionQuerySet) {
|
|
1714
|
+
renderPassDescriptor.occlusionQuerySet = renderPassProps.occlusionQuerySet.handle;
|
|
1715
|
+
}
|
|
1716
|
+
if (renderPassProps.timestampQuerySet) {
|
|
1717
|
+
const webgpuTSQuerySet = renderPassProps.timestampQuerySet;
|
|
1718
|
+
webgpuTSQuerySet == null ? void 0 : webgpuTSQuerySet._invalidateResults();
|
|
1719
|
+
renderPassDescriptor.timestampWrites = webgpuTSQuerySet ? {
|
|
1720
|
+
querySet: webgpuTSQuerySet.handle,
|
|
1721
|
+
beginningOfPassWriteIndex: renderPassProps.beginTimestampIndex,
|
|
1722
|
+
endOfPassWriteIndex: renderPassProps.endTimestampIndex
|
|
1723
|
+
} : void 0;
|
|
1724
|
+
}
|
|
1725
|
+
if (profiler) {
|
|
1726
|
+
profiler.renderPassDescriptorAssemblyCount = (profiler.renderPassDescriptorAssemblyCount || 0) + 1;
|
|
1727
|
+
profiler.renderPassDescriptorAssemblyTimeMs = (profiler.renderPassDescriptorAssemblyTimeMs || 0) + (getTimestamp() - descriptorAssemblyStartTime);
|
|
1728
|
+
}
|
|
1729
|
+
this.device.pushErrorScope("validation");
|
|
1730
|
+
const beginRenderPassStartTime = profiler ? getTimestamp() : 0;
|
|
1731
|
+
this.handle = this.props.handle || commandEncoder.beginRenderPass(renderPassDescriptor);
|
|
1732
|
+
if (profiler) {
|
|
1733
|
+
profiler.renderPassBeginCount = (profiler.renderPassBeginCount || 0) + 1;
|
|
1734
|
+
profiler.renderPassBeginTimeMs = (profiler.renderPassBeginTimeMs || 0) + (getTimestamp() - beginRenderPassStartTime);
|
|
1735
|
+
}
|
|
1736
|
+
this.device.popErrorScope((error) => {
|
|
1737
|
+
this.device.reportError(new Error(`${this} creation failed:
|
|
1738
|
+
"${error.message}"`), this)();
|
|
1739
|
+
this.device.debug();
|
|
1740
|
+
});
|
|
1741
|
+
this.handle.label = this.props.id;
|
|
1742
|
+
import_core16.log.groupCollapsed(3, `new WebGPURenderPass(${this.id})`)();
|
|
1743
|
+
import_core16.log.probe(3, JSON.stringify(renderPassDescriptor, null, 2))();
|
|
1744
|
+
import_core16.log.groupEnd(3)();
|
|
1745
|
+
} finally {
|
|
1746
|
+
if (profiler) {
|
|
1747
|
+
profiler.renderPassSetupCount = (profiler.renderPassSetupCount || 0) + 1;
|
|
1748
|
+
profiler.renderPassSetupTimeMs = (profiler.renderPassSetupTimeMs || 0) + (getTimestamp() - startTime);
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1435
1751
|
}
|
|
1436
1752
|
destroy() {
|
|
1753
|
+
this.destroyResource();
|
|
1437
1754
|
}
|
|
1438
1755
|
end() {
|
|
1756
|
+
if (this.destroyed) {
|
|
1757
|
+
return;
|
|
1758
|
+
}
|
|
1439
1759
|
this.handle.end();
|
|
1760
|
+
this.destroy();
|
|
1440
1761
|
}
|
|
1441
1762
|
setPipeline(pipeline) {
|
|
1442
1763
|
this.pipeline = pipeline;
|
|
@@ -1450,11 +1771,12 @@ var init_webgpu_render_pass = __esm({
|
|
|
1450
1771
|
}
|
|
1451
1772
|
/** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
|
|
1452
1773
|
setBindings(bindings) {
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1774
|
+
this.bindings = bindings;
|
|
1775
|
+
const bindGroups = this.pipeline && (0, import_core16._getDefaultBindGroupFactory)(this.device).getBindGroups(this.pipeline, bindings) || {};
|
|
1776
|
+
for (const [group, bindGroup] of Object.entries(bindGroups)) {
|
|
1777
|
+
if (bindGroup) {
|
|
1778
|
+
this.handle.setBindGroup(Number(group), bindGroup);
|
|
1779
|
+
}
|
|
1458
1780
|
}
|
|
1459
1781
|
}
|
|
1460
1782
|
setIndexBuffer(buffer, indexFormat, offset = 0, size) {
|
|
@@ -1561,44 +1883,60 @@ var init_webgpu_compute_pass = __esm({
|
|
|
1561
1883
|
device;
|
|
1562
1884
|
handle;
|
|
1563
1885
|
_webgpuPipeline = null;
|
|
1564
|
-
constructor(device, props) {
|
|
1886
|
+
constructor(device, props = {}, commandEncoder = device.commandEncoder.handle) {
|
|
1565
1887
|
super(device, props);
|
|
1566
1888
|
this.device = device;
|
|
1889
|
+
const { props: computePassProps } = this;
|
|
1567
1890
|
let timestampWrites;
|
|
1568
|
-
if (
|
|
1569
|
-
const webgpuQuerySet =
|
|
1891
|
+
if (computePassProps.timestampQuerySet) {
|
|
1892
|
+
const webgpuQuerySet = computePassProps.timestampQuerySet;
|
|
1570
1893
|
if (webgpuQuerySet) {
|
|
1894
|
+
webgpuQuerySet._invalidateResults();
|
|
1571
1895
|
timestampWrites = {
|
|
1572
1896
|
querySet: webgpuQuerySet.handle,
|
|
1573
|
-
beginningOfPassWriteIndex:
|
|
1574
|
-
endOfPassWriteIndex:
|
|
1897
|
+
beginningOfPassWriteIndex: computePassProps.beginTimestampIndex,
|
|
1898
|
+
endOfPassWriteIndex: computePassProps.endTimestampIndex
|
|
1575
1899
|
};
|
|
1576
1900
|
}
|
|
1577
1901
|
}
|
|
1578
|
-
this.handle = this.props.handle ||
|
|
1902
|
+
this.handle = this.props.handle || commandEncoder.beginComputePass({
|
|
1579
1903
|
label: this.props.id,
|
|
1580
1904
|
timestampWrites
|
|
1581
1905
|
});
|
|
1582
1906
|
}
|
|
1583
1907
|
/** @note no WebGPU destroy method, just gc */
|
|
1584
1908
|
destroy() {
|
|
1909
|
+
this.destroyResource();
|
|
1585
1910
|
}
|
|
1586
1911
|
end() {
|
|
1912
|
+
if (this.destroyed) {
|
|
1913
|
+
return;
|
|
1914
|
+
}
|
|
1587
1915
|
this.handle.end();
|
|
1916
|
+
this.destroy();
|
|
1588
1917
|
}
|
|
1589
1918
|
setPipeline(pipeline) {
|
|
1590
1919
|
const wgpuPipeline = pipeline;
|
|
1591
1920
|
this.handle.setPipeline(wgpuPipeline.handle);
|
|
1592
1921
|
this._webgpuPipeline = wgpuPipeline;
|
|
1593
|
-
this.
|
|
1922
|
+
const bindGroups = (0, import_core17._getDefaultBindGroupFactory)(this.device).getBindGroups(this._webgpuPipeline, this._webgpuPipeline._getBindingsByGroupWebGPU(), this._webgpuPipeline._getBindGroupCacheKeysWebGPU());
|
|
1923
|
+
for (const [group, bindGroup] of Object.entries(bindGroups)) {
|
|
1924
|
+
if (bindGroup) {
|
|
1925
|
+
this.handle.setBindGroup(Number(group), bindGroup);
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1594
1928
|
}
|
|
1595
1929
|
/**
|
|
1596
1930
|
* Sets an array of bindings (uniform buffers, samplers, textures, ...)
|
|
1597
1931
|
* TODO - still some API confusion - does this method go here or on the pipeline?
|
|
1598
1932
|
*/
|
|
1599
1933
|
setBindings(bindings) {
|
|
1600
|
-
const
|
|
1601
|
-
|
|
1934
|
+
const bindGroups = this._webgpuPipeline && (0, import_core17._getDefaultBindGroupFactory)(this.device).getBindGroups(this._webgpuPipeline, bindings) || {};
|
|
1935
|
+
for (const [group, bindGroup] of Object.entries(bindGroups)) {
|
|
1936
|
+
if (bindGroup) {
|
|
1937
|
+
this.handle.setBindGroup(Number(group), bindGroup);
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1602
1940
|
}
|
|
1603
1941
|
/**
|
|
1604
1942
|
* Dispatch work to be performed with the current ComputePipeline.
|
|
@@ -1656,6 +1994,7 @@ var init_webgpu_command_encoder = __esm({
|
|
|
1656
1994
|
this.handle.label = this.props.id;
|
|
1657
1995
|
}
|
|
1658
1996
|
destroy() {
|
|
1997
|
+
this.destroyResource();
|
|
1659
1998
|
}
|
|
1660
1999
|
finish(props) {
|
|
1661
2000
|
this.device.pushErrorScope("validation");
|
|
@@ -1667,49 +2006,105 @@ var init_webgpu_command_encoder = __esm({
|
|
|
1667
2006
|
this.device.reportError(new Error(message), this)();
|
|
1668
2007
|
this.device.debug();
|
|
1669
2008
|
});
|
|
2009
|
+
this.destroy();
|
|
1670
2010
|
return commandBuffer;
|
|
1671
2011
|
}
|
|
1672
2012
|
/**
|
|
1673
2013
|
* Allows a render pass to begin against a canvas context
|
|
1674
2014
|
* @todo need to support a "Framebuffer" equivalent (aka preconfigured RenderPassDescriptors?).
|
|
1675
2015
|
*/
|
|
1676
|
-
beginRenderPass(props) {
|
|
1677
|
-
return new WebGPURenderPass(this.device, props);
|
|
2016
|
+
beginRenderPass(props = {}) {
|
|
2017
|
+
return new WebGPURenderPass(this.device, this._applyTimeProfilingToPassProps(props), this.handle);
|
|
1678
2018
|
}
|
|
1679
|
-
beginComputePass(props) {
|
|
1680
|
-
return new WebGPUComputePass(this.device, props);
|
|
2019
|
+
beginComputePass(props = {}) {
|
|
2020
|
+
return new WebGPUComputePass(this.device, this._applyTimeProfilingToPassProps(props), this.handle);
|
|
1681
2021
|
}
|
|
1682
2022
|
// beginRenderPass(GPURenderPassDescriptor descriptor): GPURenderPassEncoder;
|
|
1683
2023
|
// beginComputePass(optional GPUComputePassDescriptor descriptor = {}): GPUComputePassEncoder;
|
|
1684
2024
|
copyBufferToBuffer(options) {
|
|
1685
2025
|
const webgpuSourceBuffer = options.sourceBuffer;
|
|
1686
|
-
const
|
|
1687
|
-
this.handle.copyBufferToBuffer(webgpuSourceBuffer.handle, options.sourceOffset ?? 0,
|
|
2026
|
+
const webgpuDestinationBuffer = options.destinationBuffer;
|
|
2027
|
+
this.handle.copyBufferToBuffer(webgpuSourceBuffer.handle, options.sourceOffset ?? 0, webgpuDestinationBuffer.handle, options.destinationOffset ?? 0, options.size ?? 0);
|
|
1688
2028
|
}
|
|
1689
2029
|
copyBufferToTexture(options) {
|
|
1690
|
-
var _a, _b, _c;
|
|
1691
2030
|
const webgpuSourceBuffer = options.sourceBuffer;
|
|
1692
|
-
const
|
|
2031
|
+
const webgpuDestinationTexture = options.destinationTexture;
|
|
2032
|
+
const copyOrigin = options.origin ?? [0, 0, 0];
|
|
2033
|
+
const copySize = options.size;
|
|
1693
2034
|
this.handle.copyBufferToTexture({
|
|
1694
2035
|
buffer: webgpuSourceBuffer.handle,
|
|
1695
|
-
offset: options.
|
|
2036
|
+
offset: options.byteOffset ?? 0,
|
|
1696
2037
|
bytesPerRow: options.bytesPerRow,
|
|
1697
2038
|
rowsPerImage: options.rowsPerImage
|
|
1698
2039
|
}, {
|
|
1699
|
-
texture:
|
|
2040
|
+
texture: webgpuDestinationTexture.handle,
|
|
1700
2041
|
mipLevel: options.mipLevel ?? 0,
|
|
1701
|
-
origin:
|
|
1702
|
-
|
|
2042
|
+
origin: {
|
|
2043
|
+
x: copyOrigin[0] ?? 0,
|
|
2044
|
+
y: copyOrigin[1] ?? 0,
|
|
2045
|
+
z: copyOrigin[2] ?? 0
|
|
2046
|
+
},
|
|
2047
|
+
aspect: options.aspect
|
|
1703
2048
|
}, {
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
depthOrArrayLayers: (_c = options.extent) == null ? void 0 : _c[2]
|
|
2049
|
+
width: copySize[0],
|
|
2050
|
+
height: copySize[1],
|
|
2051
|
+
depthOrArrayLayers: copySize[2]
|
|
1708
2052
|
});
|
|
1709
2053
|
}
|
|
1710
2054
|
copyTextureToBuffer(options) {
|
|
2055
|
+
const { sourceTexture, destinationBuffer, origin = [0, 0, 0], byteOffset = 0, width, height, depthOrArrayLayers, mipLevel, aspect } = options;
|
|
2056
|
+
const webgpuSourceTexture = sourceTexture;
|
|
2057
|
+
webgpuSourceTexture.copyToBuffer(this.handle, {
|
|
2058
|
+
x: origin[0] ?? 0,
|
|
2059
|
+
y: origin[1] ?? 0,
|
|
2060
|
+
z: origin[2] ?? 0,
|
|
2061
|
+
width,
|
|
2062
|
+
height,
|
|
2063
|
+
depthOrArrayLayers,
|
|
2064
|
+
mipLevel,
|
|
2065
|
+
aspect,
|
|
2066
|
+
byteOffset,
|
|
2067
|
+
bytesPerRow: options.bytesPerRow,
|
|
2068
|
+
rowsPerImage: options.rowsPerImage
|
|
2069
|
+
}, destinationBuffer);
|
|
1711
2070
|
}
|
|
1712
2071
|
copyTextureToTexture(options) {
|
|
2072
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2073
|
+
const webgpuSourceTexture = options.sourceTexture;
|
|
2074
|
+
const webgpuDestinationTexture = options.destinationTexture;
|
|
2075
|
+
const sourceRegion = webgpuSourceTexture._normalizeTextureReadOptions({
|
|
2076
|
+
x: ((_a = options.origin) == null ? void 0 : _a[0]) ?? 0,
|
|
2077
|
+
y: ((_b = options.origin) == null ? void 0 : _b[1]) ?? 0,
|
|
2078
|
+
z: ((_c = options.origin) == null ? void 0 : _c[2]) ?? 0,
|
|
2079
|
+
width: options.width,
|
|
2080
|
+
height: options.height,
|
|
2081
|
+
depthOrArrayLayers: options.depthOrArrayLayers,
|
|
2082
|
+
mipLevel: options.mipLevel ?? 0,
|
|
2083
|
+
aspect: options.aspect ?? "all"
|
|
2084
|
+
});
|
|
2085
|
+
this.handle.copyTextureToTexture({
|
|
2086
|
+
texture: webgpuSourceTexture.handle,
|
|
2087
|
+
mipLevel: sourceRegion.mipLevel,
|
|
2088
|
+
origin: {
|
|
2089
|
+
x: sourceRegion.x,
|
|
2090
|
+
y: sourceRegion.y,
|
|
2091
|
+
z: sourceRegion.z
|
|
2092
|
+
},
|
|
2093
|
+
aspect: sourceRegion.aspect
|
|
2094
|
+
}, {
|
|
2095
|
+
texture: webgpuDestinationTexture.handle,
|
|
2096
|
+
mipLevel: options.destinationMipLevel ?? 0,
|
|
2097
|
+
origin: {
|
|
2098
|
+
x: ((_d = options.destinationOrigin) == null ? void 0 : _d[0]) ?? 0,
|
|
2099
|
+
y: ((_e = options.destinationOrigin) == null ? void 0 : _e[1]) ?? 0,
|
|
2100
|
+
z: ((_f = options.destinationOrigin) == null ? void 0 : _f[2]) ?? 0
|
|
2101
|
+
},
|
|
2102
|
+
aspect: options.destinationAspect ?? sourceRegion.aspect
|
|
2103
|
+
}, {
|
|
2104
|
+
width: sourceRegion.width,
|
|
2105
|
+
height: sourceRegion.height,
|
|
2106
|
+
depthOrArrayLayers: sourceRegion.depthOrArrayLayers
|
|
2107
|
+
});
|
|
1713
2108
|
}
|
|
1714
2109
|
pushDebugGroup(groupLabel) {
|
|
1715
2110
|
this.handle.pushDebugGroup(groupLabel);
|
|
@@ -1725,6 +2120,21 @@ var init_webgpu_command_encoder = __esm({
|
|
|
1725
2120
|
const webgpuBuffer = destination;
|
|
1726
2121
|
this.handle.resolveQuerySet(webgpuQuerySet.handle, (options == null ? void 0 : options.firstQuery) || 0, (options == null ? void 0 : options.queryCount) || querySet.props.count - ((options == null ? void 0 : options.firstQuery) || 0), webgpuBuffer.handle, (options == null ? void 0 : options.destinationOffset) || 0);
|
|
1727
2122
|
}
|
|
2123
|
+
writeTimestamp(querySet, queryIndex) {
|
|
2124
|
+
querySet._invalidateResults();
|
|
2125
|
+
const writeTimestamp = this.handle.writeTimestamp;
|
|
2126
|
+
if (writeTimestamp) {
|
|
2127
|
+
writeTimestamp.call(this.handle, querySet.handle, queryIndex);
|
|
2128
|
+
return;
|
|
2129
|
+
}
|
|
2130
|
+
const computePass = this.handle.beginComputePass({
|
|
2131
|
+
timestampWrites: {
|
|
2132
|
+
querySet: querySet.handle,
|
|
2133
|
+
beginningOfPassWriteIndex: queryIndex
|
|
2134
|
+
}
|
|
2135
|
+
});
|
|
2136
|
+
computePass.end();
|
|
2137
|
+
}
|
|
1728
2138
|
};
|
|
1729
2139
|
}
|
|
1730
2140
|
});
|
|
@@ -1735,9 +2145,15 @@ var init_webgpu_query_set = __esm({
|
|
|
1735
2145
|
"dist/adapter/resources/webgpu-query-set.js"() {
|
|
1736
2146
|
"use strict";
|
|
1737
2147
|
import_core19 = require("@luma.gl/core");
|
|
2148
|
+
init_cpu_hotspot_profiler();
|
|
1738
2149
|
WebGPUQuerySet = class extends import_core19.QuerySet {
|
|
1739
2150
|
device;
|
|
1740
2151
|
handle;
|
|
2152
|
+
_resolveBuffer = null;
|
|
2153
|
+
_readBuffer = null;
|
|
2154
|
+
_cachedResults = null;
|
|
2155
|
+
_readResultsPromise = null;
|
|
2156
|
+
_resultsPendingResolution = false;
|
|
1741
2157
|
constructor(device, props) {
|
|
1742
2158
|
super(device, props);
|
|
1743
2159
|
this.device = device;
|
|
@@ -1749,8 +2165,133 @@ var init_webgpu_query_set = __esm({
|
|
|
1749
2165
|
}
|
|
1750
2166
|
destroy() {
|
|
1751
2167
|
var _a;
|
|
1752
|
-
(
|
|
1753
|
-
|
|
2168
|
+
if (!this.destroyed) {
|
|
2169
|
+
(_a = this.handle) == null ? void 0 : _a.destroy();
|
|
2170
|
+
this.destroyResource();
|
|
2171
|
+
this.handle = null;
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
isResultAvailable(queryIndex) {
|
|
2175
|
+
if (!this._cachedResults) {
|
|
2176
|
+
return false;
|
|
2177
|
+
}
|
|
2178
|
+
return queryIndex === void 0 ? true : queryIndex >= 0 && queryIndex < this._cachedResults.length;
|
|
2179
|
+
}
|
|
2180
|
+
async readResults(options) {
|
|
2181
|
+
const firstQuery = (options == null ? void 0 : options.firstQuery) || 0;
|
|
2182
|
+
const queryCount = (options == null ? void 0 : options.queryCount) || this.props.count - firstQuery;
|
|
2183
|
+
if (firstQuery < 0 || queryCount < 0 || firstQuery + queryCount > this.props.count) {
|
|
2184
|
+
throw new Error("Query read range is out of bounds");
|
|
2185
|
+
}
|
|
2186
|
+
let needsFreshResults = true;
|
|
2187
|
+
while (needsFreshResults) {
|
|
2188
|
+
if (!this._readResultsPromise) {
|
|
2189
|
+
this._readResultsPromise = this._readAllResults();
|
|
2190
|
+
}
|
|
2191
|
+
const readResultsPromise = this._readResultsPromise;
|
|
2192
|
+
const results = await readResultsPromise;
|
|
2193
|
+
needsFreshResults = this._resultsPendingResolution;
|
|
2194
|
+
if (!needsFreshResults) {
|
|
2195
|
+
return results.slice(firstQuery, firstQuery + queryCount);
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
throw new Error("Query read unexpectedly failed to resolve");
|
|
2199
|
+
}
|
|
2200
|
+
async readTimestampDuration(beginIndex, endIndex) {
|
|
2201
|
+
if (this.props.type !== "timestamp") {
|
|
2202
|
+
throw new Error("Timestamp durations require a timestamp QuerySet");
|
|
2203
|
+
}
|
|
2204
|
+
if (beginIndex < 0 || endIndex <= beginIndex || endIndex >= this.props.count) {
|
|
2205
|
+
throw new Error("Timestamp duration range is out of bounds");
|
|
2206
|
+
}
|
|
2207
|
+
const results = await this.readResults({
|
|
2208
|
+
firstQuery: beginIndex,
|
|
2209
|
+
queryCount: endIndex - beginIndex + 1
|
|
2210
|
+
});
|
|
2211
|
+
return Number(results[results.length - 1] - results[0]) / 1e6;
|
|
2212
|
+
}
|
|
2213
|
+
/** Marks any cached query results as stale after new writes have been encoded. */
|
|
2214
|
+
_invalidateResults() {
|
|
2215
|
+
this._cachedResults = null;
|
|
2216
|
+
this._resultsPendingResolution = true;
|
|
2217
|
+
}
|
|
2218
|
+
async _readAllResults() {
|
|
2219
|
+
this._ensureBuffers();
|
|
2220
|
+
try {
|
|
2221
|
+
if (this._resultsPendingResolution) {
|
|
2222
|
+
const commandEncoder = this.device.createCommandEncoder({
|
|
2223
|
+
id: `${this.id}-read-results`
|
|
2224
|
+
});
|
|
2225
|
+
commandEncoder.resolveQuerySet(this, this._resolveBuffer);
|
|
2226
|
+
commandEncoder.copyBufferToBuffer({
|
|
2227
|
+
sourceBuffer: this._resolveBuffer,
|
|
2228
|
+
destinationBuffer: this._readBuffer,
|
|
2229
|
+
size: this._resolveBuffer.byteLength
|
|
2230
|
+
});
|
|
2231
|
+
const commandBuffer = commandEncoder.finish({
|
|
2232
|
+
id: `${this.id}-read-results-command-buffer`
|
|
2233
|
+
});
|
|
2234
|
+
const previousSubmitReason = getCpuHotspotSubmitReason(this.device) || void 0;
|
|
2235
|
+
setCpuHotspotSubmitReason(this.device, "query-readback");
|
|
2236
|
+
try {
|
|
2237
|
+
this.device.submit(commandBuffer);
|
|
2238
|
+
} finally {
|
|
2239
|
+
setCpuHotspotSubmitReason(this.device, previousSubmitReason);
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
const data = await this._readBuffer.readAsync(0, this._readBuffer.byteLength);
|
|
2243
|
+
const resultView = new BigUint64Array(data.buffer, data.byteOffset, this.props.count);
|
|
2244
|
+
this._cachedResults = Array.from(resultView, (value) => value);
|
|
2245
|
+
this._resultsPendingResolution = false;
|
|
2246
|
+
return this._cachedResults;
|
|
2247
|
+
} finally {
|
|
2248
|
+
this._readResultsPromise = null;
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
_ensureBuffers() {
|
|
2252
|
+
if (this._resolveBuffer && this._readBuffer) {
|
|
2253
|
+
return;
|
|
2254
|
+
}
|
|
2255
|
+
const byteLength = this.props.count * 8;
|
|
2256
|
+
this._resolveBuffer = this.device.createBuffer({
|
|
2257
|
+
id: `${this.id}-resolve-buffer`,
|
|
2258
|
+
usage: import_core19.Buffer.QUERY_RESOLVE | import_core19.Buffer.COPY_SRC,
|
|
2259
|
+
byteLength
|
|
2260
|
+
});
|
|
2261
|
+
this.attachResource(this._resolveBuffer);
|
|
2262
|
+
this._readBuffer = this.device.createBuffer({
|
|
2263
|
+
id: `${this.id}-read-buffer`,
|
|
2264
|
+
usage: import_core19.Buffer.COPY_DST | import_core19.Buffer.MAP_READ,
|
|
2265
|
+
byteLength
|
|
2266
|
+
});
|
|
2267
|
+
this.attachResource(this._readBuffer);
|
|
2268
|
+
}
|
|
2269
|
+
_encodeResolveToReadBuffer(commandEncoder, options) {
|
|
2270
|
+
if (!this._resultsPendingResolution) {
|
|
2271
|
+
return false;
|
|
2272
|
+
}
|
|
2273
|
+
if (this._readResultsPromise) {
|
|
2274
|
+
return false;
|
|
2275
|
+
}
|
|
2276
|
+
this._ensureBuffers();
|
|
2277
|
+
const firstQuery = (options == null ? void 0 : options.firstQuery) || 0;
|
|
2278
|
+
const queryCount = (options == null ? void 0 : options.queryCount) || this.props.count - firstQuery;
|
|
2279
|
+
const byteLength = queryCount * BigUint64Array.BYTES_PER_ELEMENT;
|
|
2280
|
+
const byteOffset = firstQuery * BigUint64Array.BYTES_PER_ELEMENT;
|
|
2281
|
+
commandEncoder.resolveQuerySet(this, this._resolveBuffer, {
|
|
2282
|
+
firstQuery,
|
|
2283
|
+
queryCount,
|
|
2284
|
+
destinationOffset: byteOffset
|
|
2285
|
+
});
|
|
2286
|
+
commandEncoder.copyBufferToBuffer({
|
|
2287
|
+
sourceBuffer: this._resolveBuffer,
|
|
2288
|
+
sourceOffset: byteOffset,
|
|
2289
|
+
destinationBuffer: this._readBuffer,
|
|
2290
|
+
destinationOffset: byteOffset,
|
|
2291
|
+
size: byteLength
|
|
2292
|
+
});
|
|
2293
|
+
this._resultsPendingResolution = false;
|
|
2294
|
+
return true;
|
|
1754
2295
|
}
|
|
1755
2296
|
};
|
|
1756
2297
|
}
|
|
@@ -1768,25 +2309,21 @@ var init_webgpu_pipeline_layout = __esm({
|
|
|
1768
2309
|
constructor(device, props) {
|
|
1769
2310
|
super(device, props);
|
|
1770
2311
|
this.device = device;
|
|
1771
|
-
const
|
|
2312
|
+
const bindGroupEntriesByGroup = this.mapShaderLayoutToBindGroupEntriesByGroup();
|
|
1772
2313
|
this.handle = this.device.handle.createPipelineLayout({
|
|
1773
2314
|
label: (props == null ? void 0 : props.id) ?? "unnamed-pipeline-layout",
|
|
1774
|
-
bindGroupLayouts:
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
this.device.handle.createBindGroupLayout({
|
|
1779
|
-
label: "bind-group-layout",
|
|
1780
|
-
entries: bindGroupEntries
|
|
1781
|
-
})
|
|
1782
|
-
]
|
|
2315
|
+
bindGroupLayouts: bindGroupEntriesByGroup.map((entries, group) => this.device.handle.createBindGroupLayout({
|
|
2316
|
+
label: `bind-group-layout-${group}`,
|
|
2317
|
+
entries
|
|
2318
|
+
}))
|
|
1783
2319
|
});
|
|
1784
2320
|
}
|
|
1785
2321
|
destroy() {
|
|
1786
2322
|
this.handle = null;
|
|
1787
2323
|
}
|
|
1788
|
-
|
|
1789
|
-
const
|
|
2324
|
+
mapShaderLayoutToBindGroupEntriesByGroup() {
|
|
2325
|
+
const maxGroup = this.props.shaderLayout.bindings.reduce((highestGroup, binding) => Math.max(highestGroup, binding.group), -1);
|
|
2326
|
+
const bindGroupEntriesByGroup = Array.from({ length: maxGroup + 1 }, () => []);
|
|
1790
2327
|
for (const binding of this.props.shaderLayout.bindings) {
|
|
1791
2328
|
const bindingTypeInfo = {};
|
|
1792
2329
|
switch (binding.type) {
|
|
@@ -1843,13 +2380,13 @@ var init_webgpu_pipeline_layout = __esm({
|
|
|
1843
2380
|
}
|
|
1844
2381
|
}
|
|
1845
2382
|
const VISIBILITY_ALL = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;
|
|
1846
|
-
|
|
2383
|
+
bindGroupEntriesByGroup[binding.group].push({
|
|
1847
2384
|
binding: binding.location,
|
|
1848
2385
|
visibility: binding.visibility || VISIBILITY_ALL,
|
|
1849
2386
|
...bindingTypeInfo
|
|
1850
2387
|
});
|
|
1851
2388
|
}
|
|
1852
|
-
return
|
|
2389
|
+
return bindGroupEntriesByGroup;
|
|
1853
2390
|
}
|
|
1854
2391
|
};
|
|
1855
2392
|
isStorageTextureBindingLayout = (maybe) => {
|
|
@@ -1874,6 +2411,11 @@ var init_webgpu_fence = __esm({
|
|
|
1874
2411
|
this.device = device;
|
|
1875
2412
|
this.signaled = device.handle.queue.onSubmittedWorkDone().then(() => {
|
|
1876
2413
|
this._signaled = true;
|
|
2414
|
+
}).catch((error) => {
|
|
2415
|
+
if (this.device.shouldIgnoreDroppedInstanceError(error)) {
|
|
2416
|
+
return;
|
|
2417
|
+
}
|
|
2418
|
+
throw error;
|
|
1877
2419
|
});
|
|
1878
2420
|
}
|
|
1879
2421
|
isSignaled() {
|
|
@@ -1913,6 +2455,14 @@ function getShaderLayoutFromWGSL(source) {
|
|
|
1913
2455
|
members
|
|
1914
2456
|
});
|
|
1915
2457
|
}
|
|
2458
|
+
for (const storageBuffer of parsedWGSL.storage) {
|
|
2459
|
+
shaderLayout.bindings.push({
|
|
2460
|
+
type: storageBuffer.access === "read" ? "read-only-storage" : "storage",
|
|
2461
|
+
name: storageBuffer.name,
|
|
2462
|
+
group: storageBuffer.group,
|
|
2463
|
+
location: storageBuffer.binding
|
|
2464
|
+
});
|
|
2465
|
+
}
|
|
1916
2466
|
for (const texture of parsedWGSL.textures) {
|
|
1917
2467
|
const bindingDeclaration = {
|
|
1918
2468
|
type: "texture",
|
|
@@ -1996,16 +2546,583 @@ var init_get_shader_layout_wgsl = __esm({
|
|
|
1996
2546
|
}
|
|
1997
2547
|
});
|
|
1998
2548
|
|
|
2549
|
+
// dist/adapter/helpers/generate-mipmaps-webgpu.js
|
|
2550
|
+
function generateMipmapsWebGPU(device, texture) {
|
|
2551
|
+
if (texture.mipLevels <= 1) {
|
|
2552
|
+
return;
|
|
2553
|
+
}
|
|
2554
|
+
if (texture.dimension === "3d") {
|
|
2555
|
+
generateMipmaps3D(device, texture);
|
|
2556
|
+
return;
|
|
2557
|
+
}
|
|
2558
|
+
if (RENDER_DIMENSIONS.includes(texture.dimension)) {
|
|
2559
|
+
generateMipmapsRender(device, texture);
|
|
2560
|
+
return;
|
|
2561
|
+
}
|
|
2562
|
+
throw new Error(`Cannot generate mipmaps for texture dimension "${texture.dimension}" with WebGPU.`);
|
|
2563
|
+
}
|
|
2564
|
+
function generateMipmapsRender(device, texture) {
|
|
2565
|
+
validateFormatCapabilities(device, texture, ["render", "filter"], "render");
|
|
2566
|
+
const colorAttachmentFormat = getColorAttachmentFormat(texture.format, "render", texture.dimension);
|
|
2567
|
+
const viewDimension = texture.dimension;
|
|
2568
|
+
const shaderSource = getRenderMipmapWGSL(viewDimension);
|
|
2569
|
+
const sampler = device.createSampler({ minFilter: "linear", magFilter: "linear" });
|
|
2570
|
+
const uniformsBuffer = device.createBuffer({
|
|
2571
|
+
byteLength: 16,
|
|
2572
|
+
usage: import_core23.Buffer.UNIFORM | import_core23.Buffer.COPY_DST
|
|
2573
|
+
});
|
|
2574
|
+
const uniformValues = new Uint32Array(1);
|
|
2575
|
+
const sourceTextureLayout = {
|
|
2576
|
+
type: "texture",
|
|
2577
|
+
name: "sourceTexture",
|
|
2578
|
+
group: 0,
|
|
2579
|
+
location: 1,
|
|
2580
|
+
viewDimension,
|
|
2581
|
+
sampleType: "float"
|
|
2582
|
+
};
|
|
2583
|
+
const uniformsLayout = {
|
|
2584
|
+
type: "uniform",
|
|
2585
|
+
name: "uniforms",
|
|
2586
|
+
group: 0,
|
|
2587
|
+
location: 2
|
|
2588
|
+
};
|
|
2589
|
+
const renderShaderLayout = {
|
|
2590
|
+
attributes: [],
|
|
2591
|
+
bindings: [RENDER_SOURCE_SAMPLER_LAYOUT, sourceTextureLayout, uniformsLayout]
|
|
2592
|
+
};
|
|
2593
|
+
const vertexShader = device.createShader({
|
|
2594
|
+
id: "mipmap-generation-render-vs",
|
|
2595
|
+
source: shaderSource,
|
|
2596
|
+
language: "wgsl",
|
|
2597
|
+
stage: "vertex"
|
|
2598
|
+
});
|
|
2599
|
+
const fragmentShader = device.createShader({
|
|
2600
|
+
id: "mipmap-generation-render-fs",
|
|
2601
|
+
source: shaderSource,
|
|
2602
|
+
language: "wgsl",
|
|
2603
|
+
stage: "fragment"
|
|
2604
|
+
});
|
|
2605
|
+
const renderPipeline = device.createRenderPipeline({
|
|
2606
|
+
id: `mipmap-generation-render:${texture.dimension}:${texture.format}`,
|
|
2607
|
+
vs: vertexShader,
|
|
2608
|
+
fs: fragmentShader,
|
|
2609
|
+
shaderLayout: renderShaderLayout,
|
|
2610
|
+
colorAttachmentFormats: [colorAttachmentFormat],
|
|
2611
|
+
topology: "triangle-list"
|
|
2612
|
+
});
|
|
2613
|
+
let sourceWidth = texture.width;
|
|
2614
|
+
let sourceHeight = texture.height;
|
|
2615
|
+
const layerCount = texture.dimension === "2d" ? 1 : texture.depth;
|
|
2616
|
+
function renderMipmapLayer(sourceView, baseMipLevel, baseArrayLayer, destinationWidth, destinationHeight) {
|
|
2617
|
+
uniformValues[0] = baseArrayLayer;
|
|
2618
|
+
uniformsBuffer.write(uniformValues);
|
|
2619
|
+
const destinationView = texture.createView({
|
|
2620
|
+
dimension: "2d",
|
|
2621
|
+
baseMipLevel,
|
|
2622
|
+
mipLevelCount: 1,
|
|
2623
|
+
baseArrayLayer,
|
|
2624
|
+
arrayLayerCount: 1
|
|
2625
|
+
});
|
|
2626
|
+
const framebuffer = device.createFramebuffer({
|
|
2627
|
+
colorAttachments: [destinationView]
|
|
2628
|
+
});
|
|
2629
|
+
const renderPass = device.beginRenderPass({
|
|
2630
|
+
id: `mipmap-generation:${texture.format}:${baseMipLevel}:${baseArrayLayer}`,
|
|
2631
|
+
framebuffer
|
|
2632
|
+
});
|
|
2633
|
+
try {
|
|
2634
|
+
renderPass.setPipeline(renderPipeline);
|
|
2635
|
+
renderPass.setBindings({
|
|
2636
|
+
sourceSampler: sampler,
|
|
2637
|
+
sourceTexture: sourceView,
|
|
2638
|
+
uniforms: uniformsBuffer
|
|
2639
|
+
});
|
|
2640
|
+
renderPass.setParameters({
|
|
2641
|
+
viewport: [0, 0, destinationWidth, destinationHeight, 0, 1],
|
|
2642
|
+
scissorRect: [0, 0, destinationWidth, destinationHeight]
|
|
2643
|
+
});
|
|
2644
|
+
renderPass.draw({ vertexCount: 3 });
|
|
2645
|
+
renderPass.end();
|
|
2646
|
+
device.submit();
|
|
2647
|
+
} finally {
|
|
2648
|
+
destinationView.destroy();
|
|
2649
|
+
framebuffer.destroy();
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
try {
|
|
2653
|
+
for (let baseMipLevel = 1; baseMipLevel < texture.mipLevels; ++baseMipLevel) {
|
|
2654
|
+
validateFormatCapabilities(device, texture, ["render", "filter"], "render");
|
|
2655
|
+
const sourceMipLevel = baseMipLevel - 1;
|
|
2656
|
+
const destinationWidth = Math.max(1, sourceWidth >> 1);
|
|
2657
|
+
const destinationHeight = Math.max(1, sourceHeight >> 1);
|
|
2658
|
+
const sourceView = texture.createView({
|
|
2659
|
+
dimension: viewDimension,
|
|
2660
|
+
baseMipLevel: sourceMipLevel,
|
|
2661
|
+
mipLevelCount: 1,
|
|
2662
|
+
baseArrayLayer: 0,
|
|
2663
|
+
arrayLayerCount: texture.depth
|
|
2664
|
+
});
|
|
2665
|
+
try {
|
|
2666
|
+
for (let baseArrayLayer = 0; baseArrayLayer < layerCount; ++baseArrayLayer) {
|
|
2667
|
+
renderMipmapLayer(sourceView, baseMipLevel, baseArrayLayer, destinationWidth, destinationHeight);
|
|
2668
|
+
}
|
|
2669
|
+
} finally {
|
|
2670
|
+
sourceView.destroy();
|
|
2671
|
+
}
|
|
2672
|
+
sourceWidth = destinationWidth;
|
|
2673
|
+
sourceHeight = destinationHeight;
|
|
2674
|
+
}
|
|
2675
|
+
} finally {
|
|
2676
|
+
renderPipeline.destroy();
|
|
2677
|
+
vertexShader.destroy();
|
|
2678
|
+
fragmentShader.destroy();
|
|
2679
|
+
sampler.destroy();
|
|
2680
|
+
uniformsBuffer.destroy();
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
function getColorAttachmentFormat(format, path, dimension) {
|
|
2684
|
+
if (import_core23.textureFormatDecoder.isColor(format)) {
|
|
2685
|
+
return format;
|
|
2686
|
+
}
|
|
2687
|
+
throw new Error(`Cannot run ${path} mipmap generation for ${dimension} texture with format "${format}". Only color textures can be used for this operation. Required capabilities: color. Actual capabilities: color=false.`);
|
|
2688
|
+
}
|
|
2689
|
+
function generateMipmaps3D(device, texture) {
|
|
2690
|
+
validateFormatCapabilities(device, texture, ["filter", "store"], "compute");
|
|
2691
|
+
const format = getColorAttachmentFormat(texture.format, "compute", texture.dimension);
|
|
2692
|
+
const shaderSource = get3DComputeMipmapWGSL(format);
|
|
2693
|
+
const destinationTextureLayout = {
|
|
2694
|
+
type: "storage",
|
|
2695
|
+
name: "destinationTexture",
|
|
2696
|
+
group: 0,
|
|
2697
|
+
location: 1,
|
|
2698
|
+
format,
|
|
2699
|
+
viewDimension: "3d",
|
|
2700
|
+
access: "write-only"
|
|
2701
|
+
};
|
|
2702
|
+
const computeShaderLayout = {
|
|
2703
|
+
bindings: [COMPUTE_SOURCE_TEXTURE_LAYOUT, destinationTextureLayout, COMPUTE_UNIFORMS_LAYOUT]
|
|
2704
|
+
};
|
|
2705
|
+
const computeShader = device.createShader({
|
|
2706
|
+
id: "mipmap-generation-compute",
|
|
2707
|
+
source: shaderSource,
|
|
2708
|
+
language: "wgsl",
|
|
2709
|
+
stage: "compute"
|
|
2710
|
+
});
|
|
2711
|
+
const computePipeline = device.createComputePipeline({
|
|
2712
|
+
id: `mipmap-generation-compute:${texture.format}`,
|
|
2713
|
+
shader: computeShader,
|
|
2714
|
+
shaderLayout: computeShaderLayout
|
|
2715
|
+
});
|
|
2716
|
+
const uniformsBuffer = device.createBuffer({
|
|
2717
|
+
byteLength: 32,
|
|
2718
|
+
usage: import_core23.Buffer.UNIFORM | import_core23.Buffer.COPY_DST
|
|
2719
|
+
});
|
|
2720
|
+
const uniformValues = new Uint32Array(8);
|
|
2721
|
+
let sourceWidth = texture.width;
|
|
2722
|
+
let sourceHeight = texture.height;
|
|
2723
|
+
let sourceDepth = texture.depth;
|
|
2724
|
+
try {
|
|
2725
|
+
for (let destinationMipLevel = 1; destinationMipLevel < texture.mipLevels; ++destinationMipLevel) {
|
|
2726
|
+
validateFormatCapabilities(device, texture, ["filter", "store"], "compute");
|
|
2727
|
+
const destinationWidth = Math.max(1, sourceWidth >> 1);
|
|
2728
|
+
const destinationHeight = Math.max(1, sourceHeight >> 1);
|
|
2729
|
+
const destinationDepth = Math.max(1, sourceDepth >> 1);
|
|
2730
|
+
uniformValues[0] = sourceWidth;
|
|
2731
|
+
uniformValues[1] = sourceHeight;
|
|
2732
|
+
uniformValues[2] = sourceDepth;
|
|
2733
|
+
uniformValues[3] = destinationWidth;
|
|
2734
|
+
uniformValues[4] = destinationHeight;
|
|
2735
|
+
uniformValues[5] = destinationDepth;
|
|
2736
|
+
uniformValues[6] = 0;
|
|
2737
|
+
uniformsBuffer.write(uniformValues);
|
|
2738
|
+
const sourceView = texture.createView({
|
|
2739
|
+
dimension: "3d",
|
|
2740
|
+
baseMipLevel: destinationMipLevel - 1,
|
|
2741
|
+
mipLevelCount: 1,
|
|
2742
|
+
baseArrayLayer: 0,
|
|
2743
|
+
arrayLayerCount: 1
|
|
2744
|
+
});
|
|
2745
|
+
const destinationView = texture.createView({
|
|
2746
|
+
dimension: "3d",
|
|
2747
|
+
baseMipLevel: destinationMipLevel,
|
|
2748
|
+
mipLevelCount: 1,
|
|
2749
|
+
baseArrayLayer: 0,
|
|
2750
|
+
arrayLayerCount: 1
|
|
2751
|
+
});
|
|
2752
|
+
computePipeline.setBindings({
|
|
2753
|
+
sourceTexture: sourceView,
|
|
2754
|
+
destinationTexture: destinationView,
|
|
2755
|
+
uniforms: uniformsBuffer
|
|
2756
|
+
});
|
|
2757
|
+
try {
|
|
2758
|
+
const workgroupsX = Math.ceil(destinationWidth / WORKGROUP_SIZE.x);
|
|
2759
|
+
const workgroupsY = Math.ceil(destinationHeight / WORKGROUP_SIZE.y);
|
|
2760
|
+
const workgroupsZ = Math.ceil(destinationDepth / WORKGROUP_SIZE.z);
|
|
2761
|
+
const computePass = device.beginComputePass({});
|
|
2762
|
+
computePass.setPipeline(computePipeline);
|
|
2763
|
+
computePass.dispatch(workgroupsX, workgroupsY, workgroupsZ);
|
|
2764
|
+
computePass.end();
|
|
2765
|
+
device.submit();
|
|
2766
|
+
} finally {
|
|
2767
|
+
sourceView.destroy();
|
|
2768
|
+
destinationView.destroy();
|
|
2769
|
+
}
|
|
2770
|
+
sourceWidth = destinationWidth;
|
|
2771
|
+
sourceHeight = destinationHeight;
|
|
2772
|
+
sourceDepth = destinationDepth;
|
|
2773
|
+
}
|
|
2774
|
+
} finally {
|
|
2775
|
+
computePipeline.destroy();
|
|
2776
|
+
computeShader.destroy();
|
|
2777
|
+
uniformsBuffer.destroy();
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
function validateFormatCapabilities(device, texture, requiredCapabilities, path) {
|
|
2781
|
+
const { format, dimension } = texture;
|
|
2782
|
+
const capabilities = device.getTextureFormatCapabilities(format);
|
|
2783
|
+
const missingCapabilities = requiredCapabilities.filter((capability) => !capabilities[capability]);
|
|
2784
|
+
if (missingCapabilities.length > 0) {
|
|
2785
|
+
const required = requiredCapabilities.join(" + ");
|
|
2786
|
+
const actual = requiredCapabilities.map((capability) => `${capability}=${capabilities[capability]}`).join(", ");
|
|
2787
|
+
throw new Error(`Cannot run ${path} mipmap generation for ${dimension} texture with format "${format}". Required capabilities: ${required}. Actual capabilities: ${actual}.`);
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
function getSourceTextureType(dimension) {
|
|
2791
|
+
switch (dimension) {
|
|
2792
|
+
case "2d":
|
|
2793
|
+
return "texture_2d<f32>";
|
|
2794
|
+
case "2d-array":
|
|
2795
|
+
return "texture_2d_array<f32>";
|
|
2796
|
+
case "cube":
|
|
2797
|
+
return "texture_cube<f32>";
|
|
2798
|
+
case "cube-array":
|
|
2799
|
+
return "texture_cube_array<f32>";
|
|
2800
|
+
default:
|
|
2801
|
+
throw new Error(`Unsupported render dimension "${dimension}" for mipmap generation.`);
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
function getRenderMipmapWGSL(dimension) {
|
|
2805
|
+
const sourceSnippet = getRenderMipmapSampleSnippet(dimension);
|
|
2806
|
+
return `
|
|
2807
|
+
struct MipmapUniforms {
|
|
2808
|
+
sourceLayer: u32,
|
|
2809
|
+
};
|
|
2810
|
+
|
|
2811
|
+
fn _touchUniform(uniforms: MipmapUniforms) {
|
|
2812
|
+
let unusedSourceLayer = uniforms.sourceLayer;
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2815
|
+
const faceMat = array(
|
|
2816
|
+
mat3x3f(
|
|
2817
|
+
0.0, 0.0, -2.0,
|
|
2818
|
+
0.0, -2.0, 0.0,
|
|
2819
|
+
1.0, 1.0, 1.0
|
|
2820
|
+
), // pos-x
|
|
2821
|
+
mat3x3f(
|
|
2822
|
+
0.0, 0.0, 2.0,
|
|
2823
|
+
0.0, -2.0, 0.0,
|
|
2824
|
+
-1.0, 1.0, -1.0
|
|
2825
|
+
), // neg-x
|
|
2826
|
+
mat3x3f(
|
|
2827
|
+
2.0, 0.0, 0.0,
|
|
2828
|
+
0.0, 0.0, 2.0,
|
|
2829
|
+
-1.0, 1.0, -1.0
|
|
2830
|
+
), // pos-y
|
|
2831
|
+
mat3x3f(
|
|
2832
|
+
2.0, 0.0, 0.0,
|
|
2833
|
+
0.0, 0.0, -2.0,
|
|
2834
|
+
-1.0, -1.0, 1.0
|
|
2835
|
+
), // neg-y
|
|
2836
|
+
mat3x3f(
|
|
2837
|
+
2.0, 0.0, 0.0,
|
|
2838
|
+
0.0, -2.0, 0.0,
|
|
2839
|
+
-1.0, 1.0, 1.0
|
|
2840
|
+
), // pos-z
|
|
2841
|
+
mat3x3f(
|
|
2842
|
+
-2.0, 0.0, 0.0,
|
|
2843
|
+
0.0, -2.0, 0.0,
|
|
2844
|
+
1.0, 1.0, -1.0
|
|
2845
|
+
) // neg-z
|
|
2846
|
+
);
|
|
2847
|
+
|
|
2848
|
+
struct FragmentInputs {
|
|
2849
|
+
@builtin(position) position: vec4f,
|
|
2850
|
+
@location(0) texcoord: vec2f
|
|
2851
|
+
};
|
|
2852
|
+
|
|
2853
|
+
struct VertexOutput {
|
|
2854
|
+
@builtin(position) position: vec4f,
|
|
2855
|
+
@location(0) texcoord: vec2f
|
|
2856
|
+
};
|
|
2857
|
+
|
|
2858
|
+
@group(0) @binding(0) var sourceSampler: sampler;
|
|
2859
|
+
@group(0) @binding(1) var sourceTexture: ${getSourceTextureType(dimension)};
|
|
2860
|
+
@group(0) @binding(2) var<uniform> uniforms: MipmapUniforms;
|
|
2861
|
+
|
|
2862
|
+
@vertex
|
|
2863
|
+
fn vertexMain(
|
|
2864
|
+
@builtin(vertex_index) vertexIndex: u32
|
|
2865
|
+
) -> VertexOutput {
|
|
2866
|
+
const positions = array(
|
|
2867
|
+
vec2f(-1.0, -1.0),
|
|
2868
|
+
vec2f(-1.0, 3.0),
|
|
2869
|
+
vec2f( 3.0, -1.0)
|
|
2870
|
+
);
|
|
2871
|
+
|
|
2872
|
+
let xy = positions[vertexIndex];
|
|
2873
|
+
return VertexOutput(
|
|
2874
|
+
vec4f(xy, 0.0, 1.0),
|
|
2875
|
+
xy * vec2f(0.5, -0.5) + vec2f(0.5)
|
|
2876
|
+
);
|
|
2877
|
+
}
|
|
2878
|
+
|
|
2879
|
+
@fragment
|
|
2880
|
+
fn fragmentMain(fsInput: VertexOutput) -> @location(0) vec4f {
|
|
2881
|
+
_touchUniform(uniforms);
|
|
2882
|
+
return ${sourceSnippet};
|
|
2883
|
+
}
|
|
2884
|
+
`;
|
|
2885
|
+
}
|
|
2886
|
+
function getRenderMipmapSampleSnippet(dimension) {
|
|
2887
|
+
const layer = "uniforms.sourceLayer";
|
|
2888
|
+
switch (dimension) {
|
|
2889
|
+
case "2d":
|
|
2890
|
+
return "textureSampleLevel(sourceTexture, sourceSampler, fsInput.texcoord, 0.0)";
|
|
2891
|
+
case "2d-array":
|
|
2892
|
+
return `textureSampleLevel(sourceTexture, sourceSampler, fsInput.texcoord, i32(${layer}), 0.0)`;
|
|
2893
|
+
case "cube":
|
|
2894
|
+
return `textureSampleLevel(sourceTexture, sourceSampler, faceMat[i32(${layer})] * vec3f(fract(fsInput.texcoord), 1.0), 0.0)`;
|
|
2895
|
+
case "cube-array":
|
|
2896
|
+
return `textureSampleLevel(sourceTexture, sourceSampler, faceMat[i32(${layer} % 6u)] * vec3f(fract(fsInput.texcoord), 1.0), i32(${layer} / 6u), 0.0)`;
|
|
2897
|
+
default:
|
|
2898
|
+
throw new Error(`Unsupported render dimension "${dimension}" for mipmap generation.`);
|
|
2899
|
+
}
|
|
2900
|
+
}
|
|
2901
|
+
function get3DComputeMipmapWGSL(format) {
|
|
2902
|
+
return `
|
|
2903
|
+
struct MipmapUniforms {
|
|
2904
|
+
sourceWidth: u32,
|
|
2905
|
+
sourceHeight: u32,
|
|
2906
|
+
sourceDepth: u32,
|
|
2907
|
+
destinationWidth: u32,
|
|
2908
|
+
destinationHeight: u32,
|
|
2909
|
+
destinationDepth: u32,
|
|
2910
|
+
padding: u32,
|
|
2911
|
+
};
|
|
2912
|
+
|
|
2913
|
+
@group(0) @binding(0) var sourceTexture: texture_3d<f32>;
|
|
2914
|
+
@group(0) @binding(1) var destinationTexture: texture_storage_3d<${format}, write>;
|
|
2915
|
+
@group(0) @binding(2) var<uniform> uniforms: MipmapUniforms;
|
|
2916
|
+
|
|
2917
|
+
@compute @workgroup_size(${WORKGROUP_SIZE.x}, ${WORKGROUP_SIZE.y}, ${WORKGROUP_SIZE.z})
|
|
2918
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
2919
|
+
if (
|
|
2920
|
+
id.x >= uniforms.destinationWidth ||
|
|
2921
|
+
id.y >= uniforms.destinationHeight ||
|
|
2922
|
+
id.z >= uniforms.destinationDepth
|
|
2923
|
+
) {
|
|
2924
|
+
return;
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
let sourceBase = id * 2u;
|
|
2928
|
+
let sourceX0 = min(sourceBase.x, uniforms.sourceWidth - 1u);
|
|
2929
|
+
let sourceY0 = min(sourceBase.y, uniforms.sourceHeight - 1u);
|
|
2930
|
+
let sourceZ0 = min(sourceBase.z, uniforms.sourceDepth - 1u);
|
|
2931
|
+
|
|
2932
|
+
let sourceX1 = min(sourceBase.x + 1u, uniforms.sourceWidth - 1u);
|
|
2933
|
+
let sourceY1 = min(sourceBase.y + 1u, uniforms.sourceHeight - 1u);
|
|
2934
|
+
let sourceZ1 = min(sourceBase.z + 1u, uniforms.sourceDepth - 1u);
|
|
2935
|
+
|
|
2936
|
+
var sum = textureLoad(
|
|
2937
|
+
sourceTexture,
|
|
2938
|
+
vec3<i32>(i32(sourceX0), i32(sourceY0), i32(sourceZ0)),
|
|
2939
|
+
0
|
|
2940
|
+
);
|
|
2941
|
+
sum += textureLoad(
|
|
2942
|
+
sourceTexture,
|
|
2943
|
+
vec3<i32>(i32(sourceX1), i32(sourceY0), i32(sourceZ0)),
|
|
2944
|
+
0
|
|
2945
|
+
);
|
|
2946
|
+
sum += textureLoad(
|
|
2947
|
+
sourceTexture,
|
|
2948
|
+
vec3<i32>(i32(sourceX0), i32(sourceY1), i32(sourceZ0)),
|
|
2949
|
+
0
|
|
2950
|
+
);
|
|
2951
|
+
sum += textureLoad(
|
|
2952
|
+
sourceTexture,
|
|
2953
|
+
vec3<i32>(i32(sourceX1), i32(sourceY1), i32(sourceZ0)),
|
|
2954
|
+
0
|
|
2955
|
+
);
|
|
2956
|
+
sum += textureLoad(
|
|
2957
|
+
sourceTexture,
|
|
2958
|
+
vec3<i32>(i32(sourceX0), i32(sourceY0), i32(sourceZ1)),
|
|
2959
|
+
0
|
|
2960
|
+
);
|
|
2961
|
+
sum += textureLoad(
|
|
2962
|
+
sourceTexture,
|
|
2963
|
+
vec3<i32>(i32(sourceX1), i32(sourceY0), i32(sourceZ1)),
|
|
2964
|
+
0
|
|
2965
|
+
);
|
|
2966
|
+
sum += textureLoad(
|
|
2967
|
+
sourceTexture,
|
|
2968
|
+
vec3<i32>(i32(sourceX0), i32(sourceY1), i32(sourceZ1)),
|
|
2969
|
+
0
|
|
2970
|
+
);
|
|
2971
|
+
sum += textureLoad(
|
|
2972
|
+
sourceTexture,
|
|
2973
|
+
vec3<i32>(i32(sourceX1), i32(sourceY1), i32(sourceZ1)),
|
|
2974
|
+
0
|
|
2975
|
+
);
|
|
2976
|
+
|
|
2977
|
+
textureStore(
|
|
2978
|
+
destinationTexture,
|
|
2979
|
+
vec3<i32>(i32(id.x), i32(id.y), i32(id.z)),
|
|
2980
|
+
vec4<f32>(sum.xyz / 8.0, sum.w / 8.0)
|
|
2981
|
+
);
|
|
2982
|
+
}
|
|
2983
|
+
`;
|
|
2984
|
+
}
|
|
2985
|
+
var import_core23, RENDER_DIMENSIONS, WORKGROUP_SIZE, RENDER_SOURCE_SAMPLER_LAYOUT, COMPUTE_SOURCE_TEXTURE_LAYOUT, COMPUTE_UNIFORMS_LAYOUT;
|
|
2986
|
+
var init_generate_mipmaps_webgpu = __esm({
|
|
2987
|
+
"dist/adapter/helpers/generate-mipmaps-webgpu.js"() {
|
|
2988
|
+
"use strict";
|
|
2989
|
+
import_core23 = require("@luma.gl/core");
|
|
2990
|
+
RENDER_DIMENSIONS = [
|
|
2991
|
+
"2d",
|
|
2992
|
+
"2d-array",
|
|
2993
|
+
"cube",
|
|
2994
|
+
"cube-array"
|
|
2995
|
+
];
|
|
2996
|
+
WORKGROUP_SIZE = {
|
|
2997
|
+
x: 4,
|
|
2998
|
+
y: 4,
|
|
2999
|
+
z: 4
|
|
3000
|
+
};
|
|
3001
|
+
RENDER_SOURCE_SAMPLER_LAYOUT = {
|
|
3002
|
+
type: "sampler",
|
|
3003
|
+
name: "sourceSampler",
|
|
3004
|
+
group: 0,
|
|
3005
|
+
location: 0
|
|
3006
|
+
};
|
|
3007
|
+
COMPUTE_SOURCE_TEXTURE_LAYOUT = {
|
|
3008
|
+
type: "texture",
|
|
3009
|
+
name: "sourceTexture",
|
|
3010
|
+
group: 0,
|
|
3011
|
+
location: 0,
|
|
3012
|
+
viewDimension: "3d",
|
|
3013
|
+
sampleType: "float"
|
|
3014
|
+
};
|
|
3015
|
+
COMPUTE_UNIFORMS_LAYOUT = {
|
|
3016
|
+
type: "uniform",
|
|
3017
|
+
name: "uniforms",
|
|
3018
|
+
group: 0,
|
|
3019
|
+
location: 2
|
|
3020
|
+
};
|
|
3021
|
+
}
|
|
3022
|
+
});
|
|
3023
|
+
|
|
3024
|
+
// dist/adapter/helpers/get-bind-group.js
|
|
3025
|
+
function getBindGroup(device, bindGroupLayout, shaderLayout, bindings, group) {
|
|
3026
|
+
const entries = getBindGroupEntries(bindings, shaderLayout, group);
|
|
3027
|
+
if (entries.length === 0) {
|
|
3028
|
+
return null;
|
|
3029
|
+
}
|
|
3030
|
+
device.pushErrorScope("validation");
|
|
3031
|
+
const bindGroup = device.handle.createBindGroup({
|
|
3032
|
+
layout: bindGroupLayout,
|
|
3033
|
+
entries
|
|
3034
|
+
});
|
|
3035
|
+
device.popErrorScope((error) => {
|
|
3036
|
+
import_core24.log.error(`bindGroup creation: ${error.message}`, bindGroup)();
|
|
3037
|
+
});
|
|
3038
|
+
return bindGroup;
|
|
3039
|
+
}
|
|
3040
|
+
function getBindGroupEntries(bindings, shaderLayout, group) {
|
|
3041
|
+
const entries = [];
|
|
3042
|
+
for (const [bindingName, value] of Object.entries(bindings)) {
|
|
3043
|
+
const exactBindingLayout = shaderLayout.bindings.find((binding) => binding.name === bindingName);
|
|
3044
|
+
const bindingLayout = exactBindingLayout || (0, import_core24.getShaderLayoutBinding)(shaderLayout, bindingName);
|
|
3045
|
+
const isShadowedAlias = !exactBindingLayout && bindingLayout ? bindingLayout.name in bindings : false;
|
|
3046
|
+
if (!isShadowedAlias && (bindingLayout == null ? void 0 : bindingLayout.group) === group) {
|
|
3047
|
+
const entry = bindingLayout ? getBindGroupEntry(value, bindingLayout.location, void 0, bindingName) : null;
|
|
3048
|
+
if (entry) {
|
|
3049
|
+
entries.push(entry);
|
|
3050
|
+
}
|
|
3051
|
+
if (value instanceof import_core24.Texture) {
|
|
3052
|
+
const samplerBindingLayout = (0, import_core24.getShaderLayoutBinding)(shaderLayout, `${bindingName}Sampler`, {
|
|
3053
|
+
ignoreWarnings: true
|
|
3054
|
+
});
|
|
3055
|
+
const samplerEntry = samplerBindingLayout ? samplerBindingLayout.group === group ? getBindGroupEntry(value, samplerBindingLayout.location, { sampler: true }, bindingName) : null : null;
|
|
3056
|
+
if (samplerEntry) {
|
|
3057
|
+
entries.push(samplerEntry);
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
return entries;
|
|
3063
|
+
}
|
|
3064
|
+
function getBindGroupEntry(binding, index, options, bindingName = "unknown") {
|
|
3065
|
+
if (binding instanceof import_core24.Buffer) {
|
|
3066
|
+
return {
|
|
3067
|
+
binding: index,
|
|
3068
|
+
resource: {
|
|
3069
|
+
buffer: binding.handle
|
|
3070
|
+
}
|
|
3071
|
+
};
|
|
3072
|
+
}
|
|
3073
|
+
if (binding instanceof import_core24.Sampler) {
|
|
3074
|
+
return {
|
|
3075
|
+
binding: index,
|
|
3076
|
+
resource: binding.handle
|
|
3077
|
+
};
|
|
3078
|
+
}
|
|
3079
|
+
if (binding instanceof import_core24.TextureView) {
|
|
3080
|
+
return {
|
|
3081
|
+
binding: index,
|
|
3082
|
+
resource: binding.handle
|
|
3083
|
+
};
|
|
3084
|
+
}
|
|
3085
|
+
if (binding instanceof import_core24.Texture) {
|
|
3086
|
+
if (options == null ? void 0 : options.sampler) {
|
|
3087
|
+
return {
|
|
3088
|
+
binding: index,
|
|
3089
|
+
resource: binding.sampler.handle
|
|
3090
|
+
};
|
|
3091
|
+
}
|
|
3092
|
+
return {
|
|
3093
|
+
binding: index,
|
|
3094
|
+
resource: binding.view.handle
|
|
3095
|
+
};
|
|
3096
|
+
}
|
|
3097
|
+
import_core24.log.warn(`invalid binding ${bindingName}`, binding);
|
|
3098
|
+
return null;
|
|
3099
|
+
}
|
|
3100
|
+
var import_core24;
|
|
3101
|
+
var init_get_bind_group = __esm({
|
|
3102
|
+
"dist/adapter/helpers/get-bind-group.js"() {
|
|
3103
|
+
"use strict";
|
|
3104
|
+
import_core24 = require("@luma.gl/core");
|
|
3105
|
+
}
|
|
3106
|
+
});
|
|
3107
|
+
|
|
1999
3108
|
// dist/adapter/webgpu-device.js
|
|
2000
3109
|
var webgpu_device_exports = {};
|
|
2001
3110
|
__export(webgpu_device_exports, {
|
|
2002
3111
|
WebGPUDevice: () => WebGPUDevice
|
|
2003
3112
|
});
|
|
2004
|
-
|
|
3113
|
+
function scheduleMicrotask(callback) {
|
|
3114
|
+
if (globalThis.queueMicrotask) {
|
|
3115
|
+
globalThis.queueMicrotask(callback);
|
|
3116
|
+
return;
|
|
3117
|
+
}
|
|
3118
|
+
Promise.resolve().then(callback).catch(() => {
|
|
3119
|
+
});
|
|
3120
|
+
}
|
|
3121
|
+
var import_core25, WebGPUDevice;
|
|
2005
3122
|
var init_webgpu_device = __esm({
|
|
2006
3123
|
"dist/adapter/webgpu-device.js"() {
|
|
2007
3124
|
"use strict";
|
|
2008
|
-
|
|
3125
|
+
import_core25 = require("@luma.gl/core");
|
|
2009
3126
|
init_webgpu_buffer();
|
|
2010
3127
|
init_webgpu_texture();
|
|
2011
3128
|
init_webgpu_external_texture();
|
|
@@ -2016,12 +3133,16 @@ var init_webgpu_device = __esm({
|
|
|
2016
3133
|
init_webgpu_compute_pipeline();
|
|
2017
3134
|
init_webgpu_vertex_array();
|
|
2018
3135
|
init_webgpu_canvas_context();
|
|
3136
|
+
init_webgpu_presentation_context();
|
|
2019
3137
|
init_webgpu_command_encoder();
|
|
2020
3138
|
init_webgpu_query_set();
|
|
2021
3139
|
init_webgpu_pipeline_layout();
|
|
2022
3140
|
init_webgpu_fence();
|
|
2023
3141
|
init_get_shader_layout_wgsl();
|
|
2024
|
-
|
|
3142
|
+
init_generate_mipmaps_webgpu();
|
|
3143
|
+
init_get_bind_group();
|
|
3144
|
+
init_cpu_hotspot_profiler();
|
|
3145
|
+
WebGPUDevice = class extends import_core25.Device {
|
|
2025
3146
|
/** The underlying WebGPU device */
|
|
2026
3147
|
handle;
|
|
2027
3148
|
/* The underlying WebGPU adapter */
|
|
@@ -2038,6 +3159,7 @@ var init_webgpu_device = __esm({
|
|
|
2038
3159
|
lost;
|
|
2039
3160
|
canvasContext = null;
|
|
2040
3161
|
_isLost = false;
|
|
3162
|
+
_defaultSampler = null;
|
|
2041
3163
|
commandEncoder;
|
|
2042
3164
|
get [Symbol.toStringTag]() {
|
|
2043
3165
|
return "WebGPUDevice";
|
|
@@ -2064,7 +3186,7 @@ var init_webgpu_device = __esm({
|
|
|
2064
3186
|
this._isLost = true;
|
|
2065
3187
|
resolve({ reason: "destroyed", message: lostInfo.message });
|
|
2066
3188
|
});
|
|
2067
|
-
const canvasContextProps =
|
|
3189
|
+
const canvasContextProps = import_core25.Device._getCanvasContextProps(props);
|
|
2068
3190
|
if (canvasContextProps) {
|
|
2069
3191
|
this.canvasContext = new WebGPUCanvasContext(this, this.adapter, canvasContextProps);
|
|
2070
3192
|
}
|
|
@@ -2075,6 +3197,10 @@ var init_webgpu_device = __esm({
|
|
|
2075
3197
|
// const {glsl = true} = props;
|
|
2076
3198
|
// this.glslang = glsl && await loadGlslangModule();
|
|
2077
3199
|
destroy() {
|
|
3200
|
+
var _a, _b;
|
|
3201
|
+
(_a = this.commandEncoder) == null ? void 0 : _a.destroy();
|
|
3202
|
+
(_b = this._defaultSampler) == null ? void 0 : _b.destroy();
|
|
3203
|
+
this._defaultSampler = null;
|
|
2078
3204
|
this.handle.destroy();
|
|
2079
3205
|
}
|
|
2080
3206
|
get isLost() {
|
|
@@ -2103,6 +3229,12 @@ var init_webgpu_device = __esm({
|
|
|
2103
3229
|
createSampler(props) {
|
|
2104
3230
|
return new WebGPUSampler(this, props);
|
|
2105
3231
|
}
|
|
3232
|
+
getDefaultSampler() {
|
|
3233
|
+
this._defaultSampler ||= new WebGPUSampler(this, {
|
|
3234
|
+
id: `${this.id}-default-sampler`
|
|
3235
|
+
});
|
|
3236
|
+
return this._defaultSampler;
|
|
3237
|
+
}
|
|
2106
3238
|
createRenderPipeline(props) {
|
|
2107
3239
|
return new WebGPURenderPipeline(this, props);
|
|
2108
3240
|
}
|
|
@@ -2131,32 +3263,129 @@ var init_webgpu_device = __esm({
|
|
|
2131
3263
|
createCanvasContext(props) {
|
|
2132
3264
|
return new WebGPUCanvasContext(this, this.adapter, props);
|
|
2133
3265
|
}
|
|
3266
|
+
createPresentationContext(props) {
|
|
3267
|
+
return new WebGPUPresentationContext(this, props);
|
|
3268
|
+
}
|
|
2134
3269
|
createPipelineLayout(props) {
|
|
2135
3270
|
return new WebGPUPipelineLayout(this, props);
|
|
2136
3271
|
}
|
|
3272
|
+
generateMipmapsWebGPU(texture) {
|
|
3273
|
+
generateMipmapsWebGPU(this, texture);
|
|
3274
|
+
}
|
|
3275
|
+
_createBindGroupLayoutWebGPU(pipeline, group) {
|
|
3276
|
+
return pipeline.handle.getBindGroupLayout(group);
|
|
3277
|
+
}
|
|
3278
|
+
_createBindGroupWebGPU(bindGroupLayout, shaderLayout, bindings, group) {
|
|
3279
|
+
if (Object.keys(bindings).length === 0) {
|
|
3280
|
+
return this.handle.createBindGroup({
|
|
3281
|
+
layout: bindGroupLayout,
|
|
3282
|
+
entries: []
|
|
3283
|
+
});
|
|
3284
|
+
}
|
|
3285
|
+
return getBindGroup(this, bindGroupLayout, shaderLayout, bindings, group);
|
|
3286
|
+
}
|
|
2137
3287
|
submit(commandBuffer) {
|
|
3288
|
+
let submittedCommandEncoder = null;
|
|
2138
3289
|
if (!commandBuffer) {
|
|
2139
|
-
commandBuffer = this.
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
this
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
this.
|
|
3290
|
+
({ submittedCommandEncoder, commandBuffer } = this._finalizeDefaultCommandEncoderForSubmit());
|
|
3291
|
+
}
|
|
3292
|
+
const profiler = getCpuHotspotProfiler(this);
|
|
3293
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
3294
|
+
const submitReason = getCpuHotspotSubmitReason(this);
|
|
3295
|
+
try {
|
|
3296
|
+
this.pushErrorScope("validation");
|
|
3297
|
+
const queueSubmitStartTime = profiler ? getTimestamp() : 0;
|
|
3298
|
+
this.handle.queue.submit([commandBuffer.handle]);
|
|
3299
|
+
if (profiler) {
|
|
3300
|
+
profiler.queueSubmitCount = (profiler.queueSubmitCount || 0) + 1;
|
|
3301
|
+
profiler.queueSubmitTimeMs = (profiler.queueSubmitTimeMs || 0) + (getTimestamp() - queueSubmitStartTime);
|
|
3302
|
+
}
|
|
3303
|
+
this.popErrorScope((error) => {
|
|
3304
|
+
this.reportError(new Error(`${this} command submission: ${error.message}`), this)();
|
|
3305
|
+
this.debug();
|
|
3306
|
+
});
|
|
3307
|
+
if (submittedCommandEncoder) {
|
|
3308
|
+
const submitResolveKickoffStartTime = profiler ? getTimestamp() : 0;
|
|
3309
|
+
scheduleMicrotask(() => {
|
|
3310
|
+
submittedCommandEncoder.resolveTimeProfilingQuerySet().then(() => {
|
|
3311
|
+
this.commandEncoder._gpuTimeMs = submittedCommandEncoder._gpuTimeMs;
|
|
3312
|
+
}).catch(() => {
|
|
3313
|
+
});
|
|
3314
|
+
});
|
|
3315
|
+
if (profiler) {
|
|
3316
|
+
profiler.submitResolveKickoffCount = (profiler.submitResolveKickoffCount || 0) + 1;
|
|
3317
|
+
profiler.submitResolveKickoffTimeMs = (profiler.submitResolveKickoffTimeMs || 0) + (getTimestamp() - submitResolveKickoffStartTime);
|
|
3318
|
+
}
|
|
3319
|
+
}
|
|
3320
|
+
} finally {
|
|
3321
|
+
if (profiler) {
|
|
3322
|
+
profiler.submitCount = (profiler.submitCount || 0) + 1;
|
|
3323
|
+
profiler.submitTimeMs = (profiler.submitTimeMs || 0) + (getTimestamp() - startTime);
|
|
3324
|
+
const reasonCountKey = submitReason === "query-readback" ? "queryReadbackSubmitCount" : "defaultSubmitCount";
|
|
3325
|
+
const reasonTimeKey = submitReason === "query-readback" ? "queryReadbackSubmitTimeMs" : "defaultSubmitTimeMs";
|
|
3326
|
+
profiler[reasonCountKey] = (profiler[reasonCountKey] || 0) + 1;
|
|
3327
|
+
profiler[reasonTimeKey] = (profiler[reasonTimeKey] || 0) + (getTimestamp() - startTime);
|
|
3328
|
+
}
|
|
3329
|
+
const commandBufferDestroyStartTime = profiler ? getTimestamp() : 0;
|
|
3330
|
+
commandBuffer.destroy();
|
|
3331
|
+
if (profiler) {
|
|
3332
|
+
profiler.commandBufferDestroyCount = (profiler.commandBufferDestroyCount || 0) + 1;
|
|
3333
|
+
profiler.commandBufferDestroyTimeMs = (profiler.commandBufferDestroyTimeMs || 0) + (getTimestamp() - commandBufferDestroyStartTime);
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
_finalizeDefaultCommandEncoderForSubmit() {
|
|
3338
|
+
const submittedCommandEncoder = this.commandEncoder;
|
|
3339
|
+
if (submittedCommandEncoder.getTimeProfilingSlotCount() > 0 && submittedCommandEncoder.getTimeProfilingQuerySet() instanceof WebGPUQuerySet) {
|
|
3340
|
+
const querySet = submittedCommandEncoder.getTimeProfilingQuerySet();
|
|
3341
|
+
querySet._encodeResolveToReadBuffer(submittedCommandEncoder, {
|
|
3342
|
+
firstQuery: 0,
|
|
3343
|
+
queryCount: submittedCommandEncoder.getTimeProfilingSlotCount()
|
|
3344
|
+
});
|
|
3345
|
+
}
|
|
3346
|
+
const commandBuffer = submittedCommandEncoder.finish();
|
|
3347
|
+
this.commandEncoder.destroy();
|
|
3348
|
+
this.commandEncoder = this.createCommandEncoder({
|
|
3349
|
+
id: submittedCommandEncoder.props.id,
|
|
3350
|
+
timeProfilingQuerySet: submittedCommandEncoder.getTimeProfilingQuerySet()
|
|
2148
3351
|
});
|
|
3352
|
+
return { submittedCommandEncoder, commandBuffer };
|
|
2149
3353
|
}
|
|
2150
3354
|
// WebGPU specific
|
|
2151
3355
|
pushErrorScope(scope) {
|
|
3356
|
+
if (!this.props.debug) {
|
|
3357
|
+
return;
|
|
3358
|
+
}
|
|
3359
|
+
const profiler = getCpuHotspotProfiler(this);
|
|
3360
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
2152
3361
|
this.handle.pushErrorScope(scope);
|
|
3362
|
+
if (profiler) {
|
|
3363
|
+
profiler.errorScopePushCount = (profiler.errorScopePushCount || 0) + 1;
|
|
3364
|
+
profiler.errorScopeTimeMs = (profiler.errorScopeTimeMs || 0) + (getTimestamp() - startTime);
|
|
3365
|
+
}
|
|
2153
3366
|
}
|
|
2154
3367
|
popErrorScope(handler) {
|
|
3368
|
+
if (!this.props.debug) {
|
|
3369
|
+
return;
|
|
3370
|
+
}
|
|
3371
|
+
const profiler = getCpuHotspotProfiler(this);
|
|
3372
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
2155
3373
|
this.handle.popErrorScope().then((error) => {
|
|
2156
3374
|
if (error) {
|
|
2157
3375
|
handler(error);
|
|
2158
3376
|
}
|
|
3377
|
+
}).catch((error) => {
|
|
3378
|
+
if (this.shouldIgnoreDroppedInstanceError(error, "popErrorScope")) {
|
|
3379
|
+
return;
|
|
3380
|
+
}
|
|
3381
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3382
|
+
this.reportError(new Error(`${this} popErrorScope failed: ${errorMessage}`), this)();
|
|
3383
|
+
this.debug();
|
|
2159
3384
|
});
|
|
3385
|
+
if (profiler) {
|
|
3386
|
+
profiler.errorScopePopCount = (profiler.errorScopePopCount || 0) + 1;
|
|
3387
|
+
profiler.errorScopeTimeMs = (profiler.errorScopeTimeMs || 0) + (getTimestamp() - startTime);
|
|
3388
|
+
}
|
|
2160
3389
|
}
|
|
2161
3390
|
// PRIVATE METHODS
|
|
2162
3391
|
_getInfo() {
|
|
@@ -2164,10 +3393,12 @@ var init_webgpu_device = __esm({
|
|
|
2164
3393
|
const vendor = this.adapterInfo.vendor || this.adapter.__brand || "unknown";
|
|
2165
3394
|
const renderer = driver || "";
|
|
2166
3395
|
const version = driverVersion || "";
|
|
2167
|
-
const
|
|
3396
|
+
const fallback = Boolean(this.adapterInfo.isFallbackAdapter ?? this.adapter.isFallbackAdapter ?? false);
|
|
3397
|
+
const softwareRenderer = /SwiftShader/i.test(`${vendor} ${renderer} ${this.adapterInfo.architecture || ""}`);
|
|
3398
|
+
const gpu = vendor === "apple" ? "apple" : softwareRenderer || fallback ? "software" : "unknown";
|
|
2168
3399
|
const gpuArchitecture = this.adapterInfo.architecture || "unknown";
|
|
2169
3400
|
const gpuBackend = this.adapterInfo.backend || "unknown";
|
|
2170
|
-
const gpuType = (this.adapterInfo.type || "").split(" ")[0].toLowerCase() || "unknown";
|
|
3401
|
+
const gpuType = (this.adapterInfo.type || "").split(" ")[0].toLowerCase() || (softwareRenderer || fallback ? "cpu" : "unknown");
|
|
2171
3402
|
return {
|
|
2172
3403
|
type: "webgpu",
|
|
2173
3404
|
vendor,
|
|
@@ -2177,10 +3408,15 @@ var init_webgpu_device = __esm({
|
|
|
2177
3408
|
gpuType,
|
|
2178
3409
|
gpuBackend,
|
|
2179
3410
|
gpuArchitecture,
|
|
3411
|
+
fallback,
|
|
2180
3412
|
shadingLanguage: "wgsl",
|
|
2181
3413
|
shadingLanguageVersion: 100
|
|
2182
3414
|
};
|
|
2183
3415
|
}
|
|
3416
|
+
shouldIgnoreDroppedInstanceError(error, operation) {
|
|
3417
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3418
|
+
return errorMessage.includes("Instance dropped") && (!operation || errorMessage.includes(operation)) && (this._isLost || this.info.gpu === "software" || this.info.gpuType === "cpu" || Boolean(this.info.fallback));
|
|
3419
|
+
}
|
|
2184
3420
|
_getFeatures() {
|
|
2185
3421
|
const features = new Set(this.handle.features);
|
|
2186
3422
|
if (features.has("depth-clamping")) {
|
|
@@ -2197,7 +3433,6 @@ var init_webgpu_device = __esm({
|
|
|
2197
3433
|
features.add("snorm16-renderable-webgl");
|
|
2198
3434
|
}
|
|
2199
3435
|
const WEBGPU_ALWAYS_FEATURES = [
|
|
2200
|
-
"timer-query-webgl",
|
|
2201
3436
|
"compilation-status-async-webgl",
|
|
2202
3437
|
"float32-renderable-webgl",
|
|
2203
3438
|
"float16-renderable-webgl",
|
|
@@ -2208,7 +3443,7 @@ var init_webgpu_device = __esm({
|
|
|
2208
3443
|
for (const feature of WEBGPU_ALWAYS_FEATURES) {
|
|
2209
3444
|
features.add(feature);
|
|
2210
3445
|
}
|
|
2211
|
-
return new
|
|
3446
|
+
return new import_core25.DeviceFeatures(Array.from(features), this.props._disabledFeatures);
|
|
2212
3447
|
}
|
|
2213
3448
|
_getDeviceSpecificTextureFormatCapabilities(capabilities) {
|
|
2214
3449
|
const { format } = capabilities;
|
|
@@ -2236,8 +3471,8 @@ __export(dist_exports, {
|
|
|
2236
3471
|
module.exports = __toCommonJS(dist_exports);
|
|
2237
3472
|
|
|
2238
3473
|
// dist/adapter/webgpu-adapter.js
|
|
2239
|
-
var
|
|
2240
|
-
var WebGPUAdapter = class extends
|
|
3474
|
+
var import_core26 = require("@luma.gl/core");
|
|
3475
|
+
var WebGPUAdapter = class extends import_core26.Adapter {
|
|
2241
3476
|
/** type of device's created by this adapter */
|
|
2242
3477
|
type = "webgpu";
|
|
2243
3478
|
isSupported() {
|
|
@@ -2284,14 +3519,14 @@ var WebGPUAdapter = class extends import_core24.Adapter {
|
|
|
2284
3519
|
requiredLimits
|
|
2285
3520
|
});
|
|
2286
3521
|
const { WebGPUDevice: WebGPUDevice2 } = await Promise.resolve().then(() => (init_webgpu_device(), webgpu_device_exports));
|
|
2287
|
-
|
|
3522
|
+
import_core26.log.groupCollapsed(1, "WebGPUDevice created")();
|
|
2288
3523
|
try {
|
|
2289
3524
|
const device = new WebGPUDevice2(props, gpuDevice, adapter, adapterInfo);
|
|
2290
|
-
|
|
2291
|
-
|
|
3525
|
+
import_core26.log.probe(1, "Device created. For more info, set chrome://flags/#enable-webgpu-developer-features")();
|
|
3526
|
+
import_core26.log.table(1, device.info)();
|
|
2292
3527
|
return device;
|
|
2293
3528
|
} finally {
|
|
2294
|
-
|
|
3529
|
+
import_core26.log.groupEnd(1)();
|
|
2295
3530
|
}
|
|
2296
3531
|
}
|
|
2297
3532
|
async attach(handle) {
|