@luma.gl/webgpu 9.3.0-alpha.4 → 9.3.0-alpha.6
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 +2 -1
- package/dist/adapter/helpers/get-bind-group.d.ts.map +1 -1
- package/dist/adapter/helpers/get-bind-group.js +22 -18
- package/dist/adapter/helpers/get-bind-group.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 +5 -4
- package/dist/adapter/resources/webgpu-command-encoder.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-command-encoder.js +23 -5
- package/dist/adapter/resources/webgpu-command-encoder.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.d.ts +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pass.js +14 -6
- package/dist/adapter/resources/webgpu-compute-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-compute-pipeline.js +19 -3
- package/dist/adapter/resources/webgpu-compute-pipeline.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-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 +3 -0
- package/dist/adapter/resources/webgpu-render-pass.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pass.js +74 -30
- package/dist/adapter/resources/webgpu-render-pass.js.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts +7 -4
- package/dist/adapter/resources/webgpu-render-pipeline.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-render-pipeline.js +26 -15
- 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-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 +10 -4
- package/dist/adapter/resources/webgpu-texture.d.ts.map +1 -1
- package/dist/adapter/resources/webgpu-texture.js +116 -57
- 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 +5 -1
- package/dist/adapter/webgpu-device.d.ts.map +1 -1
- package/dist/adapter/webgpu-device.js +113 -9
- 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 +2815 -1681
- package/dist/dist.min.js +167 -8
- package/dist/index.cjs +1314 -199
- package/dist/index.cjs.map +4 -4
- package/package.json +4 -4
- 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 +26 -24
- 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 +32 -6
- package/src/adapter/resources/webgpu-compute-pass.ts +14 -6
- package/src/adapter/resources/webgpu-compute-pipeline.ts +21 -3
- package/src/adapter/resources/webgpu-framebuffer.ts +21 -0
- package/src/adapter/resources/webgpu-query-set.ts +185 -9
- package/src/adapter/resources/webgpu-render-pass.ts +82 -34
- package/src/adapter/resources/webgpu-render-pipeline.ts +36 -19
- package/src/adapter/resources/webgpu-sampler.ts +5 -0
- package/src/adapter/resources/webgpu-texture-view.ts +51 -11
- package/src/adapter/resources/webgpu-texture.ts +142 -93
- 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 +128 -9
- package/src/adapter/webgpu-presentation-context.ts +180 -0
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,13 +472,16 @@ var init_webgpu_texture = __esm({
|
|
|
404
472
|
};
|
|
405
473
|
}
|
|
406
474
|
readBuffer(options = {}, buffer) {
|
|
407
|
-
const { x
|
|
408
|
-
const layout = this.computeMemoryLayout(
|
|
475
|
+
const { x, y, z, width, height, depthOrArrayLayers, mipLevel, aspect } = this._getSupportedColorReadOptions(options);
|
|
476
|
+
const layout = this.computeMemoryLayout({ x, y, z, width, height, depthOrArrayLayers, mipLevel });
|
|
409
477
|
const { bytesPerRow, rowsPerImage, byteLength } = layout;
|
|
410
478
|
const readBuffer = buffer || this.device.createBuffer({
|
|
411
479
|
byteLength,
|
|
412
480
|
usage: import_core4.Buffer.COPY_DST | import_core4.Buffer.MAP_READ
|
|
413
481
|
});
|
|
482
|
+
if (readBuffer.byteLength < byteLength) {
|
|
483
|
+
throw new Error(`${this} readBuffer target is too small (${readBuffer.byteLength} < ${byteLength})`);
|
|
484
|
+
}
|
|
414
485
|
const gpuReadBuffer = readBuffer.handle;
|
|
415
486
|
const gpuDevice = this.device.handle;
|
|
416
487
|
this.device.pushErrorScope("validation");
|
|
@@ -454,16 +525,15 @@ var init_webgpu_texture = __esm({
|
|
|
454
525
|
buffer.destroy();
|
|
455
526
|
return data.buffer;
|
|
456
527
|
}
|
|
457
|
-
writeBuffer(buffer,
|
|
458
|
-
const
|
|
459
|
-
const
|
|
460
|
-
const { bytesPerRow, rowsPerImage } = layout;
|
|
528
|
+
writeBuffer(buffer, options_ = {}) {
|
|
529
|
+
const options = this._normalizeTextureWriteOptions(options_);
|
|
530
|
+
const { x, y, z, width, height, depthOrArrayLayers, mipLevel, aspect, byteOffset, bytesPerRow, rowsPerImage } = options;
|
|
461
531
|
const gpuDevice = this.device.handle;
|
|
462
532
|
this.device.pushErrorScope("validation");
|
|
463
533
|
const commandEncoder = gpuDevice.createCommandEncoder();
|
|
464
534
|
commandEncoder.copyBufferToTexture({
|
|
465
535
|
buffer: buffer.handle,
|
|
466
|
-
offset:
|
|
536
|
+
offset: byteOffset,
|
|
467
537
|
bytesPerRow,
|
|
468
538
|
rowsPerImage
|
|
469
539
|
}, {
|
|
@@ -479,33 +549,88 @@ var init_webgpu_texture = __esm({
|
|
|
479
549
|
this.device.debug();
|
|
480
550
|
});
|
|
481
551
|
}
|
|
482
|
-
writeData(data,
|
|
552
|
+
writeData(data, options_ = {}) {
|
|
483
553
|
const device = this.device;
|
|
484
|
-
const
|
|
485
|
-
const
|
|
554
|
+
const options = this._normalizeTextureWriteOptions(options_);
|
|
555
|
+
const { x, y, z, width, height, depthOrArrayLayers, mipLevel, aspect, byteOffset } = options;
|
|
556
|
+
const source = data;
|
|
557
|
+
const formatInfo = this.device.getTextureFormatInfo(this.format);
|
|
558
|
+
const packedSourceLayout = import_core4.textureFormatDecoder.computeMemoryLayout({
|
|
486
559
|
format: this.format,
|
|
487
|
-
width
|
|
488
|
-
height
|
|
489
|
-
depth:
|
|
490
|
-
byteAlignment:
|
|
560
|
+
width,
|
|
561
|
+
height,
|
|
562
|
+
depth: depthOrArrayLayers,
|
|
563
|
+
byteAlignment: 1
|
|
491
564
|
});
|
|
492
|
-
const
|
|
565
|
+
const bytesPerRow = options_.bytesPerRow ?? packedSourceLayout.bytesPerRow;
|
|
566
|
+
const rowsPerImage = options_.rowsPerImage ?? packedSourceLayout.rowsPerImage;
|
|
567
|
+
let copyWidth = width;
|
|
568
|
+
let copyHeight = height;
|
|
569
|
+
if (formatInfo.compressed) {
|
|
570
|
+
const blockWidth = formatInfo.blockWidth || 1;
|
|
571
|
+
const blockHeight = formatInfo.blockHeight || 1;
|
|
572
|
+
copyWidth = Math.ceil(width / blockWidth) * blockWidth;
|
|
573
|
+
copyHeight = Math.ceil(height / blockHeight) * blockHeight;
|
|
574
|
+
}
|
|
493
575
|
this.device.pushErrorScope("validation");
|
|
494
576
|
device.handle.queue.writeTexture({
|
|
495
577
|
texture: this.handle,
|
|
496
578
|
mipLevel,
|
|
497
579
|
aspect,
|
|
498
580
|
origin: { x, y, z }
|
|
499
|
-
},
|
|
500
|
-
offset:
|
|
581
|
+
}, source, {
|
|
582
|
+
offset: byteOffset,
|
|
501
583
|
bytesPerRow,
|
|
502
584
|
rowsPerImage
|
|
503
|
-
}, { width, height, depthOrArrayLayers });
|
|
585
|
+
}, { width: copyWidth, height: copyHeight, depthOrArrayLayers });
|
|
504
586
|
this.device.popErrorScope((error) => {
|
|
505
587
|
this.device.reportError(new Error(`${this} writeData: ${error.message}`), this)();
|
|
506
588
|
this.device.debug();
|
|
507
589
|
});
|
|
508
590
|
}
|
|
591
|
+
/**
|
|
592
|
+
* Internal-only hook for the cached CanvasContext/PresentationContext swapchain path.
|
|
593
|
+
* Rebinds this handle-backed texture wrapper to the current per-frame canvas texture
|
|
594
|
+
* without allocating a new luma.gl Texture or TextureView wrapper.
|
|
595
|
+
*/
|
|
596
|
+
_reinitialize(handle, props) {
|
|
597
|
+
const nextWidth = (props == null ? void 0 : props.width) ?? handle.width ?? this.width;
|
|
598
|
+
const nextHeight = (props == null ? void 0 : props.height) ?? handle.height ?? this.height;
|
|
599
|
+
const nextDepth = (props == null ? void 0 : props.depth) ?? this.depth;
|
|
600
|
+
const nextFormat = (props == null ? void 0 : props.format) ?? this.format;
|
|
601
|
+
const allocationMayHaveChanged = nextWidth !== this.width || nextHeight !== this.height || nextDepth !== this.depth || nextFormat !== this.format;
|
|
602
|
+
handle.label ||= this.id;
|
|
603
|
+
this.handle = handle;
|
|
604
|
+
this.width = nextWidth;
|
|
605
|
+
this.height = nextHeight;
|
|
606
|
+
if ((props == null ? void 0 : props.depth) !== void 0) {
|
|
607
|
+
this.depth = nextDepth;
|
|
608
|
+
}
|
|
609
|
+
if ((props == null ? void 0 : props.format) !== void 0) {
|
|
610
|
+
this.format = nextFormat;
|
|
611
|
+
}
|
|
612
|
+
this.props.handle = handle;
|
|
613
|
+
if ((props == null ? void 0 : props.width) !== void 0) {
|
|
614
|
+
this.props.width = props.width;
|
|
615
|
+
}
|
|
616
|
+
if ((props == null ? void 0 : props.height) !== void 0) {
|
|
617
|
+
this.props.height = props.height;
|
|
618
|
+
}
|
|
619
|
+
if ((props == null ? void 0 : props.depth) !== void 0) {
|
|
620
|
+
this.props.depth = props.depth;
|
|
621
|
+
}
|
|
622
|
+
if ((props == null ? void 0 : props.format) !== void 0) {
|
|
623
|
+
this.props.format = props.format;
|
|
624
|
+
}
|
|
625
|
+
if (allocationMayHaveChanged) {
|
|
626
|
+
const nextAllocation = this.getAllocatedByteLength();
|
|
627
|
+
if (nextAllocation !== this._allocatedByteLength) {
|
|
628
|
+
this._allocatedByteLength = nextAllocation;
|
|
629
|
+
this.trackReferencedMemory(nextAllocation, "Texture");
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
this.view._reinitialize(this);
|
|
633
|
+
}
|
|
509
634
|
};
|
|
510
635
|
}
|
|
511
636
|
});
|
|
@@ -819,14 +944,12 @@ var init_webgpu_parameters = __esm({
|
|
|
819
944
|
function getBindGroup(device, bindGroupLayout, shaderLayout, bindings) {
|
|
820
945
|
const entries = getBindGroupEntries(bindings, shaderLayout);
|
|
821
946
|
device.pushErrorScope("validation");
|
|
822
|
-
const bindGroup = device.createBindGroup({
|
|
947
|
+
const bindGroup = device.handle.createBindGroup({
|
|
823
948
|
layout: bindGroupLayout,
|
|
824
949
|
entries
|
|
825
950
|
});
|
|
826
|
-
device.popErrorScope(
|
|
827
|
-
|
|
828
|
-
import_core8.log.error(`bindGroup creation: ${error.message}`, bindGroup)();
|
|
829
|
-
}
|
|
951
|
+
device.popErrorScope((error) => {
|
|
952
|
+
import_core8.log.error(`bindGroup creation: ${error.message}`, bindGroup)();
|
|
830
953
|
});
|
|
831
954
|
return bindGroup;
|
|
832
955
|
}
|
|
@@ -840,21 +963,21 @@ function getShaderLayoutBinding(shaderLayout, bindingName, options) {
|
|
|
840
963
|
function getBindGroupEntries(bindings, shaderLayout) {
|
|
841
964
|
const entries = [];
|
|
842
965
|
for (const [bindingName, value] of Object.entries(bindings)) {
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
966
|
+
const exactBindingLayout = shaderLayout.bindings.find((binding) => binding.name === bindingName);
|
|
967
|
+
const bindingLayout = exactBindingLayout || getShaderLayoutBinding(shaderLayout, bindingName);
|
|
968
|
+
const isShadowedAlias = !exactBindingLayout && bindingLayout ? bindingLayout.name in bindings : false;
|
|
969
|
+
if (!isShadowedAlias) {
|
|
970
|
+
const entry = bindingLayout ? getBindGroupEntry(value, bindingLayout.location, void 0, bindingName) : null;
|
|
846
971
|
if (entry) {
|
|
847
972
|
entries.push(entry);
|
|
848
973
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
if (entry) {
|
|
857
|
-
entries.push(entry);
|
|
974
|
+
if (value instanceof import_core8.Texture) {
|
|
975
|
+
const samplerBindingLayout = getShaderLayoutBinding(shaderLayout, `${bindingName}Sampler`, {
|
|
976
|
+
ignoreWarnings: true
|
|
977
|
+
});
|
|
978
|
+
const samplerEntry = samplerBindingLayout ? getBindGroupEntry(value, samplerBindingLayout.location, { sampler: true }, bindingName) : null;
|
|
979
|
+
if (samplerEntry) {
|
|
980
|
+
entries.push(samplerEntry);
|
|
858
981
|
}
|
|
859
982
|
}
|
|
860
983
|
}
|
|
@@ -999,7 +1122,7 @@ var init_get_vertex_buffer_layout = __esm({
|
|
|
999
1122
|
});
|
|
1000
1123
|
|
|
1001
1124
|
// dist/adapter/resources/webgpu-render-pipeline.js
|
|
1002
|
-
var import_core10, WebGPURenderPipeline;
|
|
1125
|
+
var import_core10, EMPTY_BINDINGS, WebGPURenderPipeline;
|
|
1003
1126
|
var init_webgpu_render_pipeline = __esm({
|
|
1004
1127
|
"dist/adapter/resources/webgpu-render-pipeline.js"() {
|
|
1005
1128
|
"use strict";
|
|
@@ -1008,13 +1131,15 @@ var init_webgpu_render_pipeline = __esm({
|
|
|
1008
1131
|
init_convert_texture_format();
|
|
1009
1132
|
init_get_bind_group();
|
|
1010
1133
|
init_get_vertex_buffer_layout();
|
|
1134
|
+
EMPTY_BINDINGS = {};
|
|
1011
1135
|
WebGPURenderPipeline = class extends import_core10.RenderPipeline {
|
|
1012
1136
|
device;
|
|
1013
1137
|
handle;
|
|
1014
1138
|
vs;
|
|
1015
1139
|
fs = null;
|
|
1016
|
-
/**
|
|
1140
|
+
/** Compatibility path for direct pipeline.setBindings() usage */
|
|
1017
1141
|
_bindings;
|
|
1142
|
+
/** For internal use to create BindGroups */
|
|
1018
1143
|
_bindGroupLayout = null;
|
|
1019
1144
|
_bindGroup = null;
|
|
1020
1145
|
get [Symbol.toStringTag]() {
|
|
@@ -1040,26 +1165,36 @@ var init_webgpu_render_pipeline = __esm({
|
|
|
1040
1165
|
this.handle.label = this.props.id;
|
|
1041
1166
|
this.vs = props.vs;
|
|
1042
1167
|
this.fs = props.fs;
|
|
1043
|
-
this._bindings =
|
|
1168
|
+
this._bindings = props.bindings || EMPTY_BINDINGS;
|
|
1044
1169
|
}
|
|
1045
1170
|
destroy() {
|
|
1046
1171
|
this.handle = null;
|
|
1047
1172
|
}
|
|
1048
1173
|
/**
|
|
1049
|
-
*
|
|
1050
|
-
*
|
|
1174
|
+
* Compatibility shim for code paths that still set bindings on the pipeline.
|
|
1175
|
+
* The shared-model path passes bindings per draw and does not rely on this state.
|
|
1051
1176
|
*/
|
|
1052
1177
|
setBindings(bindings) {
|
|
1178
|
+
let bindingsChanged = false;
|
|
1053
1179
|
for (const [name, binding] of Object.entries(bindings)) {
|
|
1054
1180
|
if (this._bindings[name] !== binding) {
|
|
1055
|
-
|
|
1181
|
+
if (!bindingsChanged) {
|
|
1182
|
+
if (this._bindings === this.props.bindings || this._bindings === EMPTY_BINDINGS) {
|
|
1183
|
+
this._bindings = { ...this._bindings };
|
|
1184
|
+
}
|
|
1185
|
+
bindingsChanged = true;
|
|
1186
|
+
}
|
|
1187
|
+
this._bindings[name] = binding;
|
|
1056
1188
|
}
|
|
1057
1189
|
}
|
|
1058
|
-
|
|
1190
|
+
if (bindingsChanged) {
|
|
1191
|
+
this._bindGroup = null;
|
|
1192
|
+
}
|
|
1059
1193
|
}
|
|
1060
1194
|
/** @todo - should this be moved to renderpass? */
|
|
1061
1195
|
draw(options) {
|
|
1062
1196
|
const webgpuRenderPass = options.renderPass;
|
|
1197
|
+
const instanceCount = options.instanceCount && options.instanceCount > 0 ? options.instanceCount : 1;
|
|
1063
1198
|
this.device.pushErrorScope("validation");
|
|
1064
1199
|
webgpuRenderPass.handle.setPipeline(this.handle);
|
|
1065
1200
|
this.device.popErrorScope((error) => {
|
|
@@ -1067,31 +1202,29 @@ var init_webgpu_render_pipeline = __esm({
|
|
|
1067
1202
|
"${error.message}"`), this)();
|
|
1068
1203
|
this.device.debug();
|
|
1069
1204
|
});
|
|
1070
|
-
const bindGroup = this._getBindGroup();
|
|
1205
|
+
const bindGroup = this._getBindGroup(options.bindings);
|
|
1071
1206
|
if (bindGroup) {
|
|
1072
1207
|
webgpuRenderPass.handle.setBindGroup(0, bindGroup);
|
|
1073
1208
|
}
|
|
1074
1209
|
options.vertexArray.bindBeforeRender(options.renderPass);
|
|
1075
1210
|
if (options.indexCount) {
|
|
1076
|
-
webgpuRenderPass.handle.drawIndexed(options.indexCount,
|
|
1211
|
+
webgpuRenderPass.handle.drawIndexed(options.indexCount, instanceCount, options.firstIndex || 0, options.baseVertex || 0, options.firstInstance || 0);
|
|
1077
1212
|
} else {
|
|
1078
|
-
webgpuRenderPass.handle.draw(
|
|
1079
|
-
options.vertexCount || 0,
|
|
1080
|
-
options.instanceCount || 1,
|
|
1081
|
-
// If 0, nothing will be drawn
|
|
1082
|
-
options.firstInstance
|
|
1083
|
-
);
|
|
1213
|
+
webgpuRenderPass.handle.draw(options.vertexCount || 0, instanceCount, options.firstVertex || 0, options.firstInstance || 0);
|
|
1084
1214
|
}
|
|
1085
1215
|
options.vertexArray.unbindAfterRender(options.renderPass);
|
|
1086
1216
|
return true;
|
|
1087
1217
|
}
|
|
1088
1218
|
/** Return a bind group created by setBindings */
|
|
1089
|
-
_getBindGroup() {
|
|
1219
|
+
_getBindGroup(bindings) {
|
|
1090
1220
|
if (this.shaderLayout.bindings.length === 0) {
|
|
1091
1221
|
return null;
|
|
1092
1222
|
}
|
|
1093
1223
|
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
1094
|
-
|
|
1224
|
+
if (bindings) {
|
|
1225
|
+
return getBindGroup(this.device, this._bindGroupLayout, this.shaderLayout, bindings);
|
|
1226
|
+
}
|
|
1227
|
+
this._bindGroup = this._bindGroup || getBindGroup(this.device, this._bindGroupLayout, this.shaderLayout, this._bindings);
|
|
1095
1228
|
return this._bindGroup;
|
|
1096
1229
|
}
|
|
1097
1230
|
/**
|
|
@@ -1158,17 +1291,33 @@ var init_webgpu_framebuffer = __esm({
|
|
|
1158
1291
|
}
|
|
1159
1292
|
updateAttachments() {
|
|
1160
1293
|
}
|
|
1294
|
+
/**
|
|
1295
|
+
* Internal-only hook for the cached CanvasContext/PresentationContext swapchain path.
|
|
1296
|
+
* Rebinds the long-lived default framebuffer wrapper to the current per-frame color view
|
|
1297
|
+
* and optional depth attachment without allocating a new luma.gl Framebuffer object.
|
|
1298
|
+
*/
|
|
1299
|
+
_reinitialize(colorAttachment, depthStencilAttachment) {
|
|
1300
|
+
this.colorAttachments[0] = colorAttachment;
|
|
1301
|
+
this.depthStencilAttachment = depthStencilAttachment;
|
|
1302
|
+
this.width = colorAttachment.texture.width;
|
|
1303
|
+
this.height = colorAttachment.texture.height;
|
|
1304
|
+
this.props.width = this.width;
|
|
1305
|
+
this.props.height = this.height;
|
|
1306
|
+
this.props.colorAttachments = [colorAttachment.texture];
|
|
1307
|
+
this.props.depthStencilAttachment = (depthStencilAttachment == null ? void 0 : depthStencilAttachment.texture) || null;
|
|
1308
|
+
}
|
|
1161
1309
|
};
|
|
1162
1310
|
}
|
|
1163
1311
|
});
|
|
1164
1312
|
|
|
1165
1313
|
// dist/adapter/resources/webgpu-compute-pipeline.js
|
|
1166
|
-
var import_core12, WebGPUComputePipeline;
|
|
1314
|
+
var import_core12, EMPTY_BINDINGS2, WebGPUComputePipeline;
|
|
1167
1315
|
var init_webgpu_compute_pipeline = __esm({
|
|
1168
1316
|
"dist/adapter/resources/webgpu-compute-pipeline.js"() {
|
|
1169
1317
|
"use strict";
|
|
1170
1318
|
import_core12 = require("@luma.gl/core");
|
|
1171
1319
|
init_get_bind_group();
|
|
1320
|
+
EMPTY_BINDINGS2 = {};
|
|
1172
1321
|
WebGPUComputePipeline = class extends import_core12.ComputePipeline {
|
|
1173
1322
|
device;
|
|
1174
1323
|
handle;
|
|
@@ -1176,7 +1325,7 @@ var init_webgpu_compute_pipeline = __esm({
|
|
|
1176
1325
|
_bindGroupLayout = null;
|
|
1177
1326
|
_bindGroup = null;
|
|
1178
1327
|
/** For internal use to create BindGroups */
|
|
1179
|
-
_bindings
|
|
1328
|
+
_bindings;
|
|
1180
1329
|
constructor(device, props) {
|
|
1181
1330
|
super(device, props);
|
|
1182
1331
|
this.device = device;
|
|
@@ -1190,18 +1339,33 @@ var init_webgpu_compute_pipeline = __esm({
|
|
|
1190
1339
|
},
|
|
1191
1340
|
layout: "auto"
|
|
1192
1341
|
});
|
|
1342
|
+
this._bindings = EMPTY_BINDINGS2;
|
|
1193
1343
|
}
|
|
1194
1344
|
/**
|
|
1195
1345
|
* @todo Use renderpass.setBindings() ?
|
|
1196
1346
|
* @todo Do we want to expose BindGroups in the API and remove this?
|
|
1197
1347
|
*/
|
|
1198
1348
|
setBindings(bindings) {
|
|
1199
|
-
|
|
1349
|
+
let bindingsChanged = false;
|
|
1350
|
+
for (const [name, binding] of Object.entries(bindings)) {
|
|
1351
|
+
if (this._bindings[name] !== binding) {
|
|
1352
|
+
if (!bindingsChanged) {
|
|
1353
|
+
if (this._bindings === EMPTY_BINDINGS2) {
|
|
1354
|
+
this._bindings = {};
|
|
1355
|
+
}
|
|
1356
|
+
bindingsChanged = true;
|
|
1357
|
+
}
|
|
1358
|
+
this._bindings[name] = binding;
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
if (bindingsChanged) {
|
|
1362
|
+
this._bindGroup = null;
|
|
1363
|
+
}
|
|
1200
1364
|
}
|
|
1201
1365
|
/** Return a bind group created by setBindings */
|
|
1202
1366
|
_getBindGroup() {
|
|
1203
1367
|
this._bindGroupLayout = this._bindGroupLayout || this.handle.getBindGroupLayout(0);
|
|
1204
|
-
this._bindGroup = this._bindGroup || getBindGroup(this.device
|
|
1368
|
+
this._bindGroup = this._bindGroup || getBindGroup(this.device, this._bindGroupLayout, this.shaderLayout, this._bindings);
|
|
1205
1369
|
return this._bindGroup;
|
|
1206
1370
|
}
|
|
1207
1371
|
};
|
|
@@ -1217,7 +1381,7 @@ var init_webgpu_vertex_array = __esm({
|
|
|
1217
1381
|
import_env = require("@probe.gl/env");
|
|
1218
1382
|
WebGPUVertexArray = class extends import_core13.VertexArray {
|
|
1219
1383
|
get [Symbol.toStringTag]() {
|
|
1220
|
-
return "
|
|
1384
|
+
return "VertexArray";
|
|
1221
1385
|
}
|
|
1222
1386
|
device;
|
|
1223
1387
|
/** Vertex Array is just a helper class under WebGPU */
|
|
@@ -1280,10 +1444,13 @@ var init_webgpu_canvas_context = __esm({
|
|
|
1280
1444
|
"use strict";
|
|
1281
1445
|
import_core14 = require("@luma.gl/core");
|
|
1282
1446
|
init_webgpu_framebuffer();
|
|
1447
|
+
init_cpu_hotspot_profiler();
|
|
1283
1448
|
WebGPUCanvasContext = class extends import_core14.CanvasContext {
|
|
1284
1449
|
device;
|
|
1285
1450
|
handle;
|
|
1451
|
+
colorAttachment = null;
|
|
1286
1452
|
depthStencilAttachment = null;
|
|
1453
|
+
framebuffer = null;
|
|
1287
1454
|
get [Symbol.toStringTag]() {
|
|
1288
1455
|
return "WebGPUCanvasContext";
|
|
1289
1456
|
}
|
|
@@ -1297,9 +1464,22 @@ var init_webgpu_canvas_context = __esm({
|
|
|
1297
1464
|
this.handle = context;
|
|
1298
1465
|
this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
|
|
1299
1466
|
this._configureDevice();
|
|
1467
|
+
this._startObservers();
|
|
1300
1468
|
}
|
|
1301
1469
|
/** Destroy any textures produced while configured and remove the context configuration. */
|
|
1302
1470
|
destroy() {
|
|
1471
|
+
if (this.framebuffer) {
|
|
1472
|
+
this.framebuffer.destroy();
|
|
1473
|
+
this.framebuffer = null;
|
|
1474
|
+
}
|
|
1475
|
+
if (this.colorAttachment) {
|
|
1476
|
+
this.colorAttachment.destroy();
|
|
1477
|
+
this.colorAttachment = null;
|
|
1478
|
+
}
|
|
1479
|
+
if (this.depthStencilAttachment) {
|
|
1480
|
+
this.depthStencilAttachment.destroy();
|
|
1481
|
+
this.depthStencilAttachment = null;
|
|
1482
|
+
}
|
|
1303
1483
|
this.handle.unconfigure();
|
|
1304
1484
|
super.destroy();
|
|
1305
1485
|
}
|
|
@@ -1318,41 +1498,78 @@ var init_webgpu_canvas_context = __esm({
|
|
|
1318
1498
|
colorSpace: this.props.colorSpace,
|
|
1319
1499
|
alphaMode: this.props.alphaMode
|
|
1320
1500
|
});
|
|
1501
|
+
this._createDepthStencilAttachment(this.device.preferredDepthFormat);
|
|
1321
1502
|
}
|
|
1322
1503
|
/** Update framebuffer with properly resized "swap chain" texture views */
|
|
1323
1504
|
_getCurrentFramebuffer(options = {
|
|
1324
1505
|
depthStencilFormat: "depth24plus"
|
|
1325
1506
|
}) {
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1507
|
+
var _a;
|
|
1508
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
1509
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
1510
|
+
if (profiler) {
|
|
1511
|
+
profiler.framebufferAcquireCount = (profiler.framebufferAcquireCount || 0) + 1;
|
|
1512
|
+
profiler.activeDefaultFramebufferAcquireDepth = (profiler.activeDefaultFramebufferAcquireDepth || 0) + 1;
|
|
1513
|
+
}
|
|
1514
|
+
try {
|
|
1515
|
+
const currentColorAttachment = this._getCurrentTexture();
|
|
1516
|
+
if (currentColorAttachment.width !== this.drawingBufferWidth || currentColorAttachment.height !== this.drawingBufferHeight) {
|
|
1517
|
+
const [oldWidth, oldHeight] = this.getDrawingBufferSize();
|
|
1518
|
+
this.drawingBufferWidth = currentColorAttachment.width;
|
|
1519
|
+
this.drawingBufferHeight = currentColorAttachment.height;
|
|
1520
|
+
import_core14.log.log(1, `${this}: Resized to compensate for initial canvas size mismatch ${oldWidth}x${oldHeight} => ${this.drawingBufferWidth}x${this.drawingBufferHeight}px`)();
|
|
1521
|
+
}
|
|
1522
|
+
if (options == null ? void 0 : options.depthStencilFormat) {
|
|
1523
|
+
this._createDepthStencilAttachment(options == null ? void 0 : options.depthStencilFormat);
|
|
1524
|
+
}
|
|
1525
|
+
this.framebuffer ||= new WebGPUFramebuffer(this.device, {
|
|
1526
|
+
id: `${this.id}#framebuffer`,
|
|
1527
|
+
colorAttachments: [currentColorAttachment],
|
|
1528
|
+
depthStencilAttachment: null
|
|
1529
|
+
});
|
|
1530
|
+
this.framebuffer._reinitialize(currentColorAttachment.view, (options == null ? void 0 : options.depthStencilFormat) ? ((_a = this.depthStencilAttachment) == null ? void 0 : _a.view) || null : null);
|
|
1531
|
+
return this.framebuffer;
|
|
1532
|
+
} finally {
|
|
1533
|
+
if (profiler) {
|
|
1534
|
+
profiler.activeDefaultFramebufferAcquireDepth = (profiler.activeDefaultFramebufferAcquireDepth || 1) - 1;
|
|
1535
|
+
profiler.framebufferAcquireTimeMs = (profiler.framebufferAcquireTimeMs || 0) + (getTimestamp() - startTime);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1340
1538
|
}
|
|
1341
1539
|
// PRIMARY METHODS
|
|
1342
1540
|
/** Wrap the current canvas context texture in a luma.gl texture */
|
|
1343
1541
|
_getCurrentTexture() {
|
|
1542
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
1543
|
+
const currentTextureStartTime = profiler ? getTimestamp() : 0;
|
|
1344
1544
|
const handle = this.handle.getCurrentTexture();
|
|
1345
|
-
|
|
1346
|
-
|
|
1545
|
+
if (profiler) {
|
|
1546
|
+
profiler.currentTextureAcquireCount = (profiler.currentTextureAcquireCount || 0) + 1;
|
|
1547
|
+
profiler.currentTextureAcquireTimeMs = (profiler.currentTextureAcquireTimeMs || 0) + (getTimestamp() - currentTextureStartTime);
|
|
1548
|
+
}
|
|
1549
|
+
if (!this.colorAttachment) {
|
|
1550
|
+
this.colorAttachment = this.device.createTexture({
|
|
1551
|
+
id: `${this.id}#color-texture`,
|
|
1552
|
+
handle,
|
|
1553
|
+
format: this.device.preferredColorFormat,
|
|
1554
|
+
width: handle.width,
|
|
1555
|
+
height: handle.height
|
|
1556
|
+
});
|
|
1557
|
+
return this.colorAttachment;
|
|
1558
|
+
}
|
|
1559
|
+
this.colorAttachment._reinitialize(handle, {
|
|
1347
1560
|
handle,
|
|
1348
1561
|
format: this.device.preferredColorFormat,
|
|
1349
1562
|
width: handle.width,
|
|
1350
1563
|
height: handle.height
|
|
1351
1564
|
});
|
|
1565
|
+
return this.colorAttachment;
|
|
1352
1566
|
}
|
|
1353
1567
|
/** We build render targets on demand (i.e. not when size changes but when about to render) */
|
|
1354
1568
|
_createDepthStencilAttachment(depthStencilFormat) {
|
|
1355
|
-
|
|
1569
|
+
var _a;
|
|
1570
|
+
const needsNewDepthStencilAttachment = !this.depthStencilAttachment || this.depthStencilAttachment.width !== this.drawingBufferWidth || this.depthStencilAttachment.height !== this.drawingBufferHeight || this.depthStencilAttachment.format !== depthStencilFormat;
|
|
1571
|
+
if (needsNewDepthStencilAttachment) {
|
|
1572
|
+
(_a = this.depthStencilAttachment) == null ? void 0 : _a.destroy();
|
|
1356
1573
|
this.depthStencilAttachment = this.device.createTexture({
|
|
1357
1574
|
id: `${this.id}#depth-stencil-texture`,
|
|
1358
1575
|
usage: import_core14.Texture.RENDER_ATTACHMENT,
|
|
@@ -1367,17 +1584,157 @@ var init_webgpu_canvas_context = __esm({
|
|
|
1367
1584
|
}
|
|
1368
1585
|
});
|
|
1369
1586
|
|
|
1587
|
+
// dist/adapter/webgpu-presentation-context.js
|
|
1588
|
+
var import_core15, WebGPUPresentationContext;
|
|
1589
|
+
var init_webgpu_presentation_context = __esm({
|
|
1590
|
+
"dist/adapter/webgpu-presentation-context.js"() {
|
|
1591
|
+
"use strict";
|
|
1592
|
+
import_core15 = require("@luma.gl/core");
|
|
1593
|
+
init_webgpu_framebuffer();
|
|
1594
|
+
init_cpu_hotspot_profiler();
|
|
1595
|
+
WebGPUPresentationContext = class extends import_core15.PresentationContext {
|
|
1596
|
+
device;
|
|
1597
|
+
handle;
|
|
1598
|
+
colorAttachment = null;
|
|
1599
|
+
depthStencilAttachment = null;
|
|
1600
|
+
framebuffer = null;
|
|
1601
|
+
get [Symbol.toStringTag]() {
|
|
1602
|
+
return "WebGPUPresentationContext";
|
|
1603
|
+
}
|
|
1604
|
+
constructor(device, props = {}) {
|
|
1605
|
+
super(props);
|
|
1606
|
+
const contextLabel = `${this[Symbol.toStringTag]}(${this.id})`;
|
|
1607
|
+
const context = this.canvas.getContext("webgpu");
|
|
1608
|
+
if (!context) {
|
|
1609
|
+
throw new Error(`${contextLabel}: Failed to create WebGPU presentation context`);
|
|
1610
|
+
}
|
|
1611
|
+
this.device = device;
|
|
1612
|
+
this.handle = context;
|
|
1613
|
+
this._setAutoCreatedCanvasId(`${this.device.id}-presentation-canvas`);
|
|
1614
|
+
this._configureDevice();
|
|
1615
|
+
this._startObservers();
|
|
1616
|
+
}
|
|
1617
|
+
destroy() {
|
|
1618
|
+
if (this.framebuffer) {
|
|
1619
|
+
this.framebuffer.destroy();
|
|
1620
|
+
this.framebuffer = null;
|
|
1621
|
+
}
|
|
1622
|
+
if (this.colorAttachment) {
|
|
1623
|
+
this.colorAttachment.destroy();
|
|
1624
|
+
this.colorAttachment = null;
|
|
1625
|
+
}
|
|
1626
|
+
if (this.depthStencilAttachment) {
|
|
1627
|
+
this.depthStencilAttachment.destroy();
|
|
1628
|
+
this.depthStencilAttachment = null;
|
|
1629
|
+
}
|
|
1630
|
+
this.handle.unconfigure();
|
|
1631
|
+
super.destroy();
|
|
1632
|
+
}
|
|
1633
|
+
present() {
|
|
1634
|
+
this.device.submit();
|
|
1635
|
+
}
|
|
1636
|
+
_configureDevice() {
|
|
1637
|
+
if (this.depthStencilAttachment) {
|
|
1638
|
+
this.depthStencilAttachment.destroy();
|
|
1639
|
+
this.depthStencilAttachment = null;
|
|
1640
|
+
}
|
|
1641
|
+
this.handle.configure({
|
|
1642
|
+
device: this.device.handle,
|
|
1643
|
+
format: this.device.preferredColorFormat,
|
|
1644
|
+
colorSpace: this.props.colorSpace,
|
|
1645
|
+
alphaMode: this.props.alphaMode
|
|
1646
|
+
});
|
|
1647
|
+
this._createDepthStencilAttachment(this.device.preferredDepthFormat);
|
|
1648
|
+
}
|
|
1649
|
+
_getCurrentFramebuffer(options = {
|
|
1650
|
+
depthStencilFormat: "depth24plus"
|
|
1651
|
+
}) {
|
|
1652
|
+
var _a;
|
|
1653
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
1654
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
1655
|
+
if (profiler) {
|
|
1656
|
+
profiler.framebufferAcquireCount = (profiler.framebufferAcquireCount || 0) + 1;
|
|
1657
|
+
}
|
|
1658
|
+
try {
|
|
1659
|
+
const currentColorAttachment = this._getCurrentTexture();
|
|
1660
|
+
if (currentColorAttachment.width !== this.drawingBufferWidth || currentColorAttachment.height !== this.drawingBufferHeight) {
|
|
1661
|
+
const [oldWidth, oldHeight] = this.getDrawingBufferSize();
|
|
1662
|
+
this.drawingBufferWidth = currentColorAttachment.width;
|
|
1663
|
+
this.drawingBufferHeight = currentColorAttachment.height;
|
|
1664
|
+
import_core15.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`)();
|
|
1665
|
+
}
|
|
1666
|
+
if (options == null ? void 0 : options.depthStencilFormat) {
|
|
1667
|
+
this._createDepthStencilAttachment(options.depthStencilFormat);
|
|
1668
|
+
}
|
|
1669
|
+
this.framebuffer ||= new WebGPUFramebuffer(this.device, {
|
|
1670
|
+
id: `${this.id}#framebuffer`,
|
|
1671
|
+
colorAttachments: [currentColorAttachment],
|
|
1672
|
+
depthStencilAttachment: null
|
|
1673
|
+
});
|
|
1674
|
+
this.framebuffer._reinitialize(currentColorAttachment.view, (options == null ? void 0 : options.depthStencilFormat) ? ((_a = this.depthStencilAttachment) == null ? void 0 : _a.view) || null : null);
|
|
1675
|
+
return this.framebuffer;
|
|
1676
|
+
} finally {
|
|
1677
|
+
if (profiler) {
|
|
1678
|
+
profiler.framebufferAcquireTimeMs = (profiler.framebufferAcquireTimeMs || 0) + (getTimestamp() - startTime);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
_getCurrentTexture() {
|
|
1683
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
1684
|
+
const currentTextureStartTime = profiler ? getTimestamp() : 0;
|
|
1685
|
+
const handle = this.handle.getCurrentTexture();
|
|
1686
|
+
if (profiler) {
|
|
1687
|
+
profiler.currentTextureAcquireCount = (profiler.currentTextureAcquireCount || 0) + 1;
|
|
1688
|
+
profiler.currentTextureAcquireTimeMs = (profiler.currentTextureAcquireTimeMs || 0) + (getTimestamp() - currentTextureStartTime);
|
|
1689
|
+
}
|
|
1690
|
+
if (!this.colorAttachment) {
|
|
1691
|
+
this.colorAttachment = this.device.createTexture({
|
|
1692
|
+
id: `${this.id}#color-texture`,
|
|
1693
|
+
handle,
|
|
1694
|
+
format: this.device.preferredColorFormat,
|
|
1695
|
+
width: handle.width,
|
|
1696
|
+
height: handle.height
|
|
1697
|
+
});
|
|
1698
|
+
return this.colorAttachment;
|
|
1699
|
+
}
|
|
1700
|
+
this.colorAttachment._reinitialize(handle, {
|
|
1701
|
+
handle,
|
|
1702
|
+
format: this.device.preferredColorFormat,
|
|
1703
|
+
width: handle.width,
|
|
1704
|
+
height: handle.height
|
|
1705
|
+
});
|
|
1706
|
+
return this.colorAttachment;
|
|
1707
|
+
}
|
|
1708
|
+
_createDepthStencilAttachment(depthStencilFormat) {
|
|
1709
|
+
var _a;
|
|
1710
|
+
const needsNewDepthStencilAttachment = !this.depthStencilAttachment || this.depthStencilAttachment.width !== this.drawingBufferWidth || this.depthStencilAttachment.height !== this.drawingBufferHeight || this.depthStencilAttachment.format !== depthStencilFormat;
|
|
1711
|
+
if (needsNewDepthStencilAttachment) {
|
|
1712
|
+
(_a = this.depthStencilAttachment) == null ? void 0 : _a.destroy();
|
|
1713
|
+
this.depthStencilAttachment = this.device.createTexture({
|
|
1714
|
+
id: `${this.id}#depth-stencil-texture`,
|
|
1715
|
+
usage: import_core15.Texture.RENDER_ATTACHMENT,
|
|
1716
|
+
format: depthStencilFormat,
|
|
1717
|
+
width: this.drawingBufferWidth,
|
|
1718
|
+
height: this.drawingBufferHeight
|
|
1719
|
+
});
|
|
1720
|
+
}
|
|
1721
|
+
return this.depthStencilAttachment;
|
|
1722
|
+
}
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
});
|
|
1726
|
+
|
|
1370
1727
|
// dist/adapter/resources/webgpu-command-buffer.js
|
|
1371
|
-
var
|
|
1728
|
+
var import_core16, WebGPUCommandBuffer;
|
|
1372
1729
|
var init_webgpu_command_buffer = __esm({
|
|
1373
1730
|
"dist/adapter/resources/webgpu-command-buffer.js"() {
|
|
1374
1731
|
"use strict";
|
|
1375
|
-
|
|
1376
|
-
WebGPUCommandBuffer = class extends
|
|
1732
|
+
import_core16 = require("@luma.gl/core");
|
|
1733
|
+
WebGPUCommandBuffer = class extends import_core16.CommandBuffer {
|
|
1377
1734
|
device;
|
|
1378
1735
|
handle;
|
|
1379
1736
|
constructor(commandEncoder, props) {
|
|
1380
|
-
super(commandEncoder.device,
|
|
1737
|
+
super(commandEncoder.device, props);
|
|
1381
1738
|
this.device = commandEncoder.device;
|
|
1382
1739
|
this.handle = this.props.handle || commandEncoder.handle.finish({
|
|
1383
1740
|
label: (props == null ? void 0 : props.id) || "unnamed-command-buffer"
|
|
@@ -1391,52 +1748,85 @@ var init_webgpu_command_buffer = __esm({
|
|
|
1391
1748
|
function convertColor(color) {
|
|
1392
1749
|
return { r: color[0], g: color[1], b: color[2], a: color[3] };
|
|
1393
1750
|
}
|
|
1394
|
-
var
|
|
1751
|
+
var import_core17, WebGPURenderPass;
|
|
1395
1752
|
var init_webgpu_render_pass = __esm({
|
|
1396
1753
|
"dist/adapter/resources/webgpu-render-pass.js"() {
|
|
1397
1754
|
"use strict";
|
|
1398
|
-
|
|
1399
|
-
|
|
1755
|
+
import_core17 = require("@luma.gl/core");
|
|
1756
|
+
init_cpu_hotspot_profiler();
|
|
1757
|
+
WebGPURenderPass = class extends import_core17.RenderPass {
|
|
1400
1758
|
device;
|
|
1401
1759
|
handle;
|
|
1760
|
+
framebuffer;
|
|
1402
1761
|
/** Active pipeline */
|
|
1403
1762
|
pipeline = null;
|
|
1763
|
+
/** Latest bindings applied to this pass */
|
|
1764
|
+
bindings = {};
|
|
1404
1765
|
constructor(device, props = {}) {
|
|
1405
1766
|
super(device, props);
|
|
1406
1767
|
this.device = device;
|
|
1407
|
-
const
|
|
1408
|
-
|
|
1409
|
-
const
|
|
1410
|
-
if (
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
if (device.features.has("timestamp-query")) {
|
|
1414
|
-
const webgpuTSQuerySet = props.timestampQuerySet;
|
|
1415
|
-
renderPassDescriptor.timestampWrites = webgpuTSQuerySet ? {
|
|
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");
|
|
1768
|
+
const { props: renderPassProps } = this;
|
|
1769
|
+
this.framebuffer = renderPassProps.framebuffer || device.getCanvasContext().getCurrentFramebuffer();
|
|
1770
|
+
const profiler = getCpuHotspotProfiler(this.device);
|
|
1771
|
+
if (profiler) {
|
|
1772
|
+
const counterName = renderPassProps.framebuffer ? "explicitFramebufferRenderPassCount" : "defaultFramebufferRenderPassCount";
|
|
1773
|
+
profiler[counterName] = (profiler[counterName] || 0) + 1;
|
|
1423
1774
|
}
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
this.
|
|
1775
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
1776
|
+
try {
|
|
1777
|
+
const descriptorAssemblyStartTime = profiler ? getTimestamp() : 0;
|
|
1778
|
+
const renderPassDescriptor = this.getRenderPassDescriptor(this.framebuffer);
|
|
1779
|
+
if (renderPassProps.occlusionQuerySet) {
|
|
1780
|
+
renderPassDescriptor.occlusionQuerySet = renderPassProps.occlusionQuerySet.handle;
|
|
1781
|
+
}
|
|
1782
|
+
if (renderPassProps.timestampQuerySet) {
|
|
1783
|
+
const webgpuTSQuerySet = renderPassProps.timestampQuerySet;
|
|
1784
|
+
webgpuTSQuerySet == null ? void 0 : webgpuTSQuerySet._invalidateResults();
|
|
1785
|
+
renderPassDescriptor.timestampWrites = webgpuTSQuerySet ? {
|
|
1786
|
+
querySet: webgpuTSQuerySet.handle,
|
|
1787
|
+
beginningOfPassWriteIndex: renderPassProps.beginTimestampIndex,
|
|
1788
|
+
endOfPassWriteIndex: renderPassProps.endTimestampIndex
|
|
1789
|
+
} : void 0;
|
|
1790
|
+
}
|
|
1791
|
+
if (profiler) {
|
|
1792
|
+
profiler.renderPassDescriptorAssemblyCount = (profiler.renderPassDescriptorAssemblyCount || 0) + 1;
|
|
1793
|
+
profiler.renderPassDescriptorAssemblyTimeMs = (profiler.renderPassDescriptorAssemblyTimeMs || 0) + (getTimestamp() - descriptorAssemblyStartTime);
|
|
1794
|
+
}
|
|
1795
|
+
if (!device.commandEncoder) {
|
|
1796
|
+
throw new Error("commandEncoder not available");
|
|
1797
|
+
}
|
|
1798
|
+
this.device.pushErrorScope("validation");
|
|
1799
|
+
const beginRenderPassStartTime = profiler ? getTimestamp() : 0;
|
|
1800
|
+
this.handle = this.props.handle || device.commandEncoder.handle.beginRenderPass(renderPassDescriptor);
|
|
1801
|
+
if (profiler) {
|
|
1802
|
+
profiler.renderPassBeginCount = (profiler.renderPassBeginCount || 0) + 1;
|
|
1803
|
+
profiler.renderPassBeginTimeMs = (profiler.renderPassBeginTimeMs || 0) + (getTimestamp() - beginRenderPassStartTime);
|
|
1804
|
+
}
|
|
1805
|
+
this.device.popErrorScope((error) => {
|
|
1806
|
+
this.device.reportError(new Error(`${this} creation failed:
|
|
1428
1807
|
"${error.message}"`), this)();
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1808
|
+
this.device.debug();
|
|
1809
|
+
});
|
|
1810
|
+
this.handle.label = this.props.id;
|
|
1811
|
+
import_core17.log.groupCollapsed(3, `new WebGPURenderPass(${this.id})`)();
|
|
1812
|
+
import_core17.log.probe(3, JSON.stringify(renderPassDescriptor, null, 2))();
|
|
1813
|
+
import_core17.log.groupEnd(3)();
|
|
1814
|
+
} finally {
|
|
1815
|
+
if (profiler) {
|
|
1816
|
+
profiler.renderPassSetupCount = (profiler.renderPassSetupCount || 0) + 1;
|
|
1817
|
+
profiler.renderPassSetupTimeMs = (profiler.renderPassSetupTimeMs || 0) + (getTimestamp() - startTime);
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1435
1820
|
}
|
|
1436
1821
|
destroy() {
|
|
1822
|
+
this.destroyResource();
|
|
1437
1823
|
}
|
|
1438
1824
|
end() {
|
|
1825
|
+
if (this.destroyed) {
|
|
1826
|
+
return;
|
|
1827
|
+
}
|
|
1439
1828
|
this.handle.end();
|
|
1829
|
+
this.destroy();
|
|
1440
1830
|
}
|
|
1441
1831
|
setPipeline(pipeline) {
|
|
1442
1832
|
this.pipeline = pipeline;
|
|
@@ -1450,9 +1840,9 @@ var init_webgpu_render_pass = __esm({
|
|
|
1450
1840
|
}
|
|
1451
1841
|
/** Sets an array of bindings (uniform buffers, samplers, textures, ...) */
|
|
1452
1842
|
setBindings(bindings) {
|
|
1453
|
-
var _a
|
|
1454
|
-
|
|
1455
|
-
const bindGroup = (
|
|
1843
|
+
var _a;
|
|
1844
|
+
this.bindings = bindings;
|
|
1845
|
+
const bindGroup = (_a = this.pipeline) == null ? void 0 : _a._getBindGroup(bindings);
|
|
1456
1846
|
if (bindGroup) {
|
|
1457
1847
|
this.handle.setBindGroup(0, bindGroup);
|
|
1458
1848
|
}
|
|
@@ -1517,7 +1907,7 @@ var init_webgpu_render_pass = __esm({
|
|
|
1517
1907
|
return {
|
|
1518
1908
|
// clear values
|
|
1519
1909
|
loadOp: this.props.clearColor !== false ? "clear" : "load",
|
|
1520
|
-
clearValue: convertColor(((_a = this.props.clearColors) == null ? void 0 : _a[index]) || this.props.clearColor ||
|
|
1910
|
+
clearValue: convertColor(((_a = this.props.clearColors) == null ? void 0 : _a[index]) || this.props.clearColor || import_core17.RenderPass.defaultClearColor),
|
|
1521
1911
|
storeOp: this.props.discard ? "discard" : "store",
|
|
1522
1912
|
// ...colorAttachment,
|
|
1523
1913
|
view: colorAttachment.handle
|
|
@@ -1552,26 +1942,28 @@ var init_webgpu_render_pass = __esm({
|
|
|
1552
1942
|
});
|
|
1553
1943
|
|
|
1554
1944
|
// dist/adapter/resources/webgpu-compute-pass.js
|
|
1555
|
-
var
|
|
1945
|
+
var import_core18, WebGPUComputePass;
|
|
1556
1946
|
var init_webgpu_compute_pass = __esm({
|
|
1557
1947
|
"dist/adapter/resources/webgpu-compute-pass.js"() {
|
|
1558
1948
|
"use strict";
|
|
1559
|
-
|
|
1560
|
-
WebGPUComputePass = class extends
|
|
1949
|
+
import_core18 = require("@luma.gl/core");
|
|
1950
|
+
WebGPUComputePass = class extends import_core18.ComputePass {
|
|
1561
1951
|
device;
|
|
1562
1952
|
handle;
|
|
1563
1953
|
_webgpuPipeline = null;
|
|
1564
|
-
constructor(device, props) {
|
|
1954
|
+
constructor(device, props = {}) {
|
|
1565
1955
|
super(device, props);
|
|
1566
1956
|
this.device = device;
|
|
1957
|
+
const { props: computePassProps } = this;
|
|
1567
1958
|
let timestampWrites;
|
|
1568
|
-
if (
|
|
1569
|
-
const webgpuQuerySet =
|
|
1959
|
+
if (computePassProps.timestampQuerySet) {
|
|
1960
|
+
const webgpuQuerySet = computePassProps.timestampQuerySet;
|
|
1570
1961
|
if (webgpuQuerySet) {
|
|
1962
|
+
webgpuQuerySet._invalidateResults();
|
|
1571
1963
|
timestampWrites = {
|
|
1572
1964
|
querySet: webgpuQuerySet.handle,
|
|
1573
|
-
beginningOfPassWriteIndex:
|
|
1574
|
-
endOfPassWriteIndex:
|
|
1965
|
+
beginningOfPassWriteIndex: computePassProps.beginTimestampIndex,
|
|
1966
|
+
endOfPassWriteIndex: computePassProps.endTimestampIndex
|
|
1575
1967
|
};
|
|
1576
1968
|
}
|
|
1577
1969
|
}
|
|
@@ -1582,9 +1974,14 @@ var init_webgpu_compute_pass = __esm({
|
|
|
1582
1974
|
}
|
|
1583
1975
|
/** @note no WebGPU destroy method, just gc */
|
|
1584
1976
|
destroy() {
|
|
1977
|
+
this.destroyResource();
|
|
1585
1978
|
}
|
|
1586
1979
|
end() {
|
|
1980
|
+
if (this.destroyed) {
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1587
1983
|
this.handle.end();
|
|
1984
|
+
this.destroy();
|
|
1588
1985
|
}
|
|
1589
1986
|
setPipeline(pipeline) {
|
|
1590
1987
|
const wgpuPipeline = pipeline;
|
|
@@ -1634,15 +2031,15 @@ var init_webgpu_compute_pass = __esm({
|
|
|
1634
2031
|
});
|
|
1635
2032
|
|
|
1636
2033
|
// dist/adapter/resources/webgpu-command-encoder.js
|
|
1637
|
-
var
|
|
2034
|
+
var import_core19, WebGPUCommandEncoder;
|
|
1638
2035
|
var init_webgpu_command_encoder = __esm({
|
|
1639
2036
|
"dist/adapter/resources/webgpu-command-encoder.js"() {
|
|
1640
2037
|
"use strict";
|
|
1641
|
-
|
|
2038
|
+
import_core19 = require("@luma.gl/core");
|
|
1642
2039
|
init_webgpu_command_buffer();
|
|
1643
2040
|
init_webgpu_render_pass();
|
|
1644
2041
|
init_webgpu_compute_pass();
|
|
1645
|
-
WebGPUCommandEncoder = class extends
|
|
2042
|
+
WebGPUCommandEncoder = class extends import_core19.CommandEncoder {
|
|
1646
2043
|
device;
|
|
1647
2044
|
handle;
|
|
1648
2045
|
constructor(device, props = {}) {
|
|
@@ -1656,6 +2053,7 @@ var init_webgpu_command_encoder = __esm({
|
|
|
1656
2053
|
this.handle.label = this.props.id;
|
|
1657
2054
|
}
|
|
1658
2055
|
destroy() {
|
|
2056
|
+
this.destroyResource();
|
|
1659
2057
|
}
|
|
1660
2058
|
finish(props) {
|
|
1661
2059
|
this.device.pushErrorScope("validation");
|
|
@@ -1667,17 +2065,18 @@ var init_webgpu_command_encoder = __esm({
|
|
|
1667
2065
|
this.device.reportError(new Error(message), this)();
|
|
1668
2066
|
this.device.debug();
|
|
1669
2067
|
});
|
|
2068
|
+
this.destroy();
|
|
1670
2069
|
return commandBuffer;
|
|
1671
2070
|
}
|
|
1672
2071
|
/**
|
|
1673
2072
|
* Allows a render pass to begin against a canvas context
|
|
1674
2073
|
* @todo need to support a "Framebuffer" equivalent (aka preconfigured RenderPassDescriptors?).
|
|
1675
2074
|
*/
|
|
1676
|
-
beginRenderPass(props) {
|
|
1677
|
-
return new WebGPURenderPass(this.device, props);
|
|
2075
|
+
beginRenderPass(props = {}) {
|
|
2076
|
+
return new WebGPURenderPass(this.device, this._applyTimeProfilingToPassProps(props));
|
|
1678
2077
|
}
|
|
1679
|
-
beginComputePass(props) {
|
|
1680
|
-
return new WebGPUComputePass(this.device, props);
|
|
2078
|
+
beginComputePass(props = {}) {
|
|
2079
|
+
return new WebGPUComputePass(this.device, this._applyTimeProfilingToPassProps(props));
|
|
1681
2080
|
}
|
|
1682
2081
|
// beginRenderPass(GPURenderPassDescriptor descriptor): GPURenderPassEncoder;
|
|
1683
2082
|
// beginComputePass(optional GPUComputePassDescriptor descriptor = {}): GPUComputePassEncoder;
|
|
@@ -1725,19 +2124,40 @@ var init_webgpu_command_encoder = __esm({
|
|
|
1725
2124
|
const webgpuBuffer = destination;
|
|
1726
2125
|
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
2126
|
}
|
|
2127
|
+
writeTimestamp(querySet, queryIndex) {
|
|
2128
|
+
querySet._invalidateResults();
|
|
2129
|
+
const writeTimestamp = this.handle.writeTimestamp;
|
|
2130
|
+
if (writeTimestamp) {
|
|
2131
|
+
writeTimestamp.call(this.handle, querySet.handle, queryIndex);
|
|
2132
|
+
return;
|
|
2133
|
+
}
|
|
2134
|
+
const computePass = this.handle.beginComputePass({
|
|
2135
|
+
timestampWrites: {
|
|
2136
|
+
querySet: querySet.handle,
|
|
2137
|
+
beginningOfPassWriteIndex: queryIndex
|
|
2138
|
+
}
|
|
2139
|
+
});
|
|
2140
|
+
computePass.end();
|
|
2141
|
+
}
|
|
1728
2142
|
};
|
|
1729
2143
|
}
|
|
1730
2144
|
});
|
|
1731
2145
|
|
|
1732
2146
|
// dist/adapter/resources/webgpu-query-set.js
|
|
1733
|
-
var
|
|
2147
|
+
var import_core20, WebGPUQuerySet;
|
|
1734
2148
|
var init_webgpu_query_set = __esm({
|
|
1735
2149
|
"dist/adapter/resources/webgpu-query-set.js"() {
|
|
1736
2150
|
"use strict";
|
|
1737
|
-
|
|
1738
|
-
|
|
2151
|
+
import_core20 = require("@luma.gl/core");
|
|
2152
|
+
init_cpu_hotspot_profiler();
|
|
2153
|
+
WebGPUQuerySet = class extends import_core20.QuerySet {
|
|
1739
2154
|
device;
|
|
1740
2155
|
handle;
|
|
2156
|
+
_resolveBuffer = null;
|
|
2157
|
+
_readBuffer = null;
|
|
2158
|
+
_cachedResults = null;
|
|
2159
|
+
_readResultsPromise = null;
|
|
2160
|
+
_resultsPendingResolution = false;
|
|
1741
2161
|
constructor(device, props) {
|
|
1742
2162
|
super(device, props);
|
|
1743
2163
|
this.device = device;
|
|
@@ -1749,20 +2169,145 @@ var init_webgpu_query_set = __esm({
|
|
|
1749
2169
|
}
|
|
1750
2170
|
destroy() {
|
|
1751
2171
|
var _a;
|
|
1752
|
-
(
|
|
1753
|
-
|
|
2172
|
+
if (!this.destroyed) {
|
|
2173
|
+
(_a = this.handle) == null ? void 0 : _a.destroy();
|
|
2174
|
+
this.destroyResource();
|
|
2175
|
+
this.handle = null;
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
isResultAvailable(queryIndex) {
|
|
2179
|
+
if (!this._cachedResults) {
|
|
2180
|
+
return false;
|
|
2181
|
+
}
|
|
2182
|
+
return queryIndex === void 0 ? true : queryIndex >= 0 && queryIndex < this._cachedResults.length;
|
|
2183
|
+
}
|
|
2184
|
+
async readResults(options) {
|
|
2185
|
+
const firstQuery = (options == null ? void 0 : options.firstQuery) || 0;
|
|
2186
|
+
const queryCount = (options == null ? void 0 : options.queryCount) || this.props.count - firstQuery;
|
|
2187
|
+
if (firstQuery < 0 || queryCount < 0 || firstQuery + queryCount > this.props.count) {
|
|
2188
|
+
throw new Error("Query read range is out of bounds");
|
|
2189
|
+
}
|
|
2190
|
+
let needsFreshResults = true;
|
|
2191
|
+
while (needsFreshResults) {
|
|
2192
|
+
if (!this._readResultsPromise) {
|
|
2193
|
+
this._readResultsPromise = this._readAllResults();
|
|
2194
|
+
}
|
|
2195
|
+
const readResultsPromise = this._readResultsPromise;
|
|
2196
|
+
const results = await readResultsPromise;
|
|
2197
|
+
needsFreshResults = this._resultsPendingResolution;
|
|
2198
|
+
if (!needsFreshResults) {
|
|
2199
|
+
return results.slice(firstQuery, firstQuery + queryCount);
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
throw new Error("Query read unexpectedly failed to resolve");
|
|
2203
|
+
}
|
|
2204
|
+
async readTimestampDuration(beginIndex, endIndex) {
|
|
2205
|
+
if (this.props.type !== "timestamp") {
|
|
2206
|
+
throw new Error("Timestamp durations require a timestamp QuerySet");
|
|
2207
|
+
}
|
|
2208
|
+
if (beginIndex < 0 || endIndex <= beginIndex || endIndex >= this.props.count) {
|
|
2209
|
+
throw new Error("Timestamp duration range is out of bounds");
|
|
2210
|
+
}
|
|
2211
|
+
const results = await this.readResults({
|
|
2212
|
+
firstQuery: beginIndex,
|
|
2213
|
+
queryCount: endIndex - beginIndex + 1
|
|
2214
|
+
});
|
|
2215
|
+
return Number(results[results.length - 1] - results[0]) / 1e6;
|
|
2216
|
+
}
|
|
2217
|
+
/** Marks any cached query results as stale after new writes have been encoded. */
|
|
2218
|
+
_invalidateResults() {
|
|
2219
|
+
this._cachedResults = null;
|
|
2220
|
+
this._resultsPendingResolution = true;
|
|
2221
|
+
}
|
|
2222
|
+
async _readAllResults() {
|
|
2223
|
+
this._ensureBuffers();
|
|
2224
|
+
try {
|
|
2225
|
+
if (this._resultsPendingResolution) {
|
|
2226
|
+
const commandEncoder = this.device.createCommandEncoder({
|
|
2227
|
+
id: `${this.id}-read-results`
|
|
2228
|
+
});
|
|
2229
|
+
commandEncoder.resolveQuerySet(this, this._resolveBuffer);
|
|
2230
|
+
commandEncoder.copyBufferToBuffer({
|
|
2231
|
+
sourceBuffer: this._resolveBuffer,
|
|
2232
|
+
destinationBuffer: this._readBuffer,
|
|
2233
|
+
size: this._resolveBuffer.byteLength
|
|
2234
|
+
});
|
|
2235
|
+
const commandBuffer = commandEncoder.finish({
|
|
2236
|
+
id: `${this.id}-read-results-command-buffer`
|
|
2237
|
+
});
|
|
2238
|
+
const previousSubmitReason = getCpuHotspotSubmitReason(this.device) || void 0;
|
|
2239
|
+
setCpuHotspotSubmitReason(this.device, "query-readback");
|
|
2240
|
+
try {
|
|
2241
|
+
this.device.submit(commandBuffer);
|
|
2242
|
+
} finally {
|
|
2243
|
+
setCpuHotspotSubmitReason(this.device, previousSubmitReason);
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
const data = await this._readBuffer.readAsync(0, this._readBuffer.byteLength);
|
|
2247
|
+
const resultView = new BigUint64Array(data.buffer, data.byteOffset, this.props.count);
|
|
2248
|
+
this._cachedResults = Array.from(resultView, (value) => value);
|
|
2249
|
+
this._resultsPendingResolution = false;
|
|
2250
|
+
return this._cachedResults;
|
|
2251
|
+
} finally {
|
|
2252
|
+
this._readResultsPromise = null;
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
_ensureBuffers() {
|
|
2256
|
+
if (this._resolveBuffer && this._readBuffer) {
|
|
2257
|
+
return;
|
|
2258
|
+
}
|
|
2259
|
+
const byteLength = this.props.count * 8;
|
|
2260
|
+
this._resolveBuffer = this.device.createBuffer({
|
|
2261
|
+
id: `${this.id}-resolve-buffer`,
|
|
2262
|
+
usage: import_core20.Buffer.QUERY_RESOLVE | import_core20.Buffer.COPY_SRC,
|
|
2263
|
+
byteLength
|
|
2264
|
+
});
|
|
2265
|
+
this.attachResource(this._resolveBuffer);
|
|
2266
|
+
this._readBuffer = this.device.createBuffer({
|
|
2267
|
+
id: `${this.id}-read-buffer`,
|
|
2268
|
+
usage: import_core20.Buffer.COPY_DST | import_core20.Buffer.MAP_READ,
|
|
2269
|
+
byteLength
|
|
2270
|
+
});
|
|
2271
|
+
this.attachResource(this._readBuffer);
|
|
2272
|
+
}
|
|
2273
|
+
_encodeResolveToReadBuffer(commandEncoder, options) {
|
|
2274
|
+
if (!this._resultsPendingResolution) {
|
|
2275
|
+
return false;
|
|
2276
|
+
}
|
|
2277
|
+
if (this._readResultsPromise) {
|
|
2278
|
+
return false;
|
|
2279
|
+
}
|
|
2280
|
+
this._ensureBuffers();
|
|
2281
|
+
const firstQuery = (options == null ? void 0 : options.firstQuery) || 0;
|
|
2282
|
+
const queryCount = (options == null ? void 0 : options.queryCount) || this.props.count - firstQuery;
|
|
2283
|
+
const byteLength = queryCount * BigUint64Array.BYTES_PER_ELEMENT;
|
|
2284
|
+
const byteOffset = firstQuery * BigUint64Array.BYTES_PER_ELEMENT;
|
|
2285
|
+
commandEncoder.resolveQuerySet(this, this._resolveBuffer, {
|
|
2286
|
+
firstQuery,
|
|
2287
|
+
queryCount,
|
|
2288
|
+
destinationOffset: byteOffset
|
|
2289
|
+
});
|
|
2290
|
+
commandEncoder.copyBufferToBuffer({
|
|
2291
|
+
sourceBuffer: this._resolveBuffer,
|
|
2292
|
+
sourceOffset: byteOffset,
|
|
2293
|
+
destinationBuffer: this._readBuffer,
|
|
2294
|
+
destinationOffset: byteOffset,
|
|
2295
|
+
size: byteLength
|
|
2296
|
+
});
|
|
2297
|
+
this._resultsPendingResolution = false;
|
|
2298
|
+
return true;
|
|
1754
2299
|
}
|
|
1755
2300
|
};
|
|
1756
2301
|
}
|
|
1757
2302
|
});
|
|
1758
2303
|
|
|
1759
2304
|
// dist/adapter/resources/webgpu-pipeline-layout.js
|
|
1760
|
-
var
|
|
2305
|
+
var import_core21, WebGPUPipelineLayout, isStorageTextureBindingLayout;
|
|
1761
2306
|
var init_webgpu_pipeline_layout = __esm({
|
|
1762
2307
|
"dist/adapter/resources/webgpu-pipeline-layout.js"() {
|
|
1763
2308
|
"use strict";
|
|
1764
|
-
|
|
1765
|
-
WebGPUPipelineLayout = class extends
|
|
2309
|
+
import_core21 = require("@luma.gl/core");
|
|
2310
|
+
WebGPUPipelineLayout = class extends import_core21.PipelineLayout {
|
|
1766
2311
|
device;
|
|
1767
2312
|
handle;
|
|
1768
2313
|
constructor(device, props) {
|
|
@@ -1839,7 +2384,7 @@ var init_webgpu_pipeline_layout = __esm({
|
|
|
1839
2384
|
break;
|
|
1840
2385
|
}
|
|
1841
2386
|
default: {
|
|
1842
|
-
|
|
2387
|
+
import_core21.log.warn("unhandled binding type when creating pipeline descriptor")();
|
|
1843
2388
|
}
|
|
1844
2389
|
}
|
|
1845
2390
|
const VISIBILITY_ALL = GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT | GPUShaderStage.COMPUTE;
|
|
@@ -1859,12 +2404,12 @@ var init_webgpu_pipeline_layout = __esm({
|
|
|
1859
2404
|
});
|
|
1860
2405
|
|
|
1861
2406
|
// dist/adapter/resources/webgpu-fence.js
|
|
1862
|
-
var
|
|
2407
|
+
var import_core22, WebGPUFence;
|
|
1863
2408
|
var init_webgpu_fence = __esm({
|
|
1864
2409
|
"dist/adapter/resources/webgpu-fence.js"() {
|
|
1865
2410
|
"use strict";
|
|
1866
|
-
|
|
1867
|
-
WebGPUFence = class extends
|
|
2411
|
+
import_core22 = require("@luma.gl/core");
|
|
2412
|
+
WebGPUFence = class extends import_core22.Fence {
|
|
1868
2413
|
device;
|
|
1869
2414
|
handle = null;
|
|
1870
2415
|
signaled;
|
|
@@ -1893,7 +2438,7 @@ function getShaderLayoutFromWGSL(source) {
|
|
|
1893
2438
|
try {
|
|
1894
2439
|
parsedWGSL = parseWGSL(source);
|
|
1895
2440
|
} catch (error) {
|
|
1896
|
-
|
|
2441
|
+
import_core23.log.error(error.message)();
|
|
1897
2442
|
return shaderLayout;
|
|
1898
2443
|
}
|
|
1899
2444
|
for (const uniform of parsedWGSL.uniforms) {
|
|
@@ -1987,25 +2532,508 @@ function getTextureBindingFromReflect(v, opts) {
|
|
|
1987
2532
|
}
|
|
1988
2533
|
return { viewDimension, sampleType, multisampled };
|
|
1989
2534
|
}
|
|
1990
|
-
var
|
|
2535
|
+
var import_core23, import_wgsl_reflect;
|
|
1991
2536
|
var init_get_shader_layout_wgsl = __esm({
|
|
1992
2537
|
"dist/wgsl/get-shader-layout-wgsl.js"() {
|
|
1993
2538
|
"use strict";
|
|
1994
|
-
|
|
2539
|
+
import_core23 = require("@luma.gl/core");
|
|
1995
2540
|
import_wgsl_reflect = require("wgsl_reflect");
|
|
1996
2541
|
}
|
|
1997
2542
|
});
|
|
1998
2543
|
|
|
2544
|
+
// dist/adapter/helpers/generate-mipmaps-webgpu.js
|
|
2545
|
+
function generateMipmapsWebGPU(device, texture) {
|
|
2546
|
+
if (texture.mipLevels <= 1) {
|
|
2547
|
+
return;
|
|
2548
|
+
}
|
|
2549
|
+
if (texture.dimension === "3d") {
|
|
2550
|
+
generateMipmaps3D(device, texture);
|
|
2551
|
+
return;
|
|
2552
|
+
}
|
|
2553
|
+
if (RENDER_DIMENSIONS.includes(texture.dimension)) {
|
|
2554
|
+
generateMipmapsRender(device, texture);
|
|
2555
|
+
return;
|
|
2556
|
+
}
|
|
2557
|
+
throw new Error(`Cannot generate mipmaps for texture dimension "${texture.dimension}" with WebGPU.`);
|
|
2558
|
+
}
|
|
2559
|
+
function generateMipmapsRender(device, texture) {
|
|
2560
|
+
validateFormatCapabilities(device, texture, ["render", "filter"], "render");
|
|
2561
|
+
const colorAttachmentFormat = getColorAttachmentFormat(texture.format, "render", texture.dimension);
|
|
2562
|
+
const viewDimension = texture.dimension;
|
|
2563
|
+
const shaderSource = getRenderMipmapWGSL(viewDimension);
|
|
2564
|
+
const sampler = device.createSampler({ minFilter: "linear", magFilter: "linear" });
|
|
2565
|
+
const uniformsBuffer = device.createBuffer({
|
|
2566
|
+
byteLength: 16,
|
|
2567
|
+
usage: import_core24.Buffer.UNIFORM | import_core24.Buffer.COPY_DST
|
|
2568
|
+
});
|
|
2569
|
+
const uniformValues = new Uint32Array(1);
|
|
2570
|
+
const sourceTextureLayout = {
|
|
2571
|
+
type: "texture",
|
|
2572
|
+
name: "sourceTexture",
|
|
2573
|
+
group: 0,
|
|
2574
|
+
location: 1,
|
|
2575
|
+
viewDimension,
|
|
2576
|
+
sampleType: "float"
|
|
2577
|
+
};
|
|
2578
|
+
const uniformsLayout = {
|
|
2579
|
+
type: "uniform",
|
|
2580
|
+
name: "uniforms",
|
|
2581
|
+
group: 0,
|
|
2582
|
+
location: 2
|
|
2583
|
+
};
|
|
2584
|
+
const renderShaderLayout = {
|
|
2585
|
+
attributes: [],
|
|
2586
|
+
bindings: [RENDER_SOURCE_SAMPLER_LAYOUT, sourceTextureLayout, uniformsLayout]
|
|
2587
|
+
};
|
|
2588
|
+
const vertexShader = device.createShader({
|
|
2589
|
+
id: "mipmap-generation-render-vs",
|
|
2590
|
+
source: shaderSource,
|
|
2591
|
+
language: "wgsl",
|
|
2592
|
+
stage: "vertex"
|
|
2593
|
+
});
|
|
2594
|
+
const fragmentShader = device.createShader({
|
|
2595
|
+
id: "mipmap-generation-render-fs",
|
|
2596
|
+
source: shaderSource,
|
|
2597
|
+
language: "wgsl",
|
|
2598
|
+
stage: "fragment"
|
|
2599
|
+
});
|
|
2600
|
+
const renderPipeline = device.createRenderPipeline({
|
|
2601
|
+
id: `mipmap-generation-render:${texture.dimension}:${texture.format}`,
|
|
2602
|
+
vs: vertexShader,
|
|
2603
|
+
fs: fragmentShader,
|
|
2604
|
+
shaderLayout: renderShaderLayout,
|
|
2605
|
+
colorAttachmentFormats: [colorAttachmentFormat],
|
|
2606
|
+
topology: "triangle-list"
|
|
2607
|
+
});
|
|
2608
|
+
let sourceWidth = texture.width;
|
|
2609
|
+
let sourceHeight = texture.height;
|
|
2610
|
+
const layerCount = texture.dimension === "2d" ? 1 : texture.depth;
|
|
2611
|
+
function renderMipmapLayer(sourceView, baseMipLevel, baseArrayLayer, destinationWidth, destinationHeight) {
|
|
2612
|
+
uniformValues[0] = baseArrayLayer;
|
|
2613
|
+
uniformsBuffer.write(uniformValues);
|
|
2614
|
+
const destinationView = texture.createView({
|
|
2615
|
+
dimension: "2d",
|
|
2616
|
+
baseMipLevel,
|
|
2617
|
+
mipLevelCount: 1,
|
|
2618
|
+
baseArrayLayer,
|
|
2619
|
+
arrayLayerCount: 1
|
|
2620
|
+
});
|
|
2621
|
+
const framebuffer = device.createFramebuffer({
|
|
2622
|
+
colorAttachments: [destinationView]
|
|
2623
|
+
});
|
|
2624
|
+
const renderPass = device.beginRenderPass({
|
|
2625
|
+
id: `mipmap-generation:${texture.format}:${baseMipLevel}:${baseArrayLayer}`,
|
|
2626
|
+
framebuffer
|
|
2627
|
+
});
|
|
2628
|
+
try {
|
|
2629
|
+
renderPass.setPipeline(renderPipeline);
|
|
2630
|
+
renderPass.setBindings({
|
|
2631
|
+
sourceSampler: sampler,
|
|
2632
|
+
sourceTexture: sourceView,
|
|
2633
|
+
uniforms: uniformsBuffer
|
|
2634
|
+
});
|
|
2635
|
+
renderPass.setParameters({
|
|
2636
|
+
viewport: [0, 0, destinationWidth, destinationHeight, 0, 1],
|
|
2637
|
+
scissorRect: [0, 0, destinationWidth, destinationHeight]
|
|
2638
|
+
});
|
|
2639
|
+
renderPass.draw({ vertexCount: 3 });
|
|
2640
|
+
renderPass.end();
|
|
2641
|
+
device.submit();
|
|
2642
|
+
} finally {
|
|
2643
|
+
destinationView.destroy();
|
|
2644
|
+
framebuffer.destroy();
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
try {
|
|
2648
|
+
for (let baseMipLevel = 1; baseMipLevel < texture.mipLevels; ++baseMipLevel) {
|
|
2649
|
+
validateFormatCapabilities(device, texture, ["render", "filter"], "render");
|
|
2650
|
+
const sourceMipLevel = baseMipLevel - 1;
|
|
2651
|
+
const destinationWidth = Math.max(1, sourceWidth >> 1);
|
|
2652
|
+
const destinationHeight = Math.max(1, sourceHeight >> 1);
|
|
2653
|
+
const sourceView = texture.createView({
|
|
2654
|
+
dimension: viewDimension,
|
|
2655
|
+
baseMipLevel: sourceMipLevel,
|
|
2656
|
+
mipLevelCount: 1,
|
|
2657
|
+
baseArrayLayer: 0,
|
|
2658
|
+
arrayLayerCount: texture.depth
|
|
2659
|
+
});
|
|
2660
|
+
try {
|
|
2661
|
+
for (let baseArrayLayer = 0; baseArrayLayer < layerCount; ++baseArrayLayer) {
|
|
2662
|
+
renderMipmapLayer(sourceView, baseMipLevel, baseArrayLayer, destinationWidth, destinationHeight);
|
|
2663
|
+
}
|
|
2664
|
+
} finally {
|
|
2665
|
+
sourceView.destroy();
|
|
2666
|
+
}
|
|
2667
|
+
sourceWidth = destinationWidth;
|
|
2668
|
+
sourceHeight = destinationHeight;
|
|
2669
|
+
}
|
|
2670
|
+
} finally {
|
|
2671
|
+
renderPipeline.destroy();
|
|
2672
|
+
vertexShader.destroy();
|
|
2673
|
+
fragmentShader.destroy();
|
|
2674
|
+
sampler.destroy();
|
|
2675
|
+
uniformsBuffer.destroy();
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
function getColorAttachmentFormat(format, path, dimension) {
|
|
2679
|
+
if (import_core24.textureFormatDecoder.isColor(format)) {
|
|
2680
|
+
return format;
|
|
2681
|
+
}
|
|
2682
|
+
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.`);
|
|
2683
|
+
}
|
|
2684
|
+
function generateMipmaps3D(device, texture) {
|
|
2685
|
+
validateFormatCapabilities(device, texture, ["filter", "store"], "compute");
|
|
2686
|
+
const format = getColorAttachmentFormat(texture.format, "compute", texture.dimension);
|
|
2687
|
+
const shaderSource = get3DComputeMipmapWGSL(format);
|
|
2688
|
+
const destinationTextureLayout = {
|
|
2689
|
+
type: "storage",
|
|
2690
|
+
name: "destinationTexture",
|
|
2691
|
+
group: 0,
|
|
2692
|
+
location: 1,
|
|
2693
|
+
format,
|
|
2694
|
+
viewDimension: "3d",
|
|
2695
|
+
access: "write-only"
|
|
2696
|
+
};
|
|
2697
|
+
const computeShaderLayout = {
|
|
2698
|
+
bindings: [COMPUTE_SOURCE_TEXTURE_LAYOUT, destinationTextureLayout, COMPUTE_UNIFORMS_LAYOUT]
|
|
2699
|
+
};
|
|
2700
|
+
const computeShader = device.createShader({
|
|
2701
|
+
id: "mipmap-generation-compute",
|
|
2702
|
+
source: shaderSource,
|
|
2703
|
+
language: "wgsl",
|
|
2704
|
+
stage: "compute"
|
|
2705
|
+
});
|
|
2706
|
+
const computePipeline = device.createComputePipeline({
|
|
2707
|
+
id: `mipmap-generation-compute:${texture.format}`,
|
|
2708
|
+
shader: computeShader,
|
|
2709
|
+
shaderLayout: computeShaderLayout
|
|
2710
|
+
});
|
|
2711
|
+
const uniformsBuffer = device.createBuffer({
|
|
2712
|
+
byteLength: 32,
|
|
2713
|
+
usage: import_core24.Buffer.UNIFORM | import_core24.Buffer.COPY_DST
|
|
2714
|
+
});
|
|
2715
|
+
const uniformValues = new Uint32Array(8);
|
|
2716
|
+
let sourceWidth = texture.width;
|
|
2717
|
+
let sourceHeight = texture.height;
|
|
2718
|
+
let sourceDepth = texture.depth;
|
|
2719
|
+
try {
|
|
2720
|
+
for (let destinationMipLevel = 1; destinationMipLevel < texture.mipLevels; ++destinationMipLevel) {
|
|
2721
|
+
validateFormatCapabilities(device, texture, ["filter", "store"], "compute");
|
|
2722
|
+
const destinationWidth = Math.max(1, sourceWidth >> 1);
|
|
2723
|
+
const destinationHeight = Math.max(1, sourceHeight >> 1);
|
|
2724
|
+
const destinationDepth = Math.max(1, sourceDepth >> 1);
|
|
2725
|
+
uniformValues[0] = sourceWidth;
|
|
2726
|
+
uniformValues[1] = sourceHeight;
|
|
2727
|
+
uniformValues[2] = sourceDepth;
|
|
2728
|
+
uniformValues[3] = destinationWidth;
|
|
2729
|
+
uniformValues[4] = destinationHeight;
|
|
2730
|
+
uniformValues[5] = destinationDepth;
|
|
2731
|
+
uniformValues[6] = 0;
|
|
2732
|
+
uniformsBuffer.write(uniformValues);
|
|
2733
|
+
const sourceView = texture.createView({
|
|
2734
|
+
dimension: "3d",
|
|
2735
|
+
baseMipLevel: destinationMipLevel - 1,
|
|
2736
|
+
mipLevelCount: 1,
|
|
2737
|
+
baseArrayLayer: 0,
|
|
2738
|
+
arrayLayerCount: 1
|
|
2739
|
+
});
|
|
2740
|
+
const destinationView = texture.createView({
|
|
2741
|
+
dimension: "3d",
|
|
2742
|
+
baseMipLevel: destinationMipLevel,
|
|
2743
|
+
mipLevelCount: 1,
|
|
2744
|
+
baseArrayLayer: 0,
|
|
2745
|
+
arrayLayerCount: 1
|
|
2746
|
+
});
|
|
2747
|
+
computePipeline.setBindings({
|
|
2748
|
+
sourceTexture: sourceView,
|
|
2749
|
+
destinationTexture: destinationView,
|
|
2750
|
+
uniforms: uniformsBuffer
|
|
2751
|
+
});
|
|
2752
|
+
try {
|
|
2753
|
+
const workgroupsX = Math.ceil(destinationWidth / WORKGROUP_SIZE.x);
|
|
2754
|
+
const workgroupsY = Math.ceil(destinationHeight / WORKGROUP_SIZE.y);
|
|
2755
|
+
const workgroupsZ = Math.ceil(destinationDepth / WORKGROUP_SIZE.z);
|
|
2756
|
+
const computePass = device.beginComputePass({});
|
|
2757
|
+
computePass.setPipeline(computePipeline);
|
|
2758
|
+
computePass.dispatch(workgroupsX, workgroupsY, workgroupsZ);
|
|
2759
|
+
computePass.end();
|
|
2760
|
+
device.submit();
|
|
2761
|
+
} finally {
|
|
2762
|
+
sourceView.destroy();
|
|
2763
|
+
destinationView.destroy();
|
|
2764
|
+
}
|
|
2765
|
+
sourceWidth = destinationWidth;
|
|
2766
|
+
sourceHeight = destinationHeight;
|
|
2767
|
+
sourceDepth = destinationDepth;
|
|
2768
|
+
}
|
|
2769
|
+
} finally {
|
|
2770
|
+
computePipeline.destroy();
|
|
2771
|
+
computeShader.destroy();
|
|
2772
|
+
uniformsBuffer.destroy();
|
|
2773
|
+
}
|
|
2774
|
+
}
|
|
2775
|
+
function validateFormatCapabilities(device, texture, requiredCapabilities, path) {
|
|
2776
|
+
const { format, dimension } = texture;
|
|
2777
|
+
const capabilities = device.getTextureFormatCapabilities(format);
|
|
2778
|
+
const missingCapabilities = requiredCapabilities.filter((capability) => !capabilities[capability]);
|
|
2779
|
+
if (missingCapabilities.length > 0) {
|
|
2780
|
+
const required = requiredCapabilities.join(" + ");
|
|
2781
|
+
const actual = requiredCapabilities.map((capability) => `${capability}=${capabilities[capability]}`).join(", ");
|
|
2782
|
+
throw new Error(`Cannot run ${path} mipmap generation for ${dimension} texture with format "${format}". Required capabilities: ${required}. Actual capabilities: ${actual}.`);
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
function getSourceTextureType(dimension) {
|
|
2786
|
+
switch (dimension) {
|
|
2787
|
+
case "2d":
|
|
2788
|
+
return "texture_2d<f32>";
|
|
2789
|
+
case "2d-array":
|
|
2790
|
+
return "texture_2d_array<f32>";
|
|
2791
|
+
case "cube":
|
|
2792
|
+
return "texture_cube<f32>";
|
|
2793
|
+
case "cube-array":
|
|
2794
|
+
return "texture_cube_array<f32>";
|
|
2795
|
+
default:
|
|
2796
|
+
throw new Error(`Unsupported render dimension "${dimension}" for mipmap generation.`);
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
function getRenderMipmapWGSL(dimension) {
|
|
2800
|
+
const sourceSnippet = getRenderMipmapSampleSnippet(dimension);
|
|
2801
|
+
return `
|
|
2802
|
+
struct MipmapUniforms {
|
|
2803
|
+
sourceLayer: u32,
|
|
2804
|
+
};
|
|
2805
|
+
|
|
2806
|
+
fn _touchUniform(uniforms: MipmapUniforms) {
|
|
2807
|
+
let unusedSourceLayer = uniforms.sourceLayer;
|
|
2808
|
+
}
|
|
2809
|
+
|
|
2810
|
+
const faceMat = array(
|
|
2811
|
+
mat3x3f(
|
|
2812
|
+
0.0, 0.0, -2.0,
|
|
2813
|
+
0.0, -2.0, 0.0,
|
|
2814
|
+
1.0, 1.0, 1.0
|
|
2815
|
+
), // pos-x
|
|
2816
|
+
mat3x3f(
|
|
2817
|
+
0.0, 0.0, 2.0,
|
|
2818
|
+
0.0, -2.0, 0.0,
|
|
2819
|
+
-1.0, 1.0, -1.0
|
|
2820
|
+
), // neg-x
|
|
2821
|
+
mat3x3f(
|
|
2822
|
+
2.0, 0.0, 0.0,
|
|
2823
|
+
0.0, 0.0, 2.0,
|
|
2824
|
+
-1.0, 1.0, -1.0
|
|
2825
|
+
), // pos-y
|
|
2826
|
+
mat3x3f(
|
|
2827
|
+
2.0, 0.0, 0.0,
|
|
2828
|
+
0.0, 0.0, -2.0,
|
|
2829
|
+
-1.0, -1.0, 1.0
|
|
2830
|
+
), // neg-y
|
|
2831
|
+
mat3x3f(
|
|
2832
|
+
2.0, 0.0, 0.0,
|
|
2833
|
+
0.0, -2.0, 0.0,
|
|
2834
|
+
-1.0, 1.0, 1.0
|
|
2835
|
+
), // pos-z
|
|
2836
|
+
mat3x3f(
|
|
2837
|
+
-2.0, 0.0, 0.0,
|
|
2838
|
+
0.0, -2.0, 0.0,
|
|
2839
|
+
1.0, 1.0, -1.0
|
|
2840
|
+
) // neg-z
|
|
2841
|
+
);
|
|
2842
|
+
|
|
2843
|
+
struct FragmentInputs {
|
|
2844
|
+
@builtin(position) position: vec4f,
|
|
2845
|
+
@location(0) texcoord: vec2f
|
|
2846
|
+
};
|
|
2847
|
+
|
|
2848
|
+
struct VertexOutput {
|
|
2849
|
+
@builtin(position) position: vec4f,
|
|
2850
|
+
@location(0) texcoord: vec2f
|
|
2851
|
+
};
|
|
2852
|
+
|
|
2853
|
+
@group(0) @binding(0) var sourceSampler: sampler;
|
|
2854
|
+
@group(0) @binding(1) var sourceTexture: ${getSourceTextureType(dimension)};
|
|
2855
|
+
@group(0) @binding(2) var<uniform> uniforms: MipmapUniforms;
|
|
2856
|
+
|
|
2857
|
+
@vertex
|
|
2858
|
+
fn vertexMain(
|
|
2859
|
+
@builtin(vertex_index) vertexIndex: u32
|
|
2860
|
+
) -> VertexOutput {
|
|
2861
|
+
const positions = array(
|
|
2862
|
+
vec2f(-1.0, -1.0),
|
|
2863
|
+
vec2f(-1.0, 3.0),
|
|
2864
|
+
vec2f( 3.0, -1.0)
|
|
2865
|
+
);
|
|
2866
|
+
|
|
2867
|
+
let xy = positions[vertexIndex];
|
|
2868
|
+
return VertexOutput(
|
|
2869
|
+
vec4f(xy, 0.0, 1.0),
|
|
2870
|
+
xy * vec2f(0.5, -0.5) + vec2f(0.5)
|
|
2871
|
+
);
|
|
2872
|
+
}
|
|
2873
|
+
|
|
2874
|
+
@fragment
|
|
2875
|
+
fn fragmentMain(fsInput: VertexOutput) -> @location(0) vec4f {
|
|
2876
|
+
_touchUniform(uniforms);
|
|
2877
|
+
return ${sourceSnippet};
|
|
2878
|
+
}
|
|
2879
|
+
`;
|
|
2880
|
+
}
|
|
2881
|
+
function getRenderMipmapSampleSnippet(dimension) {
|
|
2882
|
+
const layer = "uniforms.sourceLayer";
|
|
2883
|
+
switch (dimension) {
|
|
2884
|
+
case "2d":
|
|
2885
|
+
return "textureSampleLevel(sourceTexture, sourceSampler, fsInput.texcoord, 0.0)";
|
|
2886
|
+
case "2d-array":
|
|
2887
|
+
return `textureSampleLevel(sourceTexture, sourceSampler, fsInput.texcoord, i32(${layer}), 0.0)`;
|
|
2888
|
+
case "cube":
|
|
2889
|
+
return `textureSampleLevel(sourceTexture, sourceSampler, faceMat[i32(${layer})] * vec3f(fract(fsInput.texcoord), 1.0), 0.0)`;
|
|
2890
|
+
case "cube-array":
|
|
2891
|
+
return `textureSampleLevel(sourceTexture, sourceSampler, faceMat[i32(${layer} % 6u)] * vec3f(fract(fsInput.texcoord), 1.0), i32(${layer} / 6u), 0.0)`;
|
|
2892
|
+
default:
|
|
2893
|
+
throw new Error(`Unsupported render dimension "${dimension}" for mipmap generation.`);
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
function get3DComputeMipmapWGSL(format) {
|
|
2897
|
+
return `
|
|
2898
|
+
struct MipmapUniforms {
|
|
2899
|
+
sourceWidth: u32,
|
|
2900
|
+
sourceHeight: u32,
|
|
2901
|
+
sourceDepth: u32,
|
|
2902
|
+
destinationWidth: u32,
|
|
2903
|
+
destinationHeight: u32,
|
|
2904
|
+
destinationDepth: u32,
|
|
2905
|
+
padding: u32,
|
|
2906
|
+
};
|
|
2907
|
+
|
|
2908
|
+
@group(0) @binding(0) var sourceTexture: texture_3d<f32>;
|
|
2909
|
+
@group(0) @binding(1) var destinationTexture: texture_storage_3d<${format}, write>;
|
|
2910
|
+
@group(0) @binding(2) var<uniform> uniforms: MipmapUniforms;
|
|
2911
|
+
|
|
2912
|
+
@compute @workgroup_size(${WORKGROUP_SIZE.x}, ${WORKGROUP_SIZE.y}, ${WORKGROUP_SIZE.z})
|
|
2913
|
+
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
|
|
2914
|
+
if (
|
|
2915
|
+
id.x >= uniforms.destinationWidth ||
|
|
2916
|
+
id.y >= uniforms.destinationHeight ||
|
|
2917
|
+
id.z >= uniforms.destinationDepth
|
|
2918
|
+
) {
|
|
2919
|
+
return;
|
|
2920
|
+
}
|
|
2921
|
+
|
|
2922
|
+
let sourceBase = id * 2u;
|
|
2923
|
+
let sourceX0 = min(sourceBase.x, uniforms.sourceWidth - 1u);
|
|
2924
|
+
let sourceY0 = min(sourceBase.y, uniforms.sourceHeight - 1u);
|
|
2925
|
+
let sourceZ0 = min(sourceBase.z, uniforms.sourceDepth - 1u);
|
|
2926
|
+
|
|
2927
|
+
let sourceX1 = min(sourceBase.x + 1u, uniforms.sourceWidth - 1u);
|
|
2928
|
+
let sourceY1 = min(sourceBase.y + 1u, uniforms.sourceHeight - 1u);
|
|
2929
|
+
let sourceZ1 = min(sourceBase.z + 1u, uniforms.sourceDepth - 1u);
|
|
2930
|
+
|
|
2931
|
+
var sum = textureLoad(
|
|
2932
|
+
sourceTexture,
|
|
2933
|
+
vec3<i32>(i32(sourceX0), i32(sourceY0), i32(sourceZ0)),
|
|
2934
|
+
0
|
|
2935
|
+
);
|
|
2936
|
+
sum += textureLoad(
|
|
2937
|
+
sourceTexture,
|
|
2938
|
+
vec3<i32>(i32(sourceX1), i32(sourceY0), i32(sourceZ0)),
|
|
2939
|
+
0
|
|
2940
|
+
);
|
|
2941
|
+
sum += textureLoad(
|
|
2942
|
+
sourceTexture,
|
|
2943
|
+
vec3<i32>(i32(sourceX0), i32(sourceY1), i32(sourceZ0)),
|
|
2944
|
+
0
|
|
2945
|
+
);
|
|
2946
|
+
sum += textureLoad(
|
|
2947
|
+
sourceTexture,
|
|
2948
|
+
vec3<i32>(i32(sourceX1), i32(sourceY1), i32(sourceZ0)),
|
|
2949
|
+
0
|
|
2950
|
+
);
|
|
2951
|
+
sum += textureLoad(
|
|
2952
|
+
sourceTexture,
|
|
2953
|
+
vec3<i32>(i32(sourceX0), i32(sourceY0), i32(sourceZ1)),
|
|
2954
|
+
0
|
|
2955
|
+
);
|
|
2956
|
+
sum += textureLoad(
|
|
2957
|
+
sourceTexture,
|
|
2958
|
+
vec3<i32>(i32(sourceX1), i32(sourceY0), i32(sourceZ1)),
|
|
2959
|
+
0
|
|
2960
|
+
);
|
|
2961
|
+
sum += textureLoad(
|
|
2962
|
+
sourceTexture,
|
|
2963
|
+
vec3<i32>(i32(sourceX0), i32(sourceY1), i32(sourceZ1)),
|
|
2964
|
+
0
|
|
2965
|
+
);
|
|
2966
|
+
sum += textureLoad(
|
|
2967
|
+
sourceTexture,
|
|
2968
|
+
vec3<i32>(i32(sourceX1), i32(sourceY1), i32(sourceZ1)),
|
|
2969
|
+
0
|
|
2970
|
+
);
|
|
2971
|
+
|
|
2972
|
+
textureStore(
|
|
2973
|
+
destinationTexture,
|
|
2974
|
+
vec3<i32>(i32(id.x), i32(id.y), i32(id.z)),
|
|
2975
|
+
vec4<f32>(sum.xyz / 8.0, sum.w / 8.0)
|
|
2976
|
+
);
|
|
2977
|
+
}
|
|
2978
|
+
`;
|
|
2979
|
+
}
|
|
2980
|
+
var import_core24, RENDER_DIMENSIONS, WORKGROUP_SIZE, RENDER_SOURCE_SAMPLER_LAYOUT, COMPUTE_SOURCE_TEXTURE_LAYOUT, COMPUTE_UNIFORMS_LAYOUT;
|
|
2981
|
+
var init_generate_mipmaps_webgpu = __esm({
|
|
2982
|
+
"dist/adapter/helpers/generate-mipmaps-webgpu.js"() {
|
|
2983
|
+
"use strict";
|
|
2984
|
+
import_core24 = require("@luma.gl/core");
|
|
2985
|
+
RENDER_DIMENSIONS = [
|
|
2986
|
+
"2d",
|
|
2987
|
+
"2d-array",
|
|
2988
|
+
"cube",
|
|
2989
|
+
"cube-array"
|
|
2990
|
+
];
|
|
2991
|
+
WORKGROUP_SIZE = {
|
|
2992
|
+
x: 4,
|
|
2993
|
+
y: 4,
|
|
2994
|
+
z: 4
|
|
2995
|
+
};
|
|
2996
|
+
RENDER_SOURCE_SAMPLER_LAYOUT = {
|
|
2997
|
+
type: "sampler",
|
|
2998
|
+
name: "sourceSampler",
|
|
2999
|
+
group: 0,
|
|
3000
|
+
location: 0
|
|
3001
|
+
};
|
|
3002
|
+
COMPUTE_SOURCE_TEXTURE_LAYOUT = {
|
|
3003
|
+
type: "texture",
|
|
3004
|
+
name: "sourceTexture",
|
|
3005
|
+
group: 0,
|
|
3006
|
+
location: 0,
|
|
3007
|
+
viewDimension: "3d",
|
|
3008
|
+
sampleType: "float"
|
|
3009
|
+
};
|
|
3010
|
+
COMPUTE_UNIFORMS_LAYOUT = {
|
|
3011
|
+
type: "uniform",
|
|
3012
|
+
name: "uniforms",
|
|
3013
|
+
group: 0,
|
|
3014
|
+
location: 2
|
|
3015
|
+
};
|
|
3016
|
+
}
|
|
3017
|
+
});
|
|
3018
|
+
|
|
1999
3019
|
// dist/adapter/webgpu-device.js
|
|
2000
3020
|
var webgpu_device_exports = {};
|
|
2001
3021
|
__export(webgpu_device_exports, {
|
|
2002
3022
|
WebGPUDevice: () => WebGPUDevice
|
|
2003
3023
|
});
|
|
2004
|
-
|
|
3024
|
+
function scheduleMicrotask(callback) {
|
|
3025
|
+
if (globalThis.queueMicrotask) {
|
|
3026
|
+
globalThis.queueMicrotask(callback);
|
|
3027
|
+
return;
|
|
3028
|
+
}
|
|
3029
|
+
Promise.resolve().then(callback).catch(() => {
|
|
3030
|
+
});
|
|
3031
|
+
}
|
|
3032
|
+
var import_core25, WebGPUDevice;
|
|
2005
3033
|
var init_webgpu_device = __esm({
|
|
2006
3034
|
"dist/adapter/webgpu-device.js"() {
|
|
2007
3035
|
"use strict";
|
|
2008
|
-
|
|
3036
|
+
import_core25 = require("@luma.gl/core");
|
|
2009
3037
|
init_webgpu_buffer();
|
|
2010
3038
|
init_webgpu_texture();
|
|
2011
3039
|
init_webgpu_external_texture();
|
|
@@ -2016,12 +3044,15 @@ var init_webgpu_device = __esm({
|
|
|
2016
3044
|
init_webgpu_compute_pipeline();
|
|
2017
3045
|
init_webgpu_vertex_array();
|
|
2018
3046
|
init_webgpu_canvas_context();
|
|
3047
|
+
init_webgpu_presentation_context();
|
|
2019
3048
|
init_webgpu_command_encoder();
|
|
2020
3049
|
init_webgpu_query_set();
|
|
2021
3050
|
init_webgpu_pipeline_layout();
|
|
2022
3051
|
init_webgpu_fence();
|
|
2023
3052
|
init_get_shader_layout_wgsl();
|
|
2024
|
-
|
|
3053
|
+
init_generate_mipmaps_webgpu();
|
|
3054
|
+
init_cpu_hotspot_profiler();
|
|
3055
|
+
WebGPUDevice = class extends import_core25.Device {
|
|
2025
3056
|
/** The underlying WebGPU device */
|
|
2026
3057
|
handle;
|
|
2027
3058
|
/* The underlying WebGPU adapter */
|
|
@@ -2038,6 +3069,7 @@ var init_webgpu_device = __esm({
|
|
|
2038
3069
|
lost;
|
|
2039
3070
|
canvasContext = null;
|
|
2040
3071
|
_isLost = false;
|
|
3072
|
+
_defaultSampler = null;
|
|
2041
3073
|
commandEncoder;
|
|
2042
3074
|
get [Symbol.toStringTag]() {
|
|
2043
3075
|
return "WebGPUDevice";
|
|
@@ -2064,7 +3096,7 @@ var init_webgpu_device = __esm({
|
|
|
2064
3096
|
this._isLost = true;
|
|
2065
3097
|
resolve({ reason: "destroyed", message: lostInfo.message });
|
|
2066
3098
|
});
|
|
2067
|
-
const canvasContextProps =
|
|
3099
|
+
const canvasContextProps = import_core25.Device._getCanvasContextProps(props);
|
|
2068
3100
|
if (canvasContextProps) {
|
|
2069
3101
|
this.canvasContext = new WebGPUCanvasContext(this, this.adapter, canvasContextProps);
|
|
2070
3102
|
}
|
|
@@ -2075,6 +3107,10 @@ var init_webgpu_device = __esm({
|
|
|
2075
3107
|
// const {glsl = true} = props;
|
|
2076
3108
|
// this.glslang = glsl && await loadGlslangModule();
|
|
2077
3109
|
destroy() {
|
|
3110
|
+
var _a, _b;
|
|
3111
|
+
(_a = this.commandEncoder) == null ? void 0 : _a.destroy();
|
|
3112
|
+
(_b = this._defaultSampler) == null ? void 0 : _b.destroy();
|
|
3113
|
+
this._defaultSampler = null;
|
|
2078
3114
|
this.handle.destroy();
|
|
2079
3115
|
}
|
|
2080
3116
|
get isLost() {
|
|
@@ -2103,6 +3139,12 @@ var init_webgpu_device = __esm({
|
|
|
2103
3139
|
createSampler(props) {
|
|
2104
3140
|
return new WebGPUSampler(this, props);
|
|
2105
3141
|
}
|
|
3142
|
+
getDefaultSampler() {
|
|
3143
|
+
this._defaultSampler ||= new WebGPUSampler(this, {
|
|
3144
|
+
id: `${this.id}-default-sampler`
|
|
3145
|
+
});
|
|
3146
|
+
return this._defaultSampler;
|
|
3147
|
+
}
|
|
2106
3148
|
createRenderPipeline(props) {
|
|
2107
3149
|
return new WebGPURenderPipeline(this, props);
|
|
2108
3150
|
}
|
|
@@ -2131,32 +3173,106 @@ var init_webgpu_device = __esm({
|
|
|
2131
3173
|
createCanvasContext(props) {
|
|
2132
3174
|
return new WebGPUCanvasContext(this, this.adapter, props);
|
|
2133
3175
|
}
|
|
3176
|
+
createPresentationContext(props) {
|
|
3177
|
+
return new WebGPUPresentationContext(this, props);
|
|
3178
|
+
}
|
|
2134
3179
|
createPipelineLayout(props) {
|
|
2135
3180
|
return new WebGPUPipelineLayout(this, props);
|
|
2136
3181
|
}
|
|
3182
|
+
generateMipmapsWebGPU(texture) {
|
|
3183
|
+
generateMipmapsWebGPU(this, texture);
|
|
3184
|
+
}
|
|
2137
3185
|
submit(commandBuffer) {
|
|
3186
|
+
let submittedCommandEncoder = null;
|
|
2138
3187
|
if (!commandBuffer) {
|
|
2139
|
-
|
|
3188
|
+
submittedCommandEncoder = this.commandEncoder;
|
|
3189
|
+
if (submittedCommandEncoder.getTimeProfilingSlotCount() > 0 && submittedCommandEncoder.getTimeProfilingQuerySet() instanceof WebGPUQuerySet) {
|
|
3190
|
+
const querySet = submittedCommandEncoder.getTimeProfilingQuerySet();
|
|
3191
|
+
querySet._encodeResolveToReadBuffer(submittedCommandEncoder, {
|
|
3192
|
+
firstQuery: 0,
|
|
3193
|
+
queryCount: submittedCommandEncoder.getTimeProfilingSlotCount()
|
|
3194
|
+
});
|
|
3195
|
+
}
|
|
3196
|
+
commandBuffer = submittedCommandEncoder.finish();
|
|
2140
3197
|
this.commandEncoder.destroy();
|
|
2141
|
-
this.commandEncoder = this.createCommandEncoder({
|
|
3198
|
+
this.commandEncoder = this.createCommandEncoder({
|
|
3199
|
+
id: submittedCommandEncoder.props.id,
|
|
3200
|
+
timeProfilingQuerySet: submittedCommandEncoder.getTimeProfilingQuerySet()
|
|
3201
|
+
});
|
|
3202
|
+
}
|
|
3203
|
+
const profiler = getCpuHotspotProfiler(this);
|
|
3204
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
3205
|
+
const submitReason = getCpuHotspotSubmitReason(this);
|
|
3206
|
+
try {
|
|
3207
|
+
this.pushErrorScope("validation");
|
|
3208
|
+
const queueSubmitStartTime = profiler ? getTimestamp() : 0;
|
|
3209
|
+
this.handle.queue.submit([commandBuffer.handle]);
|
|
3210
|
+
if (profiler) {
|
|
3211
|
+
profiler.queueSubmitCount = (profiler.queueSubmitCount || 0) + 1;
|
|
3212
|
+
profiler.queueSubmitTimeMs = (profiler.queueSubmitTimeMs || 0) + (getTimestamp() - queueSubmitStartTime);
|
|
3213
|
+
}
|
|
3214
|
+
this.popErrorScope((error) => {
|
|
3215
|
+
this.reportError(new Error(`${this} command submission: ${error.message}`), this)();
|
|
3216
|
+
this.debug();
|
|
3217
|
+
});
|
|
3218
|
+
if (submittedCommandEncoder) {
|
|
3219
|
+
const submitResolveKickoffStartTime = profiler ? getTimestamp() : 0;
|
|
3220
|
+
scheduleMicrotask(() => {
|
|
3221
|
+
submittedCommandEncoder.resolveTimeProfilingQuerySet().then(() => {
|
|
3222
|
+
this.commandEncoder._gpuTimeMs = submittedCommandEncoder._gpuTimeMs;
|
|
3223
|
+
}).catch(() => {
|
|
3224
|
+
});
|
|
3225
|
+
});
|
|
3226
|
+
if (profiler) {
|
|
3227
|
+
profiler.submitResolveKickoffCount = (profiler.submitResolveKickoffCount || 0) + 1;
|
|
3228
|
+
profiler.submitResolveKickoffTimeMs = (profiler.submitResolveKickoffTimeMs || 0) + (getTimestamp() - submitResolveKickoffStartTime);
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
} finally {
|
|
3232
|
+
if (profiler) {
|
|
3233
|
+
profiler.submitCount = (profiler.submitCount || 0) + 1;
|
|
3234
|
+
profiler.submitTimeMs = (profiler.submitTimeMs || 0) + (getTimestamp() - startTime);
|
|
3235
|
+
const reasonCountKey = submitReason === "query-readback" ? "queryReadbackSubmitCount" : "defaultSubmitCount";
|
|
3236
|
+
const reasonTimeKey = submitReason === "query-readback" ? "queryReadbackSubmitTimeMs" : "defaultSubmitTimeMs";
|
|
3237
|
+
profiler[reasonCountKey] = (profiler[reasonCountKey] || 0) + 1;
|
|
3238
|
+
profiler[reasonTimeKey] = (profiler[reasonTimeKey] || 0) + (getTimestamp() - startTime);
|
|
3239
|
+
}
|
|
3240
|
+
const commandBufferDestroyStartTime = profiler ? getTimestamp() : 0;
|
|
3241
|
+
commandBuffer.destroy();
|
|
3242
|
+
if (profiler) {
|
|
3243
|
+
profiler.commandBufferDestroyCount = (profiler.commandBufferDestroyCount || 0) + 1;
|
|
3244
|
+
profiler.commandBufferDestroyTimeMs = (profiler.commandBufferDestroyTimeMs || 0) + (getTimestamp() - commandBufferDestroyStartTime);
|
|
3245
|
+
}
|
|
2142
3246
|
}
|
|
2143
|
-
this.pushErrorScope("validation");
|
|
2144
|
-
this.handle.queue.submit([commandBuffer.handle]);
|
|
2145
|
-
this.popErrorScope((error) => {
|
|
2146
|
-
this.reportError(new Error(`${this} command submission: ${error.message}`), this)();
|
|
2147
|
-
this.debug();
|
|
2148
|
-
});
|
|
2149
3247
|
}
|
|
2150
3248
|
// WebGPU specific
|
|
2151
3249
|
pushErrorScope(scope) {
|
|
3250
|
+
if (!this.props.debug) {
|
|
3251
|
+
return;
|
|
3252
|
+
}
|
|
3253
|
+
const profiler = getCpuHotspotProfiler(this);
|
|
3254
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
2152
3255
|
this.handle.pushErrorScope(scope);
|
|
3256
|
+
if (profiler) {
|
|
3257
|
+
profiler.errorScopePushCount = (profiler.errorScopePushCount || 0) + 1;
|
|
3258
|
+
profiler.errorScopeTimeMs = (profiler.errorScopeTimeMs || 0) + (getTimestamp() - startTime);
|
|
3259
|
+
}
|
|
2153
3260
|
}
|
|
2154
3261
|
popErrorScope(handler) {
|
|
3262
|
+
if (!this.props.debug) {
|
|
3263
|
+
return;
|
|
3264
|
+
}
|
|
3265
|
+
const profiler = getCpuHotspotProfiler(this);
|
|
3266
|
+
const startTime = profiler ? getTimestamp() : 0;
|
|
2155
3267
|
this.handle.popErrorScope().then((error) => {
|
|
2156
3268
|
if (error) {
|
|
2157
3269
|
handler(error);
|
|
2158
3270
|
}
|
|
2159
3271
|
});
|
|
3272
|
+
if (profiler) {
|
|
3273
|
+
profiler.errorScopePopCount = (profiler.errorScopePopCount || 0) + 1;
|
|
3274
|
+
profiler.errorScopeTimeMs = (profiler.errorScopeTimeMs || 0) + (getTimestamp() - startTime);
|
|
3275
|
+
}
|
|
2160
3276
|
}
|
|
2161
3277
|
// PRIVATE METHODS
|
|
2162
3278
|
_getInfo() {
|
|
@@ -2197,7 +3313,6 @@ var init_webgpu_device = __esm({
|
|
|
2197
3313
|
features.add("snorm16-renderable-webgl");
|
|
2198
3314
|
}
|
|
2199
3315
|
const WEBGPU_ALWAYS_FEATURES = [
|
|
2200
|
-
"timer-query-webgl",
|
|
2201
3316
|
"compilation-status-async-webgl",
|
|
2202
3317
|
"float32-renderable-webgl",
|
|
2203
3318
|
"float16-renderable-webgl",
|
|
@@ -2208,7 +3323,7 @@ var init_webgpu_device = __esm({
|
|
|
2208
3323
|
for (const feature of WEBGPU_ALWAYS_FEATURES) {
|
|
2209
3324
|
features.add(feature);
|
|
2210
3325
|
}
|
|
2211
|
-
return new
|
|
3326
|
+
return new import_core25.DeviceFeatures(Array.from(features), this.props._disabledFeatures);
|
|
2212
3327
|
}
|
|
2213
3328
|
_getDeviceSpecificTextureFormatCapabilities(capabilities) {
|
|
2214
3329
|
const { format } = capabilities;
|
|
@@ -2236,8 +3351,8 @@ __export(dist_exports, {
|
|
|
2236
3351
|
module.exports = __toCommonJS(dist_exports);
|
|
2237
3352
|
|
|
2238
3353
|
// dist/adapter/webgpu-adapter.js
|
|
2239
|
-
var
|
|
2240
|
-
var WebGPUAdapter = class extends
|
|
3354
|
+
var import_core26 = require("@luma.gl/core");
|
|
3355
|
+
var WebGPUAdapter = class extends import_core26.Adapter {
|
|
2241
3356
|
/** type of device's created by this adapter */
|
|
2242
3357
|
type = "webgpu";
|
|
2243
3358
|
isSupported() {
|
|
@@ -2284,14 +3399,14 @@ var WebGPUAdapter = class extends import_core24.Adapter {
|
|
|
2284
3399
|
requiredLimits
|
|
2285
3400
|
});
|
|
2286
3401
|
const { WebGPUDevice: WebGPUDevice2 } = await Promise.resolve().then(() => (init_webgpu_device(), webgpu_device_exports));
|
|
2287
|
-
|
|
3402
|
+
import_core26.log.groupCollapsed(1, "WebGPUDevice created")();
|
|
2288
3403
|
try {
|
|
2289
3404
|
const device = new WebGPUDevice2(props, gpuDevice, adapter, adapterInfo);
|
|
2290
|
-
|
|
2291
|
-
|
|
3405
|
+
import_core26.log.probe(1, "Device created. For more info, set chrome://flags/#enable-webgpu-developer-features")();
|
|
3406
|
+
import_core26.log.table(1, device.info)();
|
|
2292
3407
|
return device;
|
|
2293
3408
|
} finally {
|
|
2294
|
-
|
|
3409
|
+
import_core26.log.groupEnd(1)();
|
|
2295
3410
|
}
|
|
2296
3411
|
}
|
|
2297
3412
|
async attach(handle) {
|